x11vnc: -capslock -skip_lockkeys; Alt keys under -rawfb cons.

pull/1/head
runge 19 years ago
parent 8417618289
commit 203eee7cfd

@ -1,3 +1,8 @@
2006-06-03 Karl Runge <runge@karlrunge.com>
* x11vnc: -capslock and -skip_lockkeys options. map some Alt keys
to Latin under linuxfb. switch to new stats API. Handle more
cases carefully when switching fb.
2006-05-06 Karl Runge <runge@karlrunge.com> 2006-05-06 Karl Runge <runge@karlrunge.com>
* x11vnc: improved support for webcams and tv tuners with * x11vnc: improved support for webcams and tv tuners with
video4linux /dev/video: -rawfb video, -freqtab etc. video4linux /dev/video: -rawfb video, -freqtab etc.

File diff suppressed because it is too large Load Diff

@ -51,8 +51,6 @@ static void interrupted (int sig);
void clean_shm(int quick) { void clean_shm(int quick) {
int i, cnt = 0; int i, cnt = 0;
if (raw_fb) quick = 1; /* raw_fb hack */
/* /*
* to avoid deadlock, etc, under quick=1 we just delete the shm * to avoid deadlock, etc, under quick=1 we just delete the shm
* areas and leave the X stuff hanging. * areas and leave the X stuff hanging.

@ -644,6 +644,7 @@ void client_gone(rfbClientPtr client) {
* we disconnect after 1 successful connection). * we disconnect after 1 successful connection).
*/ */
if ((client->state == RFB_PROTOCOL_VERSION || if ((client->state == RFB_PROTOCOL_VERSION ||
client->state == RFB_SECURITY_TYPE ||
client->state == RFB_AUTHENTICATION) && accepted_client) { client->state == RFB_AUTHENTICATION) && accepted_client) {
rfbLog("connect_once: invalid password or early " rfbLog("connect_once: invalid password or early "
"disconnect.\n"); "disconnect.\n");

@ -425,6 +425,7 @@ void print_help(int mode) {
" and last line be \"__BEGIN_VIEWONLY__\" to have 2\n" " and last line be \"__BEGIN_VIEWONLY__\" to have 2\n"
" full-access passwords)\n" " full-access passwords)\n"
"\n" "\n"
#ifndef REL81
"-unixpw [list] Use Unix username and password authentication. x11vnc\n" "-unixpw [list] Use Unix username and password authentication. x11vnc\n"
" uses the su(1) program to verify the user's password.\n" " uses the su(1) program to verify the user's password.\n"
" [list] is an optional comma separated list of allowed\n" " [list] is an optional comma separated list of allowed\n"
@ -1055,6 +1056,7 @@ void print_help(int mode) {
" -httpdir option. If not supplied it will try to guess\n" " -httpdir option. If not supplied it will try to guess\n"
" the directory as though the -http option was supplied.\n" " the directory as though the -http option was supplied.\n"
"\n" "\n"
#endif
"-usepw If no other password method was supplied on the command\n" "-usepw If no other password method was supplied on the command\n"
" line, first look for ~/.vnc/passwd and if found use it\n" " line, first look for ~/.vnc/passwd and if found use it\n"
" with -rfbauth; next, look for ~/.vnc/passwdfile and\n" " with -rfbauth; next, look for ~/.vnc/passwdfile and\n"
@ -1063,9 +1065,11 @@ void print_help(int mode) {
" the -rfbauth option. If none of these succeed x11vnc\n" " the -rfbauth option. If none of these succeed x11vnc\n"
" exits immediately.\n" " exits immediately.\n"
"\n" "\n"
#ifndef REL81
" Note: -unixpw currently does not count as a password\n" " Note: -unixpw currently does not count as a password\n"
" method by this option.\n" " method by this option.\n"
"\n" "\n"
#endif
"-storepasswd pass file Store password \"pass\" as the VNC password in the\n" "-storepasswd pass file Store password \"pass\" as the VNC password in the\n"
" file \"file\". Once the password is stored the\n" " file \"file\". Once the password is stored the\n"
" program exits. Use the password via \"-rfbauth file\"\n" " program exits. Use the password via \"-rfbauth file\"\n"
@ -1356,6 +1360,36 @@ void print_help(int mode) {
" e.g. !, @, [, are only accessible via -xkb mode and if\n" " e.g. !, @, [, are only accessible via -xkb mode and if\n"
" so then automatically enable the mode. To disable this\n" " so then automatically enable the mode. To disable this\n"
" automatic detection use -noxkb.\n" " automatic detection use -noxkb.\n"
"\n"
"-capslock When in -modtweak (the default) or -xkb mode,\n"
" if a keysym in the range A-Z comes in check the X\n"
" server to see if the Caps_Lock is set. If it is do\n"
" not artificially press Shift to generate the keysym.\n"
" This will enable the CapsLock key to behave correctly\n"
" in some circumstances: namely *both* the VNC viewer\n"
" machine and the x11vnc X server are in the CapsLock\n"
" on state. If one side has CapsLock on and the other\n"
" off and the keyboard is not behaving as you think it\n"
" should you should correct the CapsLock states (hint:\n"
" pressing CapsLock inside and outside of the viewer can\n"
" help toggle them both to the correct state). However,\n"
" for best results do not use this option, but rather\n"
" *only* enable CapsLock on the VNC viewer side (i.e. by\n"
" pressing CapsLock outside of the viewer window, also\n"
" -skip_lockkeys below). Also try -nomodtweak for a\n"
" possible workaround.\n"
"\n"
"-skip_lockkeys Have x11vnc ignore all Caps_Lock, Shift_Lock, Num_Lock,\n"
" Scroll_Lock keysyms received from viewers. The idea is\n"
" you press Caps_Lock on the VNC Viewer side but that does\n"
" not change the lock state in the x11vnc-side X server.\n"
" Nevertheless your capitalized letters come in over\n"
" the wire and are applied correctly to the x11vnc-side\n"
" X server. Note this mode probably won't do what you\n"
" want in -nomodtweak mode. Also, a kludge for KP_n\n"
" digits is always done it this mode: they are mapped to\n"
" regular digit keysyms. See also -capslock above.\n"
"\n"
"-skip_keycodes string Ignore the comma separated list of decimal keycodes.\n" "-skip_keycodes string Ignore the comma separated list of decimal keycodes.\n"
" Perhaps these are keycodes not on your keyboard but\n" " Perhaps these are keycodes not on your keyboard but\n"
" your X server thinks exist. Currently only applies\n" " your X server thinks exist. Currently only applies\n"
@ -1410,6 +1444,9 @@ void print_help(int mode) {
" \"Button1\", ..., etc. E.g: \"-remap Super_R-Button2\"\n" " \"Button1\", ..., etc. E.g: \"-remap Super_R-Button2\"\n"
" (useful for pasting on a laptop)\n" " (useful for pasting on a laptop)\n"
"\n" "\n"
" To disable a keysym (i.e. make it so it will not be\n"
" injected), remap it to \"NoSymbol\" or \"None\".\n"
"\n"
" Dead keys: \"dead\" (or silent, mute) keys are keys that\n" " Dead keys: \"dead\" (or silent, mute) keys are keys that\n"
" do not produce a character but must be followed by a 2nd\n" " do not produce a character but must be followed by a 2nd\n"
" keystroke. This is often used for accenting characters,\n" " keystroke. This is often used for accenting characters,\n"
@ -2401,6 +2438,10 @@ void print_help(int mode) {
" format to HI240, RGB565, RGB24, RGB32, RGB555, and\n" " format to HI240, RGB565, RGB24, RGB32, RGB555, and\n"
" GREY respectively. See -rawfb video for details.\n" " GREY respectively. See -rawfb video for details.\n"
"\n" "\n"
" If cmd is \"CONS\" or \"CONSn\" where n is a Linux\n"
" console number, then the linux console keystroke\n"
" insertion (see -rawfb cons) is performed.\n"
"\n"
"-gui [gui-opts] Start up a simple tcl/tk gui based on the the remote\n" "-gui [gui-opts] Start up a simple tcl/tk gui based on the the remote\n"
" control options -remote/-query described below.\n" " control options -remote/-query described below.\n"
" Requires the \"wish\" program to be installed on the\n" " Requires the \"wish\" program to be installed on the\n"
@ -2642,6 +2683,10 @@ void print_help(int mode) {
" nomodtweak enable -nomodtweak mode.\n" " nomodtweak enable -nomodtweak mode.\n"
" xkb enable -xkb modtweak mode.\n" " xkb enable -xkb modtweak mode.\n"
" noxkb disable -xkb modtweak mode.\n" " noxkb disable -xkb modtweak mode.\n"
" capslock enable -capslock mode.\n"
" nocapslock disable -capslock mode.\n"
" skip_lockkeys enable -skip_lockkeys mode.\n"
" noskip_lockkeys disable -skip_lockkeys mode.\n"
" skip_keycodes:str enable -xkb -skip_keycodes \"str\".\n" " skip_keycodes:str enable -xkb -skip_keycodes \"str\".\n"
" sloppy_keys enable -sloppy_keys mode.\n" " sloppy_keys enable -sloppy_keys mode.\n"
" nosloppy_keys disable -sloppy_keys mode.\n" " nosloppy_keys disable -sloppy_keys mode.\n"
@ -2835,8 +2880,9 @@ void print_help(int mode) {
" listen lookup nolookup accept afteraccept gone shm\n" " listen lookup nolookup accept afteraccept gone shm\n"
" noshm flipbyteorder noflipbyteorder onetile noonetile\n" " noshm flipbyteorder noflipbyteorder onetile noonetile\n"
" solid_color solid nosolid blackout xinerama noxinerama\n" " solid_color solid nosolid blackout xinerama noxinerama\n"
" xtrap noxtrap xrandr noxrandr xrandr_mode padgeom quiet\n" " xtrap noxtrap xrandr noxrandr xrandr_mode padgeom\n"
" q noquiet modtweak nomodtweak xkb noxkb skip_keycodes\n" " quiet q noquiet modtweak nomodtweak xkb noxkb capslock\n"
" nocapslock skip_lockkeys noskip_lockkeys skip_keycodes\n"
" sloppy_keys nosloppy_keys skip_dups noskip_dups\n" " sloppy_keys nosloppy_keys skip_dups noskip_dups\n"
" add_keysyms noadd_keysyms clear_mods noclear_mods\n" " add_keysyms noadd_keysyms clear_mods noclear_mods\n"
" clear_keys noclear_keys remap repeat norepeat fb nofb\n" " clear_keys noclear_keys remap repeat norepeat fb nofb\n"
@ -2874,8 +2920,12 @@ 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"

@ -531,9 +531,11 @@ static void add_remap(char *line) {
} }
} }
if (ksym1 == NoSymbol || ksym2 == NoSymbol) { if (ksym1 == NoSymbol || ksym2 == NoSymbol) {
if (strcasecmp(str2, "NoSymbol") && strcasecmp(str2, "None")) {
rfbLog("warning: skipping invalid remap line: %s", line); rfbLog("warning: skipping invalid remap line: %s", line);
return; return;
} }
}
remap = (keyremap_t *) malloc((size_t) sizeof(keyremap_t)); remap = (keyremap_t *) malloc((size_t) sizeof(keyremap_t));
remap->before = ksym1; remap->before = ksym1;
remap->after = ksym2; remap->after = ksym2;
@ -1860,6 +1862,22 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym,
} else if (ks == XK_ISO_Level3_Shift) { } else if (ks == XK_ISO_Level3_Shift) {
skip = 0; skip = 0;
} }
if (watch_capslock && kbstate.locked_mods & LockMask) {
if (keysym >= 'A' && keysym <= 'Z') {
if (ks == XK_Shift_L || ks == XK_Shift_R) {
if (debug_keyboard > 1) {
fprintf(stderr, " A-Z caplock skip Shift\n");
}
skip = 1;
} else if (ks == XK_Caps_Lock) {
if (debug_keyboard > 1) {
fprintf(stderr, " A-Z caplock noskip CapsLock\n");
}
skip = 0;
}
}
}
/* /*
* Alt, Meta, Control, Super, * Alt, Meta, Control, Super,
* Hyper, Num, Caps are skipped. * Hyper, Num, Caps are skipped.
@ -2328,9 +2346,23 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
ADJUSTMOD(XK_Mode_switch, ALTGR) ADJUSTMOD(XK_Mode_switch, ALTGR)
if ( down && keysym >= ' ' && keysym < 0x100 ) { if ( down && keysym >= ' ' && keysym < 0x100 ) {
unsigned int state = 0;
tweak = 1; tweak = 1;
if (watch_capslock && keysym >= 'A' && keysym <= 'Z') {
X_LOCK;
state = mask_state();
X_UNLOCK;
}
if (state & LockMask) {
/* capslock set for A-Z, so no tweak */
X_LOCK;
k = XKeysymToKeycode(dpy, (KeySym) keysym);
X_UNLOCK;
tweak = 0;
} else {
tweak_mod(modifiers[keysym], True); tweak_mod(modifiers[keysym], True);
k = keycodes[keysym]; k = keycodes[keysym];
}
} else { } else {
X_LOCK; X_LOCK;
k = XKeysymToKeycode(dpy, (KeySym) keysym); k = XKeysymToKeycode(dpy, (KeySym) keysym);
@ -2618,6 +2650,31 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
} }
} }
if (skip_lockkeys) {
/* we don't handle XK_ISO*_Lock or XK_Kana_Lock ... */
if (keysym == XK_Scroll_Lock || keysym == XK_Num_Lock ||
keysym == XK_Caps_Lock || keysym == XK_Shift_Lock) {
if (debug_keyboard) {
rfbLog("skipping lock key event: %d 0x%x\n",
down, keysym);
}
return;
} else if (keysym >= XK_KP_0 && keysym <= XK_KP_9) {
/* ugh this is probably what they meant... assume NumLock. */
if (debug_keyboard) {
rfbLog("changed KP digit to regular digit: %d 0x%x\n",
down, keysym);
}
keysym = (keysym - XK_KP_0) + XK_0;
} else if (keysym == XK_KP_Decimal) {
if (debug_keyboard) {
rfbLog("changed XK_KP_Decimal to XK_period: %d 0x%x\n",
down, keysym);
}
keysym = XK_period;
}
}
last_down = down; last_down = down;
last_keysym = keysym; last_keysym = keysym;
last_keyboard_time = tnow; last_keyboard_time = tnow;

@ -142,7 +142,7 @@ char *console_guess(char *str, int *fd) {
} }
void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
static int control = 0; static int control = 0, alt = 0;
if (debug_keyboard) fprintf(stderr, "console_key_command: %d %s\n", (int) keysym, down ? "down" : "up"); if (debug_keyboard) fprintf(stderr, "console_key_command: %d %s\n", (int) keysym, down ? "down" : "up");
if (pipeinput_cons_fd < 0) { if (pipeinput_cons_fd < 0) {
return; return;
@ -159,6 +159,16 @@ void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
} }
return; return;
} }
if (keysym == XK_Alt_L || keysym == XK_Alt_R) {
if (! down) {
if (alt > 0) {
alt--;
}
} else {
alt++;
}
return;
}
if (!down) { if (!down) {
return; return;
} }
@ -166,6 +176,7 @@ void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
keysym = 27; keysym = 27;
} }
if (control) { if (control) {
/* shift down to the "control" zone */
if (keysym >= 'a' && keysym <= 'z') { if (keysym >= 'a' && keysym <= 'z') {
keysym -= ('a' - 1); keysym -= ('a' - 1);
} else if (keysym >= 'A' && keysym <= 'Z') { } else if (keysym >= 'A' && keysym <= 'Z') {
@ -173,10 +184,16 @@ void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
} else { } else {
keysym = 0xffff; keysym = 0xffff;
} }
} else if (alt) {
/* shift up to the upper half Latin zone */
if (keysym >= '!' && keysym <= '~') {
keysym += 128;
}
} }
if (debug_keyboard) fprintf(stderr, "keysym now: %d\n", (int) keysym);
if (keysym == XK_Tab) { if (keysym == XK_Tab) {
keysym = '\t'; keysym = '\t';
} else if (keysym == XK_Return) { } else if (keysym == XK_Return || keysym == XK_KP_Enter) {
keysym = '\r'; keysym = '\r';
} else if (keysym == XK_BackSpace) { } else if (keysym == XK_BackSpace) {
keysym = 8; keysym = 8;
@ -196,6 +213,10 @@ void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
keysym = 2; keysym = 2;
} else if (keysym == XK_Prior || keysym == XK_KP_Prior) { } else if (keysym == XK_Prior || keysym == XK_KP_Prior) {
keysym = 2; keysym = 2;
} else {
if (keysym >= XK_KP_Multiply && keysym <= XK_KP_Equal) {
keysym -= 0xFF80;
}
} }
#if LIBVNCSERVER_HAVE_SYS_IOCTL_H && defined(TIOCSTI) #if LIBVNCSERVER_HAVE_SYS_IOCTL_H && defined(TIOCSTI)
if (keysym < 0x100) { if (keysym < 0x100) {

@ -108,6 +108,8 @@ char *cmap8to24_str = NULL;
int launch_gui = 0; /* -gui */ int launch_gui = 0; /* -gui */
int use_modifier_tweak = 1; /* use the shift/altgr modifier tweak */ int use_modifier_tweak = 1; /* use the shift/altgr modifier tweak */
int watch_capslock = 0; /* -capslock */
int skip_lockkeys = 0; /* -skip_lockkeys */
int use_iso_level3 = 0; /* ISO_Level3_Shift instead of Mode_switch */ int use_iso_level3 = 0; /* ISO_Level3_Shift instead of Mode_switch */
int clear_mods = 0; /* -clear_mods (1) and -clear_keys (2) */ int clear_mods = 0; /* -clear_mods (1) and -clear_keys (2) */
int nofb = 0; /* do not send any fb updates */ int nofb = 0; /* do not send any fb updates */

@ -83,6 +83,8 @@ extern int xform24to32;
extern int launch_gui; extern int launch_gui;
extern int use_modifier_tweak; extern int use_modifier_tweak;
extern int watch_capslock;
extern int skip_lockkeys;
extern int use_iso_level3; extern int use_iso_level3;
extern int clear_mods; extern int clear_mods;
extern int nofb; extern int nofb;

@ -350,8 +350,16 @@ db = 0;
} }
nclients++; nclients++;
#if 0
for (i=0; i<MAX_ENCODINGS; i++) {
cbs += cl->bytesSent[i];
}
rbs = cl->rawBytesEquivalent;
#else
cbs = rfbStatGetSentBytes(cl); cbs = rfbStatGetSentBytes(cl);
rbs = rfbStatGetSentBytesIfRaw(cl); rbs = rfbStatGetSentBytesIfRaw(cl);
#endif
if (init) { if (init) {
@ -432,7 +440,13 @@ if (db) fprintf(stderr, "%d client num rects req: %d mod: %d cbs: %d "
if (db) fprintf(stderr, "dt2 calc: num rects req: %d/%d mod: %d/%d " if (db) fprintf(stderr, "dt2 calc: num rects req: %d/%d mod: %d/%d "
"fbu-sent: %d dt: %.4f dt2: %.4f tm: %.4f\n", "fbu-sent: %d dt: %.4f dt2: %.4f tm: %.4f\n",
req0, req1, mod0, mod1, rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate), dt, dt2, tm); req0, req1, mod0, mod1,
#if 0
cl->framebufferUpdateMessagesSent,
#else
rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate),
#endif
dt, dt2, tm);
if (req1 != 0 && mod1 == 0) { if (req1 != 0 && mod1 == 0) {
got_t2 = 1; got_t2 = 1;
break; break;
@ -499,7 +513,13 @@ if (db) fprintf(stderr, "dt2 calc: num rects req: %d/%d mod: %d/%d "
if (db) fprintf(stderr, "dt3 calc: num rects req: %d/%d mod: %d/%d " if (db) fprintf(stderr, "dt3 calc: num rects req: %d/%d mod: %d/%d "
"fbu-sent: %d dt: %.4f dt3: %.4f tm: %.4f\n", "fbu-sent: %d dt: %.4f dt3: %.4f tm: %.4f\n",
req0, req1, mod0, mod1, rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate), dt, dt3, tm); req0, req1, mod0, mod1,
#if 0
cl->framebufferUpdateMessagesSent,
#else
rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate),
#endif
dt, dt3, tm);
if (req1 != 0 && mod1 == 0) { if (req1 != 0 && mod1 == 0) {
dts[got_t3++] = dt3; dts[got_t3++] = dt3;

@ -1957,6 +1957,38 @@ char *process_remote_cmd(char *cmd, int stringonly) {
got_noxkb = 1; got_noxkb = 1;
initialize_modtweak(); initialize_modtweak();
} else if (!strcmp(p, "capslock")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, watch_capslock);
goto qry;
}
rfbLog("remote_cmd: enabling -capslock mode\n");
watch_capslock = 1;
} else if (!strcmp(p, "nocapslock")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !watch_capslock);
goto qry;
}
rfbLog("remote_cmd: disabling -capslock mode\n");
watch_capslock = 0;
} else if (!strcmp(p, "skip_lockkeys")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, skip_lockkeys);
goto qry;
}
rfbLog("remote_cmd: enabling -skip_lockkeys mode\n");
skip_lockkeys = 1;
} else if (!strcmp(p, "noskip_lockkeys")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !skip_lockkeys);
goto qry;
}
rfbLog("remote_cmd: disabling -skip_lockkeys mode\n");
skip_lockkeys = 0;
} else if (strstr(p, "skip_keycodes") == p) { } else if (strstr(p, "skip_keycodes") == p) {
COLON_CHECK("skip_keycodes:") COLON_CHECK("skip_keycodes:")
if (query) { if (query) {
@ -3336,7 +3368,9 @@ char *process_remote_cmd(char *cmd, int stringonly) {
set_raw_fb_params(1); set_raw_fb_params(1);
} }
rfbLog("hang on tight, here we go...\n"); rfbLog("hang on tight, here we go...\n");
raw_fb_back_to_X = 1;
do_new_fb(1); do_new_fb(1);
raw_fb_back_to_X = 0;
} else if (strstr(p, "progressive") == p) { } else if (strstr(p, "progressive") == p) {
int f; int f;
@ -3869,6 +3903,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%d", p, no_external_cmds); snprintf(buf, bufn, "aro=%s:%d", p, no_external_cmds);
} else if (!strcmp(p, "passwdfile")) { } else if (!strcmp(p, "passwdfile")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(passwdfile)); snprintf(buf, bufn, "aro=%s:%s", p, NONUL(passwdfile));
#ifndef REL81
} else if (!strcmp(p, "unixpw")) { } else if (!strcmp(p, "unixpw")) {
snprintf(buf, bufn, "aro=%s:%d", p, unixpw); snprintf(buf, bufn, "aro=%s:%d", p, unixpw);
} else if (!strcmp(p, "unixpw_nis")) { } else if (!strcmp(p, "unixpw_nis")) {
@ -3887,6 +3922,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(stunnel_pem)); snprintf(buf, bufn, "aro=%s:%s", p, NONUL(stunnel_pem));
} else if (!strcmp(p, "https")) { } else if (!strcmp(p, "https")) {
snprintf(buf, bufn, "aro=%s:%d", p, https_port_num); snprintf(buf, bufn, "aro=%s:%d", p, https_port_num);
#endif
} else if (!strcmp(p, "usepw")) { } else if (!strcmp(p, "usepw")) {
snprintf(buf, bufn, "aro=%s:%d", p, usepw); snprintf(buf, bufn, "aro=%s:%d", p, usepw);
} else if (!strcmp(p, "using_shm")) { } else if (!strcmp(p, "using_shm")) {

@ -213,6 +213,7 @@ static int shm_create(XShmSegmentInfo *shm, XImage **ximg_ptr, int w, int h,
XImage *xim; XImage *xim;
static int reported_flip = 0; static int reported_flip = 0;
int db = 0;
shm->shmid = -1; shm->shmid = -1;
shm->shmaddr = (char *) -1; shm->shmaddr = (char *) -1;
@ -239,6 +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);
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);
@ -345,27 +347,28 @@ void shm_delete(XShmSegmentInfo *shm) {
} }
void shm_clean(XShmSegmentInfo *shm, XImage *xim) { void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
int db = 0;
if (db) fprintf(stderr, "shm_clean: called: 0x%x\n", xim);
X_LOCK; X_LOCK;
#if LIBVNCSERVER_HAVE_XSHM #if LIBVNCSERVER_HAVE_XSHM
if (shm != NULL && shm->shmid != -1 && dpy) { /* raw_fb hack */ if (shm != NULL && shm->shmid != -1 && dpy) {
if (db) fprintf(stderr, "shm_clean: XShmDetach_wr\n");
XShmDetach_wr(dpy, shm); XShmDetach_wr(dpy, shm);
} }
#endif #endif
if (xim != NULL) { if (xim != NULL) {
#if 0 if (! raw_fb_back_to_X) { /* raw_fb hack */
/* if (xim->bitmap_unit != -1) {
* This would be needed if you want to crazily switch if (db) fprintf(stderr, "shm_clean: XDestroyImage 0x%x\n", xim);
* back and forth between rawfb and X. You will also
* need to supply -noviewonly. xim->f is public ABI,
* but we choose not to use it. One could also
* clean up the switch.
*/
if (xim->f.destroy_image) {
#else
{
#endif
XDestroyImage(xim); XDestroyImage(xim);
} else {
if (xim->data) {
if (db) fprintf(stderr, "shm_clean: free xim->data 0x%x 0x%x\n", xim, xim->data);
free(xim->data);
xim->data = NULL;
}
}
} }
xim = NULL; xim = NULL;
} }

