diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index f5c5b73..cb34e28 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,10 @@ +2006-03-06 Karl Runge + * x11vnc: switch remote control to X11VNC_REMOTE property. Put + in -unixpw constraints for reverse connections under -inetd. + -inetd won't quit when reverse conn client leaves. Allow keyboard + input for viewonly -unixpw logins. "%*" utils for testing + -unixpw. improve start time fix bugs, small screen in gui. + 2006-03-04 Karl Runge * x11vnc: -unixpw on *bsd, hpux and tru64. Add -unixpw_nis for non-shadow systems. check stunnel dying. check SSH_CONNECTION diff --git a/x11vnc/README b/x11vnc/README index b5a1be7..ba8b723 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Sat Mar 4 17:57:40 EST 2006 +x11vnc README file Date: Mon Mar 6 10:24:41 EST 2006 The following information is taken from these URLs: @@ -5382,7 +5382,7 @@ x11vnc: a VNC server for real X displays Here are all of x11vnc command line options: % x11vnc -opts (see below for -help long descriptions) -x11vnc: allow VNC connections to real X11 displays. 0.8.1 lastmod: 2006-03-04 +x11vnc: allow VNC connections to real X11 displays. 0.8.1 lastmod: 2006-03-06 x11vnc options: -display disp -auth file @@ -5495,7 +5495,7 @@ libvncserver-tight-extension options: % x11vnc -help -x11vnc: allow VNC connections to real X11 displays. 0.8.1 lastmod: 2006-03-04 +x11vnc: allow VNC connections to real X11 displays. 0.8.1 lastmod: 2006-03-06 Typical usage is: @@ -5793,8 +5793,9 @@ Options: -novncconnect VNC program vncconnect(1). When the property is set to "host" or "host:port" establish a reverse connection. Using xprop(1) instead of vncconnect may - work (see the FAQ). The -remote control mechanism also - uses this VNC_CONNECT channel. Default: -vncconnect + work (see the FAQ). The -remote control mechanism uses + X11VNC_REMOTE channel, and this option disables/enables + it as well. Default: -vncconnect -allow host1[,host2..] Only allow client connections from hosts matching the comma separated list of hostnames or IP addresses. @@ -5909,8 +5910,8 @@ Options: x11vnc as root with the "-users +nobody" option to immediately switch to user nobody. Another source of problems are PAM modules that prompt for extra info, - e.g. password aging modules. These logins will always - fail as well. + e.g. password aging modules. These logins will fail + as well even when the correct password is supplied. *IMPORTANT*: to prevent the Unix password being sent in *clear text* over the network, two x11vnc options are @@ -5937,17 +5938,28 @@ Options: is set and appears reasonable. If it does, then the stunnel requirement is dropped since it is assumed you are using ssh for the encrypted tunnelling. - Use -stunnel to force stunnel usage. + Use -stunnel to force stunnel usage for this case. Set UNIXPW_DISABLE_LOCALHOST=1 to disable the -localhost requirement. One should never do this (i.e. allow the Unix passwords to be sniffed on the network). - NOTE: in -inetd mode the two settings are not enforced - since x11vnc does not make network connections in - that case. Be sure to use encryption from the viewer - to inetd. One can also have your own stunnel spawn - x11vnc in -inetd mode. See the FAQ. + Regarding reverse connections (e.g. -R connect:host), + the -localhost constraint is in effect and the reverse + connections can only be used to connect to the same + machine x11vnc is running on (default port 5500). + Please use a ssh or stunnel port redirection to the + viewer machine to tunnel the reverse connection over + an encrypted channel. Note that Unix username and + password *will* be prompted for (unlike VNC passwords + that are skipped for reverse connections). + + NOTE: in -inetd mode the two settings are attempted + to be enforced for reverse connections. Be sure to + use encryption from the viewer to inetd since x11vnc + cannot guess easily if it is encrpyted. Note: you can + also have your own stunnel spawn x11vnc in -inetd mode + (i.e. bypassing inetd). See the FAQ. The user names in the comma separated [list] can have per-user options after a ":", e.g. "fred:opts" @@ -5962,16 +5974,21 @@ Options: Use "deny" to explicitly deny some users if you use "*" to set a global option. --unixpw_nis [list] As -unixpw above, however do not run su(1) but rather - use the traditional getpwnam() + crypt() method instead. - This requires that the encrpyted passwords be readable. - Passwords stored in /etc/shadow will be inaccessible - unless run as root. This is called "NIS" mode - simply because in most NIS setups the user encrypted - passwords are accessible (e.g. "ypcat passwd"). - NIS is not required for this mode to work, but it - is unlikely it will work for any other environment. - All of the -unixpw options and contraints apply. + There are also some tools for testing password if [list] + starts with the "%" character. See the quick_pw() + function for details. + +-unixpw_nis [list] As -unixpw above, however do not use su(1) but rather + use the traditional getpwnam(3) + crypt(3) method + instead. This requires that the encrpyted passwords + be readable. Passwords stored in /etc/shadow will + be inaccessible unless run as root. This is called + "NIS" mode simply because in most NIS setups the + user encrypted passwords are accessible (e.g. "ypcat + passwd"). NIS is not required for this mode to + work, but it is unlikely it will work for any other + environment. All of the -unixpw options and contraints + apply. -stunnel [pem] Use the stunnel(1) (www.stunnel.org) to provide an encrypted SSL tunnel between viewers and x11vnc. @@ -7238,7 +7255,7 @@ n -remote command. The default communication channel is that of X - properties (specifically VNC_CONNECT), and so this + properties (specifically X11VNC_REMOTE), and so this command must be run with correct settings for DISPLAY and possibly XAUTHORITY to connect to the X server and set the property. Alternatively, use the -display @@ -7520,9 +7537,9 @@ n it comes back with prefix "aro=" instead of "ans=". Some -remote commands are pure actions that do not make - sense as variables, e.g. "stop" or "disconnect", - in these cases the value returned is "N/A". To direct - a query straight to the VNC_CONNECT property or connect + sense as variables, e.g. "stop" or "disconnect", in + these cases the value returned is "N/A". To direct a + query straight to the X11VNC_REMOTE property or connect file use "qry=..." instead of "cmd=..." Here is the current list of "variables" that can @@ -7621,9 +7638,9 @@ n A note about security wrt remote control commands. If someone can connect to the X display and change - the property VNC_CONNECT, then they can remotely + the property X11VNC_REMOTE, then they can remotely control x11vnc. Normally access to the X display is - protected. Note that if they can modify VNC_CONNECT + protected. Note that if they can modify X11VNC_REMOTE on the X server, they have enough permissions to also run their own x11vnc and thus have complete control of the desktop. If the "-connect /path/to/file" @@ -7633,9 +7650,9 @@ n permissions. See -privremote below. If you are paranoid and do not think -noremote is - enough, to disable the VNC_CONNECT property channel - completely use -novncconnect, or use the -safer - option that shuts many things off. + enough, to disable the X11VNC_REMOTE property channel + completely use -novncconnect, or use the -safer option + that shuts many things off. -unsafe A few remote commands are disabled by default (currently: id:pick, accept:, gone:, and diff --git a/x11vnc/connections.c b/x11vnc/connections.c index 94db970..d8dbea5 100644 --- a/x11vnc/connections.c +++ b/x11vnc/connections.c @@ -19,6 +19,9 @@ /* string for the VNC_CONNECT property */ char vnc_connect_str[VNC_CONNECT_MAX+1]; Atom vnc_connect_prop = None; +char x11vnc_remote_str[X11VNC_REMOTE_MAX+1]; +Atom x11vnc_remote_prop = None; +rfbClientPtr inetd_client = NULL; int all_clients_initialized(void); char *list_clients(void); @@ -29,7 +32,9 @@ void set_client_input(char *str); void set_child_info(void); void reverse_connect(char *str); void set_vnc_connect_prop(char *str); -void read_vnc_connect_prop(void); +void read_vnc_connect_prop(int); +void set_x11vnc_remote_prop(char *str); +void read_x11vnc_remote_prop(int); void check_connect_inputs(void); void check_gui_inputs(void); enum rfbNewClientAction new_client(rfbClientPtr client); @@ -604,8 +609,8 @@ static void client_gone(rfbClientPtr client) { free_client_data(client); - if (inetd) { - rfbLog("viewer exited.\n"); + if (inetd && client == inetd_client) { + rfbLog("inetd viewer exited.\n"); clean_up_exit(0); } if (connect_once) { @@ -1463,6 +1468,21 @@ static int do_reverse_connect(char *str) { *p = '\0'; } + if (inetd && unixpw) { + if(strcmp(host, "localhost") && strcmp(host, "127.0.0.1")) { + if (! getenv("UNIXPW_DISABLE_LOCALHOST")) { + rfbLog("reverse_connect: in -inetd only localhost\n"); + rfbLog("connections allowed under -unixpw\n"); + return 0; + } + } + if (! getenv("UNIXPW_DISABLE_STUNNEL") && ! have_ssh_env()) { + rfbLog("reverse_connect: in -inetd stunnel/ssh\n"); + rfbLog("required under -unixpw\n"); + return 0; + } + } + cl = rfbReverseConnection(screen, host, rport); free(host); @@ -1529,15 +1549,20 @@ void reverse_connect(char *str) { } /* - * Routines for monitoring the VNC_CONNECT property for changes. - * The vncconnect(1) will set it on our X display. + * Routines for monitoring the VNC_CONNECT and X11VNC_REMOTE properties + * for changes. The vncconnect(1) will set it on our X display. */ void set_vnc_connect_prop(char *str) { XChangeProperty(dpy, rootwin, vnc_connect_prop, XA_STRING, 8, PropModeReplace, (unsigned char *)str, strlen(str)); } -void read_vnc_connect_prop(void) { +void set_x11vnc_remote_prop(char *str) { + XChangeProperty(dpy, rootwin, x11vnc_remote_prop, XA_STRING, 8, + PropModeReplace, (unsigned char *)str, strlen(str)); +} + +void read_vnc_connect_prop(int nomsg) { Atom type; int format, slen, dlen; unsigned long nitems = 0, bytes_after = 0; @@ -1575,28 +1600,73 @@ void read_vnc_connect_prop(void) { } while (bytes_after > 0); vnc_connect_str[VNC_CONNECT_MAX] = '\0'; - if (! db) { + if (! db || nomsg) { ; - } else if (strstr(vnc_connect_str, "ans=stop:N/A,ans=quit:N/A,ans=")) { + } else { + rfbLog("read VNC_CONNECT: %s\n", vnc_connect_str); + } +} + +void read_x11vnc_remote_prop(int nomsg) { + Atom type; + int format, slen, dlen; + unsigned long nitems = 0, bytes_after = 0; + unsigned char* data = NULL; + int db = 1; + + x11vnc_remote_str[0] = '\0'; + slen = 0; + + if (! vnc_connect || x11vnc_remote_prop == None) { + /* not active or problem with X11VNC_REMOTE atom */ + return; + } + + /* read the property value into x11vnc_remote_str: */ + do { + if (XGetWindowProperty(dpy, DefaultRootWindow(dpy), + x11vnc_remote_prop, nitems/4, X11VNC_REMOTE_MAX/16, False, + AnyPropertyType, &type, &format, &nitems, &bytes_after, + &data) == Success) { + + dlen = nitems * (format/8); + if (slen + dlen > X11VNC_REMOTE_MAX) { + /* too big */ + rfbLog("warning: truncating large X11VNC_REMOTE" + " string > %d bytes.\n", X11VNC_REMOTE_MAX); + XFree(data); + break; + } + memcpy(x11vnc_remote_str+slen, data, dlen); + slen += dlen; + x11vnc_remote_str[slen] = '\0'; + XFree(data); + } + } while (bytes_after > 0); + + x11vnc_remote_str[X11VNC_REMOTE_MAX] = '\0'; + if (! db || nomsg) { ; - } else if (strstr(vnc_connect_str, "qry=stop,quit,exit")) { + } else if (strstr(x11vnc_remote_str, "ans=stop:N/A,ans=quit:N/A,ans=")) { ; - } else if (strstr(vnc_connect_str, "ack=") == vnc_connect_str) { + } else if (strstr(x11vnc_remote_str, "qry=stop,quit,exit")) { ; - } else if (quiet && strstr(vnc_connect_str, "qry=ping") == - vnc_connect_str) { + } else if (strstr(x11vnc_remote_str, "ack=") == x11vnc_remote_str) { ; - } else if (strstr(vnc_connect_str, "cmd=") && - strstr(vnc_connect_str, "passwd")) { - rfbLog("read VNC_CONNECT: *\n"); - } else if (strlen(vnc_connect_str) > 38) { + } else if (quiet && strstr(x11vnc_remote_str, "qry=ping") == + x11vnc_remote_str) { + ; + } else if (strstr(x11vnc_remote_str, "cmd=") && + strstr(x11vnc_remote_str, "passwd")) { + rfbLog("read X11VNC_REMOTE: *\n"); + } else if (strlen(x11vnc_remote_str) > 38) { char trim[100]; trim[0] = '\0'; - strncat(trim, vnc_connect_str, 38); - rfbLog("read VNC_CONNECT: %s ...\n", trim); + strncat(trim, x11vnc_remote_str, 38); + rfbLog("read X11VNC_REMOTE: %s ...\n", trim); } else { - rfbLog("read VNC_CONNECT: %s\n", vnc_connect_str); + rfbLog("read X11VNC_REMOTE: %s\n", x11vnc_remote_str); } } @@ -1643,6 +1713,13 @@ void check_connect_inputs(void) { vnc_connect_str[0] = '\0'; } send_client_connect(); + + /* X11VNC_REMOTE property */ + if (vnc_connect && *x11vnc_remote_str != '\0') { + client_connect = strdup(x11vnc_remote_str); + x11vnc_remote_str[0] = '\0'; + } + send_client_connect(); } void check_gui_inputs(void) { @@ -1650,7 +1727,7 @@ void check_gui_inputs(void) { int socks[ICON_MODE_SOCKS]; fd_set fds; struct timeval tv; - char buf[VNC_CONNECT_MAX+1]; + char buf[X11VNC_REMOTE_MAX+1]; ssize_t nbytes; if (unixpw_in_progress) return; @@ -1686,10 +1763,10 @@ void check_gui_inputs(void) { if (! FD_ISSET(fd, &fds)) { continue; } - for (k=0; k<=VNC_CONNECT_MAX; k++) { + for (k=0; k<=X11VNC_REMOTE_MAX; k++) { buf[k] = '\0'; } - nbytes = read(fd, buf, VNC_CONNECT_MAX); + nbytes = read(fd, buf, X11VNC_REMOTE_MAX); if (nbytes <= 0) { close(fd); icon_mode_socks[socks[i]] = -1; @@ -1726,15 +1803,20 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { last_event = last_input = time(0); + if (inetd) { /* * Set this so we exit as soon as connection closes, * otherwise client_gone is only called after RFB_CLIENT_ACCEPT */ - client->clientGoneHook = client_gone; + if (inetd_client == NULL) { + inetd_client = client; + client->clientGoneHook = client_gone; + } } clients_served++; +if (0) fprintf(stderr, "new_client: %s %d\n", client->host, clients_served); if (unixpw && unixpw_in_progress) { rfbLog("denying additional client: %s during -unixpw login.\n", @@ -1822,6 +1904,11 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { if (unixpw) { unixpw_in_progress = 1; unixpw_client = client; + unixpw_login_viewonly = 0; + if (client->viewOnly) { + unixpw_login_viewonly = 1; + client->viewOnly = FALSE; + } unixpw_last_try_time = time(0); unixpw_screen(1); unixpw_keystroke(0, 0, 1); @@ -1926,6 +2013,7 @@ void send_client_info(char *str) { strcat(pstr, "\n"); if (icon_mode_fh) { + if (0) fprintf(icon_mode_fh, "\n"); fprintf(icon_mode_fh, "%s", pstr); fflush(icon_mode_fh); } @@ -1940,6 +2028,7 @@ void send_client_info(char *str) { len = strlen(pstr); while (len > 0) { + if (0) write(sock, "\n", 1); n = write(sock, buf, len); if (n > 0) { buf += n; @@ -1965,7 +2054,11 @@ void check_new_clients(void) { int run_after_accept = 0; if (unixpw_in_progress) { - if (time(0) > unixpw_last_try_time + 30) { + if (unixpw_client && unixpw_client->viewOnly) { + unixpw_login_viewonly = 1; + unixpw_client->viewOnly = FALSE; + } + if (time(0) > unixpw_last_try_time + 25) { rfbLog("unixpw_deny: timed out waiting for reply.\n"); unixpw_deny(); } @@ -1992,7 +2085,7 @@ void check_new_clients(void) { return; } if (! client_count) { - send_client_info("none"); + send_client_info("clients:none"); return; } @@ -2037,9 +2130,12 @@ void check_new_clients(void) { } } if (send_info) { - char *str = list_clients(); + char *str, *s = list_clients(); + str = (char *) malloc(strlen("clients:") + strlen(s) + 1); + sprintf(str, "clients:%s", s); send_client_info(str); free(str); + free(s); } } diff --git a/x11vnc/connections.h b/x11vnc/connections.h index 7d51ab5..b67d983 100644 --- a/x11vnc/connections.h +++ b/x11vnc/connections.h @@ -5,6 +5,10 @@ extern char vnc_connect_str[]; extern Atom vnc_connect_prop; +extern char x11vnc_remote_str[]; +extern Atom x11vnc_remote_prop; +extern rfbClientPtr inetd_client; + extern int all_clients_initialized(void); extern char *list_clients(void); @@ -15,7 +19,9 @@ extern void set_client_input(char *str); extern void set_child_info(void); extern void reverse_connect(char *str); extern void set_vnc_connect_prop(char *str); -extern void read_vnc_connect_prop(void); +extern void read_vnc_connect_prop(int); +extern void set_x11vnc_remote_prop(char *str); +extern void read_x11vnc_remote_prop(int); extern void check_connect_inputs(void); extern void check_gui_inputs(void); extern enum rfbNewClientAction new_client(rfbClientPtr client); diff --git a/x11vnc/gui.c b/x11vnc/gui.c index b82e921..32bc51a 100644 --- a/x11vnc/gui.c +++ b/x11vnc/gui.c @@ -22,6 +22,7 @@ int tray_manager_ok = 0; Window tray_request = None; Window tray_window = None; int tray_unembed = 0; +pid_t run_gui_pid = 0; char *get_gui_code(void); @@ -183,6 +184,12 @@ static char *icon_mode_embed_id = NULL; static char *icon_mode_font = NULL; static char *icon_mode_params = NULL; +static int got_sigusr1 = 0; + +static void sigusr1 (int sig) { + got_sigusr1 = 1; +} + static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc, int simple_gui, pid_t parent, char *gui_opts) { char *x11vnc_xdisplay = NULL; @@ -191,10 +198,11 @@ static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc, char cmd[100]; char *wish = NULL, *orig_path, *full_path, *tpath, *p; char *old_xauth = NULL; - int try_max = 4, sleep = 300; + int try_max = 4, sleep = 300, totms; pid_t mypid = getpid(); FILE *pipe, *tmpf; +if (0) fprintf(stderr, "run_gui: %s -- %d %d\n", gui_xdisplay, connect_to_x11vnc, (int) parent); if (*gui_code == '\0') { rfbLog("gui: gui not compiled into this program.\n"); exit(0); @@ -234,21 +242,44 @@ static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc, scr = DefaultScreen(dpy); rootwin = RootWindow(dpy, scr); initialize_vnc_connect_prop(); + initialize_x11vnc_remote_prop(); + } + + signal(SIGUSR1, sigusr1); + got_sigusr1 = 0; + totms = 0; + while (totms < 3500) { + usleep(50*1000); + totms += 50; + if (got_sigusr1) { + fprintf(stderr, "\n"); + if (! quiet) rfbLog("gui: got SIGUSR1\n"); + break; + } + if (! start_x11vnc && totms >= 150) { + break; + } } - usleep(2200*1000); - fprintf(stderr, "\n"); - if (!quiet) { + signal(SIGUSR1, SIG_DFL); + if (! got_sigusr1) fprintf(stderr, "\n"); + + if (!quiet && ! got_sigusr1) { rfbLog("gui: trying to contact a x11vnc server at X" " display %s ...\n", NONUL(x11vnc_xdisplay)); } + for (i=0; i, gone:, and\n" diff --git a/x11vnc/params.h b/x11vnc/params.h index ad10d14..79f6624 100644 --- a/x11vnc/params.h +++ b/x11vnc/params.h @@ -30,6 +30,7 @@ #define FB_REQ 0x4 #define VNC_CONNECT_MAX 16384 +#define X11VNC_REMOTE_MAX 16384 #define PROP_MAX (131072L) #define MAXN 256 diff --git a/x11vnc/remote.c b/x11vnc/remote.c index 8f5df6d..30e9a5b 100644 --- a/x11vnc/remote.c +++ b/x11vnc/remote.c @@ -55,11 +55,11 @@ int send_remote_cmd(char *cmd, int query, int wait) { perror("fopen"); return 1; } - } else if (vnc_connect_prop == None) { - initialize_vnc_connect_prop(); - if (vnc_connect_prop == None) { + } else if (x11vnc_remote_prop == None) { + initialize_x11vnc_remote_prop(); + if (x11vnc_remote_prop == None) { fprintf(stderr, "send_remote_cmd: could not obtain " - "VNC_CONNECT X property\n"); + "X11VNC_REMOTE X property\n"); return 1; } } @@ -71,13 +71,13 @@ int send_remote_cmd(char *cmd, int query, int wait) { fclose(in); } else { fprintf(stderr, ">>> sending remote command: \"%s\" via" - " VNC_CONNECT X property.\n", cmd); - set_vnc_connect_prop(cmd); + " X11VNC_REMOTE X property.\n", cmd); + set_x11vnc_remote_prop(cmd); XFlush(dpy); } if (query || wait) { - char line[VNC_CONNECT_MAX]; + char line[X11VNC_REMOTE_MAX]; int rc=1, i=0, max=70, ms_sl=50; if (!strcmp(cmd, "cmd=stop")) { @@ -95,7 +95,7 @@ int send_remote_cmd(char *cmd, int query, int wait) { perror("fopen"); return 1; } - fgets(line, VNC_CONNECT_MAX, in); + fgets(line, X11VNC_REMOTE_MAX, in); fclose(in); q = line; while (*q != '\0') { @@ -103,8 +103,9 @@ int send_remote_cmd(char *cmd, int query, int wait) { q++; } } else { - read_vnc_connect_prop(); - strncpy(line, vnc_connect_str, VNC_CONNECT_MAX); + read_x11vnc_remote_prop(1); + strncpy(line, x11vnc_remote_str, + X11VNC_REMOTE_MAX); } if (strcmp(cmd, line)){ if (query) { @@ -581,8 +582,8 @@ char *process_remote_cmd(char *cmd, int stringonly) { #if REMOTE_CONTROL char *p = cmd; char *co = ""; - char buf[VNC_CONNECT_MAX]; - int bufn = VNC_CONNECT_MAX; + char buf[X11VNC_REMOTE_MAX]; + int bufn = X11VNC_REMOTE_MAX; int query = 0; static char *prev_cursors_mode = NULL; @@ -617,7 +618,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { strncat(tmp, q, 500); res = process_remote_cmd(tmp, 1); if (res && strlen(buf)+strlen(res) - >= VNC_CONNECT_MAX - 1) { + >= X11VNC_REMOTE_MAX - 1) { rfbLog("overflow in process_remote_cmd:" " %s -- %s\n", buf, res); free(res); @@ -3848,7 +3849,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { } } else { if (dpy) { /* raw_fb hack */ - set_vnc_connect_prop(buf); + set_x11vnc_remote_prop(buf); XFlush(dpy); } } diff --git a/x11vnc/sslcmds.c b/x11vnc/sslcmds.c index 48340de..1fc0144 100644 --- a/x11vnc/sslcmds.c +++ b/x11vnc/sslcmds.c @@ -13,6 +13,7 @@ #endif +void check_stunnel(void); int start_stunnel(int stunnel_port, int x11vnc_port); void stop_stunnel(void); void setup_stunnel(int rport, int *argc, char **argv); diff --git a/x11vnc/tkx11vnc b/x11vnc/tkx11vnc index 6c62038..c191662 100755 --- a/x11vnc/tkx11vnc +++ b/x11vnc/tkx11vnc @@ -56,6 +56,30 @@ catch {rename send {}} # -- means add a separator # +global env started time_count +set started "" +proc dtime {{msg ""}} { + global started time_count + if {$started == ""} { + return + } + set diff [expr "[exec gtod.bin] - $started"] + set diff [format "%.2f" $diff] + incr time_count + if {$msg == ""} { + set msg $time_count + } + puts -nonewline stderr "$msg $diff " + puts stderr [clock format [clock seconds]] +} + +if [info exists env(X11VNC_GUI_TIME)] { + global started time_count + set started [exec gtod.bin] + set time_count 0 + dtime "S" +} + proc set_template {} { global template set template " @@ -1746,7 +1770,6 @@ proc entry_delete {} { proc push_new_value {item name new {query 1}} { global menu_var always_update remote_output query_output - global delay_sleep extra_sleep extra_sleep_split global query_result_list set debug [in_debug_mode] @@ -2985,7 +3008,6 @@ proc do_var {item} { set debug [in_debug_mode] - set string 0 if {[is_action $item] || $item == "WindowView"} { # Menu item is action: @@ -3409,9 +3431,9 @@ proc update_clients_menu {list} { set count 0 foreach client [split $list ","] { if {![regexp {^[a-z0-9]*[a-z0-9]:} $client]} { - append_text "Skipping client line: " - append_text $client - append_text "\n" + #append_text "Skipping client line: " + #append_text $client + #append_text "\n" continue } regsub -all {[{}()~!$&*|;'"`{}<>\[\]]} $client "" client @@ -3978,9 +4000,15 @@ proc do_props {{msg ""}} { global have_labelframes ffont bfont global props_buttons icon_noadvanced global icon_mode icon_mode_at_startup + global screen_height screen_width check_update_vars + set pady 1m + if {$screen_height <= 360} { + set pady 0m + } + if [info exists menu_var(deny)] { if {$menu_var(deny) == $unset_str || $menu_var(deny) == 0} { set props_accept 1 @@ -4087,7 +4115,7 @@ proc do_props {{msg ""}} { pack $vp.l -fill x -expand 1 -padx 1m -pady 0m -side top } entry $vp.e -show "*" -textvariable props_viewpasswd -font $bfont - pack $vp.e -fill x -expand 1 -padx 1m -pady 1m -side top + pack $vp.e -fill x -expand 1 -padx 1m -pady $pady -side top lappend props_buttons $vp.e @@ -4102,7 +4130,7 @@ proc do_props {{msg ""}} { pack $pw.l -fill x -expand 1 -padx 1m -pady 0m -side top } entry $pw.e -show "*" -textvariable props_passwd -font $bfont - pack $pw.e -fill x -expand 1 -padx 1m -pady 1m -side top + pack $pw.e -fill x -expand 1 -padx 1m -pady $pady -side top if {! $icon_mode_at_startup} { $vp.e configure -state disabled @@ -4121,31 +4149,31 @@ proc do_props {{msg ""}} { frame $sh checkbutton $sh.button -text "Shared" \ -variable props_shared -anchor w -font $bfont - pack $sh.button -fill x -expand 1 -padx 1m -pady 1m + pack $sh.button -fill x -expand 1 -padx 1m -pady $pady set vo "$w.viewonly" frame $vo checkbutton $vo.button -text "All Clients ViewOnly" \ -variable props_viewonly -anchor w -font $bfont - pack $vo.button -fill x -expand 1 -padx 1m -pady 1m + pack $vo.button -fill x -expand 1 -padx 1m -pady $pady set cf "$w.confirm" frame $cf checkbutton $cf.button -text "Ask for Confirmation" \ -variable props_confirm -anchor w -font $bfont - pack $cf.button -fill x -expand 1 -padx 1m -pady 1m + pack $cf.button -fill x -expand 1 -padx 1m -pady $pady set ac "$w.accept" frame $ac checkbutton $ac.button -text "Accept Connections" \ -variable props_accept -anchor w -font $bfont - pack $ac.button -fill x -expand 1 -padx 1m -pady 1m + pack $ac.button -fill x -expand 1 -padx 1m -pady $pady set px "6m" - pack $b1 -side bottom -fill x -pady 1m -padx $px - pack $b2 -side bottom -fill x -pady 1m -padx $px - pack $vp -side bottom -fill x -pady 1m -padx $px - pack $pw -side bottom -fill x -pady 1m -padx $px + pack $b1 -side bottom -fill x -pady $pady -padx $px + pack $b2 -side bottom -fill x -pady $pady -padx $px + pack $vp -side bottom -fill x -pady $pady -padx $px + pack $pw -side bottom -fill x -pady $pady -padx $px pack $sh -side bottom -fill x -pady 0m -padx $px pack $vo -side bottom -fill x -pady 0m -padx $px pack $cf -side bottom -fill x -pady 0m -padx $px @@ -4158,7 +4186,8 @@ proc do_props {{msg ""}} { set ms "$w.msg" text $ms -font $ffont -relief ridge -width $tw -height $th $ms insert 1.0 $msg - pack $ms -side bottom -fill x -pady 1m -padx $px + pack $ms -side bottom -fill x -pady $pady -padx $px + update } lappend props_buttons $ac.button $cf.button $vo.button $sh.button @@ -4346,7 +4375,10 @@ proc read_client_info {channel} { catch {file delete $x11vnc_client_file} set read_client_info_lock 0 clean_icon_exit - } elseif {$str != "skip"} { + } elseif {$str == "skip"} { + ; + } elseif [regexp {^clients:} $str] { + regsub {^clients:} $str "" str if {$str == "none"} { set str "" } @@ -4487,6 +4519,7 @@ proc try_client_info_sock {} { global x11vnc_xdisplay0 menu_var set db 0 +#dtime t1 set start 13037 set tries 100 set socket_got_callback 0 @@ -4537,8 +4570,12 @@ proc try_client_info_sock {} { append_text "try_client_info_sock: server socket failed.\n" return } - run_remote_cmd [list "-nosync" "-R" "noop"] - after 500 + if {! $x11vnc_started} { + run_remote_cmd [list "-nosync" "-R" "noop"] + if {$db} {dtime A} + after 250 + if {$db} {dtime A} + } # set the cookie to some obscured randomness set socket_cookie [clock clicks] @@ -4557,8 +4594,18 @@ proc try_client_info_sock {} { } run_remote_cmd [list "-nosync" "-R" \ "client_info_sock:$myaddr:$port:$socket_cookie"] +#dtime t2 if {$db} {puts "client_info_sock:$myaddr:$port:$socket_cookie"} - after 500 + for {set i 0} {$i < 10} {incr i} { + after 50 + update; update idletasks +#dtime aa + if {$socket_got_callback != 0} { +#puts "break-" + break + } + } +#dtime t3 set aftid "" if {$socket_got_callback == 0} { @@ -4576,6 +4623,7 @@ proc try_client_info_sock {} { } else { setup_client_sock 1 } +#dtime t4 } proc set_icon_label {} { @@ -5022,10 +5070,14 @@ proc make_widgets {top} { global helptext helpremote helplabel global icon_mode icon_win props_win full_win global top_widget_names + global screen_height screen_width # Make the top label set label_width 80 + if {$screen_width <= 400} { + set label_width 64 + } set info_label "$top.info" label $info_label -textvariable info_str -bd 2 -relief groove \ -anchor w -width $label_width -font $ffont @@ -5124,8 +5176,14 @@ proc make_widgets {top} { pack $df -side top -fill x # text area + global text_height set text_area "$top.text" - text $text_area -height 12 -relief ridge -font $ffont + if {$screen_width <= 400} { + text $text_area -height $text_height -width $label_width \ + -relief ridge -font $ffont + } else { + text $text_area -height $text_height -relief ridge -font $ffont + } pack $text_area -side top -fill both -expand 1 set top_widget_names(text) $text_area @@ -5694,6 +5752,24 @@ proc run_remote_cmd_via_sock {opts} { if {$db} {puts stderr "run_remote_cmd_via_sock: \"$res\""} set res [string trim $res] + if [regexp {^clients:} $res] { + regsub {^clients:} $res "" tmp + if {$tmp == "none"} { + set tmp "" + } + update_clients_menu $tmp + set client_str $tmp + set_client_balloon $tmp + + if ![regexp {^clients} $opt] { + # we could block here... + if {$db} {puts stderr "run_remote_cmd_via_sock: gets"} + gets $client_sock res + if {$db} {puts stderr "run_remote_cmd_via_sock: \"$res\""} + set res [string trim $res] + } + } + set docmd "" if {$res != ""} { @@ -5806,6 +5882,7 @@ proc try_connect {} { global menu_var unset_str set db 0 +#dtime c1 if {! $connected_to_x11vnc} { if {[info exists menu_var(display)]} { @@ -5820,6 +5897,7 @@ proc try_connect {} { set_info "Pinging $x11vnc_xdisplay ..." set rargs [list "-Q" "ping"] set result [run_remote_cmd $rargs] +#dtime c2a if {$db} {puts "try_connect: \"$result\""} @@ -5831,10 +5909,12 @@ proc try_connect {} { set_connected yes setup_client_channel +#dtime c2b setup_client_sock 1 setup_client_tail fetch_displays +#dtime c3a return 1 } else { set str "x11vnc server." @@ -6007,6 +6087,10 @@ proc undo_tray_embed {} { ############################################################################ # main: +if [info exists env(X11VNC_GUI_TIME)] { + dtime M +} + wm withdraw . global env x11vnc_prog x11vnc_cmdline x11vnc_xdisplay x11vnc_connect; @@ -6017,10 +6101,10 @@ global x11vnc_auth_file x11vnc_connect_file beginner_mode simple_gui_created global helpall helptext helpremote helplabel hostname osname global all_settings reply_xdisplay always_update global max_text_height max_text_width +global text_height global menu_var unset_str menus_disabled global bfont ffont sfont snfont old_labels have_labelframes global connected_to_x11vnc -global delay_sleep extra_sleep extra_sleep_split global cache_all_query_vars global last_query_all_time query_all_freq client_tail client_sock client_info_read global icon_mode icon_mode_at_startup @@ -6028,6 +6112,7 @@ global tray_embed tray_running icon_setpasswd icon_embed_id global icon_noadvanced icon_minimal global make_gui_count text_area_str global gui_argv0 gui_start_mode +global screen_height screen_width set unset_str "(unset)" set vnc_url $unset_str @@ -6035,6 +6120,7 @@ set connected_to_x11vnc 0 set menus_disabled 0 set max_text_height 40 set max_text_width 90 +set text_height 14 set bfont "-adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*" set sfont "-adobe-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*" set snfont "-adobe-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*" @@ -6054,11 +6140,6 @@ set text_area_str "" set gui_argv0 $argv0 set gui_start_mode "" -# these are no longer used under x11vnc -sync: -set delay_sleep 350 -set extra_sleep 1000 -set extra_sleep_split 4 - if {$tk_version < 8.0} { puts stderr "" puts stderr "*** tkx11vnc: tk version is old $tk_version, please use 8.0 or higher." @@ -6075,6 +6156,19 @@ if {$tk_version < 8.4} { set have_labelframes 0 } +set screen_height [winfo screenheight .] +set screen_width [winfo screenwidth .] +if {$screen_height < 500} { + # short screen, PDA? + set max_text_height 22 + set text_height 13 + if {$screen_height <= 360} { + # very short. + set max_text_height 16 + set max_text_width 60 + set text_height 11 + } +} if {[info exists env(X11VNC_GUI_TEXT_HEIGHT)]} { set max_text_height $env(X11VNC_GUI_TEXT_HEIGHT) } @@ -6130,7 +6224,7 @@ if {[info exists env(X11VNC_CLIENT_FILE)]} { if {$client_tail != ""} { gets $client_tail tmp if [eof $client_tail] { -puts "eof $client_tail" +#puts "eof $client_tail" clean_client_tail set client_tail "" } @@ -6299,25 +6393,29 @@ key_bindings; get_default_vars +dtime D + if {$icon_mode} { if {$tray_embed} { make_gui "tray" } else { make_gui "icon" } + dtime G old_balloon if {$icon_setpasswd} { - set m "You must specify a Session\n" - set m "${m}Password before VNC clients can\n" - set m "${m}connect. Enter one in the Password\n" - set m "${m}field and then Press \"OK\". This\n" - set m "${m}password is not stored, it is only\n" - set m "${m}used for this x11vnc session.\n" + set m "You must specify a Session Password\n" + set m "${m}before VNC clients can connect.\n" + set m "${m}Enter one in the Password field\n" + set m "${m}and Press \"OK\". The password(s) is\n" + set m "${m}only for this x11vnc session.\n" do_props $m - push_new_value "unlock" "unlock" 1 0 + #push_new_value "unlock" "unlock" 1 0 } } else { make_gui "full" + dtime G } + # main loop. diff --git a/x11vnc/tkx11vnc.h b/x11vnc/tkx11vnc.h index ac0c574..e9f120b 100644 --- a/x11vnc/tkx11vnc.h +++ b/x11vnc/tkx11vnc.h @@ -67,6 +67,30 @@ char gui_code[] = ""; "# -- means add a separator\n" "#\n" "\n" +"global env started time_count\n" +"set started \"\"\n" +"proc dtime {{msg \"\"}} {\n" +" global started time_count\n" +" if {$started == \"\"} {\n" +" return\n" +" }\n" +" set diff [expr \"[exec gtod.bin] - $started\"]\n" +" set diff [format \"%.2f\" $diff]\n" +" incr time_count\n" +" if {$msg == \"\"} {\n" +" set msg $time_count\n" +" }\n" +" puts -nonewline stderr \"$msg $diff \" \n" +" puts stderr [clock format [clock seconds]]\n" +"}\n" +"\n" +"if [info exists env(X11VNC_GUI_TIME)] {\n" +" global started time_count\n" +" set started [exec gtod.bin]\n" +" set time_count 0\n" +" dtime \"S\"\n" +"}\n" +"\n" "proc set_template {} {\n" " global template\n" " set template \"\n" @@ -1757,7 +1781,6 @@ char gui_code[] = ""; "\n" "proc push_new_value {item name new {query 1}} {\n" " global menu_var always_update remote_output query_output\n" -" global delay_sleep extra_sleep extra_sleep_split\n" " global query_result_list\n" "\n" " set debug [in_debug_mode]\n" @@ -2996,7 +3019,6 @@ char gui_code[] = ""; "\n" " set debug [in_debug_mode]\n" "\n" -"\n" " set string 0\n" " if {[is_action $item] || $item == \"WindowView\"} {\n" " # Menu item is action:\n" @@ -3420,9 +3442,9 @@ char gui_code[] = ""; " set count 0\n" " foreach client [split $list \",\"] {\n" " if {![regexp {^[a-z0-9]*[a-z0-9]:} $client]} {\n" -" append_text \"Skipping client line: \"\n" -" append_text $client\n" -" append_text \"\\n\"\n" +" #append_text \"Skipping client line: \"\n" +" #append_text $client\n" +" #append_text \"\\n\"\n" " continue\n" " }\n" " regsub -all {[{}()~!$&*|;'\"`{}<>\\[\\]]} $client \"\" client\n" @@ -3989,9 +4011,15 @@ char gui_code[] = ""; " global have_labelframes ffont bfont\n" " global props_buttons icon_noadvanced\n" " global icon_mode icon_mode_at_startup\n" +" global screen_height screen_width\n" "\n" " check_update_vars\n" "\n" +" set pady 1m\n" +" if {$screen_height <= 360} {\n" +" set pady 0m\n" +" }\n" +"\n" " if [info exists menu_var(deny)] {\n" " if {$menu_var(deny) == $unset_str || $menu_var(deny) == 0} {\n" " set props_accept 1\n" @@ -4098,7 +4126,7 @@ char gui_code[] = ""; " pack $vp.l -fill x -expand 1 -padx 1m -pady 0m -side top\n" " }\n" " entry $vp.e -show \"*\" -textvariable props_viewpasswd -font $bfont\n" -" pack $vp.e -fill x -expand 1 -padx 1m -pady 1m -side top\n" +" pack $vp.e -fill x -expand 1 -padx 1m -pady $pady -side top\n" "\n" "\n" " lappend props_buttons $vp.e\n" @@ -4113,7 +4141,7 @@ char gui_code[] = ""; " pack $pw.l -fill x -expand 1 -padx 1m -pady 0m -side top\n" " }\n" " entry $pw.e -show \"*\" -textvariable props_passwd -font $bfont\n" -" pack $pw.e -fill x -expand 1 -padx 1m -pady 1m -side top\n" +" pack $pw.e -fill x -expand 1 -padx 1m -pady $pady -side top\n" "\n" " if {! $icon_mode_at_startup} {\n" " $vp.e configure -state disabled\n" @@ -4132,31 +4160,31 @@ char gui_code[] = ""; " frame $sh\n" " checkbutton $sh.button -text \"Shared\" \\\n" " -variable props_shared -anchor w -font $bfont\n" -" pack $sh.button -fill x -expand 1 -padx 1m -pady 1m\n" +" pack $sh.button -fill x -expand 1 -padx 1m -pady $pady\n" "\n" " set vo \"$w.viewonly\"\n" " frame $vo\n" " checkbutton $vo.button -text \"All Clients ViewOnly\" \\\n" " -variable props_viewonly -anchor w -font $bfont\n" -" pack $vo.button -fill x -expand 1 -padx 1m -pady 1m\n" +" pack $vo.button -fill x -expand 1 -padx 1m -pady $pady\n" "\n" " set cf \"$w.confirm\"\n" " frame $cf\n" " checkbutton $cf.button -text \"Ask for Confirmation\" \\\n" " -variable props_confirm -anchor w -font $bfont\n" -" pack $cf.button -fill x -expand 1 -padx 1m -pady 1m\n" +" pack $cf.button -fill x -expand 1 -padx 1m -pady $pady\n" "\n" " set ac \"$w.accept\"\n" " frame $ac\n" " checkbutton $ac.button -text \"Accept Connections\" \\\n" " -variable props_accept -anchor w -font $bfont\n" -" pack $ac.button -fill x -expand 1 -padx 1m -pady 1m\n" +" pack $ac.button -fill x -expand 1 -padx 1m -pady $pady\n" "\n" " set px \"6m\"\n" -" pack $b1 -side bottom -fill x -pady 1m -padx $px\n" -" pack $b2 -side bottom -fill x -pady 1m -padx $px\n" -" pack $vp -side bottom -fill x -pady 1m -padx $px\n" -" pack $pw -side bottom -fill x -pady 1m -padx $px\n" +" pack $b1 -side bottom -fill x -pady $pady -padx $px\n" +" pack $b2 -side bottom -fill x -pady $pady -padx $px\n" +" pack $vp -side bottom -fill x -pady $pady -padx $px\n" +" pack $pw -side bottom -fill x -pady $pady -padx $px\n" " pack $sh -side bottom -fill x -pady 0m -padx $px\n" " pack $vo -side bottom -fill x -pady 0m -padx $px\n" " pack $cf -side bottom -fill x -pady 0m -padx $px\n" @@ -4169,7 +4197,8 @@ char gui_code[] = ""; " set ms \"$w.msg\"\n" " text $ms -font $ffont -relief ridge -width $tw -height $th\n" " $ms insert 1.0 $msg\n" -" pack $ms -side bottom -fill x -pady 1m -padx $px\n" +" pack $ms -side bottom -fill x -pady $pady -padx $px\n" +" update\n" " }\n" "\n" " lappend props_buttons $ac.button $cf.button $vo.button $sh.button\n" @@ -4357,7 +4386,10 @@ char gui_code[] = ""; " catch {file delete $x11vnc_client_file}\n" " set read_client_info_lock 0\n" " clean_icon_exit\n" -" } elseif {$str != \"skip\"} {\n" +" } elseif {$str == \"skip\"} {\n" +" ;\n" +" } elseif [regexp {^clients:} $str] {\n" +" regsub {^clients:} $str \"\" str\n" " if {$str == \"none\"} {\n" " set str \"\"\n" " }\n" @@ -4498,6 +4530,7 @@ char gui_code[] = ""; " global x11vnc_xdisplay0 menu_var\n" "\n" " set db 0\n" +"#dtime t1\n" " set start 13037\n" " set tries 100\n" " set socket_got_callback 0\n" @@ -4548,8 +4581,12 @@ char gui_code[] = ""; " append_text \"try_client_info_sock: server socket failed.\\n\"\n" " return\n" " }\n" -" run_remote_cmd [list \"-nosync\" \"-R\" \"noop\"]\n" -" after 500\n" +" if {! $x11vnc_started} {\n" +" run_remote_cmd [list \"-nosync\" \"-R\" \"noop\"]\n" +" if {$db} {dtime A}\n" +" after 250\n" +" if {$db} {dtime A}\n" +" }\n" "\n" " # set the cookie to some obscured randomness\n" " set socket_cookie [clock clicks]\n" @@ -4568,8 +4605,18 @@ char gui_code[] = ""; " }\n" " run_remote_cmd [list \"-nosync\" \"-R\" \\\n" " \"client_info_sock:$myaddr:$port:$socket_cookie\"]\n" +"#dtime t2\n" " if {$db} {puts \"client_info_sock:$myaddr:$port:$socket_cookie\"}\n" -" after 500\n" +" for {set i 0} {$i < 10} {incr i} {\n" +" after 50\n" +" update; update idletasks\n" +"#dtime aa\n" +" if {$socket_got_callback != 0} {\n" +"#puts \"break-\"\n" +" break\n" +" }\n" +" }\n" +"#dtime t3\n" "\n" " set aftid \"\"\n" " if {$socket_got_callback == 0} {\n" @@ -4587,6 +4634,7 @@ char gui_code[] = ""; " } else {\n" " setup_client_sock 1\n" " }\n" +"#dtime t4\n" "}\n" "\n" "proc set_icon_label {} {\n" @@ -5033,10 +5081,14 @@ char gui_code[] = ""; " global helptext helpremote helplabel\n" " global icon_mode icon_win props_win full_win\n" " global top_widget_names\n" +" global screen_height screen_width\n" "\n" "\n" " # Make the top label\n" " set label_width 80\n" +" if {$screen_width <= 400} {\n" +" set label_width 64\n" +" }\n" " set info_label \"$top.info\"\n" " label $info_label -textvariable info_str -bd 2 -relief groove \\\n" " -anchor w -width $label_width -font $ffont\n" @@ -5135,8 +5187,14 @@ char gui_code[] = ""; " pack $df -side top -fill x\n" "\n" " # text area\n" +" global text_height\n" " set text_area \"$top.text\"\n" -" text $text_area -height 12 -relief ridge -font $ffont\n" +" if {$screen_width <= 400} {\n" +" text $text_area -height $text_height -width $label_width \\\n" +" -relief ridge -font $ffont\n" +" } else {\n" +" text $text_area -height $text_height -relief ridge -font $ffont\n" +" }\n" " pack $text_area -side top -fill both -expand 1\n" " set top_widget_names(text) $text_area\n" "\n" @@ -5705,6 +5763,24 @@ char gui_code[] = ""; " if {$db} {puts stderr \"run_remote_cmd_via_sock: \\\"$res\\\"\"}\n" " set res [string trim $res]\n" "\n" +" if [regexp {^clients:} $res] {\n" +" regsub {^clients:} $res \"\" tmp\n" +" if {$tmp == \"none\"} {\n" +" set tmp \"\"\n" +" }\n" +" update_clients_menu $tmp\n" +" set client_str $tmp\n" +" set_client_balloon $tmp\n" +"\n" +" if ![regexp {^clients} $opt] {\n" +" # we could block here...\n" +" if {$db} {puts stderr \"run_remote_cmd_via_sock: gets\"}\n" +" gets $client_sock res\n" +" if {$db} {puts stderr \"run_remote_cmd_via_sock: \\\"$res\\\"\"}\n" +" set res [string trim $res]\n" +" }\n" +" }\n" +"\n" " set docmd \"\"\n" "\n" " if {$res != \"\"} {\n" @@ -5817,6 +5893,7 @@ char gui_code[] = ""; " global menu_var unset_str\n" "\n" " set db 0\n" +"#dtime c1\n" "\n" " if {! $connected_to_x11vnc} {\n" " if {[info exists menu_var(display)]} {\n" @@ -5831,6 +5908,7 @@ char gui_code[] = ""; " set_info \"Pinging $x11vnc_xdisplay ...\"\n" " set rargs [list \"-Q\" \"ping\"]\n" " set result [run_remote_cmd $rargs]\n" +"#dtime c2a\n" "\n" " if {$db} {puts \"try_connect: \\\"$result\\\"\"}\n" "\n" @@ -5842,10 +5920,12 @@ char gui_code[] = ""; " set_connected yes\n" "\n" " setup_client_channel\n" +"#dtime c2b\n" " setup_client_sock 1\n" " setup_client_tail\n" "\n" " fetch_displays\n" +"#dtime c3a\n" " return 1\n" " } else {\n" " set str \"x11vnc server.\"\n" @@ -6018,6 +6098,10 @@ char gui_code[] = ""; "############################################################################\n" "# main:\n" "\n" +"if [info exists env(X11VNC_GUI_TIME)] {\n" +" dtime M\n" +"}\n" +"\n" "wm withdraw .\n" "\n" "global env x11vnc_prog x11vnc_cmdline x11vnc_xdisplay x11vnc_connect;\n" @@ -6028,10 +6112,10 @@ char gui_code[] = ""; "global helpall helptext helpremote helplabel hostname osname\n" "global all_settings reply_xdisplay always_update\n" "global max_text_height max_text_width\n" +"global text_height\n" "global menu_var unset_str menus_disabled\n" "global bfont ffont sfont snfont old_labels have_labelframes\n" "global connected_to_x11vnc\n" -"global delay_sleep extra_sleep extra_sleep_split\n" "global cache_all_query_vars\n" "global last_query_all_time query_all_freq client_tail client_sock client_info_read\n" "global icon_mode icon_mode_at_startup\n" @@ -6039,6 +6123,7 @@ char gui_code[] = ""; "global icon_noadvanced icon_minimal\n" "global make_gui_count text_area_str\n" "global gui_argv0 gui_start_mode\n" +"global screen_height screen_width\n" "\n" "set unset_str \"(unset)\"\n" "set vnc_url $unset_str\n" @@ -6046,6 +6131,7 @@ char gui_code[] = ""; "set menus_disabled 0\n" "set max_text_height 40\n" "set max_text_width 90\n" +"set text_height 14\n" "set bfont \"-adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*\"\n" "set sfont \"-adobe-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*\"\n" "set snfont \"-adobe-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*\"\n" @@ -6065,11 +6151,6 @@ char gui_code[] = ""; "set gui_argv0 $argv0\n" "set gui_start_mode \"\"\n" "\n" -"# these are no longer used under x11vnc -sync:\n" -"set delay_sleep 350\n" -"set extra_sleep 1000\n" -"set extra_sleep_split 4\n" -"\n" "if {$tk_version < 8.0} {\n" " puts stderr \"\"\n" " puts stderr \"*** tkx11vnc: tk version is old $tk_version, please use 8.0 or higher.\"\n" @@ -6086,6 +6167,19 @@ char gui_code[] = ""; " set have_labelframes 0\n" "}\n" "\n" +"set screen_height [winfo screenheight .]\n" +"set screen_width [winfo screenwidth .]\n" +"if {$screen_height < 500} {\n" +" # short screen, PDA?\n" +" set max_text_height 22\n" +" set text_height 13\n" +" if {$screen_height <= 360} {\n" +" # very short.\n" +" set max_text_height 16\n" +" set max_text_width 60\n" +" set text_height 11\n" +" }\n" +"}\n" "if {[info exists env(X11VNC_GUI_TEXT_HEIGHT)]} {\n" " set max_text_height $env(X11VNC_GUI_TEXT_HEIGHT)\n" "}\n" @@ -6141,7 +6235,7 @@ char gui_code[] = ""; " if {$client_tail != \"\"} {\n" " gets $client_tail tmp\n" " if [eof $client_tail] {\n" -"puts \"eof $client_tail\"\n" +"#puts \"eof $client_tail\"\n" " clean_client_tail\n" " set client_tail \"\"\n" " }\n" @@ -6310,27 +6404,31 @@ char gui_code[] = ""; "\n" "get_default_vars\n" "\n" +"dtime D\n" +"\n" "if {$icon_mode} {\n" " if {$tray_embed} {\n" " make_gui \"tray\"\n" " } else {\n" " make_gui \"icon\"\n" " }\n" +" dtime G\n" " old_balloon\n" " if {$icon_setpasswd} {\n" -" set m \"You must specify a Session\\n\" \n" -" set m \"${m}Password before VNC clients can\\n\" \n" -" set m \"${m}connect. Enter one in the Password\\n\" \n" -" set m \"${m}field and then Press \\\"OK\\\". This\\n\" \n" -" set m \"${m}password is not stored, it is only\\n\" \n" -" set m \"${m}used for this x11vnc session.\\n\" \n" +" set m \"You must specify a Session Password\\n\" \n" +" set m \"${m}before VNC clients can connect.\\n\" \n" +" set m \"${m}Enter one in the Password field\\n\" \n" +" set m \"${m}and Press \\\"OK\\\". The password(s) is\\n\" \n" +" set m \"${m}only for this x11vnc session.\\n\" \n" " do_props $m\n" -" push_new_value \"unlock\" \"unlock\" 1 0\n" +" #push_new_value \"unlock\" \"unlock\" 1 0\n" " }\n" "} else {\n" " make_gui \"full\"\n" +" dtime G\n" "}\n" "\n" +"\n" "# main loop.\n" #endif /* ifdef NOGUI */ diff --git a/x11vnc/unixpw.c b/x11vnc/unixpw.c index fd2dbe0..d7848d7 100644 --- a/x11vnc/unixpw.c +++ b/x11vnc/unixpw.c @@ -54,6 +54,7 @@ static void set_db(void); static void unixpw_verify(char *user, char *pass); int unixpw_in_progress = 0; +int unixpw_login_viewonly = 0; time_t unixpw_last_try_time = 0; rfbClientPtr unixpw_client = NULL; @@ -975,6 +976,9 @@ static void apply_opts (char *user) { void unixpw_accept(char *user) { apply_opts(user); + if (unixpw_login_viewonly) { + unixpw_client->viewOnly = TRUE; + } unixpw_in_progress = 0; unixpw_client = NULL; mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); diff --git a/x11vnc/unixpw.h b/x11vnc/unixpw.h index 5a8d44d..976a4dd 100644 --- a/x11vnc/unixpw.h +++ b/x11vnc/unixpw.h @@ -11,6 +11,7 @@ extern int su_verify(char *user, char *pass); extern int crypt_verify(char *user, char *pass); extern int unixpw_in_progress; +extern int unixpw_login_viewonly; extern time_t unixpw_last_try_time; extern rfbClientPtr unixpw_client; diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index 94d5e8b..e229327 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -2,7 +2,7 @@ .TH X11VNC "1" "March 2006" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.8.1, lastmod: 2006-03-04 + version: 0.8.1, lastmod: 2006-03-06 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -391,8 +391,9 @@ set to "host" or "host:port" establish a reverse connection. Using .IR xprop (1) instead of vncconnect may -work (see the FAQ). The \fB-remote\fR control mechanism also -uses this VNC_CONNECT channel. Default: \fB-vncconnect\fR +work (see the FAQ). The \fB-remote\fR control mechanism uses +X11VNC_REMOTE channel, and this option disables/enables +it as well. Default: \fB-vncconnect\fR .PP \fB-allow\fR \fIhost1[,host2..]\fR .IP @@ -530,8 +531,8 @@ this case. A possible workaround would be to start x11vnc as root with the "\fB-users\fR \fI+nobody\fR" option to immediately switch to user nobody. Another source of problems are PAM modules that prompt for extra info, -e.g. password aging modules. These logins will always -fail as well. +e.g. password aging modules. These logins will fail +as well even when the correct password is supplied. .IP *IMPORTANT*: to prevent the Unix password being sent in *clear text* over the network, two x11vnc options are @@ -564,17 +565,28 @@ will check if the environment variable SSH_CONNECTION is set and appears reasonable. If it does, then the stunnel requirement is dropped since it is assumed you are using ssh for the encrypted tunnelling. -Use \fB-stunnel\fR to force stunnel usage. +Use \fB-stunnel\fR to force stunnel usage for this case. .IP Set UNIXPW_DISABLE_LOCALHOST=1 to disable the \fB-localhost\fR requirement. One should never do this (i.e. allow the Unix passwords to be sniffed on the network). .IP -NOTE: in \fB-inetd\fR mode the two settings are not enforced -since x11vnc does not make network connections in -that case. Be sure to use encryption from the viewer -to inetd. One can also have your own stunnel spawn -x11vnc in \fB-inetd\fR mode. See the FAQ. +Regarding reverse connections (e.g. \fB-R\fR connect:host), +the \fB-localhost\fR constraint is in effect and the reverse +connections can only be used to connect to the same +machine x11vnc is running on (default port 5500). +Please use a ssh or stunnel port redirection to the +viewer machine to tunnel the reverse connection over +an encrypted channel. Note that Unix username and +password *will* be prompted for (unlike VNC passwords +that are skipped for reverse connections). +.IP +NOTE: in \fB-inetd\fR mode the two settings are attempted +to be enforced for reverse connections. Be sure to +use encryption from the viewer to inetd since x11vnc +cannot guess easily if it is encrpyted. Note: you can +also have your own stunnel spawn x11vnc in \fB-inetd\fR mode +(i.e. bypassing inetd). See the FAQ. .IP The user names in the comma separated [list] can have per-user options after a ":", e.g. "fred:opts" @@ -588,21 +600,30 @@ options apply to all users. It also means all users are allowed to log in after supplying a valid password. Use "deny" to explicitly deny some users if you use "*" to set a global option. +.IP +There are also some tools for testing password if [list] +starts with the "%" character. See the quick_pw() +function for details. .PP \fB-unixpw_nis\fR \fI[list]\fR .IP -As \fB-unixpw\fR above, however do not run +As \fB-unixpw\fR above, however do not use .IR su (1) but rather -use the traditional getpwnam() + crypt() method instead. -This requires that the encrpyted passwords be readable. -Passwords stored in /etc/shadow will be inaccessible -unless run as root. This is called "NIS" mode -simply because in most NIS setups the user encrypted -passwords are accessible (e.g. "ypcat passwd"). -NIS is not required for this mode to work, but it -is unlikely it will work for any other environment. -All of the \fB-unixpw\fR options and contraints apply. +use the traditional +.IR getpwnam (3) ++ +.IR crypt (3) +method +instead. This requires that the encrpyted passwords +be readable. Passwords stored in /etc/shadow will +be inaccessible unless run as root. This is called +"NIS" mode simply because in most NIS setups the +user encrypted passwords are accessible (e.g. "ypcat +passwd"). NIS is not required for this mode to +work, but it is unlikely it will work for any other +environment. All of the \fB-unixpw\fR options and contraints +apply. .PP \fB-stunnel\fR \fI[pem]\fR .IP @@ -2163,7 +2184,7 @@ command exits. You can often use the \fB-query\fR command \fB-remote\fR command. .IP The default communication channel is that of X -properties (specifically VNC_CONNECT), and so this +properties (specifically X11VNC_REMOTE), and so this command must be run with correct settings for DISPLAY and possibly XAUTHORITY to connect to the X server and set the property. Alternatively, use the \fB-display\fR @@ -2655,9 +2676,9 @@ to the standard output. If a variable is read-only, it comes back with prefix "aro=" instead of "ans=". .IP Some \fB-remote\fR commands are pure actions that do not make -sense as variables, e.g. "stop" or "disconnect", -in these cases the value returned is "N/A". To direct -a query straight to the VNC_CONNECT property or connect +sense as variables, e.g. "stop" or "disconnect", in +these cases the value returned is "N/A". To direct a +query straight to the X11VNC_REMOTE property or connect file use "qry=..." instead of "cmd=..." .IP Here is the current list of "variables" that can @@ -2762,9 +2783,9 @@ Default: \fB-yesremote\fR .IP A note about security wrt remote control commands. If someone can connect to the X display and change -the property VNC_CONNECT, then they can remotely +the property X11VNC_REMOTE, then they can remotely control x11vnc. Normally access to the X display is -protected. Note that if they can modify VNC_CONNECT +protected. Note that if they can modify X11VNC_REMOTE on the X server, they have enough permissions to also run their own x11vnc and thus have complete control of the desktop. If the "\fB-connect\fR \fI/path/to/file\fR" @@ -2774,9 +2795,9 @@ sure to protect the X display and that file's write permissions. See \fB-privremote\fR below. .IP If you are paranoid and do not think \fB-noremote\fR is -enough, to disable the VNC_CONNECT property channel -completely use \fB-novncconnect,\fR or use the \fB-safer\fR -option that shuts many things off. +enough, to disable the X11VNC_REMOTE property channel +completely use \fB-novncconnect,\fR or use the \fB-safer\fR option +that shuts many things off. .PP \fB-unsafe\fR .IP diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index e6f99ed..540db93 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -139,6 +139,7 @@ #include "rates.h" #include "unixpw.h" #include "inet.h" +#include "sslcmds.h" /* * main routine for the x11vnc program @@ -920,6 +921,8 @@ static void quick_pw(char *str) { * * starting "%/" or "%." means read the first line from that file. * + * "%%" or "%" means prompt user. + * * otherwise: %user:pass */ if (!strcmp(str, "%-") || !strcmp(str, "%stdin")) { @@ -932,6 +935,31 @@ static void quick_pw(char *str) { exit(1); } q = strdup(getenv("UNIXPW")); + } else if (!strcmp(str, "%%") || !strcmp(str, "%")) { + char *t, inp[1024]; + fprintf(stdout, "username: "); + if(fgets(tmp, 128, stdin) == NULL) { + exit(1); + } + strcpy(inp, tmp); + t = strchr(inp, '\n'); + if (t) { + *t = ':'; + } else { + strcat(inp, ":"); + + } + fprintf(stdout, "password: "); + system("stty -echo"); + if(fgets(tmp, 128, stdin) == NULL) { + fprintf(stdout, "\n"); + system("stty echo"); + exit(1); + } + system("stty echo"); + fprintf(stdout, "\n"); + strcat(inp, tmp); + q = strdup(inp); } else if (str[1] == '/' || str[1] == '.') { FILE *in = fopen(str+1, "r"); if (in == NULL) { @@ -1235,6 +1263,10 @@ static void check_loop_mode(int argc, char* argv[]) { } } +#define SHOW_NO_PASSWORD_WARNING \ + (!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) \ + && !query_cmd && !remote_cmd && !unixpw && !got_gui_pw) + int main(int argc, char* argv[]) { int i, len, tmpi; @@ -1244,6 +1276,7 @@ int main(int argc, char* argv[]) { char *remote_cmd = NULL; char *query_cmd = NULL; char *gui_str = NULL; + int got_gui_pw = 0; int pw_loc = -1, got_passwd = 0, got_rfbauth = 0, nopw = NOPW; int got_viewpasswd = 0, got_localhost = 0, got_passwdfile = 0; int got_stunnel = 0; @@ -1448,7 +1481,7 @@ int main(int argc, char* argv[]) { unixpw_nis = 1; } if (i < argc-1) { - char *p, *q, *s = argv[i+1]; + char *s = argv[i+1]; if (s[0] != '-') { unixpw_list = strdup(s); i++; @@ -1875,6 +1908,9 @@ int main(int argc, char* argv[]) { char *s = argv[i+1]; if (*s != '-') { gui_str = strdup(s); + if (strstr(gui_str, "setp")) { + got_gui_pw = 1; + } i++; } } @@ -2005,8 +2041,8 @@ int main(int argc, char* argv[]) { } if (launch_gui) { int sleep = 0; - if (!got_passwd && !got_rfbauth && !got_passwdfile && !nopw) { - sleep = 3; + if (SHOW_NO_PASSWORD_WARNING && !nopw) { + sleep = 2; } do_gui(gui_str, sleep); } @@ -2132,8 +2168,7 @@ int main(int argc, char* argv[]) { exit(1); } - if (!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) - && !query_cmd && !remote_cmd && !unixpw) { + if (SHOW_NO_PASSWORD_WARNING) { char message[] = "-rfbauth, -passwdfile, -passwd password, " "or -unixpw required."; if (! nopw) { @@ -2834,8 +2869,7 @@ int main(int argc, char* argv[]) { } if (! quiet) { rfbLog("screen setup finished.\n"); - if (!got_passwd && !got_rfbauth && !got_passwdfile && !unixpw - && !nopw) { + if (SHOW_NO_PASSWORD_WARNING && !nopw) { rfbLog("\n"); rfbLog("WARNING: You are running x11vnc WITHOUT" " a password. See\n"); diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index f11ce77..f91ba49 100644 --- a/x11vnc/x11vnc_defs.c +++ b/x11vnc/x11vnc_defs.c @@ -15,7 +15,7 @@ int xtrap_base_event_type = 0; int xdamage_base_event_type = 0; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.8.1 lastmod: 2006-03-04"; +char lastmod[] = "0.8.1 lastmod: 2006-03-06"; /* X display info */ diff --git a/x11vnc/xevents.c b/x11vnc/xevents.c index 58b9a55..3e9401b 100644 --- a/x11vnc/xevents.c +++ b/x11vnc/xevents.c @@ -18,6 +18,7 @@ int grab_buster = 0; int sync_tod_delay = 3; void initialize_vnc_connect_prop(void); +void initialize_x11vnc_remote_prop(void); void spawn_grab_buster(void); void sync_tod_with_servertime(void); void check_keycode_state(void); @@ -39,10 +40,16 @@ void initialize_vnc_connect_prop(void) { vnc_connect_prop = XInternAtom(dpy, "VNC_CONNECT", False); } +void initialize_x11vnc_remote_prop(void) { + x11vnc_remote_str[0] = '\0'; + x11vnc_remote_prop = XInternAtom(dpy, "X11VNC_REMOTE", False); +} + static void initialize_xevents(void) { static int did_xselect_input = 0; static int did_xcreate_simple_window = 0; static int did_vnc_connect_prop = 0; + static int did_x11vnc_remote_prop = 0; static int did_xfixes = 0; static int did_xdamage = 0; static int did_xrandr = 0; @@ -75,6 +82,14 @@ static void initialize_xevents(void) { initialize_vnc_connect_prop(); did_vnc_connect_prop = 1; } + if (vnc_connect && !did_x11vnc_remote_prop) { + initialize_x11vnc_remote_prop(); + did_x11vnc_remote_prop = 1; + } + if (run_gui_pid > 0) { + kill(run_gui_pid, SIGUSR1); + run_gui_pid = 0; + } if (xfixes_present && use_xfixes && !did_xfixes) { initialize_xfixes(); did_xfixes = 1; @@ -744,11 +759,16 @@ void check_xevents(void) { set_cutbuffer = 0; } else if (vnc_connect && vnc_connect_prop != None && xev.xproperty.atom == vnc_connect_prop) { - /* * Go retrieve VNC_CONNECT string. */ - read_vnc_connect_prop(); + read_vnc_connect_prop(0); + } else if (vnc_connect && x11vnc_remote_prop != None + && xev.xproperty.atom == x11vnc_remote_prop) { + /* + * Go retrieve X11VNC_REMOTE string. + */ + read_x11vnc_remote_prop(0); } } } diff --git a/x11vnc/xevents.h b/x11vnc/xevents.h index 0126ec2..9c5a8dc 100644 --- a/x11vnc/xevents.h +++ b/x11vnc/xevents.h @@ -7,6 +7,7 @@ extern int grab_buster; extern int sync_tod_delay; extern void initialize_vnc_connect_prop(void); +extern void initialize_x11vnc_remote_prop(void); extern void spawn_grab_buster(void); extern void sync_tod_with_servertime(void); extern void check_keycode_state(void);