x11vnc: --grabkbd, -grabptr, -env, -allowedcmds, unixpw+WAIT user fred:options

pull/1/head
runge 19 years ago
parent 363ae71df0
commit 64e731a9da

@ -65,7 +65,7 @@ static unsigned int root_rgb[NCOLOR];
static void set_root_cmap(void) { static void set_root_cmap(void) {
static time_t last_set = 0; static time_t last_set = 0;
time_t now = time(0); time_t now = time(NULL);
XWindowAttributes attr; XWindowAttributes attr;
static XColor color[NCOLOR]; static XColor color[NCOLOR];
int redo = 0; int redo = 0;

@ -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> 2006-06-12 Karl Runge <runge@karlrunge.com>
* x11vnc: word tune SSL Java viewer; fix multi-certs bug. Add * x11vnc: word tune SSL Java viewer; fix multi-certs bug. Add
-display WAIT:cmd=FINDDISPLAY builtin script and cmd=HTTPONCE -display WAIT:cmd=FINDDISPLAY builtin script and cmd=HTTPONCE

@ -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: 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: Here are all of x11vnc command line options:
% x11vnc -opts (see below for -help long descriptions) % 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: x11vnc options:
-display disp -auth file -id windowid -display disp -auth file -id windowid
@ -7205,19 +7205,20 @@ x11vnc options:
-inetd -nofilexfer -http -inetd -nofilexfer -http
-http_ssl -connect string -vncconnect -http_ssl -connect string -vncconnect
-novncconnect -allow host1[,host2..] -localhost -novncconnect -allow host1[,host2..] -localhost
-nolookup -input string -viewpasswd string -nolookup -input string -grabkbd
-passwdfile filename -unixpw [list] -unixpw_nis [list] -grabptr -viewpasswd string -passwdfile filename
-display WAIT:... -ssl [pem] -ssldir [dir] -unixpw [list] -unixpw_nis [list] -display WAIT:...
-sslverify [path] -sslGenCA [dir] -sslGenCert type name -ssl [pem] -ssldir [dir] -sslverify [path]
-sslEncKey [pem] -sslCertInfo [pem] -sslDelCert [pem] -sslGenCA [dir] -sslGenCert type name -sslEncKey [pem]
-stunnel [pem] -stunnel3 [pem] -https [port] -sslCertInfo [pem] -sslDelCert [pem] -stunnel [pem]
-usepw -storepasswd pass file -nopw -stunnel3 [pem] -https [port] -usepw
-accept string -afteraccept string -gone string -storepasswd pass file -nopw -accept string
-users list -noshm -flipbyteorder -afteraccept string -gone string -users list
-onetile -solid [color] -blackout string -noshm -flipbyteorder -onetile
-xinerama -noxinerama -xtrap -solid [color] -blackout string -xinerama
-xrandr [mode] -padgeom WxH -o logfile -noxinerama -xtrap -xrandr [mode]
-flag file -rc filename -norc -padgeom WxH -o logfile -flag file
-rc filename -norc -env VAR=VALUE
-h, -help -?, -opts -V, -version -h, -help -?, -opts -V, -version
-dbg -q -bg -dbg -q -bg
-modtweak -nomodtweak -xkb -modtweak -nomodtweak -xkb
@ -7254,7 +7255,8 @@ x11vnc options:
-remote command -query variable -QD variable -remote command -query variable -QD variable
-sync -noremote -yesremote -sync -noremote -yesremote
-unsafe -safer -privremote -unsafe -safer -privremote
-nocmds -deny_all -nocmds -allowedcmds list -deny_all
libvncserver options: libvncserver options:
-rfbport port TCP port for RFB protocol -rfbport port TCP port for RFB protocol
@ -7288,7 +7290,7 @@ libvncserver-tight-extension options:
% x11vnc -help % 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.) (type "x11vnc -opts" to just list the options.)
@ -7576,6 +7578,7 @@ Options:
option, otherwise the stderr goes to the viewer which option, otherwise the stderr goes to the viewer which
will cause it to abort. Specifying both -inetd and -q will cause it to abort. Specifying both -inetd and -q
and no -o will automatically close the stderr. and no -o will automatically close the stderr.
-nofilexfer Disable the TightVNC file transfer extension. (same as -nofilexfer Disable the TightVNC file transfer extension. (same as
-disablefiletransfer). Note that when the -viewonly -disablefiletransfer). Note that when the -viewonly
option is supplied all file transfers are disabled. option is supplied all file transfers are disabled.
@ -7583,6 +7586,7 @@ Options:
However, if the remote control mechanism is used to However, if the remote control mechanism is used to
change the global or per-client viewonly state the change the global or per-client viewonly state the
filetransfer permissions will NOT change. filetransfer permissions will NOT change.
-http Instead of using -httpdir (see below) to specify -http Instead of using -httpdir (see below) to specify
where the Java vncviewer applet is, have x11vnc try where the Java vncviewer applet is, have x11vnc try
to *guess* where the directory is by looking relative to *guess* where the directory is by looking relative
@ -7659,6 +7663,23 @@ Options:
a global -viewonly is in effect (all input is discarded a global -viewonly is in effect (all input is discarded
in that case). 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 -viewpasswd string Supply a 2nd password for view-only logins. The -passwd
(full-access) password must also be supplied. (full-access) password must also be supplied.
@ -7857,7 +7878,25 @@ Options:
as the user who just authenticated via the login and as the user who just authenticated via the login and
password prompt. 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 -unixpw allows automatic pairing of an unix
authenticated VNC user with his desktop. This could authenticated VNC user with his desktop. This could
be very useful on SunRays and also any system where be very useful on SunRays and also any system where
@ -7890,7 +7929,7 @@ Options:
5815 stream tcp nowait root /usr/sbin/tcpd .../x11vnc \ 5815 stream tcp nowait root /usr/sbin/tcpd .../x11vnc \
-inetd -q -http_ssl -display WAIT:cmd=HTTPONCE -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, Finally, one can insert a geometry between colons,
e.g. WAIT:1280x1024:... to set the size of the display 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. -rc filename Use "filename" instead of $HOME/.x11vncrc for rc file.
-norc Do not process any .x11vncrc file for options. -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. -h, -help Print this help text.
-?, -opts Only list the x11vnc options. -?, -opts Only list the x11vnc options.
-V, -version Print program version and last modification date. -V, -version Print program version and last modification date.
@ -9974,6 +10019,10 @@ n
nolookup enable -nolookup mode. nolookup enable -nolookup mode.
lookup disable -nolookup mode. lookup disable -nolookup mode.
input:str set -input to "str", empty to disable. 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 client_input:str set the K, M, B -input on a per-client
basis. select which client as for basis. select which client as for
disconnect, e.g. client_input:host:MB disconnect, e.g. client_input:host:MB
@ -10230,13 +10279,14 @@ n
scr_skip scr_inc scr_keys scr_term scr_keyrepeat scr_skip scr_inc scr_keys scr_term scr_keyrepeat
scr_parms scrollcopyrect scr noscrollcopyrect noscr scr_parms scrollcopyrect scr noscrollcopyrect noscr
fixscreen noxrecord xrecord reset_record pointer_mode fixscreen noxrecord xrecord reset_record pointer_mode
pm input_skip input client_input speeds wmdt pm input_skip input grabkbd nograbkbd grabptr
debug_pointer dp nodebug_pointer nodp debug_keyboard nograbptr client_input speeds wmdt debug_pointer dp
dk nodebug_keyboard nodk deferupdate defer wait_ui nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
wait_bog nowait_bog slow_fb wait readtimeout nap nonap nodk deferupdate defer wait_ui wait_bog nowait_bog
sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb slow_fb wait readtimeout nap nonap sb screen_blank
nosnapfb rawfb progressive rfbport http nohttp httpport fbpm nofbpm fs gaps grow fuzz snapfb nosnapfb rawfb
httpdir enablehttpproxy noenablehttpproxy alwaysshared progressive rfbport http nohttp httpport httpdir
enablehttpproxy noenablehttpproxy alwaysshared
noalwaysshared nevershared noalwaysshared dontdisconnect noalwaysshared nevershared noalwaysshared dontdisconnect
nodontdisconnect desktop debug_xevents nodebug_xevents nodontdisconnect desktop debug_xevents nodebug_xevents
debug_xevents debug_xdamage nodebug_xdamage debug_xevents debug_xdamage nodebug_xdamage
@ -10323,6 +10373,17 @@ n
remote-control is disabled it cannot be turned back on. remote-control is disabled it cannot be turned back on.
-nocmds No external commands (e.g. system(3), popen(3), exec(3)) -nocmds No external commands (e.g. system(3), popen(3), exec(3))
will be run. 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 -deny_all For use with -remote nodeny: start out denying all
incoming clients until "-remote nodeny" is used to incoming clients until "-remote nodeny" is used to

@ -312,7 +312,7 @@ static void crash_shell(void) {
} else if (*str == 's' && *(str+1) == '\0') { } else if (*str == 's' && *(str+1) == '\0') {
sprintf(cmd, "sh -c '(%s) &'", crash_stack_command1); sprintf(cmd, "sh -c '(%s) &'", crash_stack_command1);
/* crash */ /* crash */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("crash")) {
fprintf(stderr, "\nno_external_cmds=%d\n", fprintf(stderr, "\nno_external_cmds=%d\n",
no_external_cmds); no_external_cmds);
goto crash_prompt; goto crash_prompt;

@ -14,6 +14,7 @@
#include "sslcmds.h" #include "sslcmds.h"
#include "sslhelper.h" #include "sslhelper.h"
#include "xwrappers.h" #include "xwrappers.h"
#include "xevents.h"
/* /*
* routines for handling incoming, outgoing, etc connections * routines for handling incoming, outgoing, etc connections
@ -44,6 +45,7 @@ void check_gui_inputs(void);
enum rfbNewClientAction new_client(rfbClientPtr client); enum rfbNewClientAction new_client(rfbClientPtr client);
void start_client_info_sock(char *host_port_cookie); void start_client_info_sock(char *host_port_cookie);
void send_client_info(char *str); void send_client_info(char *str);
void adjust_grabs(int grab, int quiet);
void check_new_clients(void); 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. * utility to run a user supplied command setting some RFB_ env vars.
* used by, e.g., accept_client() and client_gone() * 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 *old_display = NULL;
char *addr = client->host; char *addr = client->host;
char str[100]; char str[100];
int rc; int rc, ok;
ClientData *cd = (ClientData *) client->clientData; ClientData *cd = (ClientData *) client->clientData;
if (addr == NULL || addr[0] == '\0') { if (addr == NULL || addr[0] == '\0') {
@ -414,11 +442,11 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) {
if (cd) { if (cd) {
sprintf(str, "%d", (int) cd->login_time); sprintf(str, "%d", (int) cd->login_time);
} else { } else {
sprintf(str, ">%d", (int) time(0)); sprintf(str, ">%d", (int) time(NULL));
} }
set_env("RFB_LOGIN_TIME", str); set_env("RFB_LOGIN_TIME", str);
sprintf(str, "%d", (int) time(0)); sprintf(str, "%d", (int) time(NULL));
set_env("RFB_CURRENT_TIME", str); set_env("RFB_CURRENT_TIME", str);
if (!cd || !cd->username || cd->username[0] == '\0') { 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); set_env("RFB_CLIENT_COUNT", str);
/* gone, accept, afteraccept */ /* 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); rfbLogEnable(1);
rfbLog("cannot run external commands in -nocmds mode:\n"); rfbLog("cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", cmd); rfbLog(" \"%s\"\n", cmd);
@ -1398,7 +1436,7 @@ static void check_connect_file(char *file) {
char line[VNC_CONNECT_MAX], host[VNC_CONNECT_MAX]; char line[VNC_CONNECT_MAX], host[VNC_CONNECT_MAX];
static int first_warn = 1, truncate_ok = 1; static int first_warn = 1, truncate_ok = 1;
static time_t last_time = 0; static time_t last_time = 0;
time_t now = time(0); time_t now = time(NULL);
if (last_time == 0) { if (last_time == 0) {
last_time = now; last_time = now;
@ -1846,7 +1884,7 @@ void check_gui_inputs(void) {
enum rfbNewClientAction new_client(rfbClientPtr client) { enum rfbNewClientAction new_client(rfbClientPtr client) {
ClientData *cd; ClientData *cd;
last_event = last_input = time(0); last_event = last_input = time(NULL);
if (inetd) { if (inetd) {
@ -1902,7 +1940,7 @@ if (getenv("NEW_CLIENT")) fprintf(stderr, "new_client: %s %d\n", client->host, c
cd->input[0] = '-'; cd->input[0] = '-';
cd->login_viewonly = -1; cd->login_viewonly = -1;
cd->login_time = time(0); cd->login_time = time(NULL);
cd->ssl_helper_pid = 0; cd->ssl_helper_pid = 0;
if (use_openssl && openssl_last_helper_pid) { 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++; 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) { 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; cd->raw_bytes_sent = 0;
accepted_client = 1; accepted_client = 1;
last_client = time(0); last_client = time(NULL);
if (unixpw) { if (unixpw) {
unixpw_in_progress = 1; 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; unixpw_login_viewonly = 1;
client->viewOnly = FALSE; client->viewOnly = FALSE;
} }
unixpw_last_try_time = time(0); unixpw_last_try_time = time(NULL);
unixpw_screen(1); unixpw_screen(1);
unixpw_keystroke(0, 0, 1); unixpw_keystroke(0, 0, 1);
} }
@ -2027,7 +2065,7 @@ void start_client_info_sock(char *host_port_cookie) {
if (sock >= 0) { if (sock >= 0) {
char *lst = list_clients(); char *lst = list_clients();
icon_mode_socks[next] = sock; 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, cookie, strlen(cookie)); write(sock, cookie, strlen(cookie));
write(sock, "\n", strlen("\n")); 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) { void check_new_clients(void) {
static int last_count = 0; static int last_count = 0;
rfbClientIteratorPtr iter; rfbClientIteratorPtr iter;
@ -2117,12 +2189,27 @@ void check_new_clients(void) {
unixpw_login_viewonly = 1; unixpw_login_viewonly = 1;
unixpw_client->viewOnly = FALSE; 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"); rfbLog("unixpw_deny: timed out waiting for reply.\n");
unixpw_deny(); unixpw_deny();
} }
return; 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) { if (client_count == last_count) {
return; return;
@ -2143,6 +2230,7 @@ void check_new_clients(void) {
if (! screen) { if (! screen) {
return; return;
} }
if (! client_count) { if (! client_count) {
send_client_info("clients:none"); send_client_info("clients:none");
return; return;

@ -28,6 +28,7 @@ extern void check_gui_inputs(void);
extern enum rfbNewClientAction new_client(rfbClientPtr client); extern enum rfbNewClientAction new_client(rfbClientPtr client);
extern void start_client_info_sock(char *host_port_cookie); extern void start_client_info_sock(char *host_port_cookie);
extern void send_client_info(char *str); extern void send_client_info(char *str);
extern void adjust_grabs(int grab, int quiet);
extern void check_new_clients(void); extern void check_new_clients(void);
#endif /* _X11VNC_CONNECTIONS_H */ #endif /* _X11VNC_CONNECTIONS_H */

@ -1262,7 +1262,7 @@ static int get_xfixes_cursor(int init) {
oldest++; oldest++;
} }
oldtime = curs_times[oldest]; oldtime = curs_times[oldest];
now = time(0); now = time(NULL);
for (i = CURS_DYN_MIN; i <= CURS_DYN_MAX; i++) { for (i = CURS_DYN_MIN; i <= CURS_DYN_MAX; i++) {
if (screen && screen->cursor == cursors[i]->rfb) { if (screen && screen->cursor == cursors[i]->rfb) {
; ;

@ -420,7 +420,7 @@ if (0) fprintf(stderr, "run_gui: %s -- %d %d\n", gui_xdisplay, connect_to_x11vnc
} }
/* gui */ /* gui */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("gui")) {
fprintf(stderr, "cannot run external commands in -nocmds " fprintf(stderr, "cannot run external commands in -nocmds "
"mode:\n"); "mode:\n");
fprintf(stderr, " \"%s\"\n", "gui + wish"); fprintf(stderr, " \"%s\"\n", "gui + wish");

@ -305,6 +305,7 @@ void print_help(int mode) {
" option, otherwise the stderr goes to the viewer which\n" " option, otherwise the stderr goes to the viewer which\n"
" will cause it to abort. Specifying both -inetd and -q\n" " will cause it to abort. Specifying both -inetd and -q\n"
" and no -o will automatically close the stderr.\n" " and no -o will automatically close the stderr.\n"
"\n"
"-nofilexfer Disable the TightVNC file transfer extension. (same as\n" "-nofilexfer Disable the TightVNC file transfer extension. (same as\n"
" -disablefiletransfer). Note that when the -viewonly\n" " -disablefiletransfer). Note that when the -viewonly\n"
" option is supplied all file transfers are disabled.\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" " However, if the remote control mechanism is used to\n"
" change the global or per-client viewonly state the\n" " change the global or per-client viewonly state the\n"
" filetransfer permissions will NOT change.\n" " filetransfer permissions will NOT change.\n"
"\n"
"-http Instead of using -httpdir (see below) to specify\n" "-http Instead of using -httpdir (see below) to specify\n"
" where the Java vncviewer applet is, have x11vnc try\n" " where the Java vncviewer applet is, have x11vnc try\n"
" to *guess* where the directory is by looking relative\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" " a global -viewonly is in effect (all input is discarded\n"
" in that case).\n" " in that case).\n"
"\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" "-viewpasswd string Supply a 2nd password for view-only logins. The -passwd\n"
" (full-access) password must also be supplied.\n" " (full-access) password must also be supplied.\n"
"\n" "\n"
@ -587,7 +606,25 @@ void print_help(int mode) {
" as the user who just authenticated via the login and\n" " as the user who just authenticated via the login and\n"
" password prompt.\n" " password prompt.\n"
"\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" " -unixpw allows automatic pairing of an unix\n"
" authenticated VNC user with his desktop. This could\n" " authenticated VNC user with his desktop. This could\n"
" be very useful on SunRays and also any system where\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" " 5815 stream tcp nowait root /usr/sbin/tcpd .../x11vnc \\\n"
" -inetd -q -http_ssl -display WAIT:cmd=HTTPONCE\n" " -inetd -q -http_ssl -display WAIT:cmd=HTTPONCE\n"
"\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" "\n"
" Finally, one can insert a geometry between colons,\n" " Finally, one can insert a geometry between colons,\n"
" e.g. WAIT:1280x1024:... to set the size of the display\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" "-rc filename Use \"filename\" instead of $HOME/.x11vncrc for rc file.\n"
"-norc Do not process any .x11vncrc file for options.\n" "-norc Do not process any .x11vncrc file for options.\n"
"\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" "-h, -help Print this help text.\n"
"-?, -opts Only list the x11vnc options.\n" "-?, -opts Only list the x11vnc options.\n"
"-V, -version Print program version and last modification date.\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" " nolookup enable -nolookup mode.\n"
" lookup disable -nolookup mode.\n" " lookup disable -nolookup mode.\n"
" input:str set -input to \"str\", empty to disable.\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" " client_input:str set the K, M, B -input on a per-client\n"
" basis. select which client as for\n" " basis. select which client as for\n"
" disconnect, e.g. client_input:host:MB\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_skip scr_inc scr_keys scr_term scr_keyrepeat\n"
" scr_parms scrollcopyrect scr noscrollcopyrect noscr\n" " scr_parms scrollcopyrect scr noscrollcopyrect noscr\n"
" fixscreen noxrecord xrecord reset_record pointer_mode\n" " fixscreen noxrecord xrecord reset_record pointer_mode\n"
" pm input_skip input client_input speeds wmdt\n" " pm input_skip input grabkbd nograbkbd grabptr\n"
" debug_pointer dp nodebug_pointer nodp debug_keyboard\n" " nograbptr client_input speeds wmdt debug_pointer dp\n"
" dk nodebug_keyboard nodk deferupdate defer wait_ui\n" " nodebug_pointer nodp debug_keyboard dk nodebug_keyboard\n"
" wait_bog nowait_bog slow_fb wait readtimeout nap nonap\n" " nodk deferupdate defer wait_ui wait_bog nowait_bog\n"
" sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb\n" " slow_fb wait readtimeout nap nonap sb screen_blank\n"
" nosnapfb rawfb progressive rfbport http nohttp httpport\n" " fbpm nofbpm fs gaps grow fuzz snapfb nosnapfb rawfb\n"
" httpdir enablehttpproxy noenablehttpproxy alwaysshared\n" " progressive rfbport http nohttp httpport httpdir\n"
" enablehttpproxy noenablehttpproxy alwaysshared\n"
" noalwaysshared nevershared noalwaysshared dontdisconnect\n" " noalwaysshared nevershared noalwaysshared dontdisconnect\n"
" nodontdisconnect desktop debug_xevents nodebug_xevents\n" " nodontdisconnect desktop debug_xevents nodebug_xevents\n"
" debug_xevents debug_xdamage nodebug_xdamage\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_str scaled_x scaled_y scale_numer scale_denom\n"
" scale_fac scaling_blend scaling_nomult4 scaling_pad\n" " scale_fac scaling_blend scaling_nomult4 scaling_pad\n"
" scaling_interpolate inetd privremote unsafe safer nocmds\n" " scaling_interpolate inetd privremote unsafe safer nocmds\n"
#ifndef REL81
" passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem\n" " passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem\n"
" sslverify stunnel stunnel_pem https usepw using_shm\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" " logfile o flag rc norc h help V version lastmod bg\n"
" sigpipe threads readrate netrate netlatency pipeinput\n" " sigpipe threads readrate netrate netlatency pipeinput\n"
" clients client_count pid ext_xtest ext_xtrap ext_xrecord\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" " remote-control is disabled it cannot be turned back on.\n"
"-nocmds No external commands (e.g. system(3), popen(3), exec(3))\n" "-nocmds No external commands (e.g. system(3), popen(3), exec(3))\n"
" will be run.\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" "\n"
"-deny_all For use with -remote nodeny: start out denying all\n" "-deny_all For use with -remote nodeny: start out denying all\n"
" incoming clients until \"-remote nodeny\" is used to\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" "#@ YOU ARE RUNNING X11VNC WITHOUT A PASSWORD!! @#\n"
"#@ @#\n" "#@ @#\n"
"#@ This means anyone with network access to this computer @#\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" "#@ @#\n"
"#@ >>> If you did not mean to do this Press CTRL-C now!! <<< @#\n" "#@ >>> If you did not mean to do this Press CTRL-C now!! <<< @#\n"
"#@ @#\n" "#@ @#\n"
@ -3257,16 +3312,18 @@ void nopassword_warning_msg(int gotloc) {
"#@ @#\n" "#@ @#\n"
"#@ You can create an x11vnc password file by running: @#\n" "#@ You can create an x11vnc password file by running: @#\n"
"#@ @#\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" "#@ @#\n"
"#@ and then starting x11vnc via: @#\n" "#@ and then starting x11vnc via: @#\n"
"#@ @#\n" "#@ @#\n"
"#@ x11vnc -rfbauth /path/to/passfile @#\n" "#@ x11vnc -rfbauth /path/to/passfile @#\n"
"#@ @#\n" "#@ @#\n"
"#@ an existing ~/.vnc/passwd file will work too. @#\n" "#@ an existing ~/.vnc/passwd file from another VNC @#\n"
"#@ @#\n" "#@ application will work fine too. @#\n"
"#@ Running \"x11vnc -storepasswd\" with no arguments @#\n"
"#@ will prompt for a passwd to store in ~/.vnc/passwd. @#\n"
"#@ @#\n" "#@ @#\n"
"#@ You can also use the -passwdfile or -passwd options. @#\n" "#@ You can also use the -passwdfile or -passwd options. @#\n"
"#@ (note -passwd is unsafe if local users are not trusted) @#\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" "#@ Use x11vnc -usepw to automatically use your @#\n"
"#@ ~/.vnc/passwd or ~/.vnc/passwdfile password files. @#\n" "#@ ~/.vnc/passwd or ~/.vnc/passwdfile password files. @#\n"
"#@ (and prompt you to create ~/.vnc/passwd if neither @#\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"
"#@ @#\n" "#@ @#\n"
"#@ Even with a password, the subsequent VNC traffic is @#\n" "#@ Even with a password, the subsequent VNC traffic is @#\n"

@ -324,7 +324,7 @@ void autorepeat(int restore, int bequiet) {
void check_add_keysyms(void) { void check_add_keysyms(void) {
static time_t last_check = 0; static time_t last_check = 0;
int clear_freq = 300, quiet = 1, count; int clear_freq = 300, quiet = 1, count;
time_t now = time(0); time_t now = time(NULL);
if (unixpw_in_progress) return; if (unixpw_in_progress) return;
@ -2612,7 +2612,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
KeyCode k; KeyCode k;
int idx, isbutton = 0; int idx, isbutton = 0;
allowed_input_t input; allowed_input_t input;
time_t now = time(0); time_t now = time(NULL);
double tnow; double tnow;
static int skipped_last_down; static int skipped_last_down;
static rfbBool last_down; static rfbBool last_down;

@ -75,6 +75,7 @@ int no_external_cmds = 0; /* -nocmds */
#else #else
int no_external_cmds = 1; /* cannot be turned back on. */ int no_external_cmds = 1; /* cannot be turned back on. */
#endif #endif
char *allowed_external_cmds = NULL;
int started_as_root = 0; int started_as_root = 0;
int host_lookup = 1; int host_lookup = 1;
char *users_list = NULL; /* -users */ char *users_list = NULL; /* -users */

@ -56,6 +56,7 @@ extern int safe_remote_only;
extern int priv_remote; extern int priv_remote;
extern int more_safe; extern int more_safe;
extern int no_external_cmds; extern int no_external_cmds;
extern char *allowed_external_cmds;
extern int started_as_root; extern int started_as_root;
extern int host_lookup; extern int host_lookup;
extern char *users_list; extern char *users_list;

@ -51,10 +51,10 @@ static void check_fbpm(void) {
if (! client_count) { if (! client_count) {
return; return;
} }
if (time(0) < last_fbpm + 5) { if (time(NULL) < last_fbpm + 5) {
return; return;
} }
last_fbpm = time(0); last_fbpm = time(NULL);
if (FBPMInfo(dpy, &level, &enabled)) { if (FBPMInfo(dpy, &level, &enabled)) {
if (db) fprintf(stderr, "FBPMInfo level: %d enabled: %d\n", level, enabled); if (db) fprintf(stderr, "FBPMInfo level: %d enabled: %d\n", level, enabled);

@ -319,7 +319,7 @@ static void update_x11_pointer_position(int x, int y) {
rc = set_cursor(x, y, get_which_cursor()); rc = set_cursor(x, y, get_which_cursor());
cursor_changes += rc; 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) { 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) { static void update_x11_pointer_mask(int mask) {
int snapped = 0, xr_mouse = 1, i; 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 RAWFB_RET_VOID
@ -942,7 +942,7 @@ if (0) fprintf(stderr, "initialize_pipeinput: %s -- %s\n", pipeinput_str, p);
set_child_info(); set_child_info();
/* pipeinput */ /* pipeinput */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("pipeinput")) {
rfbLogEnable(1); rfbLogEnable(1);
rfbLog("cannot run external commands in -nocmds mode:\n"); rfbLog("cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", p); rfbLog(" \"%s\"\n", p);

@ -296,7 +296,10 @@ int check_httpdir(void) {
p = strtok(path, ":"); p = strtok(path, ":");
while(p) { while(p) {
free(prog); if (prog) {
free(prog);
prog = NULL;
}
len = strlen(p) + 1 + strlen(base) + 1; len = strlen(p) + 1 + strlen(base) + 1;
prog = (char *) malloc(len); prog = (char *) malloc(len);
snprintf(prog, len, "%s/%s", p, base); snprintf(prog, len, "%s/%s", p, base);
@ -314,6 +317,7 @@ int check_httpdir(void) {
* 12345678901234567 * 12345678901234567
* /path/to/bin/../share/x11vnc/classes/ssl * /path/to/bin/../share/x11vnc/classes/ssl
* 123456789012345678901 * 123456789012345678901
* 21
*/ */
if ((q = strrchr(prog, '/')) == NULL) { if ((q = strrchr(prog, '/')) == NULL) {
rfbLog("check_httpdir: bad program path: %s\n", prog); 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 */ /* comma separated batch mode */
char *s, *q, *res; char *s, *q, *res;
char tmp[512]; char tmp[512];
strcpy(buf, ""); char **pieces;
int k = 0, n = 0;
pieces = (char **) malloc(strlen(cmd) * sizeof(char *));
s = strdup(cmd + strlen("qry=")); s = strdup(cmd + strlen("qry="));
q = strtok(s, ","); q = strtok(s, ",");
while (q) { while (q) {
strcpy(tmp, "qry="); strcpy(tmp, "qry=");
strncat(tmp, q, 500); 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) if (res && strlen(buf)+strlen(res)
>= X11VNC_REMOTE_MAX - 1) { >= X11VNC_REMOTE_MAX - 1) {
rfbLog("overflow in process_remote_cmd:" rfbLog("overflow in process_remote_cmd:"
@ -666,12 +682,14 @@ char *process_remote_cmd(char *cmd, int stringonly) {
strcat(buf, res); strcat(buf, res);
free(res); free(res);
} }
q = strtok(NULL, ","); if (k < n - 1) {
if (q) {
strcat(buf, ","); strcat(buf, ",");
} }
} }
free(s); for (k=0; k<n; k++) {
free(pieces[k]);
}
free(pieces);
goto qry; goto qry;
} }
p += strlen("qry="); p += strlen("qry=");
@ -781,7 +799,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (sscanf(p, "%d", &delay) == 1) { if (sscanf(p, "%d", &delay) == 1) {
rfbLog("damaging client fb's for %d secs " rfbLog("damaging client fb's for %d secs "
"(by not marking rects.)\n", delay); "(by not marking rects.)\n", delay);
damage_time = time(0); damage_time = time(NULL);
damage_delay = delay; damage_delay = delay;
} }
@ -3028,6 +3046,47 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (doit) { if (doit) {
initialize_allowed_input(); 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) { } else if (strstr(p, "client_input") == p) {
NOTAPP NOTAPP
COLON_CHECK("client_input:") COLON_CHECK("client_input:")

@ -99,26 +99,26 @@ void initialize_tiles(void) {
ntiles = ntiles_x * ntiles_y; ntiles = ntiles_x * ntiles_y;
tile_has_diff = (unsigned char *) 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 *) 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 *) 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 *) tile_tried = (unsigned char *)
malloc((size_t) (ntiles * sizeof(unsigned char))); calloc((size_t) (ntiles * sizeof(unsigned char)), 1);
tile_copied = (unsigned char *) tile_copied = (unsigned char *)
malloc((size_t) (ntiles * sizeof(unsigned char))); calloc((size_t) (ntiles * sizeof(unsigned char)), 1);
tile_blackout = (tile_blackout_t *) tile_blackout = (tile_blackout_t *)
malloc((size_t) (ntiles * sizeof(tile_blackout_t))); calloc((size_t) (ntiles * sizeof(tile_blackout_t)), 1);
tile_region = (region_t *) malloc((size_t) (ntiles * sizeof(region_t))); tile_region = (region_t *) calloc((size_t) (ntiles * sizeof(region_t)), 1);
tile_row = (XImage **) tile_row = (XImage **)
malloc((size_t) ((ntiles_x + 1) * sizeof(XImage *))); calloc((size_t) ((ntiles_x + 1) * sizeof(XImage *)), 1);
tile_row_shm = (XShmSegmentInfo *) 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: */ /* 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) { void free_tiles(void) {
@ -240,7 +240,7 @@ static int shm_create(XShmSegmentInfo *shm, XImage **ximg_ptr, int w, int h,
} }
return 0; 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); xim->data = (char *) malloc(xim->bytes_per_line * xim->height);
if (xim->data == NULL) { if (xim->data == NULL) {
rfbErr("XCreateImage(%s) data malloc failed.\n", name); rfbErr("XCreateImage(%s) data malloc failed.\n", name);
@ -349,7 +349,7 @@ void shm_delete(XShmSegmentInfo *shm) {
void shm_clean(XShmSegmentInfo *shm, XImage *xim) { void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
int db = 0; 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; X_LOCK;
#if LIBVNCSERVER_HAVE_XSHM #if LIBVNCSERVER_HAVE_XSHM
if (shm != NULL && shm->shmid != -1 && dpy) { if (shm != NULL && shm->shmid != -1 && dpy) {
@ -360,11 +360,11 @@ void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
if (xim != NULL) { if (xim != NULL) {
if (! raw_fb_back_to_X) { /* raw_fb hack */ if (! raw_fb_back_to_X) { /* raw_fb hack */
if (xim->bitmap_unit != -1) { 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); XDestroyImage(xim);
} else { } else {
if (xim->data) { 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); free(xim->data);
xim->data = NULL; 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. * damage_delay seconds.
*/ */
int debug = 0; int debug = 0;
if (time(0) > damage_time + damage_delay) { if (time(NULL) > damage_time + damage_delay) {
if (! quiet) { if (! quiet) {
rfbLog("damaging turned off.\n"); 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) { static void nap_set(int tile_cnt) {
int nap_in = nap_ok; int nap_in = nap_ok;
time_t now = time(0); time_t now = time(NULL);
if (scan_count == 0) { if (scan_count == 0) {
/* roll up check for all NSCAN scans */ /* roll up check for all NSCAN scans */
@ -2219,7 +2219,7 @@ static void nap_check(int tile_cnt) {
return; return;
} }
now = time(0); now = time(NULL);
if (screen_blank > 0) { if (screen_blank > 0) {
int dt_ev, dt_fbu, ms = 2000; 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 void ping_clients(int tile_cnt) {
static time_t last_send = 0; static time_t last_send = 0;
time_t now = time(0); time_t now = time(NULL);
if (rfbMaxClientWait < 20000) { if (rfbMaxClientWait < 20000) {
rfbMaxClientWait = 20000; rfbMaxClientWait = 20000;

@ -752,7 +752,7 @@ void check_padded_fb(void) {
} }
if (unixpw_in_progress) return; 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(); remove_fake_fb();
} }
} }
@ -776,7 +776,7 @@ void install_padded_fb(char *geom) {
return; return;
} }
install_fake_fb(w, h, bpp); install_fake_fb(w, h, bpp);
pad_geometry_time = time(0); pad_geometry_time = time(NULL);
} }
static void initialize_snap_fb(void) { static void initialize_snap_fb(void) {
@ -885,7 +885,7 @@ if (db) fprintf(stderr, "initialize_raw_fb reset\n");
set_child_info(); set_child_info();
q += strlen("setup:"); q += strlen("setup:");
/* rawfb-setup */ /* rawfb-setup */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("rawfb-setup")) {
rfbLogEnable(1); rfbLogEnable(1);
rfbLog("cannot run external commands in -nocmds " rfbLog("cannot run external commands in -nocmds "
"mode:\n"); "mode:\n");
@ -1354,12 +1354,12 @@ static void initialize_clipshift(void) {
static int wait_until_mapped(Window win) { static int wait_until_mapped(Window win) {
int ms = 50, waittime = 30; int ms = 50, waittime = 30;
time_t start = time(0); time_t start = time(NULL);
XWindowAttributes attr; XWindowAttributes attr;
while (1) { while (1) {
if (! valid_window(win, NULL, 0)) { if (! valid_window(win, NULL, 0)) {
if (time(0) > start + waittime) { if (time(NULL) > start + waittime) {
break; break;
} }
usleep(ms * 1000); usleep(ms * 1000);
@ -1840,7 +1840,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
fb_depth = (int) fb->depth; fb_depth = (int) fb->depth;
rfbLog("initialize_screen: fb_depth/fb_bpp/fb_Bpl %d/%d/%d\n", 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; main_bytes_per_line = fb->bytes_per_line;

@ -54,7 +54,7 @@ static int dt_cmd(char *cmd) {
} }
/* dt */ /* dt */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("dt")) {
rfbLog("cannot run external commands in -nocmds mode:\n"); rfbLog("cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", cmd); rfbLog(" \"%s\"\n", cmd);
rfbLog(" dt_cmd: returning 1\n"); rfbLog(" dt_cmd: returning 1\n");
@ -522,7 +522,11 @@ static void solid_gnome(char *color) {
if (! orig_color) { if (! orig_color) {
char *q; 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') { if (*orig_color == '\0') {
orig_color = strdup("#FFFFFF"); orig_color = strdup("#FFFFFF");
} }
@ -532,7 +536,11 @@ static void solid_gnome(char *color) {
} }
if (! orig_option) { if (! orig_option) {
char *q; 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') { if (*orig_option == '\0') {
orig_option = strdup("stretched"); orig_option = strdup("stretched");
} }

@ -32,7 +32,7 @@ static pid_t stunnel_pid = 0;
void check_stunnel(void) { void check_stunnel(void) {
static time_t last_check = 0; static time_t last_check = 0;
time_t now = time(0); time_t now = time(NULL);
if (last_check + 3 >= now) { if (last_check + 3 >= now) {
return; return;
@ -72,13 +72,14 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
path = getenv("PATH"); path = getenv("PATH");
if (! path) { if (! path) {
path = strdup(extra); path = strdup(extra+1);
} else { } else {
char *pt = path;
path = (char *) malloc(strlen(path)+strlen(extra)+1); path = (char *) malloc(strlen(path)+strlen(extra)+1);
if (! path) { if (! path) {
return 0; return 0;
} }
strcpy(path, getenv("PATH")); strcpy(path, pt);
strcat(path, extra); strcat(path, extra);
} }
@ -106,15 +107,16 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
} }
if (! stunnel_path) { if (! stunnel_path) {
free(exe);
return 0; return 0;
} }
if (stunnel_path[0] == '\0') { if (stunnel_path[0] == '\0') {
free(stunnel_path); free(exe);
return 0; return 0;
} }
/* stunnel */ /* stunnel */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("stunnel")) {
rfbLogEnable(1); rfbLogEnable(1);
rfbLog("start_stunnel: cannot run external commands in -nocmds mode:\n"); rfbLog("start_stunnel: cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", stunnel_path); rfbLog(" \"%s\"\n", stunnel_path);
@ -140,7 +142,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
if (ssl_verify) { if (ssl_verify) {
if (stat(ssl_verify, &verify_buf) != 0) { if (stat(ssl_verify, &verify_buf) != 0) {
rfbLog("stunnel: %s does not exist.\n", ssl_verify); 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) { if (stunnel_pid < 0) {
stunnel_pid = 0; stunnel_pid = 0;
free(stunnel_path); free(exe);
return 0; return 0;
} }
@ -162,7 +164,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
} }
if (use_stunnel == 3) { if (use_stunnel == 3) {
char sp[20], xp[20], *a = NULL; char sp[30], xp[30], *a = NULL;
char *st = stunnel_path; char *st = stunnel_path;
char *pm = stunnel_pem; char *pm = stunnel_pem;
char *sv = ssl_verify; char *sv = ssl_verify;
@ -179,6 +181,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
} }
if (stunnel_pem && ssl_verify) { if (stunnel_pem && ssl_verify) {
/* XXX double check -v 2 */
execlp(st, st, "-f", "-d", sp, "-r", xp, "-P", execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
"none", "-p", pm, a, sv, "-v", "2", "none", "-p", pm, a, sv, "-v", "2",
(char *) NULL); (char *) NULL);
@ -212,6 +215,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
} else { } else {
fprintf(in, "CAfile = %s\n", ssl_verify); fprintf(in, "CAfile = %s\n", ssl_verify);
} }
/* XXX double check -v 2 */
fprintf(in, "verify = 2\n"); fprintf(in, "verify = 2\n");
} }
fprintf(in, ";debug = 7\n\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); execlp(stunnel_path, stunnel_path, "-fd", fd, (char *) NULL);
exit(1); exit(1);
} }
free(stunnel_path);
free(exe);
usleep(500 * 1000); usleep(500 * 1000);
waitpid(stunnel_pid, &status, WNOHANG); waitpid(stunnel_pid, &status, WNOHANG);
@ -263,9 +268,9 @@ void stop_stunnel(void) {
void setup_stunnel(int rport, int *argc, char **argv) { void setup_stunnel(int rport, int *argc, char **argv) {
int i, xport = 0; int i, xport = 0;
if (! rport) { if (! rport && argc && argv) {
for (i=0; i< *argc; i++) { for (i=0; i< *argc; i++) {
if (!strcmp(argv[i], "-rfbport")) { if (argv[i] && !strcmp(argv[i], "-rfbport")) {
if (i < *argc - 1) { if (i < *argc - 1) {
rport = atoi(argv[i+1]); rport = atoi(argv[i+1]);
break; break;
@ -281,18 +286,21 @@ void setup_stunnel(int rport, int *argc, char **argv) {
goto stunnel_fail; goto stunnel_fail;
} }
} }
xport = find_free_port(5950, 5999); xport = find_free_port(5950, 5999);
if (! xport) { if (! xport) {
goto stunnel_fail; goto stunnel_fail;
} }
if (start_stunnel(rport, xport)) { if (start_stunnel(rport, xport)) {
int tweaked = 0; int tweaked = 0;
char tmp[20]; char tmp[30];
sprintf(tmp, "%d", xport); sprintf(tmp, "%d", xport);
if (argv) { if (argc && argv) {
for (i=0; i< *argc; i++) { for (i=0; i < *argc; i++) {
if (!strcmp(argv[i], "-rfbport")) { if (argv[i] && !strcmp(argv[i], "-rfbport")) {
if (i < *argc - 1) { if (i < *argc - 1) {
/* replace orig value */
argv[i+i] = strdup(tmp); argv[i+i] = strdup(tmp);
tweaked = 1; tweaked = 1;
break; break;
@ -353,7 +361,7 @@ char *get_Cert_dir(char *cdir_in, char **tmp_in) {
sprintf(cdir, "%s%s", home, cases1[1]); 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++) { for (i=0; i<3; i++) {
int ret; int ret;
sprintf(tmp, "%s%s", cdir, cases2[i]); sprintf(tmp, "%s%s", cdir, cases2[i]);
@ -380,35 +388,36 @@ char *get_Cert_dir(char *cdir_in, char **tmp_in) {
return cdir; return cdir;
} }
void sslGenCA(char *cdir) { static char *getsslscript(char *cdir, char *name, char *script) {
char *openssl = find_openssl_bin(); char *openssl = find_openssl_bin();
char *tmp, *cmd, *scr, *cdir_use; char *tmp, *scr, *cdir_use;
FILE *out; FILE *out;
if (! openssl) { if (! openssl || openssl[0] == '\0') {
exit(1);
}
if (!name || !script) {
exit(1); exit(1);
} }
cdir_use = get_Cert_dir(cdir, &tmp); cdir_use = get_Cert_dir(cdir, &tmp);
if (! cdir_use) { if (!cdir_use || !tmp) {
exit(1); exit(1);
} }
cmd = (char *) malloc(strlen(tmp) + 100); scr = (char *) malloc(strlen(tmp) + 1 + strlen(name) + 30);
scr = (char *) malloc(strlen(tmp) + 100);
sprintf(cmd, "%s/genca.%d.sh", tmp, getpid()); sprintf(scr, "%s/%s.%d.sh", tmp, name, getpid());
out = fopen(cmd, "w"); out = fopen(scr, "w");
if (! out) { if (! out) {
rfbLog("could not open: %s\n", cmd); rfbLog("could not open: %s\n", scr);
rfbLogPerror("fopen"); rfbLogPerror("fopen");
exit(1); exit(1);
} }
fprintf(out, "%s", genCA); fprintf(out, "%s", script);
fclose(out); fclose(out);
sprintf(scr, "/bin/sh %s", cmd);
rfbLog("Using openssl: %s\n", openssl); rfbLog("Using openssl: %s\n", openssl);
rfbLog("Using certs dir: %s\n", cdir_use); rfbLog("Using certs dir: %s\n", cdir_use);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
@ -416,45 +425,36 @@ void sslGenCA(char *cdir) {
set_env("BASE_DIR", cdir_use); set_env("BASE_DIR", cdir_use);
set_env("OPENSSL", openssl); set_env("OPENSSL", openssl);
system(scr); return scr;
unlink(cmd);
} }
void sslGenCert(char *ty, char *nm) { void sslGenCA(char *cdir) {
char *openssl = find_openssl_bin(); char *cmd, *scr = getsslscript(cdir, "genca", genCA);
char *tmp, *cmd, *scr, *cdir_use;
FILE *out;
if (! openssl) { if (! scr) {
exit(1); exit(1);
} }
cdir_use = get_Cert_dir(NULL, &tmp); cmd = (char *)malloc(strlen("/bin/sh ") + strlen(scr) + 1);
if (! cdir_use) { sprintf(cmd, "/bin/sh %s", scr);
exit(1);
}
cmd = (char *) malloc(strlen(tmp) + 100); system(cmd);
scr = (char *) malloc(strlen(tmp) + 100); unlink(scr);
sprintf(cmd, "%s/gencert.%d.sh", tmp, getpid()); free(cmd);
out = fopen(cmd, "w"); free(scr);
if (! out) { }
rfbLog("could not open: %s\n", cmd);
rfbLogPerror("fopen"); void sslGenCert(char *ty, char *nm) {
char *cmd, *scr = getsslscript(NULL, "gencert", genCert);
if (! scr) {
exit(1); exit(1);
} }
fprintf(out, "%s", genCert);
fclose(out);
sprintf(scr, "/bin/sh %s", cmd);
rfbLog("Using openssl: %s\n", openssl); cmd = (char *)malloc(strlen("/bin/sh ") + strlen(scr) + 1);
rfbLog("Using certs dir: %s\n", cdir_use); sprintf(cmd, "/bin/sh %s", scr);
fprintf(stderr, "\n");
set_env("BASE_DIR", cdir_use);
set_env("OPENSSL", openssl);
if (! ty) { if (! ty) {
set_env("TYPE", ""); set_env("TYPE", "");
} else { } else {
@ -474,17 +474,18 @@ void sslGenCert(char *ty, char *nm) {
} }
} }
system(scr); system(cmd);
unlink(cmd); unlink(scr);
free(cmd);
free(scr);
} }
void sslEncKey(char *path, int mode) { void sslEncKey(char *path, int mode) {
char *openssl = find_openssl_bin(); 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 line[1024], tmp[] = "/tmp/x11vnc-tmp.XXXXXX";
char *cdir = NULL; int tmp_fd, incert, info_only = 0, delete_only = 0, listlong = 0;
int tmp_fd, incert, info_only = 0, delete_only = 0;
int listlong = 0;
struct stat sbuf; struct stat sbuf;
FILE *file; FILE *file;
static int depth = 0; static int depth = 0;
@ -493,6 +494,11 @@ void sslEncKey(char *path, int mode) {
/* get_saved_pem may call us back. */ /* get_saved_pem may call us back. */
return; return;
} }
if (! path) {
return;
}
depth++; depth++;
if (mode == 1) { if (mode == 1) {
@ -504,8 +510,9 @@ void sslEncKey(char *path, int mode) {
if (! openssl) { if (! openssl) {
exit(1); exit(1);
} }
cdir = get_Cert_dir(NULL, &tca); cdir = get_Cert_dir(NULL, &tca);
if (! cdir) { if (! cdir || ! tca) {
fprintf(stderr, "could not find Cert dir\n"); fprintf(stderr, "could not find Cert dir\n");
exit(1); exit(1);
} }
@ -518,28 +525,38 @@ void sslEncKey(char *path, int mode) {
if (strstr(path, "SAVE") == path) { if (strstr(path, "SAVE") == path) {
char *p = get_saved_pem(path, 0); char *p = get_saved_pem(path, 0);
if (p == NULL) { 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); exit(1);
} }
path = p; path = p;
} else if (!strcmp(path, "CA") && cdir) { } else if (!strcmp(path, "CA")) {
tca = (char *) malloc(strlen(cdir) + strlen("/CA/cacert.pem") + 1); tca = (char *) malloc(strlen(cdir)+strlen("/CA/cacert.pem")+1);
sprintf(tca, "%s/CA/cacert.pem", cdir); sprintf(tca, "%s/CA/cacert.pem", cdir);
path = tca; path = tca;
} else if (info_only && (!strcasecmp(path, "LIST") || !strcasecmp(path, "LS") || } else if (info_only && (!strcasecmp(path, "LIST") ||
!strcasecmp(path, "ALL"))) { !strcasecmp(path, "LS") || !strcasecmp(path, "ALL"))) {
if (! cdir || strchr(cdir, '\'')) {
fprintf(stderr, "bad certdir char: %s\n", cdir ? cdir : "null"); 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); exit(1);
} }
tca = (char *) malloc(2*strlen(cdir) + strlen(program_name) + 1000);
sprintf(tca, "find '%s' | egrep '/(CA|tmp|clients)$|\\.(crt|pem|key|req)$' " tca = (char *) malloc(2*strlen(cdir)+strlen(program_name)+1000);
"| grep -v CA/newcerts", cdir);
sprintf(tca, "find '%s' | egrep '/(CA|tmp|clients)$|"
"\\.(crt|pem|key|req)$' | grep -v CA/newcerts", cdir);
if (!strcasecmp(path, "ALL")) { if (!strcasecmp(path, "ALL")) {
/* ugh.. */ /* 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, program_name);
strcat(tca, " -ssldir '"); strcat(tca, " -ssldir '");
strcat(tca, cdir); strcat(tca, cdir);
@ -548,6 +565,8 @@ void sslEncKey(char *path, int mode) {
strcat(tca, " | xargs ls -ld "); strcat(tca, " | xargs ls -ld ");
} }
system(tca); system(tca);
free(tca);
depth--; depth--;
return; return;
@ -562,7 +581,7 @@ void sslEncKey(char *path, int mode) {
write(tmp_fd, genCert, strlen(genCert)); write(tmp_fd, genCert, strlen(genCert));
close(tmp_fd); close(tmp_fd);
scr = (char *) malloc(strlen(tmp) + 100); scr = (char *) malloc(strlen("/bin/sh ") + strlen(tmp) + 1);
sprintf(scr, "/bin/sh %s", tmp); sprintf(scr, "/bin/sh %s", tmp);
set_env("BASE_DIR", cdir); set_env("BASE_DIR", cdir);
@ -575,57 +594,59 @@ void sslEncKey(char *path, int mode) {
} }
system(scr); system(scr);
unlink(tmp); unlink(tmp);
free(scr);
depth--; depth--;
return; return;
} }
if (stat(path, &sbuf) != 0) { if (stat(path, &sbuf) != 0) {
if (strstr(path, "client") || strchr(path, '/') == NULL) { if (strstr(path, "client") || strchr(path, '/') == NULL) {
int i; int i;
tca = (char *) malloc(strlen(cdir) + strlen("/clients") tca = (char *) malloc(strlen(cdir) + strlen(path) + 100);
+ strlen(path) + 100); for (i = 1; i <= 15; i++) {
for (i = 1; i <= 15; i++) { tca[0] = '\0';
tca[0] = '\0'; if ( i == 1) {
if ( i == 1) { sprintf(tca, "%s/%s", cdir, path);
sprintf(tca, "%s/%s", cdir, path); } else if (i == 2 && mode > 0) {
} else if (i == 2 && mode > 0) { sprintf(tca, "%s/%s.crt", cdir, path);
sprintf(tca, "%s/%s.crt", cdir, path); } else if (i == 3) {
} else if (i == 3) { sprintf(tca, "%s/%s.pem", cdir, path);
sprintf(tca, "%s/%s.pem", cdir, path); } else if (i == 4 && mode > 1) {
} else if (i == 4 && mode > 1) { sprintf(tca, "%s/%s.req", cdir, path);
sprintf(tca, "%s/%s.req", cdir, path); } else if (i == 5 && mode > 1) {
} else if (i == 5 && mode > 1) { sprintf(tca, "%s/%s.key", cdir, path);
sprintf(tca, "%s/%s.key", cdir, path); } else if (i == 6) {
} else if (i == 6) { sprintf(tca, "%s/clients/%s", cdir, path);
sprintf(tca, "%s/clients/%s", cdir, path); } else if (i == 7 && mode > 0) {
} else if (i == 7 && mode > 0) { sprintf(tca, "%s/clients/%s.crt", cdir, path);
sprintf(tca, "%s/clients/%s.crt", cdir, path); } else if (i == 8) {
} else if (i == 8) { sprintf(tca, "%s/clients/%s.pem", cdir, path);
sprintf(tca, "%s/clients/%s.pem", cdir, path); } else if (i == 9 && mode > 1) {
} else if (i == 9 && mode > 1) { sprintf(tca, "%s/clients/%s.req", cdir, path);
sprintf(tca, "%s/clients/%s.req", cdir, path); } else if (i == 10 && mode > 1) {
} else if (i == 10 && mode > 1) { sprintf(tca, "%s/clients/%s.key", cdir, path);
sprintf(tca, "%s/clients/%s.key", cdir, path); } else if (i == 11) {
} else if (i == 11) { sprintf(tca, "%s/server-%s", cdir, path);
sprintf(tca, "%s/server-%s", cdir, path); } else if (i == 12 && mode > 0) {
} else if (i == 12 && mode > 0) { sprintf(tca, "%s/server-%s.crt", cdir, path);
sprintf(tca, "%s/server-%s.crt", cdir, path); } else if (i == 13) {
} else if (i == 13) { sprintf(tca, "%s/server-%s.pem", cdir, path);
sprintf(tca, "%s/server-%s.pem", cdir, path); } else if (i == 14 && mode > 1) {
} else if (i == 14 && mode > 1) { sprintf(tca, "%s/server-%s.req", cdir, path);
sprintf(tca, "%s/server-%s.req", cdir, path); } else if (i == 15 && mode > 1) {
} else if (i == 15 && mode > 1) { sprintf(tca, "%s/server-%s.key", cdir, path);
sprintf(tca, "%s/server-%s.key", cdir, path); }
} if (tca[0] == '\0') {
if (tca[0] == '\0') { continue;
continue; }
} if (stat(tca, &sbuf) == 0) {
if (stat(tca, &sbuf) == 0) { path = tca;
path = tca; break;
break;
}
} }
} }
}
} }
if (stat(path, &sbuf) != 0) { if (stat(path, &sbuf) != 0) {
@ -635,7 +656,7 @@ void sslEncKey(char *path, int mode) {
} }
if (! info_only) { if (! info_only) {
cert = (char *) malloc(2*(sbuf.st_size + 100)); cert = (char *) malloc(2*(sbuf.st_size + 1024));
file = fopen(path, "r"); file = fopen(path, "r");
if (file == NULL) { if (file == NULL) {
rfbLog("sslEncKey: %s\n", path); rfbLog("sslEncKey: %s\n", path);
@ -645,15 +666,17 @@ void sslEncKey(char *path, int mode) {
incert = 0; incert = 0;
cert[0] = '\0'; cert[0] = '\0';
while (fgets(line, 1024, file) != NULL) { while (fgets(line, 1024, file) != NULL) {
if (strstr(line, "-----BEGIN CERTIFICATE-----") == line) { if (strstr(line, "-----BEGIN CERTIFICATE-----")
== line) {
incert = 1; incert = 1;
} }
if (incert) { if (incert) {
if (strlen(cert) + strlen(line) < 2*sbuf.st_size) { if (strlen(cert)+strlen(line) < 2*sbuf.st_size) {
strcat(cert, line); strcat(cert, line);
} }
} }
if (strstr(line, "-----END CERTIFICATE-----") == line) { if (strstr(line, "-----END CERTIFICATE-----")
== line) {
incert = 0; incert = 0;
} }
} }
@ -668,7 +691,7 @@ void sslEncKey(char *path, int mode) {
write(tmp_fd, genCert, strlen(genCert)); write(tmp_fd, genCert, strlen(genCert));
close(tmp_fd); close(tmp_fd);
scr = (char *) malloc(strlen(tmp) + 100); scr = (char *) malloc(strlen("/bin/sh ") + strlen(tmp) + 1);
sprintf(scr, "/bin/sh %s", tmp); sprintf(scr, "/bin/sh %s", tmp);
set_env("BASE_DIR", "/no/such/dir"); set_env("BASE_DIR", "/no/such/dir");
@ -691,7 +714,7 @@ void sslEncKey(char *path, int mode) {
rfbLogPerror("fopen"); rfbLogPerror("fopen");
exit(1); exit(1);
} }
fprintf(file, cert); fprintf(file, "%s", cert);
fclose(file); fclose(file);
free(cert); free(cert);
} }

@ -92,9 +92,9 @@ int openssl_present(void) {return 1;}
static void sslerrexit(void) { static void sslerrexit(void) {
unsigned long err = ERR_get_error(); unsigned long err = ERR_get_error();
char str[256];
if (err) { if (err) {
char str[256];
ERR_error_string(err, str); ERR_error_string(err, str);
fprintf(stderr, "ssl error: %s\n", str); fprintf(stderr, "ssl error: %s\n", str);
} }
@ -106,6 +106,11 @@ char *get_saved_pem(char *save, int create) {
int prompt = 0, len; int prompt = 0, len;
struct stat sbuf; struct stat sbuf;
if (! save) {
rfbLog("get_saved_pem: save string is null.\n");
clean_up_exit(1);
}
if (strstr(save, "SAVE_PROMPT") == save) { if (strstr(save, "SAVE_PROMPT") == save) {
prompt = 1; prompt = 1;
s = save + strlen("SAVE_PROMPT"); s = save + strlen("SAVE_PROMPT");
@ -121,11 +126,13 @@ char *get_saved_pem(char *save, int create) {
} }
cdir = get_Cert_dir(NULL, &tmp); cdir = get_Cert_dir(NULL, &tmp);
if (! cdir) { if (! cdir || ! tmp) {
rfbLog("get_saved_pem: could not find Cert dir.\n"); rfbLog("get_saved_pem: could not find Cert dir.\n");
clean_up_exit(1); clean_up_exit(1);
} }
len = strlen(cdir) + strlen("/server.pem") + strlen(s) + 1; len = strlen(cdir) + strlen("/server.pem") + strlen(s) + 1;
path = (char *) malloc(len); path = (char *) malloc(len);
sprintf(path, "%s/server%s.pem", cdir, s); 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) { static char *get_input(char *tag, char **in) {
char line[1024], *str; char line[1024], *str;
if (! tag || ! in || ! *in) {
return NULL;
}
fprintf(stderr, "%s:\n [%s] ", tag, *in); fprintf(stderr, "%s:\n [%s] ", tag, *in);
if (fgets(line, 1024, stdin) == NULL) { if (fgets(line, 1024, stdin) == NULL) {
rfbLog("could not read stdin!\n"); rfbLog("could not read stdin!\n");
@ -155,26 +167,28 @@ static char *get_input(char *tag, char **in) {
*str = '\0'; *str = '\0';
} }
str = lblanks(line); str = lblanks(line);
if (! strcmp(str, "")) { if (!strcmp(str, "")) {
return *in; return *in;
} else { } else {
free(*in);
return strdup(line); return strdup(line);
} }
} }
char *find_openssl_bin(void) { char *find_openssl_bin(void) {
char *path, *exe, *p; char *path, *exe, *p, *gp;
struct stat sbuf; struct stat sbuf;
int found_openssl = 0; 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"); fprintf(stderr, "could not find openssl(1) program in PATH.\n");
return NULL; 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); strcat(path, extra);
/* find openssl binary: */ /* find openssl binary: */
@ -233,31 +247,36 @@ static char *create_tmp_pem(char *pathin, int prompt) {
; ;
C = strdup("AU"); C = strdup("AU");
L = strdup(UT.sysname); L = strdup(UT.sysname ? UT.sysname : "unknown-os");
snprintf(line, 1024, "%s-%f", UT.nodename, dnow()); snprintf(line, 1024, "%s-%f", UT.nodename ? UT.nodename :
"unknown-node", dnow());
line[1024-1] = '\0'; line[1024-1] = '\0';
OU = strdup(line); OU = strdup(line);
O = strdup("x11vnc"); O = strdup("x11vnc");
if (pathin) { if (pathin) {
snprintf(line, 1024, "x11vnc-SELF-SIGNED-CERT-%d", getpid()); snprintf(line, 1024, "x11vnc-SELF-SIGNED-CERT-%d", getpid());
} else { } 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'; line[1024-1] = '\0';
CN = strdup(line); CN = strdup(line);
EM = strdup("x11vnc@server.nowhere"); EM = strdup("x11vnc@server.nowhere");
/* ssl */ /* ssl */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("ssl")) {
rfbLog("create_tmp_pem: cannot run external commands.\n"); rfbLog("create_tmp_pem: cannot run external commands.\n");
return NULL; return NULL;
} }
rfbLog("\n"); rfbLog("\n");
if (pathin) { if (pathin) {
rfbLog("Creating a self-signed PEM certificate...\n"); rfbLog("Creating a self-signed PEM certificate...\n");
} else { } else {
rfbLog("Creating a temporary, self-signed PEM certificate...\n"); rfbLog("Creating a temporary, self-signed PEM certificate...\n");
} }
rfbLog("\n"); rfbLog("\n");
rfbLog("This will NOT prevent man-in-the-middle attacks UNLESS you\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"); 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("server certificate.\n");
rfbLog("\n"); rfbLog("\n");
exe = find_openssl_bin(); exe = find_openssl_bin();
if (exe == NULL) { if (! exe) {
return NULL; return NULL;
} }
@ -401,14 +419,15 @@ static char *create_tmp_pem(char *pathin, int prompt) {
rfbLogPerror("fopen"); rfbLogPerror("fopen");
return NULL; return NULL;
} }
out = fopen(pathin, "w"); out = fopen(pathin, "w");
chmod(pathin, 0600);
if (out == NULL) { if (out == NULL) {
rfbLog("could not open: %s\n", pathin); rfbLog("could not open: %s\n", pathin);
rfbLogPerror("fopen"); rfbLogPerror("fopen");
fclose(crt); fclose(crt);
return NULL; return NULL;
} }
chmod(pathin, 0600);
in = fopen(pem, "r"); in = fopen(pem, "r");
if (in == NULL) { if (in == NULL) {
@ -461,6 +480,10 @@ static int pem_passwd_callback(char *buf, int size, int rwflag,
void *userdata) { void *userdata) {
char *q, line[1024]; char *q, line[1024];
if (! buf) {
exit(1);
}
fprintf(stderr, "\nA passphrase is needed to unlock an OpenSSL " fprintf(stderr, "\nA passphrase is needed to unlock an OpenSSL "
"private key (PEM file).\n"); "private key (PEM file).\n");
fprintf(stderr, "Enter passphrase> "); 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) { static int appendfile(FILE *out, char *infile) {
char line[1024]; 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) { if (in == NULL) {
rfbLog("appendfile: %s\n", infile); rfbLog("appendfile: %s\n", infile);
@ -520,11 +554,8 @@ static char *get_ssl_verify_file(char *str_in) {
return str_in; return str_in;
} }
str = strdup(str_in);
p = strtok(str, ",");
cdir = get_Cert_dir(NULL, &tmp); cdir = get_Cert_dir(NULL, &tmp);
if (! cdir) { if (! cdir || ! tmp) {
rfbLog("get_ssl_verify_file: invalid cert-dir.\n"); rfbLog("get_ssl_verify_file: invalid cert-dir.\n");
exit(1); exit(1);
} }
@ -535,12 +566,15 @@ static char *get_ssl_verify_file(char *str_in) {
sprintf(tfile, "%s/sslverify-load-%d.crts", tmp, getpid()); sprintf(tfile, "%s/sslverify-load-%d.crts", tmp, getpid());
file = fopen(tfile, "w"); file = fopen(tfile, "w");
chmod(tfile, 0600);
if (file == NULL) { if (file == NULL) {
rfbLog("get_ssl_verify_file: %s\n", tfile); rfbLog("get_ssl_verify_file: %s\n", tfile);
rfbLogPerror("fopen"); rfbLogPerror("fopen");
exit(1); exit(1);
} }
chmod(tfile, 0600);
str = strdup(str_in);
p = strtok(str, ",");
while (p) { while (p) {
if (!strcmp(p, "CA")) { if (!strcmp(p, "CA")) {
@ -551,9 +585,11 @@ static char *get_ssl_verify_file(char *str_in) {
} }
fprintf(stderr, "sslverify: loaded %s\n", tfile2); fprintf(stderr, "sslverify: loaded %s\n", tfile2);
count++; count++;
} else if (!strcmp(p, "clients")) { } else if (!strcmp(p, "clients")) {
DIR *dir; DIR *dir;
struct dirent *dp; struct dirent *dp;
sprintf(tfile2, "%s/clients", cdir); sprintf(tfile2, "%s/clients", cdir);
dir = opendir(tfile2); dir = opendir(tfile2);
if (! dir) { if (! dir) {
@ -565,15 +601,21 @@ static char *get_ssl_verify_file(char *str_in) {
while ( (dp = readdir(dir)) != NULL) { while ( (dp = readdir(dir)) != NULL) {
char *n = dp->d_name; char *n = dp->d_name;
char *q = strstr(n, ".crt"); char *q = strstr(n, ".crt");
if (! q || strlen(q) != strlen(".crt")) { if (! q || strlen(q) != strlen(".crt")) {
continue; continue;
} }
if (strlen(n) > 512) {
continue;
}
sprintf(tfile2, "%s/clients/%s", cdir, n); sprintf(tfile2, "%s/clients/%s", cdir, n);
if (! appendfile(file, tfile2)) { if (! appendfile(file, tfile2)) {
unlink(tfile); unlink(tfile);
exit(1); exit(1);
} }
fprintf(stderr, "sslverify: loaded %s\n", tfile2); fprintf(stderr, "sslverify: loaded %s\n",
tfile2);
count++; count++;
} }
closedir(dir); closedir(dir);
@ -599,7 +641,10 @@ static char *get_ssl_verify_file(char *str_in) {
fclose(file); fclose(file);
free(tfile2); free(tfile2);
free(str); 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; return tfile;
} }
@ -676,6 +721,7 @@ void openssl_init(void) {
clean_up_exit(1); clean_up_exit(1);
} }
tmp_pem = 1; tmp_pem = 1;
} else if (strstr(openssl_pem, "SAVE") == openssl_pem) { } else if (strstr(openssl_pem, "SAVE") == openssl_pem) {
openssl_pem = get_saved_pem(openssl_pem, 1); openssl_pem = get_saved_pem(openssl_pem, 1);
if (! openssl_pem) { if (! openssl_pem) {
@ -747,16 +793,19 @@ void openssl_init(void) {
} }
unlink(openssl_pem); unlink(openssl_pem);
free(openssl_pem); free(openssl_pem);
openssl_pem = NULL;
} }
if (ssl_verify) { if (ssl_verify) {
struct stat sbuf; struct stat sbuf;
char *file; char *file;
int lvl; int lvl;
file = get_ssl_verify_file(ssl_verify); 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", rfbLog("openssl_init: -sslverify does not exists %s.\n",
file); file ? file : "null");
rfbLogPerror("stat"); rfbLogPerror("stat");
clean_up_exit(1); clean_up_exit(1);
} }
@ -773,6 +822,7 @@ void openssl_init(void) {
sslerrexit(); sslerrexit();
} }
} }
lvl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER; lvl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER;
SSL_CTX_set_verify(ctx, lvl, NULL); SSL_CTX_set_verify(ctx, lvl, NULL);
if (strstr(file, "tmp/sslverify-load-")) { if (strstr(file, "tmp/sslverify-load-")) {
@ -860,7 +910,9 @@ void https_port(void) {
rfbLog("https_port: could not open port %d\n", port); rfbLog("https_port: could not open port %d\n", port);
clean_up_exit(1); 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; 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, static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
int mode) { int mode) {
int nfd, db = 0; 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 * increase the timeout if we know HTTP traffic has occurred
* recently: * recently:
*/ */
if (time(0) < last_https + 30) { if (time(NULL) < last_https + 30) {
tv.tv_sec = 8; tv.tv_sec = 8;
if (strstr(last_get, "VncViewer")) { if (strstr(last_get, "VncViewer")) {
tv.tv_sec = 4; 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")); db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
} }
buf = (char *) calloc(sizeof(ABSIZE+1), 1); buf = (char *) calloc((ABSIZE+1), 1);
*n_a = 0; *n_a = 0;
n = SSL_read(ssl, buf, 2); n = SSL_read(ssl, buf, 2);
@ -1614,7 +1667,7 @@ if (db) fprintf(stderr, "iface: %s\n", iface);
int i; int i;
rfbLog("SSL: but https for helper process succeeded.\n"); rfbLog("SSL: but https for helper process succeeded.\n");
if (mode != OPENSSL_HTTPS) { if (mode != OPENSSL_HTTPS) {
last_https = time(0); last_https = time(NULL);
for (i=0; i<128; i++) { for (i=0; i<128; i++) {
last_get[i] = '\0'; 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"); if (db) fprintf(stderr, "ssl_xfer begin\n");
start = time(0); start = time(NULL);
if (is_https) { if (is_https) {
tv_use = tv_https_early; tv_use = tv_https_early;
} else { } 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; tv_cutover = 0;
if (is_https) { if (is_https) {
tv_use = tv_https_later; tv_use = tv_https_later;
@ -2176,8 +2229,8 @@ void check_openssl(void) {
} }
last_check = now; last_check = now;
if (time(0) > last_waitall + 150) { if (time(NULL) > last_waitall + 150) {
last_waitall = time(0); last_waitall = time(NULL);
ssl_helper_pid(0, -2); /* waitall */ ssl_helper_pid(0, -2); /* waitall */
} }

@ -13,6 +13,8 @@ extern int openssl_port_num;
extern int https_sock; extern int https_sock;
extern pid_t openssl_last_helper_pid; 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 int openssl_present(void);
extern void openssl_init(void); extern void openssl_init(void);
extern void openssl_port(void); extern void openssl_port(void);

@ -697,9 +697,14 @@ char find_display[] =
"if [ \"X$1\" = \"X-n\" ]; then\n" "if [ \"X$1\" = \"X-n\" ]; then\n"
" showxauth=\"\"\n" " showxauth=\"\"\n"
" shift\n" " shift\n"
"elif [ \"X$1\" = \"X-f\" ]; then\n" "fi\n"
"if [ \"X$1\" = \"X-f\" ]; then\n"
" shift\n" " shift\n"
" showxauth=\"$1\"\n" " if [ ! -r $1 ]; then\n"
" echo \"\"\n"
" exit 1\n"
" fi\n"
" export XAUTHORITY=\"$1\"\n"
" shift\n" " shift\n"
"fi\n" "fi\n"
"\n" "\n"
@ -724,24 +729,46 @@ char find_display[] =
"# Now try to match X DISPLAY to user:\n" "# Now try to match X DISPLAY to user:\n"
"\n" "\n"
"# who(1) output column 2:\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" "\n"
"if [ \"X$display\" = \"X\" ]; then\n" "if [ \"X$display\" = \"X\" ]; then\n"
" # who(1) output, last column:\n" " # who(1) output, last column:\n"
" display=`who | grep \"^${user}[ ]\" | awk '{print $NF}' | grep '(:[0-9]' | sed -e 's/[()]//g' | head -1`\n" " display=`who | grep \"^${user}[ ]\" | awk '{print $NF}' \\\n"
" if [ \"X$display\" = \"X\" ]; then\n" " | grep '(:[0-9]' | sed -e 's/[()]//g' | head -1`\n"
" echo \"\" # failure\n" " if [ \"X$display\" = \"X\" ]; then\n"
" exit 1\n" " if [ \"X$X11VNC_FINDDISPLAY_SKIP_XAUTH\" != \"X\" ]; then\n"
" fi\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" "fi\n"
"\n" "\n"
"echo \"DISPLAY=$display\"\n" "echo \"DISPLAY=$display\"\n"
"if [ \"X$showxauth\" != \"X\" ]; then\n" "if [ \"X$showxauth\" != \"X\" ]; then\n"
" if [ \"X$showxauth\" = \"X1\" ]; then\n" " xauth extract - \"$display\" 2>/dev/null\n"
" xauth extract - \"$display\" 2>/dev/null\n"
" else\n"
" xauth -f \"$showxauth\" extract - \"$display\" 2>/dev/null\n"
" fi\n"
"fi\n" "fi\n"
"\n" "\n"
"exit 0\n" "exit 0\n"

@ -310,6 +310,8 @@ Permissions
=0S dontdisconnect =0S dontdisconnect
=SQA deny_all =SQA deny_all
timeout: timeout:
grabkbd
grabptr
=GAL LOFF =GAL LOFF
Tuning Tuning

@ -321,6 +321,8 @@ char gui_code[] = "";
" =0S dontdisconnect\n" " =0S dontdisconnect\n"
" =SQA deny_all\n" " =SQA deny_all\n"
" timeout:\n" " timeout:\n"
" grabkbd\n"
" grabptr\n"
" =GAL LOFF\n" " =GAL LOFF\n"
"\n" "\n"
"Tuning\n" "Tuning\n"

@ -70,6 +70,7 @@ rfbClientPtr unixpw_client = NULL;
int keep_unixpw = 0; int keep_unixpw = 0;
char *keep_unixpw_user = NULL; char *keep_unixpw_user = NULL;
char *keep_unixpw_pass = NULL; char *keep_unixpw_pass = NULL;
char *keep_unixpw_opts = NULL;
static int in_login = 0, in_passwd = 0, tries = 0; static int in_login = 0, in_passwd = 0, tries = 0;
static int char_row = 0, char_col = 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 */ /* unixpw */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("unixpw")) {
rfbLog("su_verify: cannot run external commands.\n"); rfbLog("su_verify: cannot run external commands.\n");
clean_up_exit(1); clean_up_exit(1);
} }
@ -789,50 +790,54 @@ static void unixpw_verify(char *user, char *pass) {
int x, y; int x, y;
char li[] = "Login incorrect"; char li[] = "Login incorrect";
char log[] = "login: "; char log[] = "login: ";
char *colon = NULL;
if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "********"); if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "********");
rfbLog("unixpw_verify: %s\n", user); rfbLog("unixpw_verify: %s\n", user);
colon = strchr(user, ':');
if (colon) {
*colon = '\0';
rfbLog("unixpw_verify: colon: %s\n", user);
}
if (unixpw_nis) { if (unixpw_nis) {
if (crypt_verify(user, pass)) { if (crypt_verify(user, pass)) {
unixpw_accept(user); unixpw_accept(user);
if (keep_unixpw) { if (keep_unixpw) {
keep_unixpw_user = strdup(user); keep_unixpw_user = strdup(user);
keep_unixpw_pass = strdup(pass); keep_unixpw_pass = strdup(pass);
if (colon) {
keep_unixpw_opts = strdup(colon+1);
} else {
keep_unixpw_opts = strdup("");
}
} }
if (colon) *colon = ':';
return; return;
} else { } else {
rfbLog("unixpw_verify: crypt_verify login for %s failed.\n", user); rfbLog("unixpw_verify: crypt_verify login for %s failed.\n", user);
usleep(3000*1000); 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 { } else {
if (su_verify(user, pass, NULL, NULL, NULL)) { if (su_verify(user, pass, NULL, NULL, NULL)) {
unixpw_accept(user); unixpw_accept(user);
if (keep_unixpw) { if (keep_unixpw) {
keep_unixpw_user = strdup(user); keep_unixpw_user = strdup(user);
keep_unixpw_pass = strdup(pass); keep_unixpw_pass = strdup(pass);
if (colon) {
keep_unixpw_opts = strdup(colon+1);
} else {
keep_unixpw_opts = strdup("");
}
} }
if (colon) *colon = ':';
return; return;
} }
rfbLog("unixpw_verify: su_verify login for %s failed.\n", user); rfbLog("unixpw_verify: su_verify login for %s failed.\n", user);
} }
if (colon) *colon = ':';
if (tries < 2) { if (tries < 2) {
char_row++; 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); 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); unixpw_keystroke(0, 0, 2);
tries++; tries++;
} else { } else {
@ -902,6 +907,10 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
free(keep_unixpw_pass); free(keep_unixpw_pass);
keep_unixpw_pass = NULL; keep_unixpw_pass = NULL;
} }
if (keep_unixpw_opts) {
free(keep_unixpw_opts);
keep_unixpw_opts = NULL;
}
return; return;
} }
@ -988,7 +997,12 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
return; return;
} }
#if 0
user[u_cnt++] = keystr[0]; user[u_cnt++] = keystr[0];
#else
user[u_cnt++] = (char) keysym;
keystr[0] = (char) keysym;
#endif
x = text_x(); x = text_x();
y = text_y(); y = text_y();

@ -18,5 +18,6 @@ extern rfbClientPtr unixpw_client;
extern int keep_unixpw; extern int keep_unixpw;
extern char *keep_unixpw_user; extern char *keep_unixpw_user;
extern char *keep_unixpw_pass; extern char *keep_unixpw_pass;
extern char *keep_unixpw_opts;
#endif /* _X11VNC_UNIXPW_H */ #endif /* _X11VNC_UNIXPW_H */

@ -46,7 +46,7 @@ void check_switched_user(void) {
static int did_solid = 0; static int did_solid = 0;
static int did_dummy = 0; static int did_dummy = 0;
int delay = 15; int delay = 15;
time_t now = time(0); time_t now = time(NULL);
if (unixpw_in_progress) return; 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 void try_to_switch_users(void) {
static time_t last_try = 0; static time_t last_try = 0;
time_t now = time(0); time_t now = time(NULL);
char *users, *p; char *users, *p;
if (getuid() && geteuid()) { if (getuid() && geteuid()) {
@ -934,7 +934,7 @@ void check_new_passwds(void) {
} }
if (unixpw_in_progress) return; if (unixpw_in_progress) return;
now = time(0); now = time(NULL);
if (now > last_check + 1) { if (now > last_check + 1) {
if (read_passwds(passwdfile)) { if (read_passwds(passwdfile)) {
install_passwds(); 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[]; extern char find_display[];
static XImage ximage_struct;
int wait_for_client(int *argc, char** argv, int http) { int wait_for_client(int *argc, char** argv, int http) {
static XImage ximage_struct;
XImage* fb_image; XImage* fb_image;
int w = 640, h = 480, b = 32; int w = 640, h = 480, b = 32;
int w0, h0, i; int w0, h0, i, chg_raw_fb = 0;
int chg_raw_fb = 0; char *str, *q, *p, *cmd = NULL;
char *str, *q, *p;
char *cmd = NULL;
int db = 0; int db = 0;
char tmp[] = "/tmp/x11vnc-find_display.XXXXXX"; char tmp[] = "/tmp/x11vnc-find_display.XXXXXX";
int tmp_fd = -1, dt = 0; int tmp_fd = -1, dt = 0;
@ -1047,11 +1137,11 @@ int wait_for_client(int *argc, char** argv, int http) {
return 0; return 0;
} }
for (i=0; i< *argc; i++) { for (i=0; i < *argc; i++) {
if (!strcmp(argv[i], "-desktop")) { if (!strcmp(argv[i], "-desktop")) {
dt = 1; 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); 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 (db) fprintf(stderr, "str: %s\n", str);
if (strstr(str, "cmd=") == 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:" rfbLog("wait_for_client external cmds not allowed:"
" %s\n", use_dpy); " %s\n", use_dpy);
clean_up_exit(1); clean_up_exit(1);
@ -1127,7 +1217,7 @@ int wait_for_client(int *argc, char** argv, int http) {
if (! dt) { if (! dt) {
char *s; char *s;
argv[*argc] = strdup("-desktop"); argv[*argc] = strdup("-desktop");
(*argc)++; *argc = (*argc) + 1;
if (cmd) { if (cmd) {
char *q; char *q;
@ -1141,18 +1231,27 @@ int wait_for_client(int *argc, char** argv, int http) {
} }
rfb_desktop_name = strdup(s); rfb_desktop_name = strdup(s);
argv[*argc] = s; argv[*argc] = s;
(*argc)++; *argc = (*argc) + 1;
} }
initialize_allowed_input(); initialize_allowed_input();
if (! multiple_cursors_mode) {
multiple_cursors_mode = strdup("default");
}
initialize_cursors_mode(); initialize_cursors_mode();
initialize_screen(argc, argv, fb_image); initialize_screen(argc, argv, fb_image);
initialize_signals(); 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(); handle_one_http_request();
clean_up_exit(0); clean_up_exit(0);
} }
@ -1161,12 +1260,6 @@ int wait_for_client(int *argc, char** argv, int http) {
http_connections(1); 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) { if (cmd && unixpw) {
keep_unixpw = 1; keep_unixpw = 1;
} }
@ -1176,12 +1269,15 @@ int wait_for_client(int *argc, char** argv, int http) {
} }
while (1) { while (1) {
if (! use_threads) { if (shut_down) {
rfbPE(-1); clean_up_exit(0);
} }
if (use_openssl) { if (use_openssl) {
check_openssl(); check_openssl();
} }
if (! use_threads) {
rfbPE(-1);
}
if (! screen || ! screen->clientHead) { if (! screen || ! screen->clientHead) {
usleep(100 * 1000); usleep(100 * 1000);
continue; continue;
@ -1196,6 +1292,9 @@ int wait_for_client(int *argc, char** argv, int http) {
clean_up_exit(1); clean_up_exit(1);
} }
while (1) { while (1) {
if (shut_down) {
clean_up_exit(0);
}
if (! use_threads) { if (! use_threads) {
rfbPE(-1); rfbPE(-1);
} }
@ -1238,7 +1337,6 @@ int wait_for_client(int *argc, char** argv, int http) {
char line[18000]; char line[18000];
memset(line, 0, 18000); memset(line, 0, 18000);
if (0) unixpw_msg("Looking up DISPLAY", 0);
if (keep_unixpw_user && keep_unixpw_pass) { if (keep_unixpw_user && keep_unixpw_pass) {
n = 18000; n = 18000;
@ -1329,7 +1427,6 @@ if (db) write(2, line, n); write(2, "\n", 1);
if (*q == '\n' || *q == '\r') *q = '\0'; if (*q == '\n' || *q == '\r') *q = '\0';
q++; q++;
} }
if (db) fprintf(stderr, "use_dpy: %s n: %d\n", use_dpy, n);
if (line2[0] != '\0') { if (line2[0] != '\0') {
if (strstr(line2, "XAUTHORITY=") == line2) { if (strstr(line2, "XAUTHORITY=") == line2) {
q = line2; q = line2;
@ -1360,6 +1457,9 @@ if (db) fprintf(stderr, "xauth_raw_len: %d\n", n);
if (chg_raw_fb) { if (chg_raw_fb) {
raw_fb = NULL; raw_fb = NULL;
} }
if (unixpw && keep_unixpw_opts && keep_unixpw_opts[0] != '\0') {
user_supplied_opts(keep_unixpw_opts);
}
return 1; return 1;
} }

@ -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 * it for now by CopyRect-ing the *whole* on-screen
* rectangle (whether obscured or not!) * rectangle (whether obscured or not!)
*/ */
if (time(0) > dt_bad_check + 5) { if (time(NULL) > dt_bad_check + 5) {
char *dt = guess_desktop(); char *dt = guess_desktop();
if (!strcmp(dt, "kde")) { if (!strcmp(dt, "kde")) {
dt_bad = 1; 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 { } else {
dt_bad = 0; dt_bad = 0;
} }
dt_bad_check = time(0); dt_bad_check = time(NULL);
} }
if (clipshift) { if (clipshift) {
@ -3746,7 +3746,7 @@ if (db) fprintf(stderr, "send_copyrect: %d\n", sent_copyrect);
* save the stack list, perhaps the user has * save the stack list, perhaps the user has
* paused with button down. * paused with button down.
*/ */
last_save_stacklist = time(0); last_save_stacklist = time(NULL);
} else { } else {
stack_list_num = 0; 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); sscanf(p, "%lf,%lf,%lf,%lf", &dt_cut, &Tfac_r, &Tfac_v, &Tfac_n);
} }
first = 0; first = 0;
ssec = time(0); ssec = time(NULL);
if (dtr) {} /* unused vars warning: */ if (dtr) {} /* unused vars warning: */
} }

@ -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) { int nfix(int i, int n) {
if (i < 0) { if (i < 0) {
@ -120,7 +120,7 @@ void uppercase(char *str) {
char *lblanks(char *str) { char *lblanks(char *str) {
char *p = str; char *p = str;
while (*p) { while (*p != '\0') {
if (! isspace(*p)) { if (! isspace(*p)) {
break; 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 parse_geom(char *str, int *wp, int *hp, int *xp, int *yp, int W, int H) {
int w, h, x, y; int w, h, x, y;
if (! str) {
return 0;
}
/* handle +/-x and +/-y */ /* handle +/-x and +/-y */
if (sscanf(str, "%dx%d+%d+%d", &w, &h, &x, &y) == 4) { 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) { void set_env(char *name, char *value) {
char *str; char *str;
if (!value) { if (! name) {
return;
}
if (! value) {
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); sprintf(str, "%s=%s", name, value);
putenv(str); putenv(str);
} }
@ -277,6 +283,7 @@ char *this_host(void) {
char host[MAXN]; char host[MAXN];
#if LIBVNCSERVER_HAVE_GETHOSTNAME #if LIBVNCSERVER_HAVE_GETHOSTNAME
if (gethostname(host, MAXN) == 0) { if (gethostname(host, MAXN) == 0) {
host[MAXN-1] = '\0';
return strdup(host); return strdup(host);
} }
#endif #endif
@ -286,8 +293,8 @@ char *this_host(void) {
int match_str_list(char *str, char **list) { int match_str_list(char *str, char **list) {
int i = 0, matched = 0; int i = 0, matched = 0;
if (! list) { if (! str || ! list) {
return matched; return 0;
} }
while (list[i] != NULL) { while (list[i] != NULL) {
if (!strcmp(list[i], "*")) { if (!strcmp(list[i], "*")) {
@ -304,9 +311,14 @@ int match_str_list(char *str, char **list) {
char **create_str_list(char *cslist) { char **create_str_list(char *cslist) {
int i, n; int i, n;
char *p, *str = strdup(cslist); char *p, *str;
char **list = NULL; char **list = NULL;
if (! cslist) {
return NULL;
}
str = strdup(cslist);
n = 1; n = 1;
p = str; p = str;
while (*p != '\0') { while (*p != '\0') {
@ -316,7 +328,8 @@ char **create_str_list(char *cslist) {
p++; 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++) { for(i=0; i < n+1; i++) {
list[i] = NULL; 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));
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);
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) { char *choose_title(char *display) {
static char title[(MAXN+10)]; static char title[(MAXN+10)];
memset(title, 0, MAXN+10);
strcpy(title, "x11vnc"); strcpy(title, "x11vnc");
if (display == NULL) { if (display == NULL) {
@ -465,16 +484,20 @@ char *choose_title(char *display) {
} }
title[0] = '\0'; title[0] = '\0';
if (display[0] == ':') { if (display[0] == ':') {
if (this_host() != NULL) { char *th = this_host();
strncpy(title, this_host(), MAXN - strlen(title)); if (th != NULL) {
strncpy(title, th, MAXN - strlen(title));
} }
} }
strncat(title, display, MAXN - strlen(title)); strncat(title, display, MAXN - strlen(title));
if (subwin && valid_window(subwin, NULL, 0)) { if (subwin && dpy && valid_window(subwin, NULL, 0)) {
char *name; char *name = NULL;
if (dpy && XFetchName(dpy, subwin, &name)) { if (XFetchName(dpy, subwin, &name)) {
strncat(title, " ", MAXN - strlen(title)); if (name) {
strncat(title, name, MAXN - strlen(title)); strncat(title, " ", MAXN - strlen(title));
strncat(title, name, MAXN - strlen(title));
free(name);
}
} }
} }
return title; return title;

@ -1090,7 +1090,7 @@ static char *guess_via_v4l_info(char *dev, int *fd) {
if (*fd) {} if (*fd) {}
/* v4l-info */ /* v4l-info */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("v4l-info")) {
rfbLog("guess_via_v4l_info: cannot run external " rfbLog("guess_via_v4l_info: cannot run external "
"command: v4l-info\n"); "command: v4l-info\n");
return NULL; return NULL;

@ -305,7 +305,7 @@ int pick_windowid(unsigned long *num) {
set_env("DISPLAY", use_dpy); set_env("DISPLAY", use_dpy);
} }
/* id */ /* id */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("id")) {
rfbLogEnable(1); rfbLogEnable(1);
rfbLog("cannot run external commands in -nocmds mode:\n"); rfbLog("cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", "xwininfo"); rfbLog(" \"%s\"\n", "xwininfo");

@ -2,7 +2,7 @@
.TH X11VNC "1" "June 2006" "x11vnc " "User Commands" .TH X11VNC "1" "June 2006" "x11vnc " "User Commands"
.SH NAME .SH NAME
x11vnc - allow VNC connections to real X11 displays 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 .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [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 a global \fB-viewonly\fR is in effect (all input is discarded
in that case). in that case).
.PP .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 \fB-viewpasswd\fR \fIstring\fR
.IP .IP
Supply a 2nd password for view-only logins. The \fB-passwd\fR 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 as the user who just authenticated via the login and
password prompt. password prompt.
.IP .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 \fB-unixpw\fR allows automatic pairing of an unix
authenticated VNC user with his desktop. This could authenticated VNC user with his desktop. This could
be very useful on SunRays and also any system where 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 \\ 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 \fB-inetd\fR \fB-q\fR \fB-http_ssl\fR \fB-display\fR WAIT:cmd=HTTPONCE
.IP .IP
Is used in the Apache SSL-portal example (see FAQ). It is used in the Apache SSL-portal example (see FAQ).
.IP .IP
Finally, one can insert a geometry between colons, Finally, one can insert a geometry between colons,
e.g. WAIT:1280x1024:... to set the size of the display 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 .IP
Do not process any .x11vncrc file for options. Do not process any .x11vncrc file for options.
.PP .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 \fB-h,\fR \fB-help\fR
.IP .IP
Print this help text. Print this help text.
@ -3222,6 +3274,14 @@ lookup disable \fB-nolookup\fR mode.
.IP .IP
input:str set \fB-input\fR to "str", empty to disable. input:str set \fB-input\fR to "str", empty to disable.
.IP .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 client_input:str set the K, M, B \fB-input\fR on a per-client
basis. select which client as for basis. select which client as for
disconnect, e.g. client_input:host:MB 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_skip scr_inc scr_keys scr_term scr_keyrepeat
scr_parms scrollcopyrect scr noscrollcopyrect noscr scr_parms scrollcopyrect scr noscrollcopyrect noscr
fixscreen noxrecord xrecord reset_record pointer_mode fixscreen noxrecord xrecord reset_record pointer_mode
pm input_skip input client_input speeds wmdt pm input_skip input grabkbd nograbkbd grabptr
debug_pointer dp nodebug_pointer nodp debug_keyboard nograbptr client_input speeds wmdt debug_pointer dp
dk nodebug_keyboard nodk deferupdate defer wait_ui nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
wait_bog nowait_bog slow_fb wait readtimeout nap nonap nodk deferupdate defer wait_ui wait_bog nowait_bog
sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb slow_fb wait readtimeout nap nonap sb screen_blank
nosnapfb rawfb progressive rfbport http nohttp httpport fbpm nofbpm fs gaps grow fuzz snapfb nosnapfb rawfb
httpdir enablehttpproxy noenablehttpproxy alwaysshared progressive rfbport http nohttp httpport httpdir
enablehttpproxy noenablehttpproxy alwaysshared
noalwaysshared nevershared noalwaysshared dontdisconnect noalwaysshared nevershared noalwaysshared dontdisconnect
nodontdisconnect desktop debug_xevents nodebug_xevents nodontdisconnect desktop debug_xevents nodebug_xevents
debug_xevents debug_xdamage nodebug_xdamage debug_xevents debug_xdamage nodebug_xdamage
@ -3770,6 +3831,20 @@ No external commands (e.g.
) )
will be run. will be run.
.PP .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 \fB-deny_all\fR
.IP .IP
For use with \fB-remote\fR nodeny: start out denying all For use with \fB-remote\fR nodeny: start out denying all

@ -211,7 +211,7 @@ static void check_cursor_changes(void) {
static void record_last_fb_update(void) { static void record_last_fb_update(void) {
static int rbs0 = -1; static int rbs0 = -1;
static time_t last_call = 0; static time_t last_call = 0;
time_t now = time(0); time_t now = time(NULL);
int rbs = -1; int rbs = -1;
rfbClientIteratorPtr iter; rfbClientIteratorPtr iter;
rfbClientPtr cl; 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) { static void watch_loop(void) {
int cnt = 0, tile_diffs = 0, skip_pe = 0; int cnt = 0, tile_diffs = 0, skip_pe = 0;
double tm, dtr, dt = 0.0; double tm, dtr, dt = 0.0;
time_t start = time(0); time_t start = time(NULL);
if (use_threads) { if (use_threads) {
rfbRunEventLoop(screen, -1, TRUE); 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) { if (first_conn_timeout < 0) {
start = time(0); start = time(NULL);
first_conn_timeout = -first_conn_timeout; 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) { if (! screen || ! screen->clientHead) {
/* waiting for a client */ /* waiting for a client */
if (first_conn_timeout) { 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", rfbLog("No client after %d secs.\n",
first_conn_timeout); first_conn_timeout);
shut_down = 1; shut_down = 1;
@ -1252,7 +1252,7 @@ static void store_homedir_passwd(char *file) {
str2[0] = '\0'; str2[0] = '\0';
/* storepasswd */ /* storepasswd */
if (no_external_cmds) { if (no_external_cmds || !cmd_ok("storepasswd")) {
fprintf(stderr, "-nocmds cannot be used with -storepasswd\n"); fprintf(stderr, "-nocmds cannot be used with -storepasswd\n");
exit(1); exit(1);
} }
@ -1376,6 +1376,10 @@ int main(int argc, char* argv[]) {
immediate_switch_user(argc, argv); immediate_switch_user(argc, argv);
} }
for (i=0; i < 2048; i++) {
argv_vnc[i] = NULL;
}
argv_vnc[0] = strdup(argv[0]); argv_vnc[0] = strdup(argv[0]);
program_name = strdup(argv[0]); program_name = strdup(argv[0]);
program_pid = (int) getpid(); 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++) { for (i=1; i < argc; i++) {
/* quick-n-dirty --option handling. */ /* quick-n-dirty --option handling. */
arg = argv[i]; arg = argv[i];
@ -1569,6 +1597,10 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-input")) { } else if (!strcmp(arg, "-input")) {
CHECK_ARGC CHECK_ARGC
allowed_input_str = strdup(argv[++i]); 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")) { } else if (!strcmp(arg, "-viewpasswd")) {
vpw_loc = i; vpw_loc = i;
CHECK_ARGC CHECK_ARGC
@ -1781,6 +1813,8 @@ int main(int argc, char* argv[]) {
i++; /* done above */ i++; /* done above */
} else if (!strcmp(arg, "-norc")) { } else if (!strcmp(arg, "-norc")) {
; /* done above */ ; /* done above */
} else if (!strcmp(arg, "-env")) {
i++; /* done above */
} else if (!strcmp(arg, "-h") || !strcmp(arg, "-help")) { } else if (!strcmp(arg, "-h") || !strcmp(arg, "-help")) {
print_help(0); print_help(0);
} else if (!strcmp(arg, "-?") || !strcmp(arg, "-opts")) { } else if (!strcmp(arg, "-?") || !strcmp(arg, "-opts")) {
@ -2181,6 +2215,9 @@ int main(int argc, char* argv[]) {
more_safe = 1; more_safe = 1;
} else if (!strcmp(arg, "-nocmds")) { } else if (!strcmp(arg, "-nocmds")) {
no_external_cmds = 1; no_external_cmds = 1;
} else if (!strcmp(arg, "-allowedcmds")) {
CHECK_ARGC
allowed_external_cmds = strdup(argv[++i]);
} else if (!strcmp(arg, "-deny_all")) { } else if (!strcmp(arg, "-deny_all")) {
deny_all = 1; deny_all = 1;
} else if (!strcmp(arg, "-httpdir")) { } else if (!strcmp(arg, "-httpdir")) {
@ -3157,9 +3194,14 @@ int main(int argc, char* argv[]) {
initialize_screen(&argc_vnc, argv_vnc, fb0); initialize_screen(&argc_vnc, argv_vnc, fb0);
if (waited_for_client && fake_fb) { if (waited_for_client) {
free(fake_fb); if (fake_fb) {
fake_fb = NULL; free(fake_fb);
fake_fb = NULL;
}
if (use_solid_bg && client_count) {
solid_bg(0);
}
} }
if (! waited_for_client) { if (! waited_for_client) {

@ -366,9 +366,9 @@ extern char *http_dir;
extern char vnc_desktop_name[]; extern char vnc_desktop_name[];
extern char *main_fb; /* our copy of the X11 fb */ extern char *main_fb; /* our copy of the X11 fb */
extern char *rfb_fb; /* same as main_fb unless transformation */ extern char *rfb_fb; /* same as main_fb unless transformation */
extern char *fake_fb; /* used under -padgeom */ extern char *fake_fb; /* used under -padgeom */
extern char *snap_fb; /* used under -snapfb */ extern char *snap_fb; /* used under -snapfb */
extern char *cmap8to24_fb; /* used under -8to24 */ extern char *cmap8to24_fb; /* used under -8to24 */
extern char *raw_fb; extern char *raw_fb;
extern char *raw_fb_addr; extern char *raw_fb_addr;
extern int raw_fb_offset; extern int raw_fb_offset;

@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0; int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */ /* 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 */ /* X display info */
@ -68,11 +68,11 @@ int raw_fb_seek = 0;
int raw_fb_fd = -1; int raw_fb_fd = -1;
int raw_fb_back_to_X = 0; /* kludge for testing rawfb -> X */ int raw_fb_back_to_X = 0; /* kludge for testing rawfb -> X */
int rfb_bytes_per_line; int rfb_bytes_per_line = 0;
int main_bytes_per_line; int main_bytes_per_line = 0;
unsigned long main_red_mask, main_green_mask, main_blue_mask; unsigned long main_red_mask = 0, main_green_mask = 0, main_blue_mask = 0;
unsigned short main_red_max, main_green_max, main_blue_max; unsigned short main_red_max = 0, main_green_max = 0, main_blue_max = 0;
unsigned short main_red_shift, main_green_shift, main_blue_shift; unsigned short main_red_shift = 0, main_green_shift = 0, main_blue_shift = 0;
/* scaling parameters */ /* scaling parameters */
char *scale_str = NULL; char *scale_str = NULL;
@ -123,8 +123,8 @@ int client_count = 0;
int clients_served = 0; int clients_served = 0;
/* more transient kludge variables: */ /* more transient kludge variables: */
int cursor_x, cursor_y; /* x and y from the viewer(s) */ int cursor_x = 0, cursor_y = 0; /* x and y from the viewer(s) */
int button_change_x, button_change_y; int button_change_x = 0, button_change_y = 0;
int got_user_input = 0; int got_user_input = 0;
int got_pointer_input = 0; int got_pointer_input = 0;
int got_pointer_calls = 0; int got_pointer_calls = 0;

@ -369,7 +369,7 @@ if (0) XEventsQueued(dpy, QueuedAfterFlush);
"/direct %d/%d/%d/%d\n", call, dt, tm - x11vnc_start, ecount, "/direct %d/%d/%d/%d\n", call, dt, tm - x11vnc_start, ecount,
dcount, ccount, xdamage_direct_count); dcount, ccount, xdamage_direct_count);
} }
now = time(0); now = time(NULL);
if (! last_rpt) { if (! last_rpt) {
last_rpt = now; last_rpt = now;
} }

@ -16,6 +16,8 @@
/* XXX CHECK BEFORE RELEASE */ /* XXX CHECK BEFORE RELEASE */
int grab_buster = 0; int grab_buster = 0;
int grab_kbd = 0;
int grab_ptr = 0;
int sync_tod_delay = 3; int sync_tod_delay = 3;
void initialize_vnc_connect_prop(void); 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 void bust_grab(int reset) {
static int bust_count = 0; static int bust_count = 0;
static time_t last_bust = 0; static time_t last_bust = 0;
time_t now = time(0); time_t now = time(NULL);
KeyCode key; KeyCode key;
int button, x, y, nb; int button, x, y, nb;
@ -272,7 +274,7 @@ static void bust_grab(int reset) {
XTestFakeKeyEvent_wr(dpy, key, False, CurrentTime); XTestFakeKeyEvent_wr(dpy, key, False, CurrentTime);
} }
XFlush_wr(dpy); XFlush_wr(dpy);
last_bust = time(0); last_bust = time(NULL);
} }
typedef struct _grabwatch { typedef struct _grabwatch {
@ -294,7 +296,7 @@ static int process_watch(char *str, int parent, int db) {
unsigned long xtime; unsigned long xtime;
static grabwatch_t watches[GRABWATCH]; static grabwatch_t watches[GRABWATCH];
static int first = 1; static int first = 1;
time_t now = time(0); time_t now = time(NULL);
static time_t last_bust = 0; static time_t last_bust = 0;
int too_long, problems = 0; int too_long, problems = 0;
@ -604,7 +606,7 @@ void sync_tod_with_servertime(void) {
void check_keycode_state(void) { void check_keycode_state(void) {
static time_t last_check = 0; static time_t last_check = 0;
int delay = 10, noinput = 3; int delay = 10, noinput = 3;
time_t now = time(0); time_t now = time(NULL);
if (! client_count) { if (! client_count) {
return; return;
@ -629,7 +631,7 @@ void check_keycode_state(void) {
void check_autorepeat(void) { void check_autorepeat(void) {
static time_t last_check = 0; 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; int autorepeat_is_on, autorepeat_initially_on, idle_timeout = 300;
static int idle_reset = 0; 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_init_check = 0;
static time_t last_sync = 0; static time_t last_sync = 0;
static time_t last_time_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; static double last_request = 0.0;
XErrorHandler old_handler; XErrorHandler old_handler;

@ -4,6 +4,8 @@
/* -- xevents.h -- */ /* -- xevents.h -- */
extern int grab_buster; extern int grab_buster;
extern int grab_kbd;
extern int grab_ptr;
extern int sync_tod_delay; extern int sync_tod_delay;
extern void initialize_vnc_connect_prop(void); extern void initialize_vnc_connect_prop(void);

@ -34,11 +34,11 @@ extern int known_xrandr_mode(char *s);
if (subwin) { \ if (subwin) { \
static int last = 0; \ static int last = 0; \
subwin_trap_count++; \ subwin_trap_count++; \
if (time(0) > last_subwin_trap + 60) { \ if (time(NULL) > last_subwin_trap + 60) { \
rfbLog("trapped GetImage xerror" \ rfbLog("trapped GetImage xerror" \
" in SUBWIN mode. [%d]\n", \ " in SUBWIN mode. [%d]\n", \
subwin_trap_count); \ subwin_trap_count); \
last_subwin_trap = time(0); \ last_subwin_trap = time(NULL); \
last = subwin_trap_count; \ last = subwin_trap_count; \
} \ } \
if (subwin_trap_count - last > 30) { \ if (subwin_trap_count - last > 30) { \

@ -3,6 +3,7 @@
#include "x11vnc.h" #include "x11vnc.h"
#include "xrecord.h" #include "xrecord.h"
#include "keyboard.h" #include "keyboard.h"
#include "xevents.h"
int xshm_present = 0; int xshm_present = 0;
int xtest_present = 0; int xtest_present = 0;
@ -601,8 +602,15 @@ void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
last_keyboard_keycode = key; last_keyboard_keycode = key;
} }
if (grab_kbd) {
XUngrabKeyboard(dpy, CurrentTime);
}
if (xtrap_input) { if (xtrap_input) {
XTRAP_FakeKeyEvent_wr(dpy, key, down, delay); XTRAP_FakeKeyEvent_wr(dpy, key, down, delay);
if (grab_kbd) {
adjust_grabs(1, 1);
}
return; return;
} }
@ -616,6 +624,9 @@ void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
} }
#if LIBVNCSERVER_HAVE_XTEST #if LIBVNCSERVER_HAVE_XTEST
XTestFakeKeyEvent(dpy, key, down, delay); XTestFakeKeyEvent(dpy, key, down, delay);
if (grab_kbd) {
adjust_grabs(1, 1);
}
if (debug_keyboard) { if (debug_keyboard) {
upup_downdown_warning(key, down); upup_downdown_warning(key, down);
} }
@ -648,8 +659,15 @@ void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
RAWFB_RET_VOID RAWFB_RET_VOID
if (grab_ptr) {
XUngrabPointer(dpy, CurrentTime);
}
if (xtrap_input) { if (xtrap_input) {
XTRAP_FakeButtonEvent_wr(dpy, button, is_press, delay); XTRAP_FakeButtonEvent_wr(dpy, button, is_press, delay);
if (grab_ptr) {
adjust_grabs(1, 1);
}
return; return;
} }
@ -664,6 +682,9 @@ void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
#if LIBVNCSERVER_HAVE_XTEST #if LIBVNCSERVER_HAVE_XTEST
XTestFakeButtonEvent(dpy, button, is_press, delay); XTestFakeButtonEvent(dpy, button, is_press, delay);
#endif #endif
if (grab_ptr) {
adjust_grabs(1, 1);
}
} }
void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y, 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 RAWFB_RET_VOID
if (grab_ptr) {
XUngrabPointer(dpy, CurrentTime);
}
if (xtrap_input) { if (xtrap_input) {
XTRAP_FakeMotionEvent_wr(dpy, screen, x, y, delay); XTRAP_FakeMotionEvent_wr(dpy, screen, x, y, delay);
if (grab_ptr) {
adjust_grabs(1, 1);
}
return; return;
} }
@ -702,6 +730,9 @@ void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
#if LIBVNCSERVER_HAVE_XTEST #if LIBVNCSERVER_HAVE_XTEST
XTestFakeMotionEvent(dpy, screen, x, y, delay); XTestFakeMotionEvent(dpy, screen, x, y, delay);
#endif #endif
if (grab_ptr) {
adjust_grabs(1, 1);
}
} }
Bool XTestCompareCurrentCursorWithWindow_wr(Display* dpy, Window w) { Bool XTestCompareCurrentCursorWithWindow_wr(Display* dpy, Window w) {

Loading…
Cancel
Save