@ -29,7 +29,7 @@ void set_colormap(int reset);
void set_nofb_params(int restore); void set_nofb_params(int restore);
void set_raw_fb_params(int restore); void set_raw_fb_params(int restore);
void do_new_fb(int reset_mem); void do_new_fb(int reset_mem);
void free_old_fb(char *old_main, char *old_rfb, char *old_8to24); void free_old_fb(char *old_main, char *old_rfb, char *old_8to24, char *old_snap_fb);
void check_padded_fb(void); void check_padded_fb(void);
void install_padded_fb(char *geom); void install_padded_fb(char *geom);
XImage *initialize_xdisplay_fb(void); XImage *initialize_xdisplay_fb(void);
@ -545,6 +545,9 @@ void set_raw_fb_params(int restore) {
if (dpy) { if (dpy) {
if (! quiet) rfbLog("reopened DISPLAY: %s\n", if (! quiet) rfbLog("reopened DISPLAY: %s\n",
raw_fb_orig_dpy); raw_fb_orig_dpy);
scr = DefaultScreen(dpy);
rootwin = RootWindow(dpy, scr);
check_xevents(1);
} else { } else {
if (! quiet) rfbLog("WARNING: failed to reopen " if (! quiet) rfbLog("WARNING: failed to reopen "
"DISPLAY: %s\n", raw_fb_orig_dpy); "DISPLAY: %s\n", raw_fb_orig_dpy);
@ -648,23 +651,30 @@ static void nofb_hook(rfbClientPtr cl) {
screen->displayHook = NULL; screen->displayHook = NULL;
} }
void free_old_fb(char *old_main, char *old_rfb, char *old_8to24) { void free_old_fb(char *old_main, char *old_rfb, char *old_8to24, char *old_snap_fb) {
if (old_main) { if (old_main) {
free(old_main); free(old_main);
} }
if (old_rfb && old_rfb != old_main) { if (old_rfb) {
if (old_rfb != old_main) {
free(old_rfb); free(old_rfb);
} }
if (old_8to24 && old_8to24 != old_main && old_8to24 != old_rfb) { }
if (old_8to24) {
if (old_8to24 != old_main && old_8to24 != old_rfb) {
free(old_8to24); free(old_8to24);
} }
}
if (old_snap_fb) {
if (old_snap_fb != old_main && old_snap_fb != old_rfb &&
old_snap_fb != old_8to24) {
free(old_snap_fb);
}
}
} }
void do_new_fb(int reset_mem) { void do_new_fb(int reset_mem) {
XImage *fb; XImage *fb;
char *old_main = main_fb;
char *old_rfb = rfb_fb;
char *old_8to24 = cmap8to24_fb;
/* for threaded we really should lock libvncserver out. */ /* for threaded we really should lock libvncserver out. */
if (use_threads) { if (use_threads) {
@ -678,6 +688,16 @@ void do_new_fb(int reset_mem) {
free_tiles(); free_tiles();
} }
free_old_fb(main_fb, rfb_fb, cmap8to24_fb, snap_fb);
if (raw_fb == main_fb || raw_fb == rfb_fb) {
raw_fb = NULL;
}
main_fb = NULL;
rfb_fb = NULL;
cmap8to24_fb = NULL;
snap_fb = NULL;
fb = initialize_xdisplay_fb(); fb = initialize_xdisplay_fb();
initialize_screen(NULL, NULL, fb); initialize_screen(NULL, NULL, fb);
@ -688,9 +708,6 @@ void do_new_fb(int reset_mem) {
initialize_polling_images(); initialize_polling_images();
} }
free_old_fb(old_main, old_rfb, old_8to24);
fb0 = fb;
} }
static void remove_fake_fb(void) { static void remove_fake_fb(void) {
@ -922,6 +939,14 @@ if (db) fprintf(stderr, "initialize_raw_fb reset\n");
free(last_file); free(last_file);
last_file = NULL; last_file = NULL;
} }
if (strstr(str, "Video") == str) {
if (pipeinput_str != NULL) {
free(pipeinput_str);
}
pipeinput_str = strdup("VID");
initialize_pipeinput();
str[0] = 'v';
}
if (strstr(str, "video") == str || strstr(str, "/dev/video") == str) { if (strstr(str, "video") == str || strstr(str, "/dev/video") == str) {
char *str2 = v4l_guess(str, &raw_fb_fd); char *str2 = v4l_guess(str, &raw_fb_fd);
@ -1169,6 +1194,7 @@ if (db) fprintf(stderr, "initialize_raw_fb reset\n");
raw_fb_image->height = dpy_y; raw_fb_image->height = dpy_y;
raw_fb_image->bits_per_pixel = b; raw_fb_image->bits_per_pixel = b;
raw_fb_image->bytes_per_line = dpy_x*b/8; raw_fb_image->bytes_per_line = dpy_x*b/8;
raw_fb_image->bitmap_unit = -1;
if (use_snapfb && (raw_fb_seek || raw_fb_mmap)) { if (use_snapfb && (raw_fb_seek || raw_fb_mmap)) {
int b_use = b; int b_use = b;
@ -1186,6 +1212,7 @@ if (db) fprintf(stderr, "initialize_raw_fb reset\n");
snap->height = dpy_y; snap->height = dpy_y;
snap->bits_per_pixel = b_use; snap->bits_per_pixel = b_use;
snap->bytes_per_line = dpy_x*b_use/8; snap->bytes_per_line = dpy_x*b_use/8;
snap->bitmap_unit = -1;
} }
if (rm == 0 && gm == 0 && bm == 0) { if (rm == 0 && gm == 0 && bm == 0) {
@ -2174,9 +2201,11 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
} }
screen->frameBuffer = rfb_fb; screen->frameBuffer = rfb_fb;
if (!quiet) { if (!quiet) {
fprintf(stderr, " main_fb: %p\n", main_fb);
fprintf(stderr, " rfb_fb: %p\n", rfb_fb); fprintf(stderr, " rfb_fb: %p\n", rfb_fb);
fprintf(stderr, " main_fb: %p\n", main_fb);
fprintf(stderr, " 8to24_fb: %p\n", cmap8to24_fb); fprintf(stderr, " 8to24_fb: %p\n", cmap8to24_fb);
fprintf(stderr, " snap_fb: %p\n", snap_fb);
fprintf(stderr, " raw_fb: %p\n", raw_fb);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }

@ -10,7 +10,7 @@ extern void set_colormap(int reset);
extern void set_nofb_params(int restore); extern void set_nofb_params(int restore);
extern void set_raw_fb_params(int restore); extern void set_raw_fb_params(int restore);
extern void do_new_fb(int reset_mem); extern void do_new_fb(int reset_mem);
extern void free_old_fb(char *old_main, char *old_rfb, char *old_8to24); extern void free_old_fb(char *old_main, char *old_rfb, char *old_8to24, char *old_snap_fb);
extern void check_padded_fb(void); extern void check_padded_fb(void);
extern void install_padded_fb(char *geom); extern void install_padded_fb(char *geom);
extern XImage *initialize_xdisplay_fb(void); extern XImage *initialize_xdisplay_fb(void);

@ -14,6 +14,10 @@
#endif #endif
#endif #endif
#ifdef REL81
#undef SSLCMDS
#endif
void check_stunnel(void); void check_stunnel(void);
int start_stunnel(int stunnel_port, int x11vnc_port); int start_stunnel(int stunnel_port, int x11vnc_port);
@ -39,9 +43,13 @@ void check_stunnel(void) {
if (stunnel_pid > 0) { if (stunnel_pid > 0) {
int status; int status;
#ifdef SSLCMDS
waitpid(stunnel_pid, &status, WNOHANG); waitpid(stunnel_pid, &status, WNOHANG);
#endif
if (kill(stunnel_pid, 0) != 0) { if (kill(stunnel_pid, 0) != 0) {
#ifdef SSLCMDS
waitpid(stunnel_pid, &status, WNOHANG); waitpid(stunnel_pid, &status, WNOHANG);
#endif
rfbLog("stunnel subprocess %d died.\n", stunnel_pid); rfbLog("stunnel subprocess %d died.\n", stunnel_pid);
stunnel_pid = 0; stunnel_pid = 0;
clean_up_exit(1); clean_up_exit(1);
@ -74,7 +82,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
strcat(path, extra); strcat(path, extra);
} }
exe = (char *) malloc(strlen(path) + strlen("stunnel") + 1); exe = (char *) malloc(strlen(path) + 1 + strlen("stunnel") + 1);
p = strtok(path, ":"); p = strtok(path, ":");
@ -123,7 +131,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
stunnel_pem = get_saved_pem(stunnel_pem, 1); stunnel_pem = get_saved_pem(stunnel_pem, 1);
if (! stunnel_pem) { if (! stunnel_pem) {
rfbLog("start_stunnel: could not create or open" rfbLog("start_stunnel: could not create or open"
" saved PEM:\n", stunnel_pem); " saved PEM.\n");
clean_up_exit(1); clean_up_exit(1);
} }
} }
@ -278,7 +286,7 @@ void setup_stunnel(int rport, int *argc, char **argv) {
} }
if (start_stunnel(rport, xport)) { if (start_stunnel(rport, xport)) {
int tweaked = 0; int tweaked = 0;
char tmp[10]; char tmp[20];
sprintf(tmp, "%d", xport); sprintf(tmp, "%d", xport);
if (argv) { if (argv) {
for (i=0; i< *argc; i++) { for (i=0; i< *argc; i++) {
@ -539,6 +547,7 @@ void sslEncKey(char *path, int mode) {
strcat(tca, " | xargs ls -ld "); strcat(tca, " | xargs ls -ld ");
} }
system(tca); system(tca);
depth--;
return; return;
} else if (info_only && (!strcasecmp(path, "HASHON") } else if (info_only && (!strcasecmp(path, "HASHON")
@ -565,6 +574,7 @@ void sslEncKey(char *path, int mode) {
} }
system(scr); system(scr);
unlink(tmp); unlink(tmp);
depth--;
return; return;
} }
@ -624,7 +634,7 @@ void sslEncKey(char *path, int mode) {
} }
if (! info_only) { if (! info_only) {
cert = (char *) malloc(2*sbuf.st_size); cert = (char *) malloc(2*(sbuf.st_size + 100));
file = fopen(path, "r"); file = fopen(path, "r");
if (file == NULL) { if (file == NULL) {
rfbLog("sslEncKey: %s\n", path); rfbLog("sslEncKey: %s\n", path);
@ -638,8 +648,10 @@ void sslEncKey(char *path, int mode) {
incert = 1; incert = 1;
} }
if (incert) { if (incert) {
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;
} }

@ -12,12 +12,21 @@
#define OPENSSL_VNC 2 #define OPENSSL_VNC 2
#define OPENSSL_HTTPS 3 #define OPENSSL_HTTPS 3
#define DO_DH 0
#if LIBVNCSERVER_HAVE_FORK #if LIBVNCSERVER_HAVE_FORK
#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID #if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID
#define FORK_OK #define FORK_OK
#endif #endif
#endif #endif
#ifdef REL81
#undef FORK_OK
#undef LIBVNCSERVER_HAVE_LIBSSL
#define LIBVNCSERVER_HAVE_LIBSSL 0
#endif
int openssl_sock = -1; int openssl_sock = -1;
int openssl_port_num = 0; int openssl_port_num = 0;
int https_sock = -1; int https_sock = -1;
@ -64,6 +73,7 @@ static SSL *ssl = NULL;
static void init_prng(void); static void init_prng(void);
static void sslerrexit(void); static void sslerrexit(void);
static char *get_input(char *tag, char **in);
static char *create_tmp_pem(char *path, int prompt); static char *create_tmp_pem(char *path, int prompt);
static int ssl_init(int s_in, int s_out); static int ssl_init(int s_in, int s_out);
static void raw_xfer(int csock, int s_in, int s_out); static void raw_xfer(int csock, int s_in, int s_out);
@ -146,9 +156,6 @@ static char *get_input(char *tag, char **in) {
str = lblanks(line); str = lblanks(line);
if (! strcmp(str, "")) { if (! strcmp(str, "")) {
return *in; return *in;
} else if (0 && !strcmp(str, "none")) {
free(*in);
return strdup("");
} else { } else {
free(*in); free(*in);
return strdup(line); return strdup(line);
@ -200,7 +207,7 @@ static char *create_tmp_pem(char *pathin, int prompt) {
FILE *in, *out; FILE *in, *out;
char cnf[] = "/tmp/x11vnc-cnf.XXXXXX"; char cnf[] = "/tmp/x11vnc-cnf.XXXXXX";
char pem[] = "/tmp/x11vnc-pem.XXXXXX"; char pem[] = "/tmp/x11vnc-pem.XXXXXX";
char str[7*1024], line[1024], *exe; char str[8*1024], line[1024], *exe;
int cnf_fd, pem_fd, status, show_cert = 1; int cnf_fd, pem_fd, status, show_cert = 1;
char *days; char *days;
char *C, *L, *OU, *O, *CN, *EM; char *C, *L, *OU, *O, *CN, *EM;
@ -431,9 +438,9 @@ static char *create_tmp_pem(char *pathin, int prompt) {
if (show_cert) { if (show_cert) {
char cmd[100]; char cmd[100];
if (inetd) { if (inetd) {
sprintf(cmd, "openssl x509 -text -in %s 1>&2", pem); sprintf(cmd, "openssl x509 -text -in '%s' 1>&2", pem);
} else { } else {
sprintf(cmd, "openssl x509 -text -in %s", pem); sprintf(cmd, "openssl x509 -text -in '%s'", pem);
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
system(cmd); system(cmd);
@ -600,11 +607,7 @@ void openssl_init(void) {
double ds; double ds;
long mode; long mode;
#if DO_DH do_dh = DO_DH;
do_dh = 1;
#else
do_dh = 0;
#endif
if (! quiet) { if (! quiet) {
rfbLog("\n"); rfbLog("\n");
@ -630,7 +633,7 @@ void openssl_init(void) {
} }
ds = dnow(); ds = dnow();
rsa_512 = RSA_generate_key(512,RSA_F4,NULL,NULL); rsa_512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
if (rsa_512 == NULL) { if (rsa_512 == NULL) {
rfbLog("openssl_init: RSA_generate_key(512) failed.\n"); rfbLog("openssl_init: RSA_generate_key(512) failed.\n");
sslerrexit(); sslerrexit();
@ -639,7 +642,7 @@ void openssl_init(void) {
rfbLog("created 512 bit temporary RSA key: %.3fs\n", dnow() - ds); rfbLog("created 512 bit temporary RSA key: %.3fs\n", dnow() - ds);
ds = dnow(); ds = dnow();
rsa_1024 = RSA_generate_key(1024,RSA_F4,NULL,NULL); rsa_1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
if (rsa_1024 == NULL) { if (rsa_1024 == NULL) {
rfbLog("openssl_init: RSA_generate_key(1024) failed.\n"); rfbLog("openssl_init: RSA_generate_key(1024) failed.\n");
sslerrexit(); sslerrexit();
@ -717,7 +720,7 @@ void openssl_init(void) {
rfbLog("openssl_init: SSL_CTX_use_certificate_chain_file() failed.\n"); rfbLog("openssl_init: SSL_CTX_use_certificate_chain_file() failed.\n");
sslerrexit(); sslerrexit();
} }
if(! SSL_CTX_use_RSAPrivateKey_file(ctx, openssl_pem, if (! SSL_CTX_use_RSAPrivateKey_file(ctx, openssl_pem,
SSL_FILETYPE_PEM)) { SSL_FILETYPE_PEM)) {
rfbLog("openssl_init: SSL_CTX_set_tmp_rsa(1024) failed.\n"); rfbLog("openssl_init: SSL_CTX_set_tmp_rsa(1024) failed.\n");
sslerrexit(); sslerrexit();
@ -739,7 +742,6 @@ void openssl_init(void) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fclose(in); fclose(in);
} }
} }
unlink(openssl_pem); unlink(openssl_pem);
free(openssl_pem); free(openssl_pem);
@ -866,15 +868,15 @@ static void lose_ram(void) {
* without doing exec(). we really should re-exec, but a pain * without doing exec(). we really should re-exec, but a pain
* to redo all SSL ctx. * to redo all SSL ctx.
*/ */
free_old_fb(main_fb, rfb_fb, cmap8to24_fb); free_old_fb(main_fb, rfb_fb, cmap8to24_fb, snap_fb);
if (raw_fb == main_fb || raw_fb == rfb_fb) {
raw_fb = NULL;
}
main_fb = NULL; main_fb = NULL;
rfb_fb = NULL; rfb_fb = NULL;
cmap8to24_fb = NULL; cmap8to24_fb = NULL;
if (snap_fb) {
free(snap_fb);
snap_fb = NULL; snap_fb = NULL;
}
free_tiles(); free_tiles();
} }
@ -991,7 +993,6 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
tv.tv_sec = 2; tv.tv_sec = 2;
tv.tv_usec = 0; tv.tv_usec = 0;
if (mode == OPENSSL_INETD) { if (mode == OPENSSL_INETD) {
/* /*
* https via inetd is icky because x11vnc is restarted * https via inetd is icky because x11vnc is restarted
@ -1037,7 +1038,7 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
* sniff the first couple bytes of the stream and try to see * sniff the first couple bytes of the stream and try to see
* if it is http or not. if we read them OK, we must read the * if it is http or not. if we read them OK, we must read the
* rest of the available data otherwise we may deadlock. * rest of the available data otherwise we may deadlock.
* what has be read is returned in buf_a and n_a. * what has been read is returned in buf_a and n_a.
* *buf_a is ABSIZE+1 long and zeroed. * *buf_a is ABSIZE+1 long and zeroed.
*/ */
if (getenv("ACCEPT_OPENSSL_DEBUG")) { if (getenv("ACCEPT_OPENSSL_DEBUG")) {
@ -1081,6 +1082,7 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
} }
*n_a = n; *n_a = n;
if (n > 0) { if (n > 0) {
/* XXX memcpy? */
strncpy(buf_a, buf, n); strncpy(buf_a, buf, n);
} }
return is_http; return is_http;
@ -1160,18 +1162,16 @@ if (db) fprintf(stderr, "ssl_init FAILED\n");
{ {
char *buf; char *buf;
int n, ptr; int n = 0, ptr = 0;
buf = (char *) calloc((8192+1), 1); buf = (char *) calloc((8192+1), 1);
n = 0;
ptr = 0;
while (ptr < 8192) { while (ptr < 8192) {
n = SSL_read(ssl, buf + ptr, 8192 - ptr); n = SSL_read(ssl, buf + ptr, 8192 - ptr);
if (n > 0) { if (n > 0) {
ptr += n; ptr += n;
} }
if (db) fprintf(stderr, "buf: '%s'\n", buf); if (db) fprintf(stderr, "buf: '%s'\n", buf);
if (strstr(buf, "\r\n\r\n") || strstr(buf, "\n\n")) { if (strstr(buf, "\r\n\r\n")) {
break; break;
} }
} }
@ -1708,7 +1708,7 @@ static int ssl_init(int s_in, int s_out) {
fprintf(stderr, "SSL_new failed\n"); fprintf(stderr, "SSL_new failed\n");
return 0; return 0;
} }
if (db > 1) fprintf(stderr, "a\n"); if (db > 1) fprintf(stderr, "ssl_init: 1\n");
SSL_set_session_id_context(ssl, sid, strlen((char *)sid)); SSL_set_session_id_context(ssl, sid, strlen((char *)sid));
@ -1727,13 +1727,15 @@ if (db > 1) fprintf(stderr, "a\n");
return 0; return 0;
} }
} }
if (db > 1) fprintf(stderr, "b\n"); if (db > 1) fprintf(stderr, "ssl_init: 2\n");
SSL_set_accept_state(ssl); SSL_set_accept_state(ssl);
if (db > 1) fprintf(stderr, "c\n");
if (db > 1) fprintf(stderr, "ssl_init: 3\n");
name = get_remote_host(ssock); name = get_remote_host(ssock);
if (db > 1) fprintf(stderr, "d\n");
if (db > 1) fprintf(stderr, "ssl_init: 4\n");
while (1) { while (1) {
if (db) fprintf(stderr, "calling SSL_accept...\n"); if (db) fprintf(stderr, "calling SSL_accept...\n");
@ -1751,33 +1753,44 @@ if (db > 1) fprintf(stderr, "d\n");
if (err == SSL_ERROR_NONE) { if (err == SSL_ERROR_NONE) {
break; break;
} else if (err == SSL_ERROR_WANT_READ) { } else if (err == SSL_ERROR_WANT_READ) {
if (db) fprintf(stderr, "got SSL_ERROR_WANT_READ\n"); if (db) fprintf(stderr, "got SSL_ERROR_WANT_READ\n");
rfbLog("SSL: ssl_helper: SSL_accept() failed for: %s\n", rfbLog("SSL: ssl_helper: SSL_accept() failed for: %s\n",
name); name);
return 0; return 0;
} else if (err == SSL_ERROR_WANT_WRITE) { } else if (err == SSL_ERROR_WANT_WRITE) {
if (db) fprintf(stderr, "got SSL_ERROR_WANT_WRITE\n"); if (db) fprintf(stderr, "got SSL_ERROR_WANT_WRITE\n");
rfbLog("SSL: ssl_helper: SSL_accept() failed for: %s\n", rfbLog("SSL: ssl_helper: SSL_accept() failed for: %s\n",
name); name);
return 0; return 0;
} else if (err == SSL_ERROR_SYSCALL) { } else if (err == SSL_ERROR_SYSCALL) {
if (db) fprintf(stderr, "got SSL_ERROR_SYSCALL\n"); if (db) fprintf(stderr, "got SSL_ERROR_SYSCALL\n");
rfbLog("SSL: ssl_helper: SSL_accept() failed for: %s\n", rfbLog("SSL: ssl_helper: SSL_accept() failed for: %s\n",
name); name);
return 0; return 0;
} else if (err == SSL_ERROR_ZERO_RETURN) { } else if (err == SSL_ERROR_ZERO_RETURN) {
if (db) fprintf(stderr, "got SSL_ERROR_ZERO_RETURN\n"); if (db) fprintf(stderr, "got SSL_ERROR_ZERO_RETURN\n");
rfbLog("SSL: ssl_helper: SSL_accept() failed for: %s\n", rfbLog("SSL: ssl_helper: SSL_accept() failed for: %s\n",
name); name);
return 0; return 0;
} else if (rc < 0) { } else if (rc < 0) {
rfbLog("SSL: ssl_helper: SSL_accept() fatal: %d\n", rc); rfbLog("SSL: ssl_helper: SSL_accept() fatal: %d\n", rc);
return 0; return 0;
} else if (dnow() > start + 3.0) { } else if (dnow() > start + 3.0) {
rfbLog("SSL: ssl_helper: timeout looping SSL_accept() " rfbLog("SSL: ssl_helper: timeout looping SSL_accept() "
"fatal.\n"); "fatal.\n");
return 0; return 0;
} else { } else {
BIO *bio = SSL_get_rbio(ssl); BIO *bio = SSL_get_rbio(ssl);
if (bio == NULL) { if (bio == NULL) {
@ -1819,7 +1832,7 @@ static void raw_xfer(int csock, int s_in, int s_out) {
break; break;
} else if (n > 0) { } else if (n > 0) {
m = write(s_out, buf, n); m = write(s_out, buf, n);
if (db > 1) write(2, buf, n); if (db > 1) write(2, buf, n);
if (m != n) { if (m != n) {
if (db) fprintf(stderr, "raw_xfer bad write: %d -> %d | %d/%d\n", csock, s_out, m, n); if (db) fprintf(stderr, "raw_xfer bad write: %d -> %d | %d/%d\n", csock, s_out, m, n);
break; break;

@ -8,8 +8,6 @@
#define OPENSSL_VNC 2 #define OPENSSL_VNC 2
#define OPENSSL_HTTPS 3 #define OPENSSL_HTTPS 3
#define DO_DH 0
extern int openssl_sock; extern int openssl_sock;
extern int openssl_port_num; extern int openssl_port_num;
extern int https_sock; extern int https_sock;

@ -187,12 +187,14 @@ Keyboard
modtweak modtweak
xkb xkb
-- --
=FP remap: capslock
skip_lockkeys
-- --
skip_keycodes: skip_keycodes:
sloppy_keys
skip_dups skip_dups
sloppy_keys
-- --
=FP remap:
clear_mods clear_mods
clear_keys clear_keys

@ -198,12 +198,14 @@ char gui_code[] = "";
" modtweak\n" " modtweak\n"
" xkb\n" " xkb\n"
" --\n" " --\n"
" =FP remap:\n" " capslock\n"
" skip_lockkeys\n"
" --\n" " --\n"
" skip_keycodes:\n" " skip_keycodes:\n"
" sloppy_keys\n"
" skip_dups\n" " skip_dups\n"
" sloppy_keys\n"
" --\n" " --\n"
" =FP remap:\n"
" clear_mods\n" " clear_mods\n"
" clear_keys\n" " clear_keys\n"
"\n" "\n"

@ -40,6 +40,11 @@ extern char *crypt(const char*, const char *);
#define IS_BSD #define IS_BSD
#endif #endif
#ifdef REL81
#undef UNIXPW_SU
#undef UNIXPW_CRYPT
#endif
void unixpw_screen(int init); void unixpw_screen(int init);
void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init); void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init);
void unixpw_accept(char *user); void unixpw_accept(char *user);

@ -4082,7 +4082,11 @@ int fb_update_sent(int *count) {
i = rfbGetClientIterator(screen); i = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(i)) ) { while( (cl = rfbClientIteratorNext(i)) ) {
#if 0
sent += cl->framebufferUpdateMessagesSent;
#else
sent += rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate); sent += rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate);
#endif
} }
rfbReleaseClientIterator(i); rfbReleaseClientIterator(i);
if (sent != last_count) { if (sent != last_count) {

@ -19,6 +19,7 @@ int get_window_size(Window win, int *x, int *y);
void snapshot_stack_list(int free_only, double allowed_age); void snapshot_stack_list(int free_only, double allowed_age);
void update_stack_list(void); void update_stack_list(void);
Window query_pointer(Window start); Window query_pointer(Window start);
unsigned int mask_state(void);
int pick_windowid(unsigned long *num); int pick_windowid(unsigned long *num);
Window descend_pointer(int depth, Window start, char *name_info, int len); Window descend_pointer(int depth, Window start, char *name_info, int len);
@ -279,6 +280,20 @@ Window query_pointer(Window start) {
} }
} }
unsigned int mask_state(void) {
Window r, c;
int rx, ry, wx, wy;
unsigned int mask;
RAWFB_RET(0)
if (XQueryPointer(dpy, rootwin, &r, &c, &rx, &ry, &wx, &wy, &mask)) {
return mask;
} else {
return 0;
}
}
int pick_windowid(unsigned long *num) { int pick_windowid(unsigned long *num) {
char line[512]; char line[512];
int ok = 0, n = 0, msec = 10, secmax = 15; int ok = 0, n = 0, msec = 10, secmax = 15;

@ -17,6 +17,7 @@ extern int get_window_size(Window win, int *x, int *y);
extern void snapshot_stack_list(int free_only, double allowed_age); extern void snapshot_stack_list(int free_only, double allowed_age);
extern void update_stack_list(void); extern void update_stack_list(void);
extern Window query_pointer(Window start); extern Window query_pointer(Window start);
extern unsigned int mask_state(void);
extern int pick_windowid(unsigned long *num); extern int pick_windowid(unsigned long *num);
extern Window descend_pointer(int depth, Window start, char *name_info, int len); extern Window descend_pointer(int depth, Window start, char *name_info, int len);

@ -1,8 +1,8 @@
.\" This file was automatically generated from x11vnc -help output. .\" This file was automatically generated from x11vnc -help output.
.TH X11VNC "1" "May 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.1, lastmod: 2006-05-06 version: 0.8.1, lastmod: 2006-06-03
.SH SYNOPSIS .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [OPTION]...
@ -515,696 +515,6 @@ used to have viewonly passwords. (tip: make the 3rd
and last line be "__BEGIN_VIEWONLY__" to have 2 and last line be "__BEGIN_VIEWONLY__" to have 2
full-access passwords) full-access passwords)
.PP .PP
\fB-unixpw\fR \fI[list]\fR
.IP
Use Unix username and password authentication. x11vnc
uses the
.IR su (1)
program to verify the user's password.
[list] is an optional comma separated list of allowed
Unix usernames. See below for per-user options that
can be applied.
.IP
A familiar "login:" and "Password:" dialog is
presented to the user on a black screen inside the
vncviewer. The connection is dropped if the user fails
to supply the correct password in 3 tries or does not
send one before a 25 second timeout. Existing clients
are view-only during this period.
.IP
Since the detailed behavior of
.IR su (1)
can vary from
OS to OS and for local configurations, test the mode
carefully on your systems before using it in production.
Test different combinations of valid/invalid usernames
and valid/invalid passwords to see if it behaves as
expected. x11vnc will attempt to be conservative and
reject a login if anything abnormal occurs.
.IP
On FreeBSD and the other BSD's by default it is
impossible for the user running x11vnc to validate
his *own* password via
.IR su (1)
(evidently commenting out
the pam_self.so entry in /etc/pam.d/su eliminates this
problem). So the x11vnc login will always *fail* for
this case (even when the correct password is supplied).
.IP
A possible workaround for this would be to start
x11vnc as root with the "\fB-users\fR \fI+nobody\fR" option to
immediately switch to user nobody. Another source of
problems are PAM modules that prompt for extra info,
e.g. password aging modules. These logins will fail
as well even when the correct password is supplied.
.IP
**IMPORTANT**: to prevent the Unix password being sent
in *clear text* over the network, one of two schemes
will be enforced: 1) the \fB-ssl\fR builtin SSL mode, or 2)
require both \fB-localhost\fR and \fB-stunnel\fR be enabled.
.IP
Method 1) ensures the traffic is encrypted between
viewer and server. A PEM file will be required, see the
discussion under \fB-ssl\fR below (under some circumstances
a temporary one can be automatically generated).
.IP
Method 2) requires the viewer connection to appear
to come from the same machine x11vnc is running on
(e.g. from a ssh \fB-L\fR port redirection). And that the
\fB-stunnel\fR SSL mode be used for encryption over the
network.(see the description of \fB-stunnel\fR below).
.IP
Note: as a convenience, if you
.IR ssh (1)
in and start
x11vnc it will check if the environment variable
SSH_CONNECTION is set and appears reasonable. If it
does, then the \fB-ssl\fR or \fB-stunnel\fR requirement will be
dropped since it is assumed you are using ssh for the
encrypted tunnelling. \fB-localhost\fR is still enforced.
Use \fB-ssl\fR or \fB-stunnel\fR to force SSL usage even if
SSH_CONNECTION is set.
.IP
To override the above restrictions you can set
environment variables before starting x11vnc:
.IP
Set UNIXPW_DISABLE_SSL=1 to disable requiring either
\fB-ssl\fR or \fB-stunnel.\fR Evidently you will be using a
different method to encrypt the data between the
vncviewer and x11vnc: perhaps
.IR ssh (1)
or an IPSEC VPN.
.IP
Note that use of \fB-localhost\fR with
.IR ssh (1)
is roughly
the same as requiring a Unix user login (since a Unix
password or the user's public key authentication is
used by sshd on the machine where x11vnc runs and only
local connections from that machine are accepted)
.IP
Set UNIXPW_DISABLE_LOCALHOST=1 to disable the \fB-localhost\fR
requirement in Method 2). One should never do this
(i.e. allow the Unix passwords to be sniffed on the
network).
.IP
Regarding reverse connections (e.g. \fB-R\fR connect:host
and \fB-connect\fR host), when the \fB-localhost\fR constraint is
in effect then reverse connections can only be used
to connect to the same machine x11vnc is running on
(default port 5500). Please use a ssh or stunnel port
redirection to the viewer machine to tunnel the reverse
connection over an encrypted channel. Note that in \fB-ssl\fR
mode reverse connection are disabled (see below).
.IP
In \fB-inetd\fR mode the Method 1) will be enforced (not
Method 2). With \fB-ssl\fR in effect reverse connections
are disabled. If you override this via env. var, be
sure to also use encryption from the viewer to inetd.
Tip: you can also have your own stunnel spawn x11vnc
in \fB-inetd\fR mode (thereby bypassing inetd). See the FAQ
for details.
.IP
The user names in the comma separated [list] can have
per-user options after a ":", e.g. "fred:opts"
where "opts" is a "+" separated list of
"viewonly", "fullaccess", "input=XXXX", or
"deny", e.g. "karl,fred:viewonly,boss:input=M".
For "input=" it is the K,M,B,C described under \fB-input.\fR
.IP
If a user in the list is "*" that means those
options apply to all users. It also means all users
are allowed to log in after supplying a valid password.
Use "deny" to explicitly deny some users if you use
"*" to set a global option.
.IP
There are also some utilities for testing password
if [list] starts with the "%" character. See the
quick_pw() function in the source for details.
.PP
\fB-unixpw_nis\fR \fI[list]\fR
.IP
As \fB-unixpw\fR above, however do not use
.IR su (1)
but rather
use the traditional
.IR getpwnam (3)
+
.IR crypt (3)
method to
verify passwords instead. This requires that the
encrypted passwords be readable. Passwords stored
in /etc/shadow will be inaccessible unless x11vnc
is run as root.
.IP
This is called "NIS" mode simply because in most
NIS setups the user encrypted passwords are accessible
(e.g. "ypcat passwd"). NIS is not required for this
mode to work (only that
.IR getpwnam (3)
return the encrypted
password is required), but it is unlikely it will work
for any other modern environment. All of the \fB-unixpw\fR
options and contraints apply.
.PP
\fB-ssl\fR \fI[pem]\fR
.IP
Use the openssl library (www.openssl.org) to provide a
built-in encrypted SSL tunnel between VNC viewers and
x11vnc. This requires libssl support to be compiled
into x11vnc at build time. If x11vnc is not built
with libssl support it will exit immediately when \fB-ssl\fR
is prescribed.
.IP
[pem] is optional, use "\fB-ssl\fR \fI/path/to/mycert.pem\fR"
to specify a PEM certificate file to use to identify
and provide a key for this server. See
.IR openssl (1)
for
more info about PEMs and the \fB-sslGenCert\fR option below.
.IP
The connecting VNC viewer SSL tunnel can optionally
authenticate this server if they have the public
key part of the certificate (or a common certificate
authority, CA, is a more sophisicated way to verify
this server's cert, see \fB-sslGenCA\fR below). This is
used to prevent man-in-the-middle attacks. Otherwise,
if the VNC viewer accepts this server's key without
verification, at least the traffic is protected
from passive sniffing on the network (but NOT from
man-in-the-middle attacks).
.IP
If [pem] is not supplied and the
.IR openssl (1)
utility
command exists in PATH, then a temporary, self-signed
certificate will be generated for this session (this
may take 5-30 seconds on slow machines). If
.IR openssl (1)
cannot be used to generate a temporary certificate
x11vnc exits immediately.
.IP
If successful in using
.IR openssl (1)
to generate a
temporary certificate, the public part of it will be
displayed to stderr (e.g. one could copy it to the
client-side to provide authentication of the server to
VNC viewers.) See following paragraphs for how to save
keys to reuse when x11vnc is restarted.
.IP
Set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc
print out the entire certificate, including the PRIVATE
KEY part, to stderr. One could reuse this cert if saved
in a [pem] file. Similarly, set X11VNC_KEEP_TMP_PEM=1
to not delete the temporary PEM file: the file name
will be printed to stderr (so one could move it to
a safe place for reuse). You will be prompted for a
passphrase for the private key.
.IP
If [pem] is "SAVE" then the certificate will be saved
to the file ~/.vnc/certs/server.pem, or if that file
exists it will be used directly. Similarly, if [pem]
is "SAVE_PROMPT" the server.pem certificate will be
made based on your answers to its prompts for info such
as OrganizationalName, CommonName, etc.
.IP
Use "SAVE-<string>" and "SAVE_PROMPT-<string>"
to refer to the file ~/.vnc/certs/server-<string>.pem
instead. E.g. "SAVE-charlie" will store to the file
~/.vnc/certs/server-charlie.pem
.IP
See \fB-ssldir\fR below to use a directory besides the
default ~/.vnc/certs
.IP
Example: x11vnc \fB-ssl\fR SAVE \fB-display\fR :0 ...
.IP
Reverse connections are disabled in \fB-ssl\fR mode because
there is no way to ensure that data channel will
be encrypted. Set X11VNC_SSL_ALLOW_REVERSE=1 to
override this.
.IP
Your VNC viewer will also need to be able to connect
via SSL. See the discussion below under \fB-stunnel\fR and
the FAQ (ssl_vncviewer script) for how this might be
achieved. E.g. on Unix it is easy to write a shell
script that starts up stunnel and then vncviewer.
Also in the x11vnc source a SSL enabled Java VNC Viewer
applet is provided in the classes/ssl directory.
.PP
\fB-ssldir\fR \fI[dir]\fR
.IP
Use [dir] as an alternate ssl certificate and key
management toplevel directory. The default is
~/.vnc/certs
.IP
This directory is used to store server and other
certificates and keys and also other materials. E.g. in
the simplest case, "\fB-ssl\fR \fISAVE\fR" will store the x11vnc
server cert in [dir]/server.pem
.IP
Use of alternate directories via \fB-ssldir\fR allows you to
manage multiple VNC Certificate Authority (CA) keys.
Another use is if ~/.vnc/cert is on an NFS share you
might want your certificates and keys to be on a local
filesystem to prevent network snooping (for example
\fB-ssldir\fR /var/lib/x11vnc-certs).
.IP
\fB-ssldir\fR affects nearly all of the other \fB-ssl*\fR options,
e.g. \fB-ssl\fR SAVE, \fB-sslGenCert,\fR etc..
.PP
\fB-sslverify\fR \fI[path]\fR
.IP
For either of the \fB-ssl\fR or \fB-stunnel\fR modes, use [path]
to provide certificates to authenticate incoming VNC
*Client* connections (normally only the server is
authenticated in SSL.) This can be used as a method
to replace standard password authentication of clients.
.IP
If [path] is a directory it contains the client (or CA)
certificates in separate files. If [path] is a file,
it contains multiple certificates. See special tokens
below. These correspond to the "CApath = dir" and
"CAfile = file" stunnel options. See the
.IR stunnel (8)
manpage for details.
.IP
Examples:
x11vnc \fB-ssl\fR \fB-sslverify\fR ~/my.pem
x11vnc \fB-ssl\fR \fB-sslverify\fR ~/my_pem_dir/
.IP
Note that if [path] is a directory, it must contain
the certs in separate files named like <HASH>.0, where
the value of <HASH> is found by running the command
"openssl x509 \fB-hash\fR \fB-noout\fR \fB-in\fR file.crt". Evidently
one uses <HASH>.1 if there is a collision...
.IP
The the key-management utility "\fB-sslCertInfo\fR \fIHASHON\fR"
and "\fB-sslCertInfo\fR \fIHASHOFF\fR" will create/delete these
hashes for you automatically (via symlink) in the HASH
subdirs it manages. Then you can point \fB-sslverify\fR to
the HASH subdir.
.IP
Special tokens: in \fB-ssl\fR mode, if [path] is not a file or
a directory, it is taken as a comma separated list of
tokens that are interpreted as follows:
.IP
If a token is "CA" that means load the CA/cacert.pem
file from the ssl directory. If a token is "clients"
then all the files clients/*.crt in the ssl directory
are loaded. Otherwise the file clients/token.crt
is attempted to be loaded. As a kludge, use a token
like ../server-foo to load a server cert if you find
that necessary.
.IP
Use \fB-ssldir\fR to use a directory different from the
~/.vnc/certs default.
.IP
Note that if the "CA" cert is loaded you do not need
to load any of the certs that have been signed by it.
You will need to load any additional self-signed certs
however.
.IP
Examples:
x11vnc \fB-ssl\fR \fB-sslverify\fR CA
x11vnc \fB-ssl\fR \fB-sslverify\fR self:fred,self:jim
x11vnc \fB-ssl\fR \fB-sslverify\fR CA,clients
.IP
Usually "\fB-sslverify\fR \fICA\fR" is the most effective.
See the \fB-sslGenCA\fR and \fB-sslGenCert\fR options below for
how to set up and manage the CA framework.
.IP
NOTE: the following utilities, \fB-sslGenCA,\fR \fB-sslGenCert,\fR
\fB-sslEncKey,\fR and \fB-sslCertInfo\fR are provided for
completeness, but for casual usage they are overkill.
.IP
They provide VNC Certificate Authority (CA) key creation
and server / client key generation and signing. So they
provide a basic Public Key management framework for
VNC-ing with x11vnc. (note that they require
.IR openssl (1)
be installed on the system)
.IP
However, the simplest usage mode (where x11vnc
automatically generates its own, self-signed, temporary
key and the VNC viewers always accept it, e.g. accepting
via a dialog box) is probably safe enough for most
scenarios. CA management is not needed.
.IP
To protect against Man-In-The-Middle attacks the
simplest mode can be improved by using "\fB-ssl\fR \fISAVE\fR"
to have x11vnc create a longer term self-signed
certificate, and then (safely) copy the corresponding
public key cert to the desired client machines (care
must be taken the private key part is not stolen;
you will be prompted for a passphrase).
.IP
So keep in mind no CA key creation or management
(-sslGenCA and \fB-sslGenCert)\fR is needed for either of
the above two common usage modes.
.IP
One might want to use \fB-sslGenCA\fR and \fB-sslGenCert\fR
if you had a large number of VNC client and server
workstations. That way the administrator could generate
a single CA key with \fB-sslGenCA\fR and distribute its
certificate part to all of the workstations.
.IP
Next, he could create signed VNC server keys
(-sslGenCert server ...) for each workstation or user
that then x11vnc would use to authenticate itself to
any VNC client that has the CA cert.
.IP
Optionally, the admin could also make it so the
VNC clients themselves are authenticated to x11vnc
(-sslGenCert client ...) For this \fB-sslverify\fR would be
pointed to the CA cert (and/or self-signed certs).
.IP
x11vnc will be able to use all of these cert and
key files. On the VNC client side, they will need to
be "imported" somehow. Web browsers have "Manage
Certificates" actions as does the Java applet plugin
Control Panel. stunnel can also use these files (see
the ssl_vncviewer example script in the FAQ.)
.PP
\fB-sslGenCA\fR \fI[dir]\fR
.IP
Generate your own Certificate Authority private key,
certificate, and other files in directory [dir].
.IP
If [dir] is not supplied, a \fB-ssldir\fR setting is used,
or otherwise ~/.vnc/certs is used.
.IP
This command also creates directories where server and
client certs and keys will be stored. The
.IR openssl (1)
program must be installed on the system and available
in PATH.
.IP
After the CA files and directories are created the
command exits; the VNC server is not run.
.IP
You will be prompted for information to put into the CA
certificate. The info does not have to be accurate just
as long as clients accept the cert for VNC connections.
You will also need to supply a passphrase of at least
4 characters for the CA private key.
.IP
Once you have generated the CA you can distribute
its certificate part, [dir]/CA/cacert.pem, to other
workstations where VNC viewers will be run. One will
need to "import" this certicate in the applications,
e.g. Web browser, Java applet plugin, stunnel, etc.
Next, you can create and sign keys using the CA with
the \fB-sslGenCert\fR option below.
.IP
Examples:
x11vnc \fB-sslGenCA\fR
x11vnc \fB-sslGenCA\fR ~/myCAdir
x11vnc \fB-ssldir\fR ~/myCAdir \fB-sslGenCA\fR
.IP
(the last two lines are equivalent)
.PP
\fB-sslGenCert\fR \fItype\fR \fIname\fR
.IP
Generate a VNC server or client certificate and private
key pair signed by the CA created previously with
\fB-sslGenCA.\fR The
.IR openssl (1)
program must be installed
on the system and available in PATH.
.IP
After the Certificate is generated the command exits;
the VNC server is not run.
.IP
The type of key to be generated is the string \fItype\fR.
It is either "server" (i.e. for use by x11vnc) or
"client" (for a VNC viewer). Note that typically
only "server" is used: the VNC clients authenticate
themselves by a non-public-key method (e.g. VNC or
unix password). \fItype\fR is required.
.IP
An arbitrary default name you want to associate with
the key is supplied by the \fIname\fR string. You can
change it at the various prompts when creating the key.
\fIname\fR is optional.
.IP
If name is left blank for clients keys then "nobody"
is used. If left blank for server keys, then the
primary server key: "server.pem" is created (this
is the saved one referenced by "\fB-ssl\fR \fISAVE\fR" when the
server is started)
.IP
If \fIname\fR begins with the string "self:" then
a self-signed certificate is created instead of one
signed by your CA key.
.IP
If \fIname\fR begins with the string "req:" then only a
key (.key) and a certificate signing *request* (.req)
are generated. You can then send the .req file to
an external CA (even a professional one, e.g. Thawte)
and then combine the .key and the received cert into
the .pem file with the same basename.
.IP
The distinction between "server" and "client" is
simply the choice of output filenames and sub-directory.
This makes it so the \fB-ssl\fR SAVE-name option can easily
pick up the x11vnc PEM file this option generates.
And similarly makes it easy for the \fB-sslverify\fR option
to pick up your client certs.
.IP
There is nothing special about the filename or directory
location of either the "server" and "client" certs.
You can rename the files or move them to wherever
you like.
.IP
Precede this option with \fB-ssldir\fR [dir] to use a
directory other than the default ~/.vnc/certs You will
need to run \fB-sslGenCA\fR on that directory first before
doing any \fB-sslGenCert\fR key creation.
.IP
Note you cannot recreate a cert with exactly the same
distiguished name (DN) as an existing one. To do so,
you will need to edit the [dir]/CA/index.txt file to
delete the line.
.IP
Similar to \fB-sslGenCA,\fR you will be prompted to fill
in some information that will be recorded in the
certificate when it is created. Tip: if you know
the fully-quailified hostname other people will be
connecting to you can use that as the CommonName "CN"
to avoid some applications (e.g. web browsers and java
plugin) complaining it does not match the hostname.
.IP
You will also need to supply the CA private key
passphrase to unlock the private key created from
\fB-sslGenCA.\fR This private key is used to sign the server
or client certicate.
.IP
The "server" certs can be used by x11vnc directly by
pointing to them via the \fB-ssl\fR [pem] option. The default
file will be ~/.vnc/certs/server.pem. This one would
be used by simply typing \fB-ssl\fR SAVE. The pem file
contains both the certificate and the private key.
server.crt file contains the cert only.
.IP
The "client" cert + private key file will need
to be copied and imported into the VNC viewer
side applications (Web browser, Java plugin,
stunnel, etc.) Once that is done you can delete the
"client" private key file on this machine since
it is only needed on the VNC viewer side. The,
e.g. ~/.vnc/certs/clients/<name>.pem contains both
the cert and private key. The <name>.crt contains the
certificate only.
.IP
NOTE: It is very important to know one should always
generate new keys with a passphrase. Otherwise if an
untrusted user steals the key file he could use it to
masquerade as the x11vnc server (or VNC viewer client).
You will be prompted whether to encrypt the key with
a passphrase or not. It is recommended that you do.
One inconvenience to a passphrase is that it must
be suppled every time x11vnc or the client app is
started up.
.IP
Examples:
.IP
x11vnc \fB-sslGenCert\fR server
x11vnc \fB-ssl\fR SAVE \fB-display\fR :0 ...
.IP
and then on viewer using ssl_vncviewer stunnel wrapper
(see the FAQ):
ssl_vncviewer \fB-verify\fR ./cacert.crt hostname:0
.IP
(this assumes the cacert.crt cert from \fB-sslGenCA\fR
was safely copied to the VNC viewer machine where
ssl_vncviewer is run)
.IP
Example using a name:
.IP
x11vnc \fB-sslGenCert\fR server charlie
x11vnc \fB-ssl\fR SAVE-charlie \fB-display\fR :0 ...
.IP
Example for a client certificate (rarely used):
.IP
x11vnc \fB-sslGenCert\fR client roger
scp ~/.vnc/certs/clients/roger.pem somehost:.
rm ~/.vnc/certs/clients/roger.pem
.IP
x11vnc is then started with the the option \fB-sslverify\fR
~/.vnc/certs/clients/roger.crt (or simply \fB-sslverify\fR
roger), and on the viewer user on somehost could do
for example:
.IP
ssl_vncviewer \fB-mycert\fR ./roger.pem hostname:0
.PP
\fB-sslEncKey\fR \fI[pem]\fR
.IP
Utility to encrypt an existing PEM file with a
passphrase you supply when prompted. For that key to be
used (e.g. by x11vnc) the passphrase must be supplied
each time.
.IP
The "SAVE" notation described under \fB-ssl\fR applies as
well. (precede this option with \fB-ssldir\fR [dir] to refer
a directory besides the default ~/.vnc/certs)
.IP
The
.IR openssl (1)
program must be installed on the system
and available in PATH. After the Key file is encrypted
the command exits; the VNC server is not run.
.IP
Examples:
x11vnc \fB-sslEncKey\fR /path/to/foo.pem
x11vnc \fB-sslEncKey\fR SAVE
x11vnc \fB-sslEncKey\fR SAVE-charlie
.PP
\fB-sslCertInfo\fR \fI[pem]\fR
.IP
Prints out information about an existing PEM file.
In addition the public certificate is also printed.
The
.IR openssl (1)
program must be in PATH. Basically the
command "openssl x509 \fB-text"\fR is run on the pem.
.IP
The "SAVE" notation described under \fB-ssl\fR applies
as well.
.IP
Using "LIST" will give a list of all certs being
managed (in the ~/.vnc/certs dir, use \fB-ssldir\fR to refer
to another dir). "ALL" will print out the info for
every managed key (this can be very long). Giving a
client or server cert shortname will also try a lookup
(e.g. \fB-sslCertInfo\fR charlie). Use "LISTL" or "LL"
for a long (ls \fB-l\fR style) listing.
.IP
Using "HASHON" will create subdirs [dir]/HASH and
[dir]/HASH with OpenSSL hash filenames (e.g. 0d5fbbf1.0)
symlinks pointing up to the corresponding *.crt file.
([dir] is ~/.vnc/certs or one given by \fB-ssldir.)\fR
This is a useful way for other OpenSSL applications
(e.g. stunnel) to access all of the certs without
having to concatenate them. x11vnc will not use them
unless you specifically reference them. "HASHOFF"
removes these HASH subdirs.
.IP
The LIST, LISTL, LL, ALL, HASHON, HASHOFF words can
also be lowercase, e.g. "list".
.PP
\fB-sslDelCert\fR \fI[pem]\fR
.IP
Prompts you to delete all .crt .pem .key .req files
associated with [pem]. "SAVE" and lookups as in
\fB-sslCertInfo\fR apply as well.
.PP
\fB-stunnel\fR \fI[pem]\fR
.IP
Use the
.IR stunnel (8)
(www.stunnel.org) to provide an
encrypted SSL tunnel between viewers and x11vnc.
.IP
This external tunnel method was implemented prior to the
integrated \fB-ssl\fR encryption described above. It still
works well. This requires stunnel to be installed
on the system and available via PATH (n.b. stunnel is
often installed in sbin directories). Version 4.x of
stunnel is assumed (but see \fB-stunnel3\fR below.)
.IP
[pem] is optional, use "\fB-stunnel\fR \fI/path/to/stunnel.pem\fR"
to specify a PEM certificate file to pass to stunnel.
Whether one is needed or not depends on your stunnel
configuration. stunnel often generates one at install
time. See the stunnel documentation for details.
.IP
stunnel is started up as a child process of x11vnc and
any SSL connections stunnel receives are decrypted and
sent to x11vnc over a local socket. The strings
"The SSL VNC desktop is ..." and "SSLPORT=..."
are printed out at startup to indicate this.
.IP
The \fB-localhost\fR option is enforced by default
to avoid people routing around the SSL channel.
Set STUNNEL_DISABLE_LOCALHOST=1 before starting x11vnc
to disable the requirement.
.IP
Your VNC viewer will also need to be able to connect via
SSL. Unfortunately not too many do this. UltraVNC has
an encryption plugin but it does not seem to be SSL.
.IP
Also, in the x11vnc distribution, a patched TightVNC
Java applet is provided in classes/ssl that does SSL
connections (only).
.IP
It is also not too difficult to set up an stunnel or
other SSL tunnel on the viewer side. A simple example
on Unix using stunnel 3.x is:
.IP
% stunnel \fB-c\fR \fB-d\fR localhost:5901 \fB-r\fR remotehost:5900
% vncviewer localhost:1
.IP
For Windows, stunnel has been ported to it and there
are probably other such tools available. See the FAQ
for more examples.
.PP
\fB-stunnel3\fR \fI[pem]\fR
.IP
Use version 3.x stunnel command line syntax instead of
version 4.x
.PP
\fB-https\fR \fI[port]\fR
.IP
Choose a separate HTTPS port (-ssl mode only).
.IP
In \fB-ssl\fR mode, it turns out you can use the
single VNC port (e.g. 5900) for both VNC and HTTPS
connections. (HTTPS is used to retrieve a SSL-aware
VncViewer.jar applet that is provided with x11vnc).
Since both use SSL the implementation was extended to
detect if HTTP traffic (i.e. GET) is taking place and
handle it accordingly. The URL would be, e.g.:
.IP
https://mymachine.org:5900/
.IP
This is convenient for firewalls, etc, because only one
port needs to be allowed in. However, this heuristic
adds a few seconds delay to each connection and can be
unreliable (especially if the user takes much time to
ponder the Certificate dialogs in his browser, Java VM,
or VNC Viewer applet. That's right 3 separate "Are
you sure you want to connect" dialogs!)
.IP
So use the \fB-https\fR option to provide a separate, more
reliable HTTPS port that x11vnc will listen on. If
[port] is not provided (or is 0), one is autoselected.
The URL to use is printed out at startup.
.IP
The SSL Java applet directory is specified via the
\fB-httpdir\fR option. If not supplied it will try to guess
the directory as though the \fB-http\fR option was supplied.
.PP
\fB-usepw\fR \fB-usepw\fR
.IP .IP
If no other password method was supplied on the command If no other password method was supplied on the command
@ -1214,9 +524,6 @@ use it with \fB-passwdfile;\fR otherwise, prompt the user
for a password to create ~/.vnc/passwd and use it with for a password to create ~/.vnc/passwd and use it with
the \fB-rfbauth\fR option. If none of these succeed x11vnc the \fB-rfbauth\fR option. If none of these succeed x11vnc
exits immediately. exits immediately.
.IP
Note: \fB-unixpw\fR currently does not count as a password
method by this option.
.PP .PP
\fB-storepasswd\fR \fIpass\fR \fIfile\fR \fB-storepasswd\fR \fIpass\fR \fIfile\fR
.IP .IP
@ -1600,6 +907,39 @@ e.g. !, @, [, are only accessible via \fB-xkb\fR mode and if
so then automatically enable the mode. To disable this so then automatically enable the mode. To disable this
automatic detection use \fB-noxkb.\fR automatic detection use \fB-noxkb.\fR
.PP .PP
\fB-capslock\fR
.IP
When in \fB-modtweak\fR (the default) or \fB-xkb\fR mode,
if a keysym in the range A-Z comes in check the X
server to see if the Caps_Lock is set. If it is do
not artificially press Shift to generate the keysym.
This will enable the CapsLock key to behave correctly
in some circumstances: namely *both* the VNC viewer
machine and the x11vnc X server are in the CapsLock
on state. If one side has CapsLock on and the other
off and the keyboard is not behaving as you think it
should you should correct the CapsLock states (hint:
pressing CapsLock inside and outside of the viewer can
help toggle them both to the correct state). However,
for best results do not use this option, but rather
*only* enable CapsLock on the VNC viewer side (i.e. by
pressing CapsLock outside of the viewer window, also
\fB-skip_lockkeys\fR below). Also try \fB-nomodtweak\fR for a
possible workaround.
.PP
\fB-skip_lockkeys\fR
.IP
Have x11vnc ignore all Caps_Lock, Shift_Lock, Num_Lock,
Scroll_Lock keysyms received from viewers. The idea is
you press Caps_Lock on the VNC Viewer side but that does
not change the lock state in the x11vnc-side X server.
Nevertheless your capitalized letters come in over
the wire and are applied correctly to the x11vnc-side
X server. Note this mode probably won't do what you
want in \fB-nomodtweak\fR mode. Also, a kludge for KP_n
digits is always done it this mode: they are mapped to
regular digit keysyms. See also \fB-capslock\fR above.
.PP
\fB-skip_keycodes\fR \fIstring\fR \fB-skip_keycodes\fR \fIstring\fR
.IP .IP
Ignore the comma separated list of decimal keycodes. Ignore the comma separated list of decimal keycodes.
@ -1667,6 +1007,9 @@ To map a key to a button click, use the fake Keysyms
"Button1", ..., etc. E.g: "\fB-remap\fR \fISuper_R-Button2\fR" "Button1", ..., etc. E.g: "\fB-remap\fR \fISuper_R-Button2\fR"
(useful for pasting on a laptop) (useful for pasting on a laptop)
.IP .IP
To disable a keysym (i.e. make it so it will not be
injected), remap it to "NoSymbol" or "None".
.IP
Dead keys: "dead" (or silent, mute) keys are keys that Dead keys: "dead" (or silent, mute) keys are keys that
do not produce a character but must be followed by a 2nd do not produce a character but must be followed by a 2nd
keystroke. This is often used for accenting characters, keystroke. This is often used for accenting characters,
@ -2848,6 +2191,10 @@ Up and Down arrows adjust the station (if a tuner)
F1, F2, ..., F6 will switch the video capture pixel F1, F2, ..., F6 will switch the video capture pixel
format to HI240, RGB565, RGB24, RGB32, RGB555, and format to HI240, RGB565, RGB24, RGB32, RGB555, and
GREY respectively. See \fB-rawfb\fR video for details. GREY respectively. See \fB-rawfb\fR video for details.
.IP
If cmd is "CONS" or "CONSn" where n is a Linux
console number, then the linux console keystroke
insertion (see \fB-rawfb\fR cons) is performed.
.PP .PP
\fB-gui\fR \fI[gui-opts]\fR \fB-gui\fR \fI[gui-opts]\fR
.IP .IP
@ -3165,6 +2512,14 @@ xkb enable \fB-xkb\fR modtweak mode.
.IP .IP
noxkb disable \fB-xkb\fR modtweak mode. noxkb disable \fB-xkb\fR modtweak mode.
.IP .IP
capslock enable \fB-capslock\fR mode.
.IP
nocapslock disable \fB-capslock\fR mode.
.IP
skip_lockkeys enable \fB-skip_lockkeys\fR mode.
.IP
noskip_lockkeys disable \fB-skip_lockkeys\fR mode.
.IP
skip_keycodes:str enable \fB-xkb\fR \fB-skip_keycodes\fR "str". skip_keycodes:str enable \fB-xkb\fR \fB-skip_keycodes\fR "str".
.IP .IP
sloppy_keys enable \fB-sloppy_keys\fR mode. sloppy_keys enable \fB-sloppy_keys\fR mode.
@ -3502,8 +2857,9 @@ unlock connect allowonce allow localhost nolocalhost
listen lookup nolookup accept afteraccept gone shm listen lookup nolookup accept afteraccept gone shm
noshm flipbyteorder noflipbyteorder onetile noonetile noshm flipbyteorder noflipbyteorder onetile noonetile
solid_color solid nosolid blackout xinerama noxinerama solid_color solid nosolid blackout xinerama noxinerama
xtrap noxtrap xrandr noxrandr xrandr_mode padgeom quiet xtrap noxtrap xrandr noxrandr xrandr_mode padgeom
q noquiet modtweak nomodtweak xkb noxkb skip_keycodes quiet q noquiet modtweak nomodtweak xkb noxkb capslock
nocapslock skip_lockkeys noskip_lockkeys skip_keycodes
sloppy_keys nosloppy_keys skip_dups noskip_dups sloppy_keys nosloppy_keys skip_dups noskip_dups
add_keysyms noadd_keysyms clear_mods noclear_mods add_keysyms noadd_keysyms clear_mods noclear_mods
clear_keys noclear_keys remap repeat norepeat fb nofb clear_keys noclear_keys remap repeat norepeat fb nofb
@ -3541,8 +2897,7 @@ http_url auth xauth users rootshift clipshift
scale_str scaled_x scaled_y scale_numer scale_denom scale_str scaled_x scaled_y scale_numer scale_denom
scale_fac scaling_blend scaling_nomult4 scaling_pad scale_fac scaling_blend scaling_nomult4 scaling_pad
scaling_interpolate inetd privremote unsafe safer nocmds scaling_interpolate inetd privremote unsafe safer nocmds
passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem passwdfile usepw using_shm
sslverify stunnel stunnel_pem https usepw using_shm
logfile o flag rc norc h help V version lastmod bg logfile o flag rc norc h help V version lastmod bg
sigpipe threads readrate netrate netlatency pipeinput sigpipe threads readrate netrate netlatency pipeinput
clients client_count pid ext_xtest ext_xtrap ext_xrecord clients client_count pid ext_xtest ext_xtrap ext_xrecord
@ -3658,6 +3013,14 @@ max time in ms to wait for RFB client
use authentication on RFB protocol use authentication on RFB protocol
(use 'storepasswd' to create a password file) (use 'storepasswd' to create a password file)
.PP .PP
\fB-rfbversion\fR \fI3.x\fR
.IP
Set the version of the RFB we choose to advertise
.PP
\fB-permitfiletransfer\fR
.IP
permit file transfer support
.PP
\fB-passwd\fR \fIplain-password\fR \fB-passwd\fR \fIplain-password\fR
.IP .IP
use authentication use authentication

@ -239,7 +239,11 @@ static void record_last_fb_update(void) {
iter = rfbGetClientIterator(screen); iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) { while( (cl = rfbClientIteratorNext(iter)) ) {
#if 0
rbs += cl->rawBytesEquivalent; rbs += cl->rawBytesEquivalent;
#else
rbs += rfbStatGetSentBytesIfRaw(cl);
#endif
} }
rfbReleaseClientIterator(iter); rfbReleaseClientIterator(iter);
@ -467,7 +471,7 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
} }
check_new_clients(); check_new_clients();
check_xevents(); check_xevents(0);
check_autorepeat(); check_autorepeat();
check_pm(); check_pm();
check_keycode_state(); check_keycode_state();
@ -1384,6 +1388,7 @@ int main(int argc, char* argv[]) {
int dt = 0, bg = 0; int dt = 0, bg = 0;
int got_rfbwait = 0; int got_rfbwait = 0;
int got_httpdir = 0, try_http = 0; int got_httpdir = 0, try_http = 0;
XImage *fb0 = NULL;
/* used to pass args we do not know about to rfbGetScreen(): */ /* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc = 1; char *argv_vnc[128]; int argc_vnc = 1; char *argv_vnc[128];
@ -1592,6 +1597,7 @@ int main(int argc, char* argv[]) {
CHECK_ARGC CHECK_ARGC
passwdfile = strdup(argv[++i]); passwdfile = strdup(argv[++i]);
got_passwdfile = 1; got_passwdfile = 1;
#ifndef REL81
} else if (strstr(arg, "-unixpw") == arg) { } else if (strstr(arg, "-unixpw") == arg) {
unixpw = 1; unixpw = 1;
if (strstr(arg, "-unixpw_nis")) { if (strstr(arg, "-unixpw_nis")) {
@ -1709,6 +1715,7 @@ int main(int argc, char* argv[]) {
i++; i++;
} }
} }
#endif
} else if (!strcmp(arg, "-nopw")) { } else if (!strcmp(arg, "-nopw")) {
nopw = 1; nopw = 1;
} else if (!strcmp(arg, "-usepw")) { } else if (!strcmp(arg, "-usepw")) {
@ -1826,6 +1833,10 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-noxkb")) { } else if (!strcmp(arg, "-noxkb")) {
use_xkb_modtweak = 0; use_xkb_modtweak = 0;
got_noxkb = 1; got_noxkb = 1;
} else if (!strcmp(arg, "-capslock")) {
watch_capslock = 1;
} else if (!strcmp(arg, "-skip_lockkeys")) {
skip_lockkeys = 1;
} else if (!strcmp(arg, "-xkbcompat")) { } else if (!strcmp(arg, "-xkbcompat")) {
xkbcompat = 1; xkbcompat = 1;
} else if (!strcmp(arg, "-skip_keycodes")) { } else if (!strcmp(arg, "-skip_keycodes")) {

@ -114,6 +114,8 @@
#define PASSWD_UNLESS_NOPW 0 #define PASSWD_UNLESS_NOPW 0
#endif #endif
#define REL81
/* /*
* Beginning of support for small binary footprint build for embedded * Beginning of support for small binary footprint build for embedded
* systems, PDA's etc. It currently just cuts out the low-hanging * systems, PDA's etc. It currently just cuts out the low-hanging
@ -234,7 +236,6 @@ extern int h_errno;
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
/* XXX autoconf */
#if LIBVNCSERVER_HAVE_PWD_H #if LIBVNCSERVER_HAVE_PWD_H
#include <pwd.h> #include <pwd.h>
#endif #endif
@ -335,7 +336,6 @@ extern int num_buttons;
extern XImage *scanline; extern XImage *scanline;
extern XImage *fullscreen; extern XImage *fullscreen;
extern XImage **tile_row; /* for all possible row runs */ extern XImage **tile_row; /* for all possible row runs */
extern XImage *fb0;
extern XImage *snaprect; /* for XShmGetImage (fs_factor) */ extern XImage *snaprect; /* for XShmGetImage (fs_factor) */
extern XImage *snap; /* the full snap fb */ extern XImage *snap; /* the full snap fb */
extern XImage *raw_fb_image; /* the raw fb */ extern XImage *raw_fb_image; /* the raw fb */
@ -373,6 +373,7 @@ extern int raw_fb_shm;
extern int raw_fb_mmap; extern int raw_fb_mmap;
extern int raw_fb_seek; extern int raw_fb_seek;
extern int raw_fb_fd; extern int raw_fb_fd;
extern int raw_fb_back_to_X;
extern int rfb_bytes_per_line; extern int rfb_bytes_per_line;
extern int main_bytes_per_line; extern int main_bytes_per_line;

@ -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.1 lastmod: 2006-05-06"; char lastmod[] = "0.8.1 lastmod: 2006-06-03";
/* X display info */ /* X display info */
@ -37,7 +37,6 @@ int num_buttons = -1;
XImage *scanline = NULL; XImage *scanline = NULL;
XImage *fullscreen = NULL; XImage *fullscreen = NULL;
XImage **tile_row = NULL; /* for all possible row runs */ XImage **tile_row = NULL; /* for all possible row runs */
XImage *fb0 = NULL;
XImage *snaprect = NULL; /* for XShmGetImage (fs_factor) */ XImage *snaprect = NULL; /* for XShmGetImage (fs_factor) */
XImage *snap = NULL; /* the full snap fb */ XImage *snap = NULL; /* the full snap fb */
XImage *raw_fb_image = NULL; /* the raw fb */ XImage *raw_fb_image = NULL; /* the raw fb */
@ -58,13 +57,14 @@ char *rfb_fb = NULL; /* same as main_fb unless transformation */
char *fake_fb = NULL; /* used under -padgeom */ char *fake_fb = NULL; /* used under -padgeom */
char *snap_fb = NULL; /* used under -snapfb */ char *snap_fb = NULL; /* used under -snapfb */
char *cmap8to24_fb = NULL; /* used under -8to24 */ char *cmap8to24_fb = NULL; /* used under -8to24 */
char *raw_fb = NULL; char *raw_fb = NULL; /* when used should be main_fb */
char *raw_fb_addr = NULL; char *raw_fb_addr = NULL;
int raw_fb_offset = 0; int raw_fb_offset = 0;
int raw_fb_shm = 0; int raw_fb_shm = 0;
int raw_fb_mmap = 0; int raw_fb_mmap = 0;
int raw_fb_seek = 0; 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 rfb_bytes_per_line; int rfb_bytes_per_line;
int main_bytes_per_line; int main_bytes_per_line;

@ -12,6 +12,7 @@
#include "gui.h" #include "gui.h"
#include "connections.h" #include "connections.h"
#include "unixpw.h" #include "unixpw.h"
#include "cleanup.h"
/* XXX CHECK BEFORE RELEASE */ /* XXX CHECK BEFORE RELEASE */
int grab_buster = 0; int grab_buster = 0;
@ -24,11 +25,11 @@ void spawn_grab_buster(void);
void sync_tod_with_servertime(void); void sync_tod_with_servertime(void);
void check_keycode_state(void); void check_keycode_state(void);
void check_autorepeat(void); void check_autorepeat(void);
void check_xevents(void); void check_xevents(int reset);
void xcut_receive(char *text, int len, rfbClientPtr cl); void xcut_receive(char *text, int len, rfbClientPtr cl);
static void initialize_xevents(void); static void initialize_xevents(int reset);
static void print_xevent_bases(void); static void print_xevent_bases(void);
static void get_prop(char *str, int len, Atom prop); static void get_prop(char *str, int len, Atom prop);
static void bust_grab(int reset); static void bust_grab(int reset);
@ -62,7 +63,7 @@ void initialize_clipboard_atom(void) {
} }
} }
static void initialize_xevents(void) { static void initialize_xevents(int reset) {
static int did_xselect_input = 0; static int did_xselect_input = 0;
static int did_xcreate_simple_window = 0; static int did_xcreate_simple_window = 0;
static int did_vnc_connect_prop = 0; static int did_vnc_connect_prop = 0;
@ -73,6 +74,18 @@ static void initialize_xevents(void) {
static int did_xrandr = 0; static int did_xrandr = 0;
RAWFB_RET_VOID RAWFB_RET_VOID
if (reset) {
did_xselect_input = 0;
did_xcreate_simple_window = 0;
did_vnc_connect_prop = 0;
did_x11vnc_remote_prop = 0;
did_clipboard_atom = 0;
did_xfixes = 0;
did_xdamage = 0;
did_xrandr = 0;
}
if ((watch_selection || vnc_connect) && !did_xselect_input) { if ((watch_selection || vnc_connect) && !did_xselect_input) {
/* /*
* register desired event(s) for notification. * register desired event(s) for notification.
@ -688,7 +701,7 @@ void check_autorepeat(void) {
* This routine is periodically called to check for selection related * This routine is periodically called to check for selection related
* and other X11 events and respond to them as needed. * and other X11 events and respond to them as needed.
*/ */
void check_xevents(void) { void check_xevents(int reset) {
XEvent xev; XEvent xev;
int tmp, have_clients = 0; int tmp, have_clients = 0;
static int sent_some_sel = 0; static int sent_some_sel = 0;
@ -699,14 +712,18 @@ void check_xevents(void) {
static time_t last_time_sync = 0; static time_t last_time_sync = 0;
time_t now = time(0); time_t now = time(0);
static double last_request = 0.0; static double last_request = 0.0;
XErrorHandler old_handler;
RAWFB_RET_VOID RAWFB_RET_VOID
if (unixpw_in_progress) return; if (unixpw_in_progress) return;
if (now > last_init_check+1) { if (now > last_init_check+1 || reset) {
last_init_check = now; last_init_check = now;
initialize_xevents(); initialize_xevents(reset);
if (reset) {
return;
}
} }
if (screen && screen->clientHead) { if (screen && screen->clientHead) {
@ -719,6 +736,7 @@ void check_xevents(void) {
* the client... so instead of sending right away we wait a * the client... so instead of sending right away we wait a
* the few seconds. * the few seconds.
*/ */
if (have_clients && watch_selection && !sent_some_sel if (have_clients && watch_selection && !sent_some_sel
&& now > last_client + sel_waittime) { && now > last_client + sel_waittime) {
if (XGetSelectionOwner(dpy, XA_PRIMARY) == None) { if (XGetSelectionOwner(dpy, XA_PRIMARY) == None) {
@ -741,6 +759,10 @@ void check_xevents(void) {
if (now > last_call+1) { if (now > last_call+1) {
/* we only check these once a second or so. */ /* we only check these once a second or so. */
int n = 0; int n = 0;
trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror);
while (XCheckTypedEvent(dpy, MappingNotify, &xev)) { while (XCheckTypedEvent(dpy, MappingNotify, &xev)) {
XRefreshKeyboardMapping((XMappingEvent *) &xev); XRefreshKeyboardMapping((XMappingEvent *) &xev);
n++; n++;
@ -769,6 +791,9 @@ void check_xevents(void) {
while (XCheckTypedEvent(dpy, ClientMessage, &xev)) { while (XCheckTypedEvent(dpy, ClientMessage, &xev)) {
; ;
} }
XSetErrorHandler(old_handler);
trapped_xerror = 0;
} }
/* check for CUT_BUFFER0 and VNC_CONNECT changes: */ /* check for CUT_BUFFER0 and VNC_CONNECT changes: */
@ -908,6 +933,9 @@ void check_xevents(void) {
if (own_primary || own_clipboard) { if (own_primary || own_clipboard) {
/* we own PRIMARY or CLIPBOARD, see if someone requested it: */ /* we own PRIMARY or CLIPBOARD, see if someone requested it: */
trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror);
if (XCheckTypedEvent(dpy, SelectionRequest, &xev)) { if (XCheckTypedEvent(dpy, SelectionRequest, &xev)) {
if (own_primary && xev.type == SelectionRequest && if (own_primary && xev.type == SelectionRequest &&
xev.xselectionrequest.selection == XA_PRIMARY) { xev.xselectionrequest.selection == XA_PRIMARY) {
@ -944,6 +972,9 @@ void check_xevents(void) {
} }
} }
} }
XSetErrorHandler(old_handler);
trapped_xerror = 0;
} }
if (watch_bell || now > last_bell+1) { if (watch_bell || now > last_bell+1) {

@ -13,7 +13,7 @@ extern void spawn_grab_buster(void);
extern void sync_tod_with_servertime(void); extern void sync_tod_with_servertime(void);
extern void check_keycode_state(void); extern void check_keycode_state(void);
extern void check_autorepeat(void); extern void check_autorepeat(void);
extern void check_xevents(void); extern void check_xevents(int reset);
extern void xcut_receive(char *text, int len, rfbClientPtr cl); extern void xcut_receive(char *text, int len, rfbClientPtr cl);
#endif /* _X11VNC_XEVENTS_H */ #endif /* _X11VNC_XEVENTS_H */

@ -265,6 +265,7 @@ XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth,
xi->bitmap_pad = bitmap_pad; xi->bitmap_pad = bitmap_pad;
xi->bytes_per_line = bytes_per_line ? bytes_per_line : xi->bytes_per_line = bytes_per_line ? bytes_per_line :
xi->width * xi->bits_per_pixel / 8; xi->width * xi->bits_per_pixel / 8;
xi->bitmap_unit = -1; /* hint to not call XDestroyImage */
return xi; return xi;
} }

Loading…
Cancel
Save