summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrunge <runge>2006-06-18 23:59:45 +0000
committerrunge <runge>2006-06-18 23:59:45 +0000
commit64e731a9da82e3cc614e274d6fca6f855d0359b7 (patch)
tree540bca0a021f3e74b768a747bc3d75435848ca0d
parent363ae71df0f25b018136d19eed20be954e1dd088 (diff)
downloadlibtdevnc-64e731a9.tar.gz
libtdevnc-64e731a9.zip
x11vnc: --grabkbd, -grabptr, -env, -allowedcmds, unixpw+WAIT user fred:options
-rw-r--r--x11vnc/8to24.c2
-rw-r--r--x11vnc/ChangeLog5
-rw-r--r--x11vnc/README113
-rw-r--r--x11vnc/cleanup.c2
-rw-r--r--x11vnc/connections.c112
-rw-r--r--x11vnc/connections.h1
-rw-r--r--x11vnc/cursor.c2
-rw-r--r--x11vnc/gui.c2
-rw-r--r--x11vnc/help.c98
-rw-r--r--x11vnc/keyboard.c4
-rw-r--r--x11vnc/options.c1
-rw-r--r--x11vnc/options.h1
-rw-r--r--x11vnc/pm.c4
-rw-r--r--x11vnc/pointer.c6
-rw-r--r--x11vnc/remote.c73
-rw-r--r--x11vnc/scan.c36
-rw-r--r--x11vnc/screen.c12
-rw-r--r--x11vnc/solid.c14
-rw-r--r--x11vnc/sslcmds.c271
-rw-r--r--x11vnc/sslhelper.c121
-rw-r--r--x11vnc/sslhelper.h2
-rw-r--r--x11vnc/ssltools.h55
-rwxr-xr-xx11vnc/tkx11vnc2
-rw-r--r--x11vnc/tkx11vnc.h2
-rw-r--r--x11vnc/unixpw.c52
-rw-r--r--x11vnc/unixpw.h1
-rw-r--r--x11vnc/user.c148
-rw-r--r--x11vnc/userinput.c8
-rw-r--r--x11vnc/util.c53
-rw-r--r--x11vnc/v4l.c2
-rw-r--r--x11vnc/win_utils.c2
-rw-r--r--x11vnc/x11vnc.195
-rw-r--r--x11vnc/x11vnc.c58
-rw-r--r--x11vnc/x11vnc.h6
-rw-r--r--x11vnc/x11vnc_defs.c16
-rw-r--r--x11vnc/xdamage.c2
-rw-r--r--x11vnc/xevents.c14
-rw-r--r--x11vnc/xevents.h2
-rw-r--r--x11vnc/xrandr.h4
-rw-r--r--x11vnc/xwrappers.c31
40 files changed, 1058 insertions, 377 deletions
diff --git a/x11vnc/8to24.c b/x11vnc/8to24.c
index 5304a52..b7efdab 100644
--- a/x11vnc/8to24.c
+++ b/x11vnc/8to24.c
@@ -65,7 +65,7 @@ static unsigned int root_rgb[NCOLOR];
static void set_root_cmap(void) {
static time_t last_set = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
XWindowAttributes attr;
static XColor color[NCOLOR];
int redo = 0;
diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog
index 4c8257c..278d4e3 100644
--- a/x11vnc/ChangeLog
+++ b/x11vnc/ChangeLog
@@ -1,3 +1,8 @@
+2006-06-18 Karl Runge <runge@karlrunge.com>
+ * x11vnc: -grabkbd, -grabptr, -env options. under -unixpw +
+ WAIT let user add some options after his username (e.g. runge:3/4)
+ -allowedcmds to fine tune vs. -nocmds. general cleanup.
+
2006-06-12 Karl Runge <runge@karlrunge.com>
* x11vnc: word tune SSL Java viewer; fix multi-certs bug. Add
-display WAIT:cmd=FINDDISPLAY builtin script and cmd=HTTPONCE
diff --git a/x11vnc/README b/x11vnc/README
index d538a04..ca73da0 100644
--- a/x11vnc/README
+++ b/x11vnc/README
@@ -1,5 +1,5 @@
-x11vnc README file Date: Mon Jun 12 22:23:23 EDT 2006
+x11vnc README file Date: Sun Jun 18 19:37:38 EDT 2006
The following information is taken from these URLs:
@@ -7192,7 +7192,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.2 lastmod: 2006-06-12
+x11vnc: allow VNC connections to real X11 displays. 0.8.2 lastmod: 2006-06-18
x11vnc options:
-display disp -auth file -id windowid
@@ -7205,19 +7205,20 @@ x11vnc options:
-inetd -nofilexfer -http
-http_ssl -connect string -vncconnect
-novncconnect -allow host1[,host2..] -localhost
- -nolookup -input string -viewpasswd string
- -passwdfile filename -unixpw [list] -unixpw_nis [list]
- -display WAIT:... -ssl [pem] -ssldir [dir]
- -sslverify [path] -sslGenCA [dir] -sslGenCert type name
- -sslEncKey [pem] -sslCertInfo [pem] -sslDelCert [pem]
- -stunnel [pem] -stunnel3 [pem] -https [port]
- -usepw -storepasswd pass file -nopw
- -accept string -afteraccept string -gone string
- -users list -noshm -flipbyteorder
- -onetile -solid [color] -blackout string
- -xinerama -noxinerama -xtrap
- -xrandr [mode] -padgeom WxH -o logfile
- -flag file -rc filename -norc
+ -nolookup -input string -grabkbd
+ -grabptr -viewpasswd string -passwdfile filename
+ -unixpw [list] -unixpw_nis [list] -display WAIT:...
+ -ssl [pem] -ssldir [dir] -sslverify [path]
+ -sslGenCA [dir] -sslGenCert type name -sslEncKey [pem]
+ -sslCertInfo [pem] -sslDelCert [pem] -stunnel [pem]
+ -stunnel3 [pem] -https [port] -usepw
+ -storepasswd pass file -nopw -accept string
+ -afteraccept string -gone string -users list
+ -noshm -flipbyteorder -onetile
+ -solid [color] -blackout string -xinerama
+ -noxinerama -xtrap -xrandr [mode]
+ -padgeom WxH -o logfile -flag file
+ -rc filename -norc -env VAR=VALUE
-h, -help -?, -opts -V, -version
-dbg -q -bg
-modtweak -nomodtweak -xkb
@@ -7254,7 +7255,8 @@ x11vnc options:
-remote command -query variable -QD variable
-sync -noremote -yesremote
-unsafe -safer -privremote
- -nocmds -deny_all
+ -nocmds -allowedcmds list -deny_all
+
libvncserver options:
-rfbport port TCP port for RFB protocol
@@ -7288,7 +7290,7 @@ libvncserver-tight-extension options:
% x11vnc -help
-x11vnc: allow VNC connections to real X11 displays. 0.8.2 lastmod: 2006-06-12
+x11vnc: allow VNC connections to real X11 displays. 0.8.2 lastmod: 2006-06-18
(type "x11vnc -opts" to just list the options.)
@@ -7576,6 +7578,7 @@ Options:
option, otherwise the stderr goes to the viewer which
will cause it to abort. Specifying both -inetd and -q
and no -o will automatically close the stderr.
+
-nofilexfer Disable the TightVNC file transfer extension. (same as
-disablefiletransfer). Note that when the -viewonly
option is supplied all file transfers are disabled.
@@ -7583,6 +7586,7 @@ Options:
However, if the remote control mechanism is used to
change the global or per-client viewonly state the
filetransfer permissions will NOT change.
+
-http Instead of using -httpdir (see below) to specify
where the Java vncviewer applet is, have x11vnc try
to *guess* where the directory is by looking relative
@@ -7659,6 +7663,23 @@ Options:
a global -viewonly is in effect (all input is discarded
in that case).
+-grabkbd When VNC viewers are connected, attempt to the grab the
+ keyboard so someone sitting at the physical display
+ is not able to enter keystrokes. This method uses
+ XGrabKeyboard(3X11) and so it is not secure and does not
+ rule out the person at the physical display injecting
+ keystrokes by flooding the server with them, grabbing
+ the keyboard himself, etc. Some degree of cooperation
+ from the person at the display is assumed.
+-grabptr As -grabkbd, but for the mouse pointer using
+ XGrabPointer(3X11). Unfortunately due to the way the X
+ server works, the mouse can still be moved around by the
+ user at the physical display, but he will not be able to
+ change window focus with it. Also some window managers
+ that call XGrabServer(3X11) for resizes, etc, will
+ act on the local user's input. Again, some degree of
+ cooperation from the person at the display is assumed.
+
-viewpasswd string Supply a 2nd password for view-only logins. The -passwd
(full-access) password must also be supplied.
@@ -7857,7 +7878,25 @@ Options:
as the user who just authenticated via the login and
password prompt.
- Thus the combination of -display WAIT:cmd=... and
+ Also in the case of -unixpw, the user logging in can
+ place a colon at the end of his username and supply
+ a few options: scale=, scale_cursor=, solid, id=,
+ clear_mods, clear_keys, repeat, or speeds= separated
+ by commas if there is more than one. After the user
+ logs in successfully, these options will be applied to
+ the VNC screen. For example,
+
+ login: fred:scale=3/4,repeat
+ Password: ...
+
+ for convenience m/n implies scale= e.g. fred:3/4
+ To disable this set the environment variable
+ X11VNC_NO_UNIXPW_OPTS=1. To set any other options,
+ the user can use the gui (x11vnc -gui connect) or the
+ remote control method (x11vnc -R opt:val) during his
+ VNC session.
+
+ So the combination of -display WAIT:cmd=... and
-unixpw allows automatic pairing of an unix
authenticated VNC user with his desktop. This could
be very useful on SunRays and also any system where
@@ -7890,7 +7929,7 @@ Options:
5815 stream tcp nowait root /usr/sbin/tcpd .../x11vnc \
-inetd -q -http_ssl -display WAIT:cmd=HTTPONCE
- Is used in the Apache SSL-portal example (see FAQ).
+ It is used in the Apache SSL-portal example (see FAQ).
Finally, one can insert a geometry between colons,
e.g. WAIT:1280x1024:... to set the size of the display
@@ -8672,6 +8711,12 @@ Options:
-rc filename Use "filename" instead of $HOME/.x11vncrc for rc file.
-norc Do not process any .x11vncrc file for options.
+-env VAR=VALUE Set the environment variable 'VAR' to value 'VALUE'
+ at x11vnc startup. This is a convenience utility to
+ avoid shell script wrappers, etc. to set the env. var.
+ You may specify as many of these as needed on the
+ command line.
+
-h, -help Print this help text.
-?, -opts Only list the x11vnc options.
-V, -version Print program version and last modification date.
@@ -9974,6 +10019,10 @@ n
nolookup enable -nolookup mode.
lookup disable -nolookup mode.
input:str set -input to "str", empty to disable.
+ grabkbd enable -grabkbd mode.
+ nograbkbd disable -grabkbd mode.
+ grabptr enable -grabptr mode.
+ nograbptr disable -grabptr mode.
client_input:str set the K, M, B -input on a per-client
basis. select which client as for
disconnect, e.g. client_input:host:MB
@@ -10230,13 +10279,14 @@ n
scr_skip scr_inc scr_keys scr_term scr_keyrepeat
scr_parms scrollcopyrect scr noscrollcopyrect noscr
fixscreen noxrecord xrecord reset_record pointer_mode
- pm input_skip input client_input speeds wmdt
- debug_pointer dp nodebug_pointer nodp debug_keyboard
- dk nodebug_keyboard nodk deferupdate defer wait_ui
- wait_bog nowait_bog slow_fb wait readtimeout nap nonap
- sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb
- nosnapfb rawfb progressive rfbport http nohttp httpport
- httpdir enablehttpproxy noenablehttpproxy alwaysshared
+ pm input_skip input grabkbd nograbkbd grabptr
+ nograbptr client_input speeds wmdt debug_pointer dp
+ nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
+ nodk deferupdate defer wait_ui wait_bog nowait_bog
+ slow_fb wait readtimeout nap nonap sb screen_blank
+ fbpm nofbpm fs gaps grow fuzz snapfb nosnapfb rawfb
+ progressive rfbport http nohttp httpport httpdir
+ enablehttpproxy noenablehttpproxy alwaysshared
noalwaysshared nevershared noalwaysshared dontdisconnect
nodontdisconnect desktop debug_xevents nodebug_xevents
debug_xevents debug_xdamage nodebug_xdamage
@@ -10323,6 +10373,17 @@ n
remote-control is disabled it cannot be turned back on.
-nocmds No external commands (e.g. system(3), popen(3), exec(3))
will be run.
+-allowedcmds list "list" contains a comma separated list of the only
+ external commands that can be run. The full list of
+ associated options is:
+
+ stunnel, ssl, unixpw, WAIT, id, accept, afteraccept,
+ gone, pipeinput, v4l-info, rawfb-setup, dt, gui,
+ storepasswd, crash.
+
+ See each option's help to learn the associated external
+ command. Note that the -nocmds option takes precedence
+ and disables all external commands.
-deny_all For use with -remote nodeny: start out denying all
incoming clients until "-remote nodeny" is used to
diff --git a/x11vnc/cleanup.c b/x11vnc/cleanup.c
index 0d5926e..bbf2d29 100644
--- a/x11vnc/cleanup.c
+++ b/x11vnc/cleanup.c
@@ -312,7 +312,7 @@ static void crash_shell(void) {
} else if (*str == 's' && *(str+1) == '\0') {
sprintf(cmd, "sh -c '(%s) &'", crash_stack_command1);
/* crash */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("crash")) {
fprintf(stderr, "\nno_external_cmds=%d\n",
no_external_cmds);
goto crash_prompt;
diff --git a/x11vnc/connections.c b/x11vnc/connections.c
index ec77101..37ba798 100644
--- a/x11vnc/connections.c
+++ b/x11vnc/connections.c
@@ -14,6 +14,7 @@
#include "sslcmds.h"
#include "sslhelper.h"
#include "xwrappers.h"
+#include "xevents.h"
/*
* routines for handling incoming, outgoing, etc connections
@@ -44,6 +45,7 @@ void check_gui_inputs(void);
enum rfbNewClientAction new_client(rfbClientPtr client);
void start_client_info_sock(char *host_port_cookie);
void send_client_info(char *str);
+void adjust_grabs(int grab, int quiet);
void check_new_clients(void);
@@ -328,6 +330,32 @@ void set_child_info(void) {
}
}
+int cmd_ok(char *cmd) {
+ char *p, *str;
+ if (no_external_cmds) {
+ return 0;
+ }
+ if (! cmd || cmd[0] == '\0') {
+ return 0;
+ }
+ if (! allowed_external_cmds) {
+ /* default, allow any (overridden by -nocmds) */
+ return 1;
+ }
+
+ str = strdup(allowed_external_cmds);
+ p = strtok(str, ",");
+ while (p) {
+ if (!strcmp(p, cmd)) {
+ free(str);
+ return 1;
+ }
+ p = strtok(NULL, ",");
+ }
+ free(str);
+ return 0;
+}
+
/*
* utility to run a user supplied command setting some RFB_ env vars.
* used by, e.g., accept_client() and client_gone()
@@ -336,7 +364,7 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) {
char *old_display = NULL;
char *addr = client->host;
char str[100];
- int rc;
+ int rc, ok;
ClientData *cd = (ClientData *) client->clientData;
if (addr == NULL || addr[0] == '\0') {
@@ -414,11 +442,11 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) {
if (cd) {
sprintf(str, "%d", (int) cd->login_time);
} else {
- sprintf(str, ">%d", (int) time(0));
+ sprintf(str, ">%d", (int) time(NULL));
}
set_env("RFB_LOGIN_TIME", str);
- sprintf(str, "%d", (int) time(0));
+ sprintf(str, "%d", (int) time(NULL));
set_env("RFB_CURRENT_TIME", str);
if (!cd || !cd->username || cd->username[0] == '\0') {
@@ -449,7 +477,17 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) {
set_env("RFB_CLIENT_COUNT", str);
/* gone, accept, afteraccept */
- if (no_external_cmds) {
+ ok = 0;
+ if (!strcmp(mode, "accept") && cmd_ok("accept")) {
+ ok = 1;
+ }
+ if (!strcmp(mode, "afteraccept") && cmd_ok("afteraccept")) {
+ ok = 1;
+ }
+ if (!strcmp(mode, "gone") && cmd_ok("gone")) {
+ ok = 1;
+ }
+ if (no_external_cmds || !ok) {
rfbLogEnable(1);
rfbLog("cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", cmd);
@@ -1398,7 +1436,7 @@ static void check_connect_file(char *file) {
char line[VNC_CONNECT_MAX], host[VNC_CONNECT_MAX];
static int first_warn = 1, truncate_ok = 1;
static time_t last_time = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
if (last_time == 0) {
last_time = now;
@@ -1846,7 +1884,7 @@ void check_gui_inputs(void) {
enum rfbNewClientAction new_client(rfbClientPtr client) {
ClientData *cd;
- last_event = last_input = time(0);
+ last_event = last_input = time(NULL);
if (inetd) {
@@ -1902,7 +1940,7 @@ if (getenv("NEW_CLIENT")) fprintf(stderr, "new_client: %s %d\n", client->host, c
cd->input[0] = '-';
cd->login_viewonly = -1;
- cd->login_time = time(0);
+ cd->login_time = time(NULL);
cd->ssl_helper_pid = 0;
if (use_openssl && openssl_last_helper_pid) {
@@ -1933,7 +1971,7 @@ if (0) fprintf(stderr, "SET ssl_helper_pid: %d\n", openssl_last_helper_pid);
}
client_count++;
- last_keyboard_input = last_pointer_input = time(0);
+ last_keyboard_input = last_pointer_input = time(NULL);
if (no_autorepeat && client_count == 1 && ! view_only) {
/*
@@ -1958,7 +1996,7 @@ if (0) fprintf(stderr, "SET ssl_helper_pid: %d\n", openssl_last_helper_pid);
cd->raw_bytes_sent = 0;
accepted_client = 1;
- last_client = time(0);
+ last_client = time(NULL);
if (unixpw) {
unixpw_in_progress = 1;
@@ -1968,7 +2006,7 @@ if (0) fprintf(stderr, "SET ssl_helper_pid: %d\n", openssl_last_helper_pid);
unixpw_login_viewonly = 1;
client->viewOnly = FALSE;
}
- unixpw_last_try_time = time(0);
+ unixpw_last_try_time = time(NULL);
unixpw_screen(1);
unixpw_keystroke(0, 0, 1);
}
@@ -2027,7 +2065,7 @@ void start_client_info_sock(char *host_port_cookie) {
if (sock >= 0) {
char *lst = list_clients();
icon_mode_socks[next] = sock;
- start_time[next] = time(0);
+ start_time[next] = time(NULL);
write(sock, "COOKIE:", strlen("COOKIE:"));
write(sock, cookie, strlen(cookie));
write(sock, "\n", strlen("\n"));
@@ -2105,6 +2143,40 @@ void send_client_info(char *str) {
}
}
+void adjust_grabs(int grab, int quiet) {
+ RAWFB_RET_VOID
+ /* n.b. caller decides to X_LOCK or not. */
+ if (grab) {
+ if (grab_kbd) {
+ if (! quiet) {
+ rfbLog("grabbing keyboard with XGrabKeyboard\n");
+ }
+ XGrabKeyboard(dpy, window, False, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+ }
+ if (grab_ptr) {
+ if (! quiet) {
+ rfbLog("grabbing pointer with XGrabPointer\n");
+ }
+ XGrabPointer(dpy, window, False, 0, GrabModeAsync,
+ GrabModeAsync, None, None, CurrentTime);
+ }
+ } else {
+ if (grab_kbd) {
+ if (! quiet) {
+ rfbLog("ungrabbing keyboard with XUngrabKeyboard\n");
+ }
+ XUngrabKeyboard(dpy, CurrentTime);
+ }
+ if (grab_ptr) {
+ if (! quiet) {
+ rfbLog("ungrabbing pointer with XUngrabPointer\n");
+ }
+ XUngrabPointer(dpy, CurrentTime);
+ }
+ }
+}
+
void check_new_clients(void) {
static int last_count = 0;
rfbClientIteratorPtr iter;
@@ -2117,12 +2189,27 @@ void check_new_clients(void) {
unixpw_login_viewonly = 1;
unixpw_client->viewOnly = FALSE;
}
- if (time(0) > unixpw_last_try_time + 25) {
+ if (time(NULL) > unixpw_last_try_time + 25) {
rfbLog("unixpw_deny: timed out waiting for reply.\n");
unixpw_deny();
}
return;
}
+
+ if (grab_kbd || grab_ptr) {
+ static double last_force = 0.0;
+ if (client_count != last_count || dnow() > last_force + 0.25) {
+ int q = (client_count == last_count);
+ last_force = dnow();
+ X_LOCK;
+ if (client_count) {
+ adjust_grabs(1, q);
+ } else {
+ adjust_grabs(0, q);
+ }
+ X_UNLOCK;
+ }
+ }
if (client_count == last_count) {
return;
@@ -2143,6 +2230,7 @@ void check_new_clients(void) {
if (! screen) {
return;
}
+
if (! client_count) {
send_client_info("clients:none");
return;
diff --git a/x11vnc/connections.h b/x11vnc/connections.h
index 6b736ed..1f70d42 100644
--- a/x11vnc/connections.h
+++ b/x11vnc/connections.h
@@ -28,6 +28,7 @@ extern void check_gui_inputs(void);
extern enum rfbNewClientAction new_client(rfbClientPtr client);
extern void start_client_info_sock(char *host_port_cookie);
extern void send_client_info(char *str);
+extern void adjust_grabs(int grab, int quiet);
extern void check_new_clients(void);
#endif /* _X11VNC_CONNECTIONS_H */
diff --git a/x11vnc/cursor.c b/x11vnc/cursor.c
index e9a2d54..2c2a763 100644
--- a/x11vnc/cursor.c
+++ b/x11vnc/cursor.c
@@ -1262,7 +1262,7 @@ static int get_xfixes_cursor(int init) {
oldest++;
}
oldtime = curs_times[oldest];
- now = time(0);
+ now = time(NULL);
for (i = CURS_DYN_MIN; i <= CURS_DYN_MAX; i++) {
if (screen && screen->cursor == cursors[i]->rfb) {
;
diff --git a/x11vnc/gui.c b/x11vnc/gui.c
index 99d35ba..d38640d 100644
--- a/x11vnc/gui.c
+++ b/x11vnc/gui.c
@@ -420,7 +420,7 @@ if (0) fprintf(stderr, "run_gui: %s -- %d %d\n", gui_xdisplay, connect_to_x11vnc
}
/* gui */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("gui")) {
fprintf(stderr, "cannot run external commands in -nocmds "
"mode:\n");
fprintf(stderr, " \"%s\"\n", "gui + wish");
diff --git a/x11vnc/help.c b/x11vnc/help.c
index 87062ce..5d8eb61 100644
--- a/x11vnc/help.c
+++ b/x11vnc/help.c
@@ -305,6 +305,7 @@ void print_help(int mode) {
" option, otherwise the stderr goes to the viewer which\n"
" will cause it to abort. Specifying both -inetd and -q\n"
" and no -o will automatically close the stderr.\n"
+"\n"
"-nofilexfer Disable the TightVNC file transfer extension. (same as\n"
" -disablefiletransfer). Note that when the -viewonly\n"
" option is supplied all file transfers are disabled.\n"
@@ -312,6 +313,7 @@ void print_help(int mode) {
" However, if the remote control mechanism is used to\n"
" change the global or per-client viewonly state the\n"
" filetransfer permissions will NOT change.\n"
+"\n"
"-http Instead of using -httpdir (see below) to specify\n"
" where the Java vncviewer applet is, have x11vnc try\n"
" to *guess* where the directory is by looking relative\n"
@@ -388,6 +390,23 @@ void print_help(int mode) {
" a global -viewonly is in effect (all input is discarded\n"
" in that case).\n"
"\n"
+"-grabkbd When VNC viewers are connected, attempt to the grab the\n"
+" keyboard so someone sitting at the physical display\n"
+" is not able to enter keystrokes. This method uses\n"
+" XGrabKeyboard(3X11) and so it is not secure and does not\n"
+" rule out the person at the physical display injecting\n"
+" keystrokes by flooding the server with them, grabbing\n"
+" the keyboard himself, etc. Some degree of cooperation\n"
+" from the person at the display is assumed.\n"
+"-grabptr As -grabkbd, but for the mouse pointer using\n"
+" XGrabPointer(3X11). Unfortunately due to the way the X\n"
+" server works, the mouse can still be moved around by the\n"
+" user at the physical display, but he will not be able to\n"
+" change window focus with it. Also some window managers\n"
+" that call XGrabServer(3X11) for resizes, etc, will\n"
+" act on the local user's input. Again, some degree of\n"
+" cooperation from the person at the display is assumed.\n"
+"\n"
"-viewpasswd string Supply a 2nd password for view-only logins. The -passwd\n"
" (full-access) password must also be supplied.\n"
"\n"
@@ -587,7 +606,25 @@ void print_help(int mode) {
" as the user who just authenticated via the login and\n"
" password prompt.\n"
"\n"
-" Thus the combination of -display WAIT:cmd=... and\n"
+" Also in the case of -unixpw, the user logging in can\n"
+" place a colon at the end of his username and supply\n"
+" a few options: scale=, scale_cursor=, solid, id=,\n"
+" clear_mods, clear_keys, repeat, or speeds= separated\n"
+" by commas if there is more than one. After the user\n"
+" logs in successfully, these options will be applied to\n"
+" the VNC screen. For example,\n"
+"\n"
+" login: fred:scale=3/4,repeat\n"
+" Password: ...\n"
+"\n"
+" for convenience m/n implies scale= e.g. fred:3/4\n"
+" To disable this set the environment variable\n"
+" X11VNC_NO_UNIXPW_OPTS=1. To set any other options,\n"
+" the user can use the gui (x11vnc -gui connect) or the\n"
+" remote control method (x11vnc -R opt:val) during his\n"
+" VNC session.\n"
+"\n"
+" So the combination of -display WAIT:cmd=... and\n"
" -unixpw allows automatic pairing of an unix\n"
" authenticated VNC user with his desktop. This could\n"
" be very useful on SunRays and also any system where\n"
@@ -620,7 +657,7 @@ void print_help(int mode) {
" 5815 stream tcp nowait root /usr/sbin/tcpd .../x11vnc \\\n"
" -inetd -q -http_ssl -display WAIT:cmd=HTTPONCE\n"
"\n"
-" Is used in the Apache SSL-portal example (see FAQ).\n"
+" It is used in the Apache SSL-portal example (see FAQ).\n"
"\n"
" Finally, one can insert a geometry between colons,\n"
" e.g. WAIT:1280x1024:... to set the size of the display\n"
@@ -1404,6 +1441,12 @@ void print_help(int mode) {
"-rc filename Use \"filename\" instead of $HOME/.x11vncrc for rc file.\n"
"-norc Do not process any .x11vncrc file for options.\n"
"\n"
+"-env VAR=VALUE Set the environment variable 'VAR' to value 'VALUE'\n"
+" at x11vnc startup. This is a convenience utility to\n"
+" avoid shell script wrappers, etc. to set the env. var.\n"
+" You may specify as many of these as needed on the\n"
+" command line.\n"
+"\n"
"-h, -help Print this help text.\n"
"-?, -opts Only list the x11vnc options.\n"
"-V, -version Print program version and last modification date.\n"
@@ -2719,6 +2762,10 @@ void print_help(int mode) {
" nolookup enable -nolookup mode.\n"
" lookup disable -nolookup mode.\n"
" input:str set -input to \"str\", empty to disable.\n"
+" grabkbd enable -grabkbd mode.\n"
+" nograbkbd disable -grabkbd mode.\n"
+" grabptr enable -grabptr mode.\n"
+" nograbptr disable -grabptr mode.\n"
" client_input:str set the K, M, B -input on a per-client\n"
" basis. select which client as for\n"
" disconnect, e.g. client_input:host:MB\n"
@@ -2976,13 +3023,14 @@ void print_help(int mode) {
" scr_skip scr_inc scr_keys scr_term scr_keyrepeat\n"
" scr_parms scrollcopyrect scr noscrollcopyrect noscr\n"
" fixscreen noxrecord xrecord reset_record pointer_mode\n"
-" pm input_skip input client_input speeds wmdt\n"
-" debug_pointer dp nodebug_pointer nodp debug_keyboard\n"
-" dk nodebug_keyboard nodk deferupdate defer wait_ui\n"
-" wait_bog nowait_bog slow_fb wait readtimeout nap nonap\n"
-" sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb\n"
-" nosnapfb rawfb progressive rfbport http nohttp httpport\n"
-" httpdir enablehttpproxy noenablehttpproxy alwaysshared\n"
+" pm input_skip input grabkbd nograbkbd grabptr\n"
+" nograbptr client_input speeds wmdt debug_pointer dp\n"
+" nodebug_pointer nodp debug_keyboard dk nodebug_keyboard\n"
+" nodk deferupdate defer wait_ui wait_bog nowait_bog\n"
+" slow_fb wait readtimeout nap nonap sb screen_blank\n"
+" fbpm nofbpm fs gaps grow fuzz snapfb nosnapfb rawfb\n"
+" progressive rfbport http nohttp httpport httpdir\n"
+" enablehttpproxy noenablehttpproxy alwaysshared\n"
" noalwaysshared nevershared noalwaysshared dontdisconnect\n"
" nodontdisconnect desktop debug_xevents nodebug_xevents\n"
" debug_xevents debug_xdamage nodebug_xdamage\n"
@@ -2997,12 +3045,8 @@ void print_help(int mode) {
" scale_str scaled_x scaled_y scale_numer scale_denom\n"
" scale_fac scaling_blend scaling_nomult4 scaling_pad\n"
" scaling_interpolate inetd privremote unsafe safer nocmds\n"
-#ifndef REL81
" passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem\n"
" sslverify stunnel stunnel_pem https usepw using_shm\n"
-#else
-" passwdfile usepw using_shm\n"
-#endif
" logfile o flag rc norc h help V version lastmod bg\n"
" sigpipe threads readrate netrate netlatency pipeinput\n"
" clients client_count pid ext_xtest ext_xtrap ext_xrecord\n"
@@ -3073,6 +3117,17 @@ void print_help(int mode) {
" remote-control is disabled it cannot be turned back on.\n"
"-nocmds No external commands (e.g. system(3), popen(3), exec(3))\n"
" will be run.\n"
+"-allowedcmds list \"list\" contains a comma separated list of the only\n"
+" external commands that can be run. The full list of\n"
+" associated options is:\n"
+"\n"
+" stunnel, ssl, unixpw, WAIT, id, accept, afteraccept,\n"
+" gone, pipeinput, v4l-info, rawfb-setup, dt, gui,\n"
+" storepasswd, crash.\n"
+"\n"
+" See each option's help to learn the associated external\n"
+" command. Note that the -nocmds option takes precedence\n"
+" and disables all external commands.\n"
"\n"
"-deny_all For use with -remote nodeny: start out denying all\n"
" incoming clients until \"-remote nodeny\" is used to\n"
@@ -3247,7 +3302,7 @@ void nopassword_warning_msg(int gotloc) {
"#@ YOU ARE RUNNING X11VNC WITHOUT A PASSWORD!! @#\n"
"#@ @#\n"
"#@ This means anyone with network access to this computer @#\n"
-"#@ will be able to easily view and control your desktop. @#\n"
+"#@ will be able to view and control your desktop. @#\n"
"#@ @#\n"
"#@ >>> If you did not mean to do this Press CTRL-C now!! <<< @#\n"
"#@ @#\n"
@@ -3257,16 +3312,18 @@ void nopassword_warning_msg(int gotloc) {
"#@ @#\n"
"#@ You can create an x11vnc password file by running: @#\n"
"#@ @#\n"
-"#@ x11vnc -storepasswd password /path/to/passfile @#\n"
+"#@ x11vnc -storepasswd password /path/to/passfile @#\n"
+"#@ or x11vnc -storepasswd /path/to/passfile @#\n"
+"#@ or x11vnc -storepasswd @#\n"
+"#@ @#\n"
+"#@ (the last one will use ~/.vnc/passwd) @#\n"
"#@ @#\n"
"#@ and then starting x11vnc via: @#\n"
"#@ @#\n"
"#@ x11vnc -rfbauth /path/to/passfile @#\n"
"#@ @#\n"
-"#@ an existing ~/.vnc/passwd file will work too. @#\n"
-"#@ @#\n"
-"#@ Running \"x11vnc -storepasswd\" with no arguments @#\n"
-"#@ will prompt for a passwd to store in ~/.vnc/passwd. @#\n"
+"#@ an existing ~/.vnc/passwd file from another VNC @#\n"
+"#@ application will work fine too. @#\n"
"#@ @#\n"
"#@ You can also use the -passwdfile or -passwd options. @#\n"
"#@ (note -passwd is unsafe if local users are not trusted) @#\n"
@@ -3277,7 +3334,8 @@ void nopassword_warning_msg(int gotloc) {
"#@ Use x11vnc -usepw to automatically use your @#\n"
"#@ ~/.vnc/passwd or ~/.vnc/passwdfile password files. @#\n"
"#@ (and prompt you to create ~/.vnc/passwd if neither @#\n"
-"#@ file exists.) @#\n"
+"#@ file exists.) Under -usepw, x11vnc will exit if it @#\n"
+"#@ cannot find a password to use. @#\n"
"#@ @#\n"
"#@ @#\n"
"#@ Even with a password, the subsequent VNC traffic is @#\n"
diff --git a/x11vnc/keyboard.c b/x11vnc/keyboard.c
index c160726..a2ae349 100644
--- a/x11vnc/keyboard.c
+++ b/x11vnc/keyboard.c
@@ -324,7 +324,7 @@ void autorepeat(int restore, int bequiet) {
void check_add_keysyms(void) {
static time_t last_check = 0;
int clear_freq = 300, quiet = 1, count;
- time_t now = time(0);
+ time_t now = time(NULL);
if (unixpw_in_progress) return;
@@ -2612,7 +2612,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
KeyCode k;
int idx, isbutton = 0;
allowed_input_t input;
- time_t now = time(0);
+ time_t now = time(NULL);
double tnow;
static int skipped_last_down;
static rfbBool last_down;
diff --git a/x11vnc/options.c b/x11vnc/options.c
index b14967b..5e60627 100644
--- a/x11vnc/options.c
+++ b/x11vnc/options.c
@@ -75,6 +75,7 @@ int no_external_cmds = 0; /* -nocmds */
#else
int no_external_cmds = 1; /* cannot be turned back on. */
#endif
+char *allowed_external_cmds = NULL;
int started_as_root = 0;
int host_lookup = 1;
char *users_list = NULL; /* -users */
diff --git a/x11vnc/options.h b/x11vnc/options.h
index f49c70a..059db27 100644
--- a/x11vnc/options.h
+++ b/x11vnc/options.h
@@ -56,6 +56,7 @@ extern int safe_remote_only;
extern int priv_remote;
extern int more_safe;
extern int no_external_cmds;
+extern char *allowed_external_cmds;
extern int started_as_root;
extern int host_lookup;
extern char *users_list;
diff --git a/x11vnc/pm.c b/x11vnc/pm.c
index 2ddb009..75e4e1e 100644
--- a/x11vnc/pm.c
+++ b/x11vnc/pm.c
@@ -51,10 +51,10 @@ static void check_fbpm(void) {
if (! client_count) {
return;
}
- if (time(0) < last_fbpm + 5) {
+ if (time(NULL) < last_fbpm + 5) {
return;
}
- last_fbpm = time(0);
+ last_fbpm = time(NULL);
if (FBPMInfo(dpy, &level, &enabled)) {
if (db) fprintf(stderr, "FBPMInfo level: %d enabled: %d\n", level, enabled);
diff --git a/x11vnc/pointer.c b/x11vnc/pointer.c
index 1ad10e9..30268e7 100644
--- a/x11vnc/pointer.c
+++ b/x11vnc/pointer.c
@@ -319,7 +319,7 @@ static void update_x11_pointer_position(int x, int y) {
rc = set_cursor(x, y, get_which_cursor());
cursor_changes += rc;
- last_event = last_input = last_pointer_input = time(0);
+ last_event = last_input = last_pointer_input = time(NULL);
}
void do_button_mask_change(int mask, int button) {
@@ -390,7 +390,7 @@ void do_button_mask_change(int mask, int button) {
static void update_x11_pointer_mask(int mask) {
int snapped = 0, xr_mouse = 1, i;
- last_event = last_input = last_pointer_input = time(0);
+ last_event = last_input = last_pointer_input = time(NULL);
RAWFB_RET_VOID
@@ -942,7 +942,7 @@ if (0) fprintf(stderr, "initialize_pipeinput: %s -- %s\n", pipeinput_str, p);
set_child_info();
/* pipeinput */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("pipeinput")) {
rfbLogEnable(1);
rfbLog("cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", p);
diff --git a/x11vnc/remote.c b/x11vnc/remote.c
index b68e9b1..ae5361f 100644
--- a/x11vnc/remote.c
+++ b/x11vnc/remote.c
@@ -296,7 +296,10 @@ int check_httpdir(void) {
p = strtok(path, ":");
while(p) {
- free(prog);
+ if (prog) {
+ free(prog);
+ prog = NULL;
+ }
len = strlen(p) + 1 + strlen(base) + 1;
prog = (char *) malloc(len);
snprintf(prog, len, "%s/%s", p, base);
@@ -314,6 +317,7 @@ int check_httpdir(void) {
* 12345678901234567
* /path/to/bin/../share/x11vnc/classes/ssl
* 123456789012345678901
+ * 21
*/
if ((q = strrchr(prog, '/')) == NULL) {
rfbLog("check_httpdir: bad program path: %s\n", prog);
@@ -648,13 +652,25 @@ char *process_remote_cmd(char *cmd, int stringonly) {
/* comma separated batch mode */
char *s, *q, *res;
char tmp[512];
- strcpy(buf, "");
+ char **pieces;
+ int k = 0, n = 0;
+
+ pieces = (char **) malloc(strlen(cmd) * sizeof(char *));
s = strdup(cmd + strlen("qry="));
q = strtok(s, ",");
+
while (q) {
strcpy(tmp, "qry=");
strncat(tmp, q, 500);
- res = process_remote_cmd(tmp, 1);
+ pieces[n] = strdup(tmp);
+ n++;
+ q = strtok(NULL, ",");
+ }
+ free(s);
+
+ strcpy(buf, "");
+ for (k=0; k<n; k++) {
+ res = process_remote_cmd(pieces[k], 1);
if (res && strlen(buf)+strlen(res)
>= X11VNC_REMOTE_MAX - 1) {
rfbLog("overflow in process_remote_cmd:"
@@ -666,12 +682,14 @@ char *process_remote_cmd(char *cmd, int stringonly) {
strcat(buf, res);
free(res);
}
- q = strtok(NULL, ",");
- if (q) {
+ if (k < n - 1) {
strcat(buf, ",");
}
}
- free(s);
+ for (k=0; k<n; k++) {
+ free(pieces[k]);
+ }
+ free(pieces);
goto qry;
}
p += strlen("qry=");
@@ -781,7 +799,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (sscanf(p, "%d", &delay) == 1) {
rfbLog("damaging client fb's for %d secs "
"(by not marking rects.)\n", delay);
- damage_time = time(0);
+ damage_time = time(NULL);
damage_delay = delay;
}
@@ -3028,6 +3046,47 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (doit) {
initialize_allowed_input();
}
+ } else if (!strcmp(p, "grabkbd")) {
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p, grab_kbd);
+ goto qry;
+ }
+ grab_kbd = 1;
+ rfbLog("enabled grab_kbd\n");
+ } else if (!strcmp(p, "nograbkbd")) {
+ int orig = grab_kbd;
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p, !grab_kbd);
+ goto qry;
+ }
+ grab_kbd = 0;
+ if (orig && dpy) {
+ X_LOCK;
+ XUngrabKeyboard(dpy, CurrentTime);
+ X_UNLOCK;
+ }
+ rfbLog("disabled grab_kbd\n");
+ } else if (!strcmp(p, "grabptr")) {
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p, grab_ptr);
+ goto qry;
+ }
+ grab_ptr = 1;
+ rfbLog("enabled grab_ptr\n");
+ } else if (!strcmp(p, "nograbptr")) {
+ int orig = grab_ptr;
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p, !grab_ptr);
+ goto qry;
+ }
+ grab_ptr = 0;
+ if (orig && dpy) {
+ X_LOCK;
+ XUngrabPointer(dpy, CurrentTime);
+ X_UNLOCK;
+ }
+ rfbLog("disabled grab_ptr\n");
+
} else if (strstr(p, "client_input") == p) {
NOTAPP
COLON_CHECK("client_input:")
diff --git a/x11vnc/scan.c b/x11vnc/scan.c
index ba08d43..162c53f 100644
--- a/x11vnc/scan.c
+++ b/x11vnc/scan.c
@@ -99,26 +99,26 @@ void initialize_tiles(void) {
ntiles = ntiles_x * ntiles_y;
tile_has_diff = (unsigned char *)
- malloc((size_t) (ntiles * sizeof(unsigned char)));
+ calloc((size_t) (ntiles * sizeof(unsigned char)), 1);
tile_has_xdamage_diff = (unsigned char *)
- malloc((size_t) (ntiles * sizeof(unsigned char)));
+ calloc((size_t) (ntiles * sizeof(unsigned char)), 1);
tile_row_has_xdamage_diff = (unsigned char *)
- malloc((size_t) (ntiles_y * sizeof(unsigned char)));
+ calloc((size_t) (ntiles_y * sizeof(unsigned char)), 1);
tile_tried = (unsigned char *)
- malloc((size_t) (ntiles * sizeof(unsigned char)));
+ calloc((size_t) (ntiles * sizeof(unsigned char)), 1);
tile_copied = (unsigned char *)
- malloc((size_t) (ntiles * sizeof(unsigned char)));
+ calloc((size_t) (ntiles * sizeof(unsigned char)), 1);
tile_blackout = (tile_blackout_t *)
- malloc((size_t) (ntiles * sizeof(tile_blackout_t)));
- tile_region = (region_t *) malloc((size_t) (ntiles * sizeof(region_t)));
+ calloc((size_t) (ntiles * sizeof(tile_blackout_t)), 1);
+ tile_region = (region_t *) calloc((size_t) (ntiles * sizeof(region_t)), 1);
tile_row = (XImage **)
- malloc((size_t) ((ntiles_x + 1) * sizeof(XImage *)));
+ calloc((size_t) ((ntiles_x + 1) * sizeof(XImage *)), 1);
tile_row_shm = (XShmSegmentInfo *)
- malloc((size_t) ((ntiles_x + 1) * sizeof(XShmSegmentInfo)));
+ calloc((size_t) ((ntiles_x + 1) * sizeof(XShmSegmentInfo)), 1);
/* there will never be more hints than tiles: */
- hint_list = (hint_t *) malloc((size_t) (ntiles * sizeof(hint_t)));
+ hint_list = (hint_t *) calloc((size_t) (ntiles * sizeof(hint_t)), 1);
}
void free_tiles(void) {
@@ -240,7 +240,7 @@ static int shm_create(XShmSegmentInfo *shm, XImage **ximg_ptr, int w, int h,
}
return 0;
}
- if (db) fprintf(stderr, "shm_create simple %d %d\t0x%x %s\n", w, h, xim, name);
+ if (db) fprintf(stderr, "shm_create simple %d %d\t%p %s\n", w, h, xim, name);
xim->data = (char *) malloc(xim->bytes_per_line * xim->height);
if (xim->data == NULL) {
rfbErr("XCreateImage(%s) data malloc failed.\n", name);
@@ -349,7 +349,7 @@ void shm_delete(XShmSegmentInfo *shm) {
void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
int db = 0;
- if (db) fprintf(stderr, "shm_clean: called: 0x%x\n", xim);
+ if (db) fprintf(stderr, "shm_clean: called: %p\n", xim);
X_LOCK;
#if LIBVNCSERVER_HAVE_XSHM
if (shm != NULL && shm->shmid != -1 && dpy) {
@@ -360,11 +360,11 @@ void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
if (xim != NULL) {
if (! raw_fb_back_to_X) { /* raw_fb hack */
if (xim->bitmap_unit != -1) {
- if (db) fprintf(stderr, "shm_clean: XDestroyImage 0x%x\n", xim);
+ if (db) fprintf(stderr, "shm_clean: XDestroyImage %p\n", xim);
XDestroyImage(xim);
} else {
if (xim->data) {
- if (db) fprintf(stderr, "shm_clean: free xim->data 0x%x 0x%x\n", xim, xim->data);
+ if (db) fprintf(stderr, "shm_clean: free xim->data %p %p\n", xim, xim->data);
free(xim->data);
xim->data = NULL;
}
@@ -1228,7 +1228,7 @@ void mark_rect_as_modified(int x1, int y1, int x2, int y2, int force) {
* damage_delay seconds.
*/
int debug = 0;
- if (time(0) > damage_time + damage_delay) {
+ if (time(NULL) > damage_time + damage_delay) {
if (! quiet) {
rfbLog("damaging turned off.\n");
}
@@ -2153,7 +2153,7 @@ if (db && snapcnt++ < 5) rfbLog("rawfb copy_snap took: %.5f secs\n", dnow() - st
*/
static void nap_set(int tile_cnt) {
int nap_in = nap_ok;
- time_t now = time(0);
+ time_t now = time(NULL);
if (scan_count == 0) {
/* roll up check for all NSCAN scans */
@@ -2219,7 +2219,7 @@ static void nap_check(int tile_cnt) {
return;
}
- now = time(0);
+ now = time(NULL);
if (screen_blank > 0) {
int dt_ev, dt_fbu, ms = 2000;
@@ -2254,7 +2254,7 @@ static void nap_check(int tile_cnt) {
*/
static void ping_clients(int tile_cnt) {
static time_t last_send = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
if (rfbMaxClientWait < 20000) {
rfbMaxClientWait = 20000;
diff --git a/x11vnc/screen.c b/x11vnc/screen.c
index 117bc30..a309c5c 100644
--- a/x11vnc/screen.c
+++ b/x11vnc/screen.c
@@ -752,7 +752,7 @@ void check_padded_fb(void) {
}
if (unixpw_in_progress) return;
- if (time(0) > pad_geometry_time+1 && all_clients_initialized()) {
+ if (time(NULL) > pad_geometry_time+1 && all_clients_initialized()) {
remove_fake_fb();
}
}
@@ -776,7 +776,7 @@ void install_padded_fb(char *geom) {
return;
}
install_fake_fb(w, h, bpp);
- pad_geometry_time = time(0);
+ pad_geometry_time = time(NULL);
}
static void initialize_snap_fb(void) {
@@ -885,7 +885,7 @@ if (db) fprintf(stderr, "initialize_raw_fb reset\n");
set_child_info();
q += strlen("setup:");
/* rawfb-setup */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("rawfb-setup")) {
rfbLogEnable(1);
rfbLog("cannot run external commands in -nocmds "
"mode:\n");
@@ -1354,12 +1354,12 @@ static void initialize_clipshift(void) {
static int wait_until_mapped(Window win) {
int ms = 50, waittime = 30;
- time_t start = time(0);
+ time_t start = time(NULL);
XWindowAttributes attr;
while (1) {
if (! valid_window(win, NULL, 0)) {
- if (time(0) > start + waittime) {
+ if (time(NULL) > start + waittime) {
break;
}
usleep(ms * 1000);
@@ -1840,7 +1840,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
fb_depth = (int) fb->depth;
rfbLog("initialize_screen: fb_depth/fb_bpp/fb_Bpl %d/%d/%d\n", fb_depth,
- fb_depth, fb_Bpl);
+ fb_bpp, fb_Bpl);
main_bytes_per_line = fb->bytes_per_line;
diff --git a/x11vnc/solid.c b/x11vnc/solid.c
index 25d92e2..16e1628 100644
--- a/x11vnc/solid.c
+++ b/x11vnc/solid.c
@@ -54,7 +54,7 @@ static int dt_cmd(char *cmd) {
}
/* dt */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("dt")) {
rfbLog("cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", cmd);
rfbLog(" dt_cmd: returning 1\n");
@@ -522,7 +522,11 @@ static void solid_gnome(char *color) {
if (! orig_color) {
char *q;
- orig_color = strdup(cmd_output(get_color));
+ if (cmd_ok("dt")) {
+ orig_color = strdup(cmd_output(get_color));
+ } else {
+ orig_color = "";
+ }
if (*orig_color == '\0') {
orig_color = strdup("#FFFFFF");
}
@@ -532,7 +536,11 @@ static void solid_gnome(char *color) {
}
if (! orig_option) {
char *q;
- orig_option = strdup(cmd_output(get_option));
+ if (cmd_ok("dt")) {
+ orig_option = strdup(cmd_output(get_option));
+ } else {
+ orig_color = "";
+ }
if (*orig_option == '\0') {
orig_option = strdup("stretched");
}
diff --git a/x11vnc/sslcmds.c b/x11vnc/sslcmds.c
index db31b5e..88254d1 100644
--- a/x11vnc/sslcmds.c
+++ b/x11vnc/sslcmds.c
@@ -32,7 +32,7 @@ static pid_t stunnel_pid = 0;
void check_stunnel(void) {
static time_t last_check = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
if (last_check + 3 >= now) {
return;
@@ -72,13 +72,14 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
path = getenv("PATH");
if (! path) {
- path = strdup(extra);
+ path = strdup(extra+1);
} else {
+ char *pt = path;
path = (char *) malloc(strlen(path)+strlen(extra)+1);
if (! path) {
return 0;
}
- strcpy(path, getenv("PATH"));
+ strcpy(path, pt);
strcat(path, extra);
}
@@ -106,15 +107,16 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
}
if (! stunnel_path) {
+ free(exe);
return 0;
}
if (stunnel_path[0] == '\0') {
- free(stunnel_path);
+ free(exe);
return 0;
}
/* stunnel */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("stunnel")) {
rfbLogEnable(1);
rfbLog("start_stunnel: cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", stunnel_path);
@@ -140,7 +142,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
if (ssl_verify) {
if (stat(ssl_verify, &verify_buf) != 0) {
rfbLog("stunnel: %s does not exist.\n", ssl_verify);
- return 0;
+ clean_up_exit(1);
}
}
@@ -148,7 +150,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
if (stunnel_pid < 0) {
stunnel_pid = 0;
- free(stunnel_path);
+ free(exe);
return 0;
}
@@ -162,7 +164,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
}
if (use_stunnel == 3) {
- char sp[20], xp[20], *a = NULL;
+ char sp[30], xp[30], *a = NULL;
char *st = stunnel_path;
char *pm = stunnel_pem;
char *sv = ssl_verify;
@@ -179,6 +181,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
}
if (stunnel_pem && ssl_verify) {
+ /* XXX double check -v 2 */
execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
"none", "-p", pm, a, sv, "-v", "2",
(char *) NULL);
@@ -212,6 +215,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
} else {
fprintf(in, "CAfile = %s\n", ssl_verify);
}
+ /* XXX double check -v 2 */
fprintf(in, "verify = 2\n");
}
fprintf(in, ";debug = 7\n\n");
@@ -226,7 +230,8 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
execlp(stunnel_path, stunnel_path, "-fd", fd, (char *) NULL);
exit(1);
}
- free(stunnel_path);
+
+ free(exe);
usleep(500 * 1000);
waitpid(stunnel_pid, &status, WNOHANG);
@@ -263,9 +268,9 @@ void stop_stunnel(void) {
void setup_stunnel(int rport, int *argc, char **argv) {
int i, xport = 0;
- if (! rport) {
+ if (! rport && argc && argv) {
for (i=0; i< *argc; i++) {
- if (!strcmp(argv[i], "-rfbport")) {
+ if (argv[i] && !strcmp(argv[i], "-rfbport")) {
if (i < *argc - 1) {
rport = atoi(argv[i+1]);
break;
@@ -281,18 +286,21 @@ void setup_stunnel(int rport, int *argc, char **argv) {
goto stunnel_fail;
}
}
+
xport = find_free_port(5950, 5999);
if (! xport) {
goto stunnel_fail;
}
+
if (start_stunnel(rport, xport)) {
int tweaked = 0;
- char tmp[20];
+ char tmp[30];
sprintf(tmp, "%d", xport);
- if (argv) {
- for (i=0; i< *argc; i++) {
- if (!strcmp(argv[i], "-rfbport")) {
+ if (argc && argv) {
+ for (i=0; i < *argc; i++) {
+ if (argv[i] && !strcmp(argv[i], "-rfbport")) {
if (i < *argc - 1) {
+ /* replace orig value */
argv[i+i] = strdup(tmp);
tweaked = 1;
break;
@@ -353,7 +361,7 @@ char *get_Cert_dir(char *cdir_in, char **tmp_in) {
sprintf(cdir, "%s%s", home, cases1[1]);
}
- tmp = (char *) malloc(strlen(cdir) + 10);
+ tmp = (char *) malloc(strlen(cdir) + strlen("/tmp") + 1);
for (i=0; i<3; i++) {
int ret;
sprintf(tmp, "%s%s", cdir, cases2[i]);
@@ -380,35 +388,36 @@ char *get_Cert_dir(char *cdir_in, char **tmp_in) {
return cdir;
}
-void sslGenCA(char *cdir) {
+static char *getsslscript(char *cdir, char *name, char *script) {
char *openssl = find_openssl_bin();
- char *tmp, *cmd, *scr, *cdir_use;
+ char *tmp, *scr, *cdir_use;
FILE *out;
- if (! openssl) {
+ if (! openssl || openssl[0] == '\0') {
+ exit(1);
+ }
+
+ if (!name || !script) {
exit(1);
}
cdir_use = get_Cert_dir(cdir, &tmp);
- if (! cdir_use) {
+ if (!cdir_use || !tmp) {
exit(1);
}
- cmd = (char *) malloc(strlen(tmp) + 100);
- scr = (char *) malloc(strlen(tmp) + 100);
+ scr = (char *) malloc(strlen(tmp) + 1 + strlen(name) + 30);
- sprintf(cmd, "%s/genca.%d.sh", tmp, getpid());
- out = fopen(cmd, "w");
+ sprintf(scr, "%s/%s.%d.sh", tmp, name, getpid());
+ out = fopen(scr, "w");
if (! out) {
- rfbLog("could not open: %s\n", cmd);
+ rfbLog("could not open: %s\n", scr);
rfbLogPerror("fopen");
exit(1);
}
- fprintf(out, "%s", genCA);
+ fprintf(out, "%s", script);
fclose(out);
- sprintf(scr, "/bin/sh %s", cmd);
-
rfbLog("Using openssl: %s\n", openssl);
rfbLog("Using certs dir: %s\n", cdir_use);
fprintf(stderr, "\n");
@@ -416,45 +425,36 @@ void sslGenCA(char *cdir) {
set_env("BASE_DIR", cdir_use);
set_env("OPENSSL", openssl);
- system(scr);
- unlink(cmd);
+ return scr;
}
-void sslGenCert(char *ty, char *nm) {
- char *openssl = find_openssl_bin();
- char *tmp, *cmd, *scr, *cdir_use;
- FILE *out;
+void sslGenCA(char *cdir) {
+ char *cmd, *scr = getsslscript(cdir, "genca", genCA);
- if (! openssl) {
+ if (! scr) {
exit(1);
}
- cdir_use = get_Cert_dir(NULL, &tmp);
- if (! cdir_use) {
- exit(1);
- }
+ cmd = (char *)malloc(strlen("/bin/sh ") + strlen(scr) + 1);
+ sprintf(cmd, "/bin/sh %s", scr);
- cmd = (char *) malloc(strlen(tmp) + 100);
- scr = (char *) malloc(strlen(tmp) + 100);
+ system(cmd);
+ unlink(scr);
- sprintf(cmd, "%s/gencert.%d.sh", tmp, getpid());
- out = fopen(cmd, "w");
- if (! out) {
- rfbLog("could not open: %s\n", cmd);
- rfbLogPerror("fopen");
+ free(cmd);
+ free(scr);
+}
+
+void sslGenCert(char *ty, char *nm) {
+ char *cmd, *scr = getsslscript(NULL, "gencert", genCert);
+
+ if (! scr) {
exit(1);
}
- fprintf(out, "%s", genCert);
- fclose(out);
-
- sprintf(scr, "/bin/sh %s", cmd);
- rfbLog("Using openssl: %s\n", openssl);
- rfbLog("Using certs dir: %s\n", cdir_use);
- fprintf(stderr, "\n");
+ cmd = (char *)malloc(strlen("/bin/sh ") + strlen(scr) + 1);
+ sprintf(cmd, "/bin/sh %s", scr);
- set_env("BASE_DIR", cdir_use);
- set_env("OPENSSL", openssl);
if (! ty) {
set_env("TYPE", "");
} else {
@@ -474,17 +474,18 @@ void sslGenCert(char *ty, char *nm) {
}
}
- system(scr);
- unlink(cmd);
+ system(cmd);
+ unlink(scr);
+
+ free(cmd);
+ free(scr);
}
void sslEncKey(char *path, int mode) {
char *openssl = find_openssl_bin();
- char *scr, *cert = NULL, *tca;
+ char *scr, *cert = NULL, *tca, *cdir = NULL;
char line[1024], tmp[] = "/tmp/x11vnc-tmp.XXXXXX";
- char *cdir = NULL;
- int tmp_fd, incert, info_only = 0, delete_only = 0;
- int listlong = 0;
+ int tmp_fd, incert, info_only = 0, delete_only = 0, listlong = 0;
struct stat sbuf;
FILE *file;
static int depth = 0;
@@ -493,6 +494,11 @@ void sslEncKey(char *path, int mode) {
/* get_saved_pem may call us back. */
return;
}
+
+ if (! path) {
+ return;
+ }
+
depth++;
if (mode == 1) {
@@ -504,8 +510,9 @@ void sslEncKey(char *path, int mode) {
if (! openssl) {
exit(1);
}
+
cdir = get_Cert_dir(NULL, &tca);
- if (! cdir) {
+ if (! cdir || ! tca) {
fprintf(stderr, "could not find Cert dir\n");
exit(1);
}
@@ -518,28 +525,38 @@ void sslEncKey(char *path, int mode) {
if (strstr(path, "SAVE") == path) {
char *p = get_saved_pem(path, 0);
if (p == NULL) {
- fprintf(stderr, "could not find saved pem matching: %s\n", path);
+ fprintf(stderr, "could not find saved pem "
+ "matching: %s\n", path);
exit(1);
}
path = p;
- } else if (!strcmp(path, "CA") && cdir) {
- tca = (char *) malloc(strlen(cdir) + strlen("/CA/cacert.pem") + 1);
+ } else if (!strcmp(path, "CA")) {
+ tca = (char *) malloc(strlen(cdir)+strlen("/CA/cacert.pem")+1);
sprintf(tca, "%s/CA/cacert.pem", cdir);
path = tca;
- } else if (info_only && (!strcasecmp(path, "LIST") || !strcasecmp(path, "LS") ||
- !strcasecmp(path, "ALL"))) {
- if (! cdir || strchr(cdir, '\'')) {
- fprintf(stderr, "bad certdir char: %s\n", cdir ? cdir : "null");
+ } else if (info_only && (!strcasecmp(path, "LIST") ||
+ !strcasecmp(path, "LS") || !strcasecmp(path, "ALL"))) {
+
+ if (! program_name || strchr(program_name, ' ')) {
+ fprintf(stderr, "bad program name.\n");
+ exit(1);
+ }
+ if (strchr(cdir, '\'')) {
+ fprintf(stderr, "bad certdir char: %s\n", cdir);
exit(1);
}
- tca = (char *) malloc(2*strlen(cdir) + strlen(program_name) + 1000);
- sprintf(tca, "find '%s' | egrep '/(CA|tmp|clients)$|\\.(crt|pem|key|req)$' "
- "| grep -v CA/newcerts", cdir);
+
+ tca = (char *) malloc(2*strlen(cdir)+strlen(program_name)+1000);
+
+ sprintf(tca, "find '%s' | egrep '/(CA|tmp|clients)$|"
+ "\\.(crt|pem|key|req)$' | grep -v CA/newcerts", cdir);
+
if (!strcasecmp(path, "ALL")) {
/* ugh.. */
- strcat(tca, " | egrep -v 'private/cakey.pem|(CA|tmp|clients)$' | xargs -n1 ");
+ strcat(tca, " | egrep -v 'private/cakey.pem|"
+ "(CA|tmp|clients)$' | xargs -n1 ");
strcat(tca, program_name);
strcat(tca, " -ssldir '");
strcat(tca, cdir);
@@ -548,6 +565,8 @@ void sslEncKey(char *path, int mode) {
strcat(tca, " | xargs ls -ld ");
}
system(tca);
+ free(tca);
+
depth--;
return;
@@ -562,7 +581,7 @@ void sslEncKey(char *path, int mode) {
write(tmp_fd, genCert, strlen(genCert));
close(tmp_fd);
- scr = (char *) malloc(strlen(tmp) + 100);
+ scr = (char *) malloc(strlen("/bin/sh ") + strlen(tmp) + 1);
sprintf(scr, "/bin/sh %s", tmp);
set_env("BASE_DIR", cdir);
@@ -575,57 +594,59 @@ void sslEncKey(char *path, int mode) {
}
system(scr);
unlink(tmp);
+ free(scr);
+
depth--;
return;
}
+
if (stat(path, &sbuf) != 0) {
- if (strstr(path, "client") || strchr(path, '/') == NULL) {
- int i;
- tca = (char *) malloc(strlen(cdir) + strlen("/clients")
- + strlen(path) + 100);
- for (i = 1; i <= 15; i++) {
- tca[0] = '\0';
- if ( i == 1) {
- sprintf(tca, "%s/%s", cdir, path);
- } else if (i == 2 && mode > 0) {
- sprintf(tca, "%s/%s.crt", cdir, path);
- } else if (i == 3) {
- sprintf(tca, "%s/%s.pem", cdir, path);
- } else if (i == 4 && mode > 1) {
- sprintf(tca, "%s/%s.req", cdir, path);
- } else if (i == 5 && mode > 1) {
- sprintf(tca, "%s/%s.key", cdir, path);
- } else if (i == 6) {
- sprintf(tca, "%s/clients/%s", cdir, path);
- } else if (i == 7 && mode > 0) {
- sprintf(tca, "%s/clients/%s.crt", cdir, path);
- } else if (i == 8) {
- sprintf(tca, "%s/clients/%s.pem", cdir, path);
- } else if (i == 9 && mode > 1) {
- sprintf(tca, "%s/clients/%s.req", cdir, path);
- } else if (i == 10 && mode > 1) {
- sprintf(tca, "%s/clients/%s.key", cdir, path);
- } else if (i == 11) {
- sprintf(tca, "%s/server-%s", cdir, path);
- } else if (i == 12 && mode > 0) {
- sprintf(tca, "%s/server-%s.crt", cdir, path);
- } else if (i == 13) {
- sprintf(tca, "%s/server-%s.pem", cdir, path);
- } else if (i == 14 && mode > 1) {
- sprintf(tca, "%s/server-%s.req", cdir, path);
- } else if (i == 15 && mode > 1) {
- sprintf(tca, "%s/server-%s.key", cdir, path);
- }
- if (tca[0] == '\0') {
- continue;
- }
- if (stat(tca, &sbuf) == 0) {
- path = tca;
- break;
- }
+ if (strstr(path, "client") || strchr(path, '/') == NULL) {
+ int i;
+ tca = (char *) malloc(strlen(cdir) + strlen(path) + 100);
+ for (i = 1; i <= 15; i++) {
+ tca[0] = '\0';
+ if ( i == 1) {
+ sprintf(tca, "%s/%s", cdir, path);
+ } else if (i == 2 && mode > 0) {
+ sprintf(tca, "%s/%s.crt", cdir, path);
+ } else if (i == 3) {
+ sprintf(tca, "%s/%s.pem", cdir, path);
+ } else if (i == 4 && mode > 1) {
+ sprintf(tca, "%s/%s.req", cdir, path);
+ } else if (i == 5 && mode > 1) {
+ sprintf(tca, "%s/%s.key", cdir, path);
+ } else if (i == 6) {
+ sprintf(tca, "%s/clients/%s", cdir, path);
+ } else if (i == 7 && mode > 0) {
+ sprintf(tca, "%s/clients/%s.crt", cdir, path);
+ } else if (i == 8) {
+ sprintf(tca, "%s/clients/%s.pem", cdir, path);
+ } else if (i == 9 && mode > 1) {
+ sprintf(tca, "%s/clients/%s.req", cdir, path);
+ } else if (i == 10 && mode > 1) {
+ sprintf(tca, "%s/clients/%s.key", cdir, path);
+ } else if (i == 11) {
+ sprintf(tca, "%s/server-%s", cdir, path);
+ } else if (i == 12 && mode > 0) {
+ sprintf(tca, "%s/server-%s.crt", cdir, path);
+ } else if (i == 13) {
+ sprintf(tca, "%s/server-%s.pem", cdir, path);
+ } else if (i == 14 && mode > 1) {
+ sprintf(tca, "%s/server-%s.req", cdir, path);
+ } else if (i == 15 && mode > 1) {
+ sprintf(tca, "%s/server-%s.key", cdir, path);
+ }
+ if (tca[0] == '\0') {
+ continue;
+ }
+ if (stat(tca, &sbuf) == 0) {
+ path = tca;
+ break;
}
}
+ }
}
if (stat(path, &sbuf) != 0) {
@@ -635,7 +656,7 @@ void sslEncKey(char *path, int mode) {
}
if (! info_only) {
- cert = (char *) malloc(2*(sbuf.st_size + 100));
+ cert = (char *) malloc(2*(sbuf.st_size + 1024));
file = fopen(path, "r");
if (file == NULL) {
rfbLog("sslEncKey: %s\n", path);
@@ -645,15 +666,17 @@ void sslEncKey(char *path, int mode) {
incert = 0;
cert[0] = '\0';
while (fgets(line, 1024, file) != NULL) {
- if (strstr(line, "-----BEGIN CERTIFICATE-----") == line) {
+ if (strstr(line, "-----BEGIN CERTIFICATE-----")
+ == line) {
incert = 1;
}
if (incert) {
- if (strlen(cert) + strlen(line) < 2*sbuf.st_size) {
+ if (strlen(cert)+strlen(line) < 2*sbuf.st_size) {
strcat(cert, line);
}
}
- if (strstr(line, "-----END CERTIFICATE-----") == line) {
+ if (strstr(line, "-----END CERTIFICATE-----")
+ == line) {
incert = 0;
}
}
@@ -668,7 +691,7 @@ void sslEncKey(char *path, int mode) {
write(tmp_fd, genCert, strlen(genCert));
close(tmp_fd);
- scr = (char *) malloc(strlen(tmp) + 100);
+ scr = (char *) malloc(strlen("/bin/sh ") + strlen(tmp) + 1);
sprintf(scr, "/bin/sh %s", tmp);
set_env("BASE_DIR", "/no/such/dir");
@@ -691,7 +714,7 @@ void sslEncKey(char *path, int mode) {
rfbLogPerror("fopen");
exit(1);
}
- fprintf(file, cert);
+ fprintf(file, "%s", cert);
fclose(file);
free(cert);
}
diff --git a/x11vnc/sslhelper.c b/x11vnc/sslhelper.c
index b98ff28..32df174 100644
--- a/x11vnc/sslhelper.c
+++ b/x11vnc/sslhelper.c
@@ -92,9 +92,9 @@ int openssl_present(void) {return 1;}
static void sslerrexit(void) {
unsigned long err = ERR_get_error();
- char str[256];
if (err) {
+ char str[256];
ERR_error_string(err, str);
fprintf(stderr, "ssl error: %s\n", str);
}
@@ -106,6 +106,11 @@ char *get_saved_pem(char *save, int create) {
int prompt = 0, len;
struct stat sbuf;
+ if (! save) {
+ rfbLog("get_saved_pem: save string is null.\n");
+ clean_up_exit(1);
+ }
+
if (strstr(save, "SAVE_PROMPT") == save) {
prompt = 1;
s = save + strlen("SAVE_PROMPT");
@@ -121,11 +126,13 @@ char *get_saved_pem(char *save, int create) {
}
cdir = get_Cert_dir(NULL, &tmp);
- if (! cdir) {
+ if (! cdir || ! tmp) {
rfbLog("get_saved_pem: could not find Cert dir.\n");
clean_up_exit(1);
}
+
len = strlen(cdir) + strlen("/server.pem") + strlen(s) + 1;
+
path = (char *) malloc(len);
sprintf(path, "%s/server%s.pem", cdir, s);
@@ -145,6 +152,11 @@ char *get_saved_pem(char *save, int create) {
static char *get_input(char *tag, char **in) {
char line[1024], *str;
+
+ if (! tag || ! in || ! *in) {
+ return NULL;
+ }
+
fprintf(stderr, "%s:\n [%s] ", tag, *in);
if (fgets(line, 1024, stdin) == NULL) {
rfbLog("could not read stdin!\n");
@@ -155,26 +167,28 @@ static char *get_input(char *tag, char **in) {
*str = '\0';
}
str = lblanks(line);
- if (! strcmp(str, "")) {
+ if (!strcmp(str, "")) {
return *in;
} else {
- free(*in);
return strdup(line);
}
}
char *find_openssl_bin(void) {
- char *path, *exe, *p;
+ char *path, *exe, *p, *gp;
struct stat sbuf;
int found_openssl = 0;
- char extra[] = ":/usr/bin:/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/sfw/bin";
+ char extra[] = ":/usr/bin:/bin:/usr/sbin:/usr/local/bin"
+ ":/usr/local/sbin:/usr/sfw/bin";
- if (! getenv("PATH")) {
+ gp = getenv("PATH");
+ if (! gp) {
fprintf(stderr, "could not find openssl(1) program in PATH.\n");
return NULL;
}
- path = (char *) malloc(strlen(getenv("PATH")) + strlen(extra) + 1);
- strcpy(path, getenv("PATH"));
+
+ path = (char *) malloc(strlen(gp) + strlen(extra) + 1);
+ strcpy(path, gp);
strcat(path, extra);
/* find openssl binary: */
@@ -233,31 +247,36 @@ static char *create_tmp_pem(char *pathin, int prompt) {
;
C = strdup("AU");
- L = strdup(UT.sysname);
- snprintf(line, 1024, "%s-%f", UT.nodename, dnow());
+ L = strdup(UT.sysname ? UT.sysname : "unknown-os");
+ snprintf(line, 1024, "%s-%f", UT.nodename ? UT.nodename :
+ "unknown-node", dnow());
line[1024-1] = '\0';
+
OU = strdup(line);
O = strdup("x11vnc");
if (pathin) {
snprintf(line, 1024, "x11vnc-SELF-SIGNED-CERT-%d", getpid());
} else {
- snprintf(line, 1024, "x11vnc-SELF-SIGNED-TEMPORARY-CERT-%d", getpid());
+ snprintf(line, 1024, "x11vnc-SELF-SIGNED-TEMPORARY-CERT-%d",
+ getpid());
}
line[1024-1] = '\0';
CN = strdup(line);
EM = strdup("x11vnc@server.nowhere");
/* ssl */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("ssl")) {
rfbLog("create_tmp_pem: cannot run external commands.\n");
return NULL;
}
+
rfbLog("\n");
if (pathin) {
rfbLog("Creating a self-signed PEM certificate...\n");
} else {
rfbLog("Creating a temporary, self-signed PEM certificate...\n");
}
+
rfbLog("\n");
rfbLog("This will NOT prevent man-in-the-middle attacks UNLESS you\n");
rfbLog("get the certificate information to the VNC viewers SSL\n");
@@ -274,9 +293,8 @@ static char *create_tmp_pem(char *pathin, int prompt) {
rfbLog("server certificate.\n");
rfbLog("\n");
-
exe = find_openssl_bin();
- if (exe == NULL) {
+ if (! exe) {
return NULL;
}
@@ -401,14 +419,15 @@ static char *create_tmp_pem(char *pathin, int prompt) {
rfbLogPerror("fopen");
return NULL;
}
+
out = fopen(pathin, "w");
+ chmod(pathin, 0600);
if (out == NULL) {
rfbLog("could not open: %s\n", pathin);
rfbLogPerror("fopen");
fclose(crt);
return NULL;
}
- chmod(pathin, 0600);
in = fopen(pem, "r");
if (in == NULL) {
@@ -461,6 +480,10 @@ static int pem_passwd_callback(char *buf, int size, int rwflag,
void *userdata) {
char *q, line[1024];
+ if (! buf) {
+ exit(1);
+ }
+
fprintf(stderr, "\nA passphrase is needed to unlock an OpenSSL "
"private key (PEM file).\n");
fprintf(stderr, "Enter passphrase> ");
@@ -488,7 +511,18 @@ static int pem_passwd_callback(char *buf, int size, int rwflag,
static int appendfile(FILE *out, char *infile) {
char line[1024];
- FILE *in = fopen(infile, "r");
+ FILE *in;
+
+ if (! infile) {
+ rfbLog("appendfile: null infile.\n");
+ return 0;
+ }
+ if (! out) {
+ rfbLog("appendfile: null out handle.\n");
+ return 0;
+ }
+
+ in = fopen(infile, "r");
if (in == NULL) {
rfbLog("appendfile: %s\n", infile);
@@ -520,11 +554,8 @@ static char *get_ssl_verify_file(char *str_in) {
return str_in;
}
- str = strdup(str_in);
- p = strtok(str, ",");
-
cdir = get_Cert_dir(NULL, &tmp);
- if (! cdir) {
+ if (! cdir || ! tmp) {
rfbLog("get_ssl_verify_file: invalid cert-dir.\n");
exit(1);
}
@@ -535,12 +566,15 @@ static char *get_ssl_verify_file(char *str_in) {
sprintf(tfile, "%s/sslverify-load-%d.crts", tmp, getpid());
file = fopen(tfile, "w");
+ chmod(tfile, 0600);
if (file == NULL) {
rfbLog("get_ssl_verify_file: %s\n", tfile);
rfbLogPerror("fopen");
exit(1);
}
- chmod(tfile, 0600);
+
+ str = strdup(str_in);
+ p = strtok(str, ",");
while (p) {
if (!strcmp(p, "CA")) {
@@ -551,9 +585,11 @@ static char *get_ssl_verify_file(char *str_in) {
}
fprintf(stderr, "sslverify: loaded %s\n", tfile2);
count++;
+
} else if (!strcmp(p, "clients")) {
DIR *dir;
struct dirent *dp;
+
sprintf(tfile2, "%s/clients", cdir);
dir = opendir(tfile2);
if (! dir) {
@@ -565,15 +601,21 @@ static char *get_ssl_verify_file(char *str_in) {
while ( (dp = readdir(dir)) != NULL) {
char *n = dp->d_name;
char *q = strstr(n, ".crt");
+
if (! q || strlen(q) != strlen(".crt")) {
continue;
}
+ if (strlen(n) > 512) {
+ continue;
+ }
+
sprintf(tfile2, "%s/clients/%s", cdir, n);
if (! appendfile(file, tfile2)) {
unlink(tfile);
exit(1);
}
- fprintf(stderr, "sslverify: loaded %s\n", tfile2);
+ fprintf(stderr, "sslverify: loaded %s\n",
+ tfile2);
count++;
}
closedir(dir);
@@ -599,7 +641,10 @@ static char *get_ssl_verify_file(char *str_in) {
fclose(file);
free(tfile2);
free(str);
- fprintf(stderr, "sslverify: using %d client certs in %s\n", count, tfile);
+
+ fprintf(stderr, "sslverify: using %d client certs in %s\n", count,
+ tfile);
+
return tfile;
}
@@ -676,6 +721,7 @@ void openssl_init(void) {
clean_up_exit(1);
}
tmp_pem = 1;
+
} else if (strstr(openssl_pem, "SAVE") == openssl_pem) {
openssl_pem = get_saved_pem(openssl_pem, 1);
if (! openssl_pem) {
@@ -747,16 +793,19 @@ void openssl_init(void) {
}
unlink(openssl_pem);
free(openssl_pem);
+ openssl_pem = NULL;
}
if (ssl_verify) {
struct stat sbuf;
char *file;
int lvl;
+
file = get_ssl_verify_file(ssl_verify);
- if (stat(file, &sbuf) != 0) {
+
+ if (!file || stat(file, &sbuf) != 0) {
rfbLog("openssl_init: -sslverify does not exists %s.\n",
- file);
+ file ? file : "null");
rfbLogPerror("stat");
clean_up_exit(1);
}
@@ -773,6 +822,7 @@ void openssl_init(void) {
sslerrexit();
}
}
+
lvl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER;
SSL_CTX_set_verify(ctx, lvl, NULL);
if (strstr(file, "tmp/sslverify-load-")) {
@@ -860,7 +910,9 @@ void https_port(void) {
rfbLog("https_port: could not open port %d\n", port);
clean_up_exit(1);
}
- if (db) fprintf(stderr, "https_port: listen on port/sock %d/%d\n", port, sock);
+ if (db) fprintf(stderr, "https_port: listen on port/sock %d/%d\n",
+ port, sock);
+
https_sock = sock;
}
@@ -978,6 +1030,7 @@ if (db) fprintf(stderr, "waitpid(%d) 2\n", helpers[i]);
}
}
+/* AUDIT */
static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
int mode) {
int nfd, db = 0;
@@ -1008,7 +1061,7 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
* increase the timeout if we know HTTP traffic has occurred
* recently:
*/
- if (time(0) < last_https + 30) {
+ if (time(NULL) < last_https + 30) {
tv.tv_sec = 8;
if (strstr(last_get, "VncViewer")) {
tv.tv_sec = 4;
@@ -1047,7 +1100,7 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
}
- buf = (char *) calloc(sizeof(ABSIZE+1), 1);
+ buf = (char *) calloc((ABSIZE+1), 1);
*n_a = 0;
n = SSL_read(ssl, buf, 2);
@@ -1614,7 +1667,7 @@ if (db) fprintf(stderr, "iface: %s\n", iface);
int i;
rfbLog("SSL: but https for helper process succeeded.\n");
if (mode != OPENSSL_HTTPS) {
- last_https = time(0);
+ last_https = time(NULL);
for (i=0; i<128; i++) {
last_get[i] = '\0';
}
@@ -1856,7 +1909,7 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) {
if (db) fprintf(stderr, "ssl_xfer begin\n");
- start = time(0);
+ start = time(NULL);
if (is_https) {
tv_use = tv_https_early;
} else {
@@ -1967,7 +2020,7 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) {
}
}
- if (tv_cutover && time(0) > start + tv_cutover) {
+ if (tv_cutover && time(NULL) > start + tv_cutover) {
tv_cutover = 0;
if (is_https) {
tv_use = tv_https_later;
@@ -2176,8 +2229,8 @@ void check_openssl(void) {
}
last_check = now;
- if (time(0) > last_waitall + 150) {
- last_waitall = time(0);
+ if (time(NULL) > last_waitall + 150) {
+ last_waitall = time(NULL);
ssl_helper_pid(0, -2); /* waitall */
}
diff --git a/x11vnc/sslhelper.h b/x11vnc/sslhelper.h
index 46ed070..cdba866 100644
--- a/x11vnc/sslhelper.h
+++ b/x11vnc/sslhelper.h
@@ -13,6 +13,8 @@ extern int openssl_port_num;
extern int https_sock;
extern pid_t openssl_last_helper_pid;
+extern void raw_xfer(int csock, int s_in, int s_out);
+
extern int openssl_present(void);
extern void openssl_init(void);
extern void openssl_port(void);
diff --git a/x11vnc/ssltools.h b/x11vnc/ssltools.h
index 98ee802..73b2686 100644
--- a/x11vnc/ssltools.h
+++ b/x11vnc/ssltools.h
@@ -697,9 +697,14 @@ char find_display[] =
"if [ \"X$1\" = \"X-n\" ]; then\n"
" showxauth=\"\"\n"
" shift\n"
-"elif [ \"X$1\" = \"X-f\" ]; then\n"
+"fi\n"
+"if [ \"X$1\" = \"X-f\" ]; then\n"
" shift\n"
-" showxauth=\"$1\"\n"
+" if [ ! -r $1 ]; then\n"
+" echo \"\"\n"
+" exit 1\n"
+" fi\n"
+" export XAUTHORITY=\"$1\"\n"
" shift\n"
"fi\n"
"\n"
@@ -724,24 +729,46 @@ char find_display[] =
"# Now try to match X DISPLAY to user:\n"
"\n"
"# who(1) output column 2:\n"
-"display=`who | grep \"^${user}[ ][ ]*:[0-9]\" | head -1 | awk '{print $2}'`\n"
+"display=`who | grep \"^${user}[ ][ ]*:[0-9]\" | head -1 \\\n"
+" | awk '{print $2}'`\n"
"\n"
"if [ \"X$display\" = \"X\" ]; then\n"
-" # who(1) output, last column:\n"
-" display=`who | grep \"^${user}[ ]\" | awk '{print $NF}' | grep '(:[0-9]' | sed -e 's/[()]//g' | head -1`\n"
-" if [ \"X$display\" = \"X\" ]; then\n"
-" echo \"\" # failure\n"
-" exit 1\n"
-" fi\n"
+" # who(1) output, last column:\n"
+" display=`who | grep \"^${user}[ ]\" | awk '{print $NF}' \\\n"
+" | grep '(:[0-9]' | sed -e 's/[()]//g' | head -1`\n"
+" if [ \"X$display\" = \"X\" ]; then\n"
+" if [ \"X$X11VNC_FINDDISPLAY_SKIP_XAUTH\" != \"X\" ]; then\n"
+" echo \"\" # failure\n"
+" exit 1\n"
+" fi\n"
+" # loop over xauth list items machine ^hostname/unix:N\n"
+" host=`hostname | sed -e 's/\\..*$//'`\n"
+" for d in `xauth list | awk '{print $1}' | grep /unix \\\n"
+" | grep \"^${host}\" | sed -e 's/^.*://' | sort -n | uniq`\n"
+" do\n"
+" xdpyinfo -display \":$d\" >/dev/null 2>&1\n"
+" if [ $? = 0 ]; then\n"
+" # try again with no authority:\n"
+" env XAUTHORITY=/dev/null xdpyinfo \\\n"
+" -display \":$d\" >/dev/null 2>&1\n"
+" # 0 means got in for free... skip it.\n"
+" if [ $? != 0 ]; then\n"
+" # keep it\n"
+" display=\":$d\"\n"
+" break\n"
+" fi\n"
+" fi\n"
+" done\n"
+" if [ \"X$display\" = \"X\" ]; then\n"
+" echo \"\" # failure\n"
+" exit 1\n"
+" fi\n"
+" fi\n"
"fi\n"
"\n"
"echo \"DISPLAY=$display\"\n"
"if [ \"X$showxauth\" != \"X\" ]; then\n"
-" if [ \"X$showxauth\" = \"X1\" ]; then\n"
-" xauth extract - \"$display\" 2>/dev/null\n"
-" else\n"
-" xauth -f \"$showxauth\" extract - \"$display\" 2>/dev/null\n"
-" fi\n"
+" xauth extract - \"$display\" 2>/dev/null\n"
"fi\n"
"\n"
"exit 0\n"
diff --git a/x11vnc/tkx11vnc b/x11vnc/tkx11vnc
index 4eaa665..10dbb50 100755
--- a/x11vnc/tkx11vnc
+++ b/x11vnc/tkx11vnc
@@ -310,6 +310,8 @@ Permissions
=0S dontdisconnect
=SQA deny_all
timeout:
+ grabkbd
+ grabptr
=GAL LOFF
Tuning
diff --git a/x11vnc/tkx11vnc.h b/x11vnc/tkx11vnc.h
index 98749ac..b4f9232 100644
--- a/x11vnc/tkx11vnc.h
+++ b/x11vnc/tkx11vnc.h
@@ -321,6 +321,8 @@ char gui_code[] = "";
" =0S dontdisconnect\n"
" =SQA deny_all\n"
" timeout:\n"
+" grabkbd\n"
+" grabptr\n"
" =GAL LOFF\n"
"\n"
"Tuning\n"
diff --git a/x11vnc/unixpw.c b/x11vnc/unixpw.c
index c09f00e..297a8e2 100644
--- a/x11vnc/unixpw.c
+++ b/x11vnc/unixpw.c
@@ -70,6 +70,7 @@ rfbClientPtr unixpw_client = NULL;
int keep_unixpw = 0;
char *keep_unixpw_user = NULL;
char *keep_unixpw_pass = NULL;
+char *keep_unixpw_opts = NULL;
static int in_login = 0, in_passwd = 0, tries = 0;
static int char_row = 0, char_col = 0;
@@ -398,7 +399,7 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size) {
}
}
/* unixpw */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("unixpw")) {
rfbLog("su_verify: cannot run external commands.\n");
clean_up_exit(1);
}
@@ -789,50 +790,54 @@ static void unixpw_verify(char *user, char *pass) {
int x, y;
char li[] = "Login incorrect";
char log[] = "login: ";
+ char *colon = NULL;
if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "********");
rfbLog("unixpw_verify: %s\n", user);
+ colon = strchr(user, ':');
+ if (colon) {
+ *colon = '\0';
+ rfbLog("unixpw_verify: colon: %s\n", user);
+ }
+
+
if (unixpw_nis) {
if (crypt_verify(user, pass)) {
unixpw_accept(user);
if (keep_unixpw) {
keep_unixpw_user = strdup(user);
keep_unixpw_pass = strdup(pass);
+ if (colon) {
+ keep_unixpw_opts = strdup(colon+1);
+ } else {
+ keep_unixpw_opts = strdup("");
+ }
}
+ if (colon) *colon = ':';
return;
} else {
rfbLog("unixpw_verify: crypt_verify login for %s failed.\n", user);
usleep(3000*1000);
}
- } else if (0) {
- char buf[8192];
- int n = 8000;
- int res = su_verify(user, pass, "/home/runge/wallycom yegg 33", buf, &n);
-
- fprintf(stderr, "su_verify ret: n=%d ", n);
- write(2, buf, n);
-
- if (res) {
- unixpw_accept(user);
- if (keep_unixpw) {
- keep_unixpw_user = strdup(user);
- keep_unixpw_pass = strdup(pass);
- }
- return;
- }
- rfbLog("unixpw_verify: su_verify login for %s failed.\n", user);
} else {
if (su_verify(user, pass, NULL, NULL, NULL)) {
unixpw_accept(user);
if (keep_unixpw) {
keep_unixpw_user = strdup(user);
keep_unixpw_pass = strdup(pass);
+ if (colon) {
+ keep_unixpw_opts = strdup(colon+1);
+ } else {
+ keep_unixpw_opts = strdup("");
+ }
}
+ if (colon) *colon = ':';
return;
}
rfbLog("unixpw_verify: su_verify login for %s failed.\n", user);
}
+ if (colon) *colon = ':';
if (tries < 2) {
char_row++;
@@ -856,7 +861,7 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
}
- unixpw_last_try_time = time(0);
+ unixpw_last_try_time = time(NULL);
unixpw_keystroke(0, 0, 2);
tries++;
} else {
@@ -902,6 +907,10 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
free(keep_unixpw_pass);
keep_unixpw_pass = NULL;
}
+ if (keep_unixpw_opts) {
+ free(keep_unixpw_opts);
+ keep_unixpw_opts = NULL;
+ }
return;
}
@@ -988,7 +997,12 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
return;
}
+#if 0
user[u_cnt++] = keystr[0];
+#else
+ user[u_cnt++] = (char) keysym;
+ keystr[0] = (char) keysym;
+#endif
x = text_x();
y = text_y();
diff --git a/x11vnc/unixpw.h b/x11vnc/unixpw.h
index aa443d4..a0d8245 100644
--- a/x11vnc/unixpw.h
+++ b/x11vnc/unixpw.h
@@ -18,5 +18,6 @@ extern rfbClientPtr unixpw_client;
extern int keep_unixpw;
extern char *keep_unixpw_user;
extern char *keep_unixpw_pass;
+extern char *keep_unixpw_opts;
#endif /* _X11VNC_UNIXPW_H */
diff --git a/x11vnc/user.c b/x11vnc/user.c
index 7dfb5d1..0b78f99 100644
--- a/x11vnc/user.c
+++ b/x11vnc/user.c
@@ -46,7 +46,7 @@ void check_switched_user(void) {
static int did_solid = 0;
static int did_dummy = 0;
int delay = 15;
- time_t now = time(0);
+ time_t now = time(NULL);
if (unixpw_in_progress) return;
@@ -675,7 +675,7 @@ static int switch_user_env(uid_t uid, char *name, char *home, int fb_mode) {
static void try_to_switch_users(void) {
static time_t last_try = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
char *users, *p;
if (getuid() && geteuid()) {
@@ -934,7 +934,7 @@ void check_new_passwds(void) {
}
if (unixpw_in_progress) return;
- now = time(0);
+ now = time(NULL);
if (now > last_check + 1) {
if (read_passwds(passwdfile)) {
install_passwds();
@@ -1029,16 +1029,106 @@ static void handle_one_http_request(void) {
}
}
+void user_supplied_opts(char *opts) {
+ char *p, *str;
+ char *allow[] = {
+ "skip-display", "skip-auth", "skip-shared",
+ "scale", "scale_cursor", "solid", "id", "clear_mods",
+ "clear_keys", "repeat", "speeds",
+ NULL
+ };
+
+ if (getenv("X11VNC_NO_UNIXPW_OPTS")) {
+ return;
+ }
+
+ str = strdup(opts);
+
+ p = strtok(str, ",");
+ while (p) {
+ char *q;
+ int i, n, m, ok = 0;
+
+ i = 0;
+ while (allow[i] != NULL) {
+ if (strstr(allow[i], "skip-")) {
+ i++;
+ continue;
+ }
+ if (strstr(p, allow[i]) == p) {
+ ok = 1;
+ break;
+ }
+ i++;
+ }
+
+ if (! ok && sscanf(p, "%d/%d", &n, &m) == 2) {
+ if (scale_str) free(scale_str);
+ scale_str = strdup(p);
+ } else if (ok) {
+ if (strstr(p, "display=") == p) {
+ if (use_dpy) free(use_dpy);
+ use_dpy = strdup(p + strlen("display="));
+ } else if (strstr(p, "auth=") == p) {
+ if (auth_file) free(auth_file);
+ auth_file = strdup(p + strlen("auth="));
+ } else if (strstr(p, "scale=") == p) {
+ if (scale_str) free(scale_str);
+ scale_str = strdup(p + strlen("scale="));
+ } else if (strstr(p, "scale_cursor=") == p) {
+ if (scale_cursor_str) free(scale_cursor_str);
+ scale_cursor_str = strdup(p +
+ strlen("scale_cursor="));
+ } else if (!strcmp(p, "shared")) {
+ shared = 1;
+ } else if (!strcmp(p, "solid")) {
+ use_solid_bg = 1;
+ if (!solid_str) {
+ solid_str = strdup(solid_default);
+ }
+ } else if (strstr(p, "solid=") == p) {
+ use_solid_bg = 1;
+ if (solid_str) free(solid_str);
+ solid_str = strdup(p + strlen("solid="));
+ } else if (strstr(p, "id=") == p) {
+ unsigned long win;
+ q = p + strlen("id=");
+ if (strcmp(q, "pick")) {
+ if (scan_hexdec(q, &win)) {
+ subwin = win;
+ }
+ }
+ } else if (!strcmp(p, "clear_mods")) {
+ clear_mods = 1;
+ } else if (!strcmp(p, "clear_keys")) {
+ clear_mods = 2;
+ } else if (!strcmp(p, "repeat")) {
+ no_autorepeat = 0;
+ } else if (strstr(p, "speeds=") == p) {
+ if (speeds_str) free(speeds_str);
+ speeds_str = strdup(p + strlen("speeds="));
+ q = speeds_str;
+ while (*q != '\0') {
+ if (*q == '-') {
+ *q = ',';
+ }
+ q++;
+ }
+ }
+ }
+ p = strtok(NULL, ",");
+ }
+ free(str);
+}
+
extern char find_display[];
+static XImage ximage_struct;
int wait_for_client(int *argc, char** argv, int http) {
- static XImage ximage_struct;
XImage* fb_image;
int w = 640, h = 480, b = 32;
- int w0, h0, i;
- int chg_raw_fb = 0;
- char *str, *q, *p;
- char *cmd = NULL;
+ int w0, h0, i, chg_raw_fb = 0;
+ char *str, *q, *p, *cmd = NULL;
int db = 0;
char tmp[] = "/tmp/x11vnc-find_display.XXXXXX";
int tmp_fd = -1, dt = 0;
@@ -1047,11 +1137,11 @@ int wait_for_client(int *argc, char** argv, int http) {
return 0;
}
- for (i=0; i< *argc; i++) {
+ for (i=0; i < *argc; i++) {
if (!strcmp(argv[i], "-desktop")) {
dt = 1;
}
- if (0) fprintf(stderr, "args %d %s\n", i, argv[i]);
+ if (1) fprintf(stderr, "args %d %s\n", i, argv[i]);
}
str = strdup(use_dpy);
@@ -1085,7 +1175,7 @@ int wait_for_client(int *argc, char** argv, int http) {
if (db) fprintf(stderr, "str: %s\n", str);
if (strstr(str, "cmd=") == str) {
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("WAIT")) {
rfbLog("wait_for_client external cmds not allowed:"
" %s\n", use_dpy);
clean_up_exit(1);
@@ -1127,7 +1217,7 @@ int wait_for_client(int *argc, char** argv, int http) {
if (! dt) {
char *s;
argv[*argc] = strdup("-desktop");
- (*argc)++;
+ *argc = (*argc) + 1;
if (cmd) {
char *q;
@@ -1141,18 +1231,27 @@ int wait_for_client(int *argc, char** argv, int http) {
}
rfb_desktop_name = strdup(s);
argv[*argc] = s;
- (*argc)++;
+ *argc = (*argc) + 1;
}
initialize_allowed_input();
+ if (! multiple_cursors_mode) {
+ multiple_cursors_mode = strdup("default");
+ }
initialize_cursors_mode();
initialize_screen(argc, argv, fb_image);
initialize_signals();
- if (!strcmp(cmd, "HTTPONCE")) {
+ if (! raw_fb) {
+ chg_raw_fb = 1;
+ /* kludge to get RAWFB_RET with dpy == NULL guards */
+ raw_fb = (char *) 0x1;
+ }
+
+ if (cmd && !strcmp(cmd, "HTTPONCE")) {
handle_one_http_request();
clean_up_exit(0);
}
@@ -1161,12 +1260,6 @@ int wait_for_client(int *argc, char** argv, int http) {
http_connections(1);
}
- if (! raw_fb) {
- chg_raw_fb = 1;
- /* kludge to get RAWFB_RET with dpy == NULL guards */
- raw_fb = "null";
- }
-
if (cmd && unixpw) {
keep_unixpw = 1;
}
@@ -1176,12 +1269,15 @@ int wait_for_client(int *argc, char** argv, int http) {
}
while (1) {
- if (! use_threads) {
- rfbPE(-1);
+ if (shut_down) {
+ clean_up_exit(0);
}
if (use_openssl) {
check_openssl();
}
+ if (! use_threads) {
+ rfbPE(-1);
+ }
if (! screen || ! screen->clientHead) {
usleep(100 * 1000);
continue;
@@ -1196,6 +1292,9 @@ int wait_for_client(int *argc, char** argv, int http) {
clean_up_exit(1);
}
while (1) {
+ if (shut_down) {
+ clean_up_exit(0);
+ }
if (! use_threads) {
rfbPE(-1);
}
@@ -1238,7 +1337,6 @@ int wait_for_client(int *argc, char** argv, int http) {
char line[18000];
memset(line, 0, 18000);
- if (0) unixpw_msg("Looking up DISPLAY", 0);
if (keep_unixpw_user && keep_unixpw_pass) {
n = 18000;
@@ -1329,7 +1427,6 @@ if (db) write(2, line, n); write(2, "\n", 1);
if (*q == '\n' || *q == '\r') *q = '\0';
q++;
}
-if (db) fprintf(stderr, "use_dpy: %s n: %d\n", use_dpy, n);
if (line2[0] != '\0') {
if (strstr(line2, "XAUTHORITY=") == line2) {
q = line2;
@@ -1360,6 +1457,9 @@ if (db) fprintf(stderr, "xauth_raw_len: %d\n", n);
if (chg_raw_fb) {
raw_fb = NULL;
}
+ if (unixpw && keep_unixpw_opts && keep_unixpw_opts[0] != '\0') {
+ user_supplied_opts(keep_unixpw_opts);
+ }
return 1;
}
diff --git a/x11vnc/userinput.c b/x11vnc/userinput.c
index 10e56d6..1395c71 100644
--- a/x11vnc/userinput.c
+++ b/x11vnc/userinput.c
@@ -2807,7 +2807,7 @@ static int try_copyrect(Window frame, int x, int y, int w, int h, int dx, int dy
* it for now by CopyRect-ing the *whole* on-screen
* rectangle (whether obscured or not!)
*/
- if (time(0) > dt_bad_check + 5) {
+ if (time(NULL) > dt_bad_check + 5) {
char *dt = guess_desktop();
if (!strcmp(dt, "kde")) {
dt_bad = 1;
@@ -2816,7 +2816,7 @@ static int try_copyrect(Window frame, int x, int y, int w, int h, int dx, int dy
} else {
dt_bad = 0;
}
- dt_bad_check = time(0);
+ dt_bad_check = time(NULL);
}
if (clipshift) {
@@ -3746,7 +3746,7 @@ if (db) fprintf(stderr, "send_copyrect: %d\n", sent_copyrect);
* save the stack list, perhaps the user has
* paused with button down.
*/
- last_save_stacklist = time(0);
+ last_save_stacklist = time(NULL);
} else {
stack_list_num = 0;
}
@@ -4126,7 +4126,7 @@ static void check_user_input4(double dt, double dtr, int tile_diffs) {
sscanf(p, "%lf,%lf,%lf,%lf", &dt_cut, &Tfac_r, &Tfac_v, &Tfac_n);
}
first = 0;
- ssec = time(0);
+ ssec = time(NULL);
if (dtr) {} /* unused vars warning: */
}
diff --git a/x11vnc/util.c b/x11vnc/util.c
index 1995164..fa28853 100644
--- a/x11vnc/util.c
+++ b/x11vnc/util.c
@@ -51,7 +51,7 @@ char *choose_title(char *display);
/*
- * routine to keep 0 <= i < n, should use in more places...
+ * routine to keep 0 <= i < n
*/
int nfix(int i, int n) {
if (i < 0) {
@@ -120,7 +120,7 @@ void uppercase(char *str) {
char *lblanks(char *str) {
char *p = str;
- while (*p) {
+ while (*p != '\0') {
if (! isspace(*p)) {
break;
}
@@ -150,6 +150,9 @@ int scan_hexdec(char *str, unsigned long *num) {
int parse_geom(char *str, int *wp, int *hp, int *xp, int *yp, int W, int H) {
int w, h, x, y;
+ if (! str) {
+ return 0;
+ }
/* handle +/-x and +/-y */
if (sscanf(str, "%dx%d+%d+%d", &w, &h, &x, &y) == 4) {
;
@@ -176,10 +179,13 @@ int parse_geom(char *str, int *wp, int *hp, int *xp, int *yp, int W, int H) {
void set_env(char *name, char *value) {
char *str;
- if (!value) {
+ if (! name) {
+ return;
+ }
+ if (! value) {
value = "";
}
- str = (char *) malloc(strlen(name)+strlen(value)+2);
+ str = (char *) malloc(strlen(name) + 1 + strlen(value) + 1);
sprintf(str, "%s=%s", name, value);
putenv(str);
}
@@ -277,6 +283,7 @@ char *this_host(void) {
char host[MAXN];
#if LIBVNCSERVER_HAVE_GETHOSTNAME
if (gethostname(host, MAXN) == 0) {
+ host[MAXN-1] = '\0';
return strdup(host);
}
#endif
@@ -286,8 +293,8 @@ char *this_host(void) {
int match_str_list(char *str, char **list) {
int i = 0, matched = 0;
- if (! list) {
- return matched;
+ if (! str || ! list) {
+ return 0;
}
while (list[i] != NULL) {
if (!strcmp(list[i], "*")) {
@@ -304,9 +311,14 @@ int match_str_list(char *str, char **list) {
char **create_str_list(char *cslist) {
int i, n;
- char *p, *str = strdup(cslist);
+ char *p, *str;
char **list = NULL;
+
+ if (! cslist) {
+ return NULL;
+ }
+ str = strdup(cslist);
n = 1;
p = str;
while (*p != '\0') {
@@ -316,7 +328,8 @@ char **create_str_list(char *cslist) {
p++;
}
- list = (char **) malloc((n+1)*sizeof(char *));
+ /* the extra last one holds NULL */
+ list = (char **) malloc( (n+1)*sizeof(char *) );
for(i=0; i < n+1; i++) {
list[i] = NULL;
}
@@ -427,6 +440,10 @@ double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1,
a = nabs((x2 - x1) * (y2 - y1));
A = nabs((X2 - X1) * (Y2 - Y1));
+ if (a == 0 || A == 0) {
+ return 0.0;
+ }
+
r = sraRgnCreateRect(x1, y1, x2, y2);
R = sraRgnCreateRect(X1, Y1, X2, Y2);
@@ -455,6 +472,8 @@ double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1,
*/
char *choose_title(char *display) {
static char title[(MAXN+10)];
+
+ memset(title, 0, MAXN+10);
strcpy(title, "x11vnc");
if (display == NULL) {
@@ -465,16 +484,20 @@ char *choose_title(char *display) {
}
title[0] = '\0';
if (display[0] == ':') {
- if (this_host() != NULL) {
- strncpy(title, this_host(), MAXN - strlen(title));
+ char *th = this_host();
+ if (th != NULL) {
+ strncpy(title, th, MAXN - strlen(title));
}
}
strncat(title, display, MAXN - strlen(title));
- if (subwin && valid_window(subwin, NULL, 0)) {
- char *name;
- if (dpy && XFetchName(dpy, subwin, &name)) {
- strncat(title, " ", MAXN - strlen(title));
- strncat(title, name, MAXN - strlen(title));
+ if (subwin && dpy && valid_window(subwin, NULL, 0)) {
+ char *name = NULL;
+ if (XFetchName(dpy, subwin, &name)) {
+ if (name) {
+ strncat(title, " ", MAXN - strlen(title));
+ strncat(title, name, MAXN - strlen(title));
+ free(name);
+ }
}
}
return title;
diff --git a/x11vnc/v4l.c b/x11vnc/v4l.c
index 7799354..22b4d00 100644
--- a/x11vnc/v4l.c
+++ b/x11vnc/v4l.c
@@ -1090,7 +1090,7 @@ static char *guess_via_v4l_info(char *dev, int *fd) {
if (*fd) {}
/* v4l-info */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("v4l-info")) {
rfbLog("guess_via_v4l_info: cannot run external "
"command: v4l-info\n");
return NULL;
diff --git a/x11vnc/win_utils.c b/x11vnc/win_utils.c
index 88c3987..f923262 100644
--- a/x11vnc/win_utils.c
+++ b/x11vnc/win_utils.c
@@ -305,7 +305,7 @@ int pick_windowid(unsigned long *num) {
set_env("DISPLAY", use_dpy);
}
/* id */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("id")) {
rfbLogEnable(1);
rfbLog("cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", "xwininfo");
diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1
index 0f0285d..3bb336e 100644
--- a/x11vnc/x11vnc.1
+++ b/x11vnc/x11vnc.1
@@ -2,7 +2,7 @@
.TH X11VNC "1" "June 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
- version: 0.8.2, lastmod: 2006-06-12
+ version: 0.8.2, lastmod: 2006-06-18
.SH SYNOPSIS
.B x11vnc
[OPTION]...
@@ -474,6 +474,32 @@ users to move the mouse. This option is ignored when
a global \fB-viewonly\fR is in effect (all input is discarded
in that case).
.PP
+\fB-grabkbd\fR
+.IP
+When VNC viewers are connected, attempt to the grab the
+keyboard so someone sitting at the physical display
+is not able to enter keystrokes. This method uses
+.IR XGrabKeyboard (3X11)
+and so it is not secure and does not
+rule out the person at the physical display injecting
+keystrokes by flooding the server with them, grabbing
+the keyboard himself, etc. Some degree of cooperation
+from the person at the display is assumed.
+.PP
+\fB-grabptr\fR
+.IP
+As \fB-grabkbd,\fR but for the mouse pointer using
+.IR XGrabPointer (3X11).
+Unfortunately due to the way the X
+server works, the mouse can still be moved around by the
+user at the physical display, but he will not be able to
+change window focus with it. Also some window managers
+that call
+.IR XGrabServer (3X11)
+for resizes, etc, will
+act on the local user's input. Again, some degree of
+cooperation from the person at the display is assumed.
+.PP
\fB-viewpasswd\fR \fIstring\fR
.IP
Supply a 2nd password for view-only logins. The \fB-passwd\fR
@@ -704,7 +730,25 @@ In the case of \fB-unixpw,\fR then the above command is run
as the user who just authenticated via the login and
password prompt.
.IP
-Thus the combination of \fB-display\fR WAIT:cmd=... and
+Also in the case of \fB-unixpw,\fR the user logging in can
+place a colon at the end of his username and supply
+a few options: scale=, scale_cursor=, solid, id=,
+clear_mods, clear_keys, repeat, or speeds= separated
+by commas if there is more than one. After the user
+logs in successfully, these options will be applied to
+the VNC screen. For example,
+.IP
+login: fred:scale=3/4,repeat
+Password: ...
+.IP
+for convenience m/n implies scale= e.g. fred:3/4
+To disable this set the environment variable
+X11VNC_NO_UNIXPW_OPTS=1. To set any other options,
+the user can use the gui (x11vnc \fB-gui\fR connect) or the
+remote control method (x11vnc \fB-R\fR opt:val) during his
+VNC session.
+.IP
+So the combination of \fB-display\fR WAIT:cmd=... and
\fB-unixpw\fR allows automatic pairing of an unix
authenticated VNC user with his desktop. This could
be very useful on SunRays and also any system where
@@ -738,7 +782,7 @@ by client web browsers. For example:
5815 stream tcp nowait root /usr/sbin/tcpd .../x11vnc \\
\fB-inetd\fR \fB-q\fR \fB-http_ssl\fR \fB-display\fR WAIT:cmd=HTTPONCE
.IP
-Is used in the Apache SSL-portal example (see FAQ).
+It is used in the Apache SSL-portal example (see FAQ).
.IP
Finally, one can insert a geometry between colons,
e.g. WAIT:1280x1024:... to set the size of the display
@@ -1629,6 +1673,14 @@ Use \fIfilename\fR instead of $HOME/.x11vncrc for rc file.
.IP
Do not process any .x11vncrc file for options.
.PP
+\fB-env\fR \fIVAR=VALUE\fR
+.IP
+Set the environment variable 'VAR' to value 'VALUE'
+at x11vnc startup. This is a convenience utility to
+avoid shell script wrappers, etc. to set the env. var.
+You may specify as many of these as needed on the
+command line.
+.PP
\fB-h,\fR \fB-help\fR
.IP
Print this help text.
@@ -3222,6 +3274,14 @@ lookup disable \fB-nolookup\fR mode.
.IP
input:str set \fB-input\fR to "str", empty to disable.
.IP
+grabkbd enable \fB-grabkbd\fR mode.
+.IP
+nograbkbd disable \fB-grabkbd\fR mode.
+.IP
+grabptr enable \fB-grabptr\fR mode.
+.IP
+nograbptr disable \fB-grabptr\fR mode.
+.IP
client_input:str set the K, M, B \fB-input\fR on a per-client
basis. select which client as for
disconnect, e.g. client_input:host:MB
@@ -3653,13 +3713,14 @@ nowf wirecopyrect wcr nowirecopyrect nowcr scr_area
scr_skip scr_inc scr_keys scr_term scr_keyrepeat
scr_parms scrollcopyrect scr noscrollcopyrect noscr
fixscreen noxrecord xrecord reset_record pointer_mode
-pm input_skip input client_input speeds wmdt
-debug_pointer dp nodebug_pointer nodp debug_keyboard
-dk nodebug_keyboard nodk deferupdate defer wait_ui
-wait_bog nowait_bog slow_fb wait readtimeout nap nonap
-sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb
-nosnapfb rawfb progressive rfbport http nohttp httpport
-httpdir enablehttpproxy noenablehttpproxy alwaysshared
+pm input_skip input grabkbd nograbkbd grabptr
+nograbptr client_input speeds wmdt debug_pointer dp
+nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
+nodk deferupdate defer wait_ui wait_bog nowait_bog
+slow_fb wait readtimeout nap nonap sb screen_blank
+fbpm nofbpm fs gaps grow fuzz snapfb nosnapfb rawfb
+progressive rfbport http nohttp httpport httpdir
+enablehttpproxy noenablehttpproxy alwaysshared
noalwaysshared nevershared noalwaysshared dontdisconnect
nodontdisconnect desktop debug_xevents nodebug_xevents
debug_xevents debug_xdamage nodebug_xdamage
@@ -3770,6 +3831,20 @@ No external commands (e.g.
)
will be run.
.PP
+\fB-allowedcmds\fR \fIlist\fR
+.IP
+\fIlist\fR contains a comma separated list of the only
+external commands that can be run. The full list of
+associated options is:
+.IP
+stunnel, ssl, unixpw, WAIT, id, accept, afteraccept,
+gone, pipeinput, v4l-info, rawfb-setup, dt, gui,
+storepasswd, crash.
+.IP
+See each option's help to learn the associated external
+command. Note that the \fB-nocmds\fR option takes precedence
+and disables all external commands.
+.PP
\fB-deny_all\fR
.IP
For use with \fB-remote\fR nodeny: start out denying all
diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c
index ab4451a..6d418a0 100644
--- a/x11vnc/x11vnc.c
+++ b/x11vnc/x11vnc.c
@@ -211,7 +211,7 @@ static void check_cursor_changes(void) {
static void record_last_fb_update(void) {
static int rbs0 = -1;
static time_t last_call = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
int rbs = -1;
rfbClientIteratorPtr iter;
rfbClientPtr cl;
@@ -399,7 +399,7 @@ if (0 && dt > 0.0) fprintf(stderr, "dt: %.5f %.4f\n", dt, dnow() - x11vnc_start)
static void watch_loop(void) {
int cnt = 0, tile_diffs = 0, skip_pe = 0;
double tm, dtr, dt = 0.0;
- time_t start = time(0);
+ time_t start = time(NULL);
if (use_threads) {
rfbRunEventLoop(screen, -1, TRUE);
@@ -489,7 +489,7 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
}
if (first_conn_timeout < 0) {
- start = time(0);
+ start = time(NULL);
first_conn_timeout = -first_conn_timeout;
}
}
@@ -497,7 +497,7 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
if (! screen || ! screen->clientHead) {
/* waiting for a client */
if (first_conn_timeout) {
- if (time(0) - start > first_conn_timeout) {
+ if (time(NULL) - start > first_conn_timeout) {
rfbLog("No client after %d secs.\n",
first_conn_timeout);
shut_down = 1;
@@ -1252,7 +1252,7 @@ static void store_homedir_passwd(char *file) {
str2[0] = '\0';
/* storepasswd */
- if (no_external_cmds) {
+ if (no_external_cmds || !cmd_ok("storepasswd")) {
fprintf(stderr, "-nocmds cannot be used with -storepasswd\n");
exit(1);
}
@@ -1376,6 +1376,10 @@ int main(int argc, char* argv[]) {
immediate_switch_user(argc, argv);
}
+ for (i=0; i < 2048; i++) {
+ argv_vnc[i] = NULL;
+ }
+
argv_vnc[0] = strdup(argv[0]);
program_name = strdup(argv[0]);
program_pid = (int) getpid();
@@ -1431,6 +1435,30 @@ int main(int argc, char* argv[]) {
}
}
+ /*
+ * do a quick check for -env parameters
+ */
+ for (i=1; i < argc; i++) {
+ char *p, *q;
+ arg = argv[i];
+ if (strstr(arg, "--") == arg) {
+ arg++;
+ }
+ if (!strcmp(arg, "-env")) {
+ CHECK_ARGC
+ p = strdup(argv[++i]);
+ q = strchr(p, '=');
+ if (! q) {
+ fprintf(stderr, "no -env '=' found: %s\n", p);
+ exit(1);
+ } else {
+ *q = '\0';
+ }
+ set_env(p, q+1);
+ free(p);
+ }
+ }
+
for (i=1; i < argc; i++) {
/* quick-n-dirty --option handling. */
arg = argv[i];
@@ -1569,6 +1597,10 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-input")) {
CHECK_ARGC
allowed_input_str = strdup(argv[++i]);
+ } else if (!strcmp(arg, "-grabkbd")) {
+ grab_kbd = 1;
+ } else if (!strcmp(arg, "-grabptr")) {
+ grab_ptr = 1;
} else if (!strcmp(arg, "-viewpasswd")) {
vpw_loc = i;
CHECK_ARGC
@@ -1781,6 +1813,8 @@ int main(int argc, char* argv[]) {
i++; /* done above */
} else if (!strcmp(arg, "-norc")) {
; /* done above */
+ } else if (!strcmp(arg, "-env")) {
+ i++; /* done above */
} else if (!strcmp(arg, "-h") || !strcmp(arg, "-help")) {
print_help(0);
} else if (!strcmp(arg, "-?") || !strcmp(arg, "-opts")) {
@@ -2181,6 +2215,9 @@ int main(int argc, char* argv[]) {
more_safe = 1;
} else if (!strcmp(arg, "-nocmds")) {
no_external_cmds = 1;
+ } else if (!strcmp(arg, "-allowedcmds")) {
+ CHECK_ARGC
+ allowed_external_cmds = strdup(argv[++i]);
} else if (!strcmp(arg, "-deny_all")) {
deny_all = 1;
} else if (!strcmp(arg, "-httpdir")) {
@@ -3157,9 +3194,14 @@ int main(int argc, char* argv[]) {
initialize_screen(&argc_vnc, argv_vnc, fb0);
- if (waited_for_client && fake_fb) {
- free(fake_fb);
- fake_fb = NULL;
+ if (waited_for_client) {
+ if (fake_fb) {
+ free(fake_fb);
+ fake_fb = NULL;
+ }
+ if (use_solid_bg && client_count) {
+ solid_bg(0);
+ }
}
if (! waited_for_client) {
diff --git a/x11vnc/x11vnc.h b/x11vnc/x11vnc.h
index 643c103..c8431f7 100644
--- a/x11vnc/x11vnc.h
+++ b/x11vnc/x11vnc.h
@@ -366,9 +366,9 @@ extern char *http_dir;
extern char vnc_desktop_name[];
extern char *main_fb; /* our copy of the X11 fb */
extern char *rfb_fb; /* same as main_fb unless transformation */
-extern char *fake_fb; /* used under -padgeom */
-extern char *snap_fb; /* used under -snapfb */
-extern char *cmap8to24_fb; /* used under -8to24 */
+extern char *fake_fb; /* used under -padgeom */
+extern char *snap_fb; /* used under -snapfb */
+extern char *cmap8to24_fb; /* used under -8to24 */
extern char *raw_fb;
extern char *raw_fb_addr;
extern int raw_fb_offset;
diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c
index b2cce67..c432d32 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.2 lastmod: 2006-06-12";
+char lastmod[] = "0.8.2 lastmod: 2006-06-18";
/* X display info */
@@ -68,11 +68,11 @@ int raw_fb_seek = 0;
int raw_fb_fd = -1;
int raw_fb_back_to_X = 0; /* kludge for testing rawfb -> X */
-int rfb_bytes_per_line;
-int main_bytes_per_line;
-unsigned long main_red_mask, main_green_mask, main_blue_mask;
-unsigned short main_red_max, main_green_max, main_blue_max;
-unsigned short main_red_shift, main_green_shift, main_blue_shift;
+int rfb_bytes_per_line = 0;
+int main_bytes_per_line = 0;
+unsigned long main_red_mask = 0, main_green_mask = 0, main_blue_mask = 0;
+unsigned short main_red_max = 0, main_green_max = 0, main_blue_max = 0;
+unsigned short main_red_shift = 0, main_green_shift = 0, main_blue_shift = 0;
/* scaling parameters */
char *scale_str = NULL;
@@ -123,8 +123,8 @@ int client_count = 0;
int clients_served = 0;
/* more transient kludge variables: */
-int cursor_x, cursor_y; /* x and y from the viewer(s) */
-int button_change_x, button_change_y;
+int cursor_x = 0, cursor_y = 0; /* x and y from the viewer(s) */
+int button_change_x = 0, button_change_y = 0;
int got_user_input = 0;
int got_pointer_input = 0;
int got_pointer_calls = 0;
diff --git a/x11vnc/xdamage.c b/x11vnc/xdamage.c
index 4c9319a..655b496 100644
--- a/x11vnc/xdamage.c
+++ b/x11vnc/xdamage.c
@@ -369,7 +369,7 @@ if (0) XEventsQueued(dpy, QueuedAfterFlush);
"/direct %d/%d/%d/%d\n", call, dt, tm - x11vnc_start, ecount,
dcount, ccount, xdamage_direct_count);
}
- now = time(0);
+ now = time(NULL);
if (! last_rpt) {
last_rpt = now;
}
diff --git a/x11vnc/xevents.c b/x11vnc/xevents.c
index ab49f0b..f027731 100644
--- a/x11vnc/xevents.c
+++ b/x11vnc/xevents.c
@@ -16,6 +16,8 @@
/* XXX CHECK BEFORE RELEASE */
int grab_buster = 0;
+int grab_kbd = 0;
+int grab_ptr = 0;
int sync_tod_delay = 3;
void initialize_vnc_connect_prop(void);
@@ -187,7 +189,7 @@ static void get_prop(char *str, int len, Atom prop) {
static void bust_grab(int reset) {
static int bust_count = 0;
static time_t last_bust = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
KeyCode key;
int button, x, y, nb;
@@ -272,7 +274,7 @@ static void bust_grab(int reset) {
XTestFakeKeyEvent_wr(dpy, key, False, CurrentTime);
}
XFlush_wr(dpy);
- last_bust = time(0);
+ last_bust = time(NULL);
}
typedef struct _grabwatch {
@@ -294,7 +296,7 @@ static int process_watch(char *str, int parent, int db) {
unsigned long xtime;
static grabwatch_t watches[GRABWATCH];
static int first = 1;
- time_t now = time(0);
+ time_t now = time(NULL);
static time_t last_bust = 0;
int too_long, problems = 0;
@@ -604,7 +606,7 @@ void sync_tod_with_servertime(void) {
void check_keycode_state(void) {
static time_t last_check = 0;
int delay = 10, noinput = 3;
- time_t now = time(0);
+ time_t now = time(NULL);
if (! client_count) {
return;
@@ -629,7 +631,7 @@ void check_keycode_state(void) {
void check_autorepeat(void) {
static time_t last_check = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
int autorepeat_is_on, autorepeat_initially_on, idle_timeout = 300;
static int idle_reset = 0;
@@ -710,7 +712,7 @@ void check_xevents(int reset) {
static time_t last_init_check = 0;
static time_t last_sync = 0;
static time_t last_time_sync = 0;
- time_t now = time(0);
+ time_t now = time(NULL);
static double last_request = 0.0;
XErrorHandler old_handler;
diff --git a/x11vnc/xevents.h b/x11vnc/xevents.h
index 0e501b0..3200063 100644
--- a/x11vnc/xevents.h
+++ b/x11vnc/xevents.h
@@ -4,6 +4,8 @@
/* -- xevents.h -- */
extern int grab_buster;
+extern int grab_kbd;
+extern int grab_ptr;
extern int sync_tod_delay;
extern void initialize_vnc_connect_prop(void);
diff --git a/x11vnc/xrandr.h b/x11vnc/xrandr.h
index baab196..5e3a7d6 100644
--- a/x11vnc/xrandr.h
+++ b/x11vnc/xrandr.h
@@ -34,11 +34,11 @@ extern int known_xrandr_mode(char *s);
if (subwin) { \
static int last = 0; \
subwin_trap_count++; \
- if (time(0) > last_subwin_trap + 60) { \
+ if (time(NULL) > last_subwin_trap + 60) { \
rfbLog("trapped GetImage xerror" \
" in SUBWIN mode. [%d]\n", \
subwin_trap_count); \
- last_subwin_trap = time(0); \
+ last_subwin_trap = time(NULL); \
last = subwin_trap_count; \
} \
if (subwin_trap_count - last > 30) { \
diff --git a/x11vnc/xwrappers.c b/x11vnc/xwrappers.c
index 88413b6..d58e914 100644
--- a/x11vnc/xwrappers.c
+++ b/x11vnc/xwrappers.c
@@ -3,6 +3,7 @@
#include "x11vnc.h"
#include "xrecord.h"
#include "keyboard.h"
+#include "xevents.h"
int xshm_present = 0;
int xtest_present = 0;
@@ -601,8 +602,15 @@ void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
last_keyboard_keycode = key;
}
+ if (grab_kbd) {
+ XUngrabKeyboard(dpy, CurrentTime);
+ }
+
if (xtrap_input) {
XTRAP_FakeKeyEvent_wr(dpy, key, down, delay);
+ if (grab_kbd) {
+ adjust_grabs(1, 1);
+ }
return;
}
@@ -616,6 +624,9 @@ void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
}
#if LIBVNCSERVER_HAVE_XTEST
XTestFakeKeyEvent(dpy, key, down, delay);
+ if (grab_kbd) {
+ adjust_grabs(1, 1);
+ }
if (debug_keyboard) {
upup_downdown_warning(key, down);
}
@@ -648,8 +659,15 @@ void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
RAWFB_RET_VOID
+ if (grab_ptr) {
+ XUngrabPointer(dpy, CurrentTime);
+ }
+
if (xtrap_input) {
XTRAP_FakeButtonEvent_wr(dpy, button, is_press, delay);
+ if (grab_ptr) {
+ adjust_grabs(1, 1);
+ }
return;
}
@@ -664,6 +682,9 @@ void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
#if LIBVNCSERVER_HAVE_XTEST
XTestFakeButtonEvent(dpy, button, is_press, delay);
#endif
+ if (grab_ptr) {
+ adjust_grabs(1, 1);
+ }
}
void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
@@ -690,8 +711,15 @@ void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
RAWFB_RET_VOID
+ if (grab_ptr) {
+ XUngrabPointer(dpy, CurrentTime);
+ }
+
if (xtrap_input) {
XTRAP_FakeMotionEvent_wr(dpy, screen, x, y, delay);
+ if (grab_ptr) {
+ adjust_grabs(1, 1);
+ }
return;
}
@@ -702,6 +730,9 @@ void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
#if LIBVNCSERVER_HAVE_XTEST
XTestFakeMotionEvent(dpy, screen, x, y, delay);
#endif
+ if (grab_ptr) {
+ adjust_grabs(1, 1);
+ }
}
Bool XTestCompareCurrentCursorWithWindow_wr(Display* dpy, Window w) {