From 3129ef668abf2b3f9b624bdb4c5ac0365ae2583b Mon Sep 17 00:00:00 2001 From: runge Date: Thu, 8 Oct 2009 17:30:36 -0400 Subject: Huge number of changes, see x11vnc/ChangeLog --- .../tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch | 7 +- x11vnc/ChangeLog | 34 + x11vnc/README | 1598 ++++--- x11vnc/connections.c | 519 ++- x11vnc/connections.h | 5 + x11vnc/enc.h | 3 +- x11vnc/help.c | 496 +- x11vnc/keyboard.c | 7 +- x11vnc/options.c | 7 + x11vnc/options.h | 7 + x11vnc/params.h | 4 +- x11vnc/remote.c | 488 +- x11vnc/remote.h | 3 + x11vnc/screen.c | 177 +- x11vnc/selection.c | 49 +- x11vnc/selection.h | 1 + x11vnc/solid.c | 125 +- x11vnc/solid.h | 1 + x11vnc/sslcmds.c | 97 +- x11vnc/sslcmds.h | 2 +- x11vnc/sslhelper.c | 4903 ++++++++++---------- x11vnc/sslhelper.h | 2 + x11vnc/ssltools.h | 94 +- x11vnc/tkx11vnc | 78 +- x11vnc/tkx11vnc.h | 78 +- x11vnc/unixpw.c | 402 +- x11vnc/unixpw.h | 2 +- x11vnc/user.c | 77 +- x11vnc/util.c | 73 +- x11vnc/util.h | 2 +- x11vnc/x11vnc.1 | 541 ++- x11vnc/x11vnc.c | 179 +- x11vnc/x11vnc_defs.c | 2 +- x11vnc/xdamage.c | 56 +- x11vnc/xdamage.h | 2 + x11vnc/xevents.c | 181 +- x11vnc/xevents.h | 2 +- x11vnc/xwrappers.c | 2 - 38 files changed, 6737 insertions(+), 3569 deletions(-) diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch index 22eeede..bb70214 100644 --- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch +++ b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch @@ -73,8 +73,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java --- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_javasrc/SSLSocketToMe.java 2009-06-19 10:23:50.000000000 -0400 -@@ -0,0 +1,1726 @@ ++++ vnc_javasrc/SSLSocketToMe.java 2009-08-13 09:16:42.000000000 -0400 +@@ -0,0 +1,1727 @@ +/* + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. + * @@ -83,7 +83,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. ++ * the Free Software Foundation; version 2 of the License, or ++ * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 4ce858b..f66a563 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,37 @@ +2009-10-08 Karl Runge + * x11vnc: bcx_xattach/x2x desktop switching facility. + More remote control features: grab_state, ping:mystring, + grablocal, resend_cutbuffer, resend_clipboard, resend_primary, + keycode, keysym, ptr, sleep, get_xprop, set_xprop, wininfo, + pointer_pos, mouse_xy, noop, guess_dbus Add DIRECT: for + remote control w/o server. X11VNC_NO_CHECK_PM for more + quiet DIRECT: usage. Options -query_retries, -remote_prefix, + and X11VNC_SYNC_TIMEOUT for remote control. Add scripting + to remote control. ping clients during in unixpw login. + Option -unixpw_system_greeter as shortcut to XDM/GDM/etc panel. + Add clear_all, viewonly, nodisplay, to unixpw username:opts. + F1 help for options (including smaller console font). + Document FD_TAG. Eat multiple property change events in one + sitting (also PROP_DBG=1). Support more -ssl features (special + cert names, single port, client certs, etc.) in -stunnel + external SSL helper mode. Reorganize openssl code to allow + integration with stunnel features if not compiled with openssl. + X11VNC_HTTPS_VS_VNC_TIMEOUT Fix dbus session address for -solid + in gnome. Use dbus-launch in -create mode if available. + X11VNC_SKIP_DISPLAY=all in -find/-create mode. let noxauth + unset XAUTHORITY for use with su - $USER. CREATE_DISPLAY_EXEC + debugging. Add x_terminal_emulator to -create cmd search. + Option -extra_fbur to tune fb update requests tracking; make + default tracking more aggressive. RATE_VERB/CHECK_RATE env. for + fbur rate. Env. vars to set Tk gui fonts. Catch closed + socket reads/writes. Try to detect 'crazy' xdamage insertion, + e.g. from some xscreensavers (needs work.). Don't switch + on server autorepeat if any keys are pressed down to work + around Xorg server and/or gnome bug. If PATH is empty, set + it to minimal one. Fix bug with -bg and -dp/-dk printout if + logfile present. + * classes/ssl: license statement. + 2009-06-18 Karl Runge * classes/ssl: java viewer now handles auth-basic proxy logins. * misc/enhanced_tightvnc_viewer: update ssvnc. diff --git a/x11vnc/README b/x11vnc/README index 80269e3..a04c02a 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -2,7 +2,7 @@ Copyright (C) 2002-2009 Karl J. Runge All rights reserved. -x11vnc README file Date: Mon Aug 10 13:38:13 EDT 2009 +x11vnc README file Date: Wed Oct 7 23:29:05 EDT 2009 The following information is taken from these URLs: @@ -908,21 +908,54 @@ make the environment variable "RFB_UNIXPW_CMD_RUN" as the logged-in user. The mode "[126]-unixpw_nis ..." has also been made more consistent. + * The [127]-unixpw_system_greeter option, when used in combined + unixpw and XDMCP FINDCREATEDISPLAY mode (e.g. [128]-xdmsvc), + enables the user to press Escape to jump directly to the + XDM/GDM/KDM login greeter screen. This way the user avoids + entering his unix password twice at X session creation time. Also, + the unixpw login panel now has a short help displayed if the user + presses 'F1'. + * The [129]-stunnel option (like [130]-ssl but uses stunnel as an + external helper program) now works with the [131]-ssl "SAVE" and + "TMP" special certificate names. The [132]-sslverify and + [133]-sslCRL options now work correctly in [134]-stunnel mode. + Single port HTTPS connections are also supported for this mode. + * x11vnc now tries to be a little bit more aggressive in keeping up + with VNC client's framebuffer update requests. Some broken VNC + clients like Eggplant and JollysFastVNC continuously spray these + requests at VNC servers (regardless of whether they have received + any updates or not.) Under some circumstances this could lead to + x11vnc falling behind. The [135]-extra_fbur option allows one to + fine tune the setting. Additionally, one may also dial down + delays: e.g. "[136]-defer 5" and "[137]-wait 5" (or to 1 or even + 0) or [138]-nonap or [139]-allinput to keep up with these VNC + clients at the expense of increased system load. + * The XDAMAGE mechanism is now automatically disabled for a period + of time if a game or screensaver generates too many XDAMAGE + rectangles per second. This avoids the X11 event queue from + soaking up too much memory. + * The fonts in the GUI ([140]-gui) can now by set via environment + variables, e.g. -env X11VNC_FONT_BOLD='Helvetica -16 bold' and + -env X11VNC_FONT_FIXED='Courier -14'. + * The remote control command [141]-R can be used to instruct x11vnc + to resend its most recent copy of the Clipboard, Primary, or + Cutbuffer selections: "x11vnc -R resend_clipboard", "x11vnc -R + resend_primary", and "x11vnc -R resend_cutbuffer". * There is an experimental workaround: "-env X11VNC_WATCH_DX_DY=1" that tries to avoid problems with poorly constructed menu themes that place the initial position of the mouse cursor inside a menu - item's active zone. More information [127]can be found here. + item's active zone. More information [142]can be found here. Here are some features that appeared in the 0.9.8 release: - * Stability improvements to [128]-threads mode. Running x11vnc this + * Stability improvements to [143]-threads mode. Running x11vnc this way is more reliable now. Threaded operation sometimes gives better interactive response and faster updates: try it out. The threaded mode now supports multiple VNC viewers using the same VNC encoding. The threaded mode can also yield a performance enhancement in the many client case (e.g. class-room broadcast.) We have tested with 30 to 50 simultaneous clients. See also - [129]-reflect. + [144]-reflect. For simultaneous clients: the ZRLE encoding is thread safe on all platforms, and the Tight and Zlib encodings are currently only thread safe on Linux where thread local storage, __thread, is @@ -931,12 +964,12 @@ make connected client, all encodings are safe on all platforms. Note that some features (e.g. scroll detection and -ncache) may be disabled or run with reduced functionality in -threads mode. - * Automatically tries to work around an [130]Xorg server bug + * Automatically tries to work around an [145]Xorg server bug involving infinitely repeating keys when turning off key - repeating. Use [131]-repeat if the automatic workaround fails. + repeating. Use [146]-repeat if the automatic workaround fails. * Improved reliability of the Single Port SSL VNC and HTTPS java viewer applet delivery mechanism. - * The [132]-clip mode works under [133]-rawfb. + * The [147]-clip mode works under [148]-rawfb. Here are some features that appeared in the 0.9.7 release: @@ -946,38 +979,38 @@ make case the special file /dev/vcsa2 is used to retrieve vt2's current text. Text and colors are shown, but no graphics. * Support for less than 8 bits per pixel framebuffers (e.g. 4 or 1 - bpp) in the [134]-rawfb mode. + bpp) in the [149]-rawfb mode. * The SSL enabled UltraVNC Java viewer applet now has a [Home] entry in the "drives" drop down menu. This menu can be configured with the ftpDropDown applet parameter. All of the applet parameters are documented in classes/ssl/README. - * Experimental support for [135]VirtualGL's [136]TurboVNC (an + * Experimental support for [150]VirtualGL's [151]TurboVNC (an enhanced TightVNC for fast LAN high framerate usage.) * The CUPS Terminal Services helper mode has been improved. - * Improvements to the [137]-ncache_cr that allows smooth opaque + * Improvements to the [152]-ncache_cr that allows smooth opaque window motions using the 'copyrect' encoding when using - [138]-ncache mode. - * The [139]-rmflag option enables a way to indicate to other + [153]-ncache mode. + * The [154]-rmflag option enables a way to indicate to other processes x11vnc has exited. * Reverse connections using anonymous Diffie Hellman SSL encryption now work. Here are some features that appeared in the 0.9.6 release: - * Support for [140]VeNCrypt SSL/TLS encrypted connections. It is - enabled by default in the [141]-ssl mode. VNC Viewers like + * Support for [155]VeNCrypt SSL/TLS encrypted connections. It is + enabled by default in the [156]-ssl mode. VNC Viewers like vinagre, gvncviewer/gtk-vnc, the vencrypt package, and others support this encryption mode. It can also be used with the - [142]-unixpw option to enable Unix username and password + [157]-unixpw option to enable Unix username and password authentication (VeNCrypt's "*Plain" modes.) A similar but older VNC security type "ANONTLS" (used by vino) is supported as well. - See the [143]-vencrypt and [144]-anontls options for additional + See the [158]-vencrypt and [159]-anontls options for additional control. The difference between x11vnc's normal -ssl mode and VeNCrypt is that the former wraps the entire VNC connection in SSL (like HTTPS does for HTTP, i.e. "vncs://") while VeNCrypt switches on the SSL/TLS at a certain point during the VNC handshake. Use - [145]-sslonly to disable both VeNCrypt and ANONTLS (vino.) - * The "[146]-ssl ANON" option enables Anonymous Diffie-Hellman (ADH) + [160]-sslonly to disable both VeNCrypt and ANONTLS (vino.) + * The "[161]-ssl ANON" option enables Anonymous Diffie-Hellman (ADH) key exchange for x11vnc's normal SSL/TLS operation. Note that Anonymous Diffie-Hellman uses encryption for privacy, but provides no authentication and so is susceptible to Man-In-The-Middle @@ -985,17 +1018,17 @@ make SAVE", etc. and have the VNC viewer verify the cert.) The ANONTLS mode (vino) only supports ADH. VeNCrypt mode supports both ADH and regular X509 SSL certificates modes. For these ADH is enabled by - default. See [147]-vencrypt and [148]-anontls for how to disable + default. See [162]-vencrypt and [163]-anontls for how to disable ADH. * For x11vnc's SSL/TLS modes, one can now specify a Certificate - Revocation List (CRL) with the [149]-sslCRL option. This will only + Revocation List (CRL) with the [164]-sslCRL option. This will only be useful for wide deployments: say a company-wide x11vnc SSL access deployment using a central Certificate Authority (CA) via - [150]-sslGenCA and [151]-sslGenCert. This way if a user has his + [165]-sslGenCA and [166]-sslGenCert. This way if a user has his laptop lost or stolen, you only have to revoke his key instead of creating a new Certificate Authority and redeploying new keys to all users. - * The default SSL/TLS mode, "[152]-ssl" (no pem file parameter + * The default SSL/TLS mode, "[167]-ssl" (no pem file parameter supplied), is now the same as "-ssl SAVE" and will save the generated self-signed cert in "~/.vnc/certs/server.pem". Previously "-ssl" would create a temporary self-signed cert that @@ -1005,45 +1038,45 @@ make same x11vnc server. Use "-ssl TMP" to regain the previous behavior. Use "-ssl SAVE_NOPROMPT" to avoid being prompted about using passphrase when the certificate is created. - * The option [153]-http_oneport enables single-port HTTP connections + * The option [168]-http_oneport enables single-port HTTP connections via the Java VNC Viewer. So, for example, the web browser URL "http://myhost.org:5900" works the same as "http://myhost.org:5800", but with the convenience of only involving one port instead of two. This works for both unencrypted - connections and for SSH tunnels (see [154]-httpsredir if the + connections and for SSH tunnels (see [169]-httpsredir if the tunnel port differs.) Note that HTTPS single-port operation in - [155]-ssl SSL encrypted mode has been available since x11vnc + [170]-ssl SSL encrypted mode has been available since x11vnc version 0.8.3. - * For the [156]-avahi/[157]-zeroconf Service Advertizing mode, if + * For the [171]-avahi/[172]-zeroconf Service Advertizing mode, if x11vnc was not compiled with the avahi-client library, then an external helper program, either avahi-publish(1) (on Unix) or dns-sd(1) (on Mac OS X), is used instead. - * The "[158]-rfbport PROMPT" option will prompt the user via the GUI + * The "[173]-rfbport PROMPT" option will prompt the user via the GUI to select the VNC port (e.g. 5901) to listen on, and a few other basic settings. This enables a handy GUI mode for naive users: x11vnc -gui tray=setpass -rfbport PROMPT -logfile $HOME/.x11vnc.log.%VNCDISP LAY suitable for putting in a launcher or menu, e.g. - [159]x11vnc.desktop. The [160]-logfile expansion is new too. In + [174]x11vnc.desktop. The [175]-logfile expansion is new too. In the GUI, the tray=setpass Properties panel has been improved. - * The [161]-solid solid background color option now works for the + * The [176]-solid solid background color option now works for the Mac OS X console. - * The [162]-reopen option instructs x11vnc to try to reopen the X + * The [177]-reopen option instructs x11vnc to try to reopen the X display if it is prematurely closed by, say, the display manager - (e.g. [163]GDM.) + (e.g. [178]GDM.) Here are some features that appeared in the 0.9.5 release: - * Symmetric key [164]encryption ciphers. ARC4, AES-128, AES-256, + * Symmetric key [179]encryption ciphers. ARC4, AES-128, AES-256, blowfish, and 3des are supported. Salt and initialization vector seeding is provided. These compliment the more widely used SSL and - SSH encryption access methods. [165]SSVNC also supports these + SSH encryption access methods. [180]SSVNC also supports these encryption modes. * Scaling differently along the X- and Y-directions. E.g. - "[166]-scale 1280x1024" or "-scale 0.8x0.75" Also, - "[167]-geometry WxH" is an alias for "-scale WxH" + "[181]-scale 1280x1024" or "-scale 0.8x0.75" Also, + "[182]-geometry WxH" is an alias for "-scale WxH" * By having SSVNC version 1.0.21 or later available in your $PATH, - the [168]-chatwindow option allows a UltraVNC Text Chat window to + the [183]-chatwindow option allows a UltraVNC Text Chat window to appear on the local X11 console/display (this way the remote viewer can chat with the person at the physical display; e.g. helpdesk mode.) This also works on the Mac OS X console if the @@ -1055,46 +1088,46 @@ LAY Here are some features that appeared in the 0.9.4 release: - * Improvements to the [169]-find and [170]-create X session finding + * Improvements to the [184]-find and [185]-create X session finding or creating modes: new desktop types and service redirection options. Personal cupsd daemon and SSH port redirection helper for - use with [171]SSVNC's Terminal Services feature. - * Reverse VNC connections via [172]-connect work in the [173]-find, - [174]-create and related [175]-display WAIT:... modes. + use with [186]SSVNC's Terminal Services feature. + * Reverse VNC connections via [187]-connect work in the [188]-find, + [189]-create and related [190]-display WAIT:... modes. * Reverse VNC connections (either normal or SSL) can use a Web Proxy or a SOCKS proxy, or a SSH connection, or even a CGI URL to make - the outgoing connection. See: [176]-proxy. Forward connections can - also use: [177]-ssh. - * Reverse VNC connections via the [178]UltraVNC repeater proxy + the outgoing connection. See: [191]-proxy. Forward connections can + also use: [192]-ssh. + * Reverse VNC connections via the [193]UltraVNC repeater proxy (either normal or SSL) are supported. Use either the - "[179]-connect repeater=ID:NNNN+host:port" or "[180]-connect - repeater://host:port+ID:NNNN" notation. The [181]SSVNC VNC viewer + "[194]-connect repeater=ID:NNNN+host:port" or "[195]-connect + repeater://host:port+ID:NNNN" notation. The [196]SSVNC VNC viewer also supports the UltraVNC repeater. * Support for indexed colormaps (PseudoColor) with depths other than 8 (from 1 to 16 now work) for non-standard hardware. Option - "[182]-advertise_truecolor" to handle some workaround in this + "[197]-advertise_truecolor" to handle some workaround in this mode. * Support for the ZYWRLE encoding, this is the RealVNC ZRLE encoding extended to do motion video and photo regions more efficiently by way of a Wavelet based transformation. - * The [183]-finddpy and [184]-listdpy utilities help to debug and - configure the [185]-find, [186]-create, and [187]-display WAIT:... + * The [198]-finddpy and [199]-listdpy utilities help to debug and + configure the [200]-find, [201]-create, and [202]-display WAIT:... modes. * Some automatic detection of screen resizes are handled even if the - [188]-xrandr option is not supplied. - * The [189]-autoport options gives more control over the VNC port + [203]-xrandr option is not supplied. + * The [204]-autoport options gives more control over the VNC port x11vnc chooses. - * The [190]-ping secs can be used to help keep idle connections + * The [205]-ping secs can be used to help keep idle connections alive. * Pasting of the selection/clipboard into remote applications (e.g. Java) has been improved. * Fixed a bug if a client disconnects during the 'speed-estimation' phase. * To unset Caps_Lock, Num_Lock and raise all keys in the X server - use [191]-clear_all. + use [206]-clear_all. * Usage with dvorak keyboards has been improved. See also: - [192]-xkb. - * The [193]Java Viewer applet source code is now included in the + [207]-xkb. + * The [208]Java Viewer applet source code is now included in the x11vnc-0.9.*.tar.gz tarball. This means you can now build the Java viewer applet jar files from source. If you stopped shipping the Java viewer applet jar files due to lack of source code, you can @@ -1102,7 +1135,7 @@ LAY Here are some features that appeared in the 0.9.3 release: - * [194]Viewer-side pixmap caching. A large area of pixels (at least + * [209]Viewer-side pixmap caching. A large area of pixels (at least 2-3 times as big as the framebuffer itself; the bigger the better... default is 10X) is placed below the framebuffer to act as a buffer/cache area for pixel data. The VNC CopyRect encoding @@ -1110,7 +1143,7 @@ LAY Until we start modifying viewers you will be able to see the cache area if you scroll down (this makes it easier to debug!) For testing the default is "-ncache 10". The unix Enhanced TightVNC - Viewer [195]ssvnc has a nice [196]-ycrop option to help hide the + Viewer [210]ssvnc has a nice [211]-ycrop option to help hide the pixel cache area from view. @@ -1123,14 +1156,14 @@ LAY * If UltraVNC file transfer or chat is detected, then VNC clients are "pinged" more often to prevent these side channels from becoming serviced too infrequently. - * In [197]-unixpw mode in the username and password dialog no text + * In [212]-unixpw mode in the username and password dialog no text will be echoed if the first character sent is "Escape". This enables a convenience feature in SSVNC to send the username and password automatically. Here are some features that appeared in the 0.9.1 release: - * The [198]UltraVNC Java viewer has been enhanced to support SSL (as + * The [213]UltraVNC Java viewer has been enhanced to support SSL (as the TightVNC viewer had been previously.) The UltraVNC Java supports ultravnc filetransfer, and so can be used as a VNC viewer on Unix that supports ultravnc filetransfer. It is in the @@ -1141,12 +1174,12 @@ LAY Some other bugs in the UltraVNC Java viewer were fixed and a few improvements to the UI made. * A new Unix username login mode for VNC Viewers authenticated via a - Client SSL Certificate: "[199]-users sslpeer=". The emailAddress + Client SSL Certificate: "[214]-users sslpeer=". The emailAddress subject field is inspected for username@hostname and then acts as though "-users +username" has been supplied. This way the Unix username is identified by (i.e. simply extracted from) the Client - SSL Certificate. This could be useful with [200]-find, - [201]-create and [202]-svc modes if you are also have set up and + SSL Certificate. This could be useful with [215]-find, + [216]-create and [217]-svc modes if you are also have set up and use VNC Client SSL Certificate authentication. * For external display finding/creating programs (e.g. WAIT:cmd=...) if the VNC Viewer is authenticated via a Client SSL Certificate, @@ -1155,41 +1188,41 @@ LAY Here are some features that appeared in the 0.9 release: - * [203]VNC Service advertising via mDNS / ZeroConf / BonJour with - the [204]Avahi client library. Enable via "[205]-avahi" or - "[206]-zeroconf". + * [218]VNC Service advertising via mDNS / ZeroConf / BonJour with + the [219]Avahi client library. Enable via "[220]-avahi" or + "[221]-zeroconf". * Implementations of UltraVNC's TextChat, SingleWindow, and - ServerInput extensions (requires ultravnc viewer or [207]ssvnc + ServerInput extensions (requires ultravnc viewer or [222]ssvnc Unix viewer.) They toggle the selection of a single window - ([208]-id), and disable (friendly) user input and viewing (monitor + ([223]-id), and disable (friendly) user input and viewing (monitor blank) at the VNC server. - * Short aliases "[209]-find", "[210]-create", "[211]-svc", and - "[212]-xdmsvc" for commonly used FINDCREATEDISPLAY usage modes. + * Short aliases "[224]-find", "[225]-create", "[226]-svc", and + "[227]-xdmsvc" for commonly used FINDCREATEDISPLAY usage modes. * Reverse VNC connections (viewer listening) now work in SSL - ([213]-ssl) mode. + ([228]-ssl) mode. * New options to control the Monitor power state and keyboard/mouse - grabbing: [214]-forcedpms, [215]-clientdpms, [216]-noserverdpms, - and [217]-grabalways. + grabbing: [229]-forcedpms, [230]-clientdpms, [231]-noserverdpms, + and [232]-grabalways. * A simple way to emulate inetd(8) to some degree via the - "[218]-loopbg" option. - * Monitor the accuracy of XDAMAGE and apply "[219]-noxdamage" if it - is not working well. OpenGL applications like like [220]beryl and + "[233]-loopbg" option. + * Monitor the accuracy of XDAMAGE and apply "[234]-noxdamage" if it + is not working well. OpenGL applications like like [235]beryl and MythTv have been shown to make XDAMAGE not work properly. * For Java SSL connections involving a router/firewall port - redirection, an option [221]-httpsredir to spare the user from + redirection, an option [236]-httpsredir to spare the user from needing to include &PORT=NNN in the browser URL. Here are some features that appeared in the 0.8.4 release: - * Native [222]Mac OS X Aqua/Quartz support. (i.e. OSXvnc + * Native [237]Mac OS X Aqua/Quartz support. (i.e. OSXvnc alternative; some activities are faster) - * A [223]new login mode: "-display WAIT:cmd=FINDCREATEDISPLAY + * A [238]new login mode: "-display WAIT:cmd=FINDCREATEDISPLAY -unixpw ..." that will Create a new X session (either virtual or real and with or without a display manager, e.g. kdm) for the user if it cannot find the user's X session display via the FINDDISPLAY - method. See the [224]-svc and the [225]-xdmsvc aliases. - * x11vnc can act as a VNC [226]reflector/repeater using the - "[227]-reflect host:N" option. Instead of polling an X display, + method. See the [239]-svc and the [240]-xdmsvc aliases. + * x11vnc can act as a VNC [241]reflector/repeater using the + "[242]-reflect host:N" option. Instead of polling an X display, the remote VNC Server host:N is connected to and re-exported via VNC. This is intended for use in broadcasting a display to many (e.g. > 16; classroom or large demo) VNC viewers where bandwidth @@ -1197,16 +1230,16 @@ LAY number of repeaters. * Wireframe copyrect detection for local user activity (e.g. someone sitting at the physical display moving windows) Use - [228]-nowireframelocal to disable. - * The "[229]-N" option couples the VNC Display number to the X + [243]-nowireframelocal to disable. + * The "[244]-N" option couples the VNC Display number to the X Display number. E.g. if your X DISPLAY is :2 then the VNC display will be :2 (i.e. using port 5902.) If that port is taken x11vnc will exit. - * Option [230]-nodpms to avoid problems with programs like KDE's + * Option [245]-nodpms to avoid problems with programs like KDE's kdesktop_lock that keep restarting the screen saver every few seconds. * To automatically fix the common mouse motion problem on XINERAMA - (multi-headed) displays, the [231]-xwarppointer option is enabled + (multi-headed) displays, the [246]-xwarppointer option is enabled by default when XINERAMA is active. If you have a Mac please try out the native Mac OS X support, build @@ -1216,62 +1249,62 @@ LAY Here are some features that appeared in the 0.8.3 release: - * The [232]-ssl option provides SSL encryption and authentication - natively via the [233]www.openssl.org library. One can use from a + * The [247]-ssl option provides SSL encryption and authentication + natively via the [248]www.openssl.org library. One can use from a simple self-signed certificate server certificate up to full CA and client certificate authentication schemes. - * Similar to -ssl, the [234]-stunnel option starts up a SSL tunnel + * Similar to -ssl, the [249]-stunnel option starts up a SSL tunnel server stunnel (that must be installed separately on the system: - [235]www.stunnel.org [236]stunnel.mirt.net ) to allow only + [250]www.stunnel.org [251]stunnel.mirt.net ) to allow only encrypted SSL connections from the network. - * The [237]-sslverify option allows for authenticating VNC clients + * The [252]-sslverify option allows for authenticating VNC clients via their certificates in either -ssl or -stunnel modes. * Certificate creation and management tools are provide in the - [238]-sslGenCert, [239]-sslGenCA, and [240]related options. + [253]-sslGenCert, [254]-sslGenCA, and [255]related options. * An SSL enabled Java applet VNC Viewer applet is provided by x11vnc in classes/ssl/VncViewer.jar. In addition to normal HTTP, the applet may be loaded into the web browser via HTTPS (HTTP over SSL.) (one can use the VNC port, e.g. https://host:5900/, or also - the separate [241]-https port option.) A wrapper shell script - [242]ss_vncviewer is also provided that sets up a stunnel - client-side tunnel on Unix systems. See [243]Enhanced TightVNC + the separate [256]-https port option.) A wrapper shell script + [257]ss_vncviewer is also provided that sets up a stunnel + client-side tunnel on Unix systems. See [258]Enhanced TightVNC Viewer (SSVNC) for other SSL/SSH viewer possibilities. - * The [244]-unixpw option supports Unix username and password - authentication (a simpler variant is the [245]-unixpw_nis option + * The [259]-unixpw option supports Unix username and password + authentication (a simpler variant is the [260]-unixpw_nis option that works in environments where the encrypted passwords are - readable, e.g. NIS.) The [246]-ssl or [247]-localhost + - [248]-stunnel options are enforced in this mode to prevent + readable, e.g. NIS.) The [261]-ssl or [262]-localhost + + [263]-stunnel options are enforced in this mode to prevent password sniffing. As a convenience, these requirements are lifted if a SSH tunnel can be deduced (but -localhost still applies.) - * Coupling [249]-unixpw with "[250]-display WAIT:cmd=FINDDISPLAY" or + * Coupling [264]-unixpw with "[265]-display WAIT:cmd=FINDDISPLAY" or "-display WAIT:cmd=FINDCREATEDISPLAY" provides a way to allow a user to login with their UNIX password and have their display - connected to [251]automatically. See the [252]-svc and the - [253]-xdmsvc aliases. - * Hooks are provided in the [254]-unixpw_cmd and "[255]-passwdfile + connected to [266]automatically. See the [267]-svc and the + [268]-xdmsvc aliases. + * Hooks are provided in the [269]-unixpw_cmd and "[270]-passwdfile cmd:,custom:..." options to allow you to supply your own authentication and password lookup programs. * x11vnc can be configured and built to not depend on X11 libraries - "./configure --without-x" for [256]-rawfb only operation (e.g. + "./configure --without-x" for [271]-rawfb only operation (e.g. embedded linux console devices.) - * The [257]-rotate option enables you to rotate or reflect the + * The [272]-rotate option enables you to rotate or reflect the screen before exporting via VNC. This is intended for use on handhelds and other devices where the rotation orientation is not "natural". - * The "[258]-ultrafilexfer" alias is provided and improved UltraVNC + * The "[273]-ultrafilexfer" alias is provided and improved UltraVNC filetransfer rates have been achieved. - * Under the "[259]-connect_or_exit host" option x11vnc will exit + * Under the "[274]-connect_or_exit host" option x11vnc will exit immediately unless the reverse connection to host succeeds. The "-rfbport 0" option disables TCP listening for connections (useful for this mode.) - * The "[260]-rawfb rand" and "-rawfb none" options are useful for + * The "[275]-rawfb rand" and "-rawfb none" options are useful for testing automation scripts, etc., without requiring a full desktop. - * Reduced spewing of information at startup, use "[261]-verbose" + * Reduced spewing of information at startup, use "[276]-verbose" (also "-v") to turn it back on for debugging or if you are going to send me a problem report. - Here are some [262]Previous Release Notes + Here are some [277]Previous Release Notes _________________________________________________________________ Some Notes: @@ -1298,13 +1331,13 @@ LAY protocol.) I suggest using xsetroot, dtstyle or similar utility to set a solid background while using x11vnc. You can turn the pretty background image back on when you are using the display directly. - Update: As of Feb/2005 x11vnc has the [263]-solid [color] option that + Update: As of Feb/2005 x11vnc has the [278]-solid [color] option that works on recent GNOME, KDE, and CDE and also on classic X (background image is on the root window.) Update: As of Oct/2007 x11vnc has the - [264]-ncache option that does a reasonable job caching the background + [279]-ncache option that does a reasonable job caching the background (and other) pixmap data on the viewer side. - I also find the [265]TightVNC encoding gives the best response for my + I also find the [280]TightVNC encoding gives the best response for my usage (Unix <-> Unix over cable modem.) One needs a tightvnc-aware vncviewer to take advantage of this encoding. @@ -1316,17 +1349,17 @@ LAY is X11's default listening port.) Had port 5900 been taken by some other application, x11vnc would have next tried 5901. That would mean the viewer command above should be changed to vncviewer - far-away.east:1. You can force the port with the "[266]-rfbport NNNN" + far-away.east:1. You can force the port with the "[281]-rfbport NNNN" option where NNNN is the desired port number. If that port is already - taken, x11vnc will exit immediately. The "[267]-N" option will try to + taken, x11vnc will exit immediately. The "[282]-N" option will try to match the VNC display number to the X display. (also see the "SunRay Gotcha" note below) Options: x11vnc has (far too) many features that may be activated - via its [268]command line options. Useful options are, e.g., -scale to + via its [283]command line options. Useful options are, e.g., -scale to do server-side scaling, and -rfbauth passwd-file to use VNC password protection (the vncpasswd or storepasswd programs, or the x11vnc - [269]-storepasswd option can be used to create the password file.) + [284]-storepasswd option can be used to create the password file.) Algorithm: How does x11vnc do it? Rather brute-forcedly: it continuously polls the X11 framebuffer for changes using @@ -1354,7 +1387,7 @@ LAY first testing out the programs. You get an interesting recursive/feedback effect where vncviewer images keep popping up each one contained in the previous one and slightly shifted a bit by the - window manager decorations. There will be an [270]even more + window manager decorations. There will be an [285]even more interesting effect if -scale is used. Also, if the XKEYBOARD is supported and the XBell "beeps" once, you get an infinite loop of beeps going off. Although all of this is mildly exciting it is not @@ -1364,8 +1397,8 @@ LAY Sun Ray Notes: - You can run x11vnc on your (connected or disconnected) [271]SunRay - session. Here are some [272]notes on SunRay usage with x11vnc. + You can run x11vnc on your (connected or disconnected) [286]SunRay + session. Here are some [287]notes on SunRay usage with x11vnc. _________________________________________________________________ @@ -1377,7 +1410,7 @@ LAY than you normally do to minimize the effects (e.g. do fullpage paging rather than line-by-line scrolling, and move windows in a single, quick motion.) Recent work has provided the - [273]-scrollcopyrect and [274]-wireframe speedups using the + [288]-scrollcopyrect and [289]-wireframe speedups using the CopyRect VNC encoding and other things, but they only speed up some activities, not all. * A rate limiting factor for x11vnc performance is that graphics @@ -1436,18 +1469,18 @@ LAY but we mention it because it may be of use for special purpose applications. You may need to use the "-cc 4" option to force Xvfb to use a TrueColor visual instead of DirectColor. See also the - description of the [275]-create option that does all of this + description of the [290]-create option that does all of this automatically for you. Also, a faster and more accurate way is to use the "dummy" XFree86/Xorg device driver (or our Xdummy wrapper script.) See - [276]this FAQ for details. + [291]this FAQ for details. * Somewhat surprisingly, the X11 mouse (cursor) shape is write-only and cannot be queried from the X server. So traditionally in x11vnc the cursor shape stays fixed at an arrow. (see the "-cursor - X" and "-cursor some" [277]options, however, for a partial hack + X" and "-cursor some" [292]options, however, for a partial hack for the root window, etc.) However, on Solaris using the SUN_OVL overlay extension, x11vnc can show the correct mouse cursor when - the [278]-overlay option is also supplied. A similar thing is done + the [293]-overlay option is also supplied. A similar thing is done on IRIX as well when -overlay is supplied. More generally, as of Dec/2004 x11vnc supports the new XFIXES extension (in Xorg and Solaris 10) to query the X server for the @@ -1455,18 +1488,18 @@ LAY with transparency (alpha channel) need to approximated to solid RGB values (some cursors look worse than others.) * Audio from applications is of course not redirected (separate - redirectors do exist, e.g. esd, see [279]the FAQ on this below.) + redirectors do exist, e.g. esd, see [294]the FAQ on this below.) The XBell() "beeps" will work if the X server supports the XKEYBOARD extension. (Note that on Solaris XKEYBOARD is disabled by default. Passing +kb to Xsun enables it.) - * The scroll detection algorithm for the [280]-scrollcopyrect option + * The scroll detection algorithm for the [295]-scrollcopyrect option can give choppy or bunched up transient output and occasionally painting errors. * Using -threads can expose some bugs/crashes in libvncserver. - Please feel free to [281]contact me if you have any questions, + Please feel free to [296]contact me if you have any questions, problems, or comments about x11vnc, etc. - Also, some people ask if they can make a donation, see [282]this link + Also, some people ask if they can make a donation, see [297]this link for that. References @@ -1597,162 +1630,177 @@ References 124. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create 125. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_cmd 126. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_nis - 127. http://ubuntuforums.org/showthread.php?t=1223490 - 128. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-threads - 129. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect - 130. http://bugs.freedesktop.org/show_bug.cgi?id=21454 - 131. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-repeat - 132. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clip - 133. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 134. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 135. http://www.virtualgl.org/ - 136. http://www.karlrunge.com/x11vnc/faq.html#faq-turbovnc - 137. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache_cr - 138. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache - 139. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rmflag - 140. http://sourceforge.net/projects/vencrypt/ - 141. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 142. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 143. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vencrypt - 144. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-anontls - 145. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslonly - 146. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 147. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vencrypt - 148. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-anontls - 149. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCRL - 150. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA - 151. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert - 152. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 153. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-http_oneport - 154. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir - 155. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 156. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi - 157. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf - 158. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport - 159. http://www.karlrunge.com/x11vnc/x11vnc.desktop - 160. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-o - 161. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid - 162. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reopen - 163. http://www.karlrunge.com/x11vnc/faq.html#infaq_gdm - 164. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-enc - 165. http://www.karlrunge.com/x11vnc/ssvnc.html - 166. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale - 167. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-geometry - 168. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-chatwindow - 169. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 170. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 171. http://www.karlrunge.com/x11vnc/ssvnc.html - 172. http://www.karlrunge.com/x11vnc/faq.html#faq-reverse-connect - 173. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 174. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 175. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 176. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy - 177. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssh - 178. http://www.uvnc.com/addons/repeater.html - 179. http://www.karlrunge.com/x11vnc/faq.html#faq-reverse-connect - 180. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 181. http://www.karlrunge.com/x11vnc/ssvnc.html - 182. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-advertise_truecolor - 183. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-finddpy - 184. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-listdpy - 185. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 186. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 187. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 188. http://www.karlrunge.com/x11vnc/faq.html#faq-xrandr - 189. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-autoport - 190. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ping - 191. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_all - 192. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb - 193. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-viewers - 194. http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching - 195. http://www.karlrunge.com/x11vnc/ssvnc.html - 196. http://www.karlrunge.com/x11vnc/ssvnc.html#ycrop - 197. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 198. http://www.ultravnc.com/ - 199. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users - 200. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 127. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_system_greeter + 128. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 129. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel + 130. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 131. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 132. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 133. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCRL + 134. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel + 135. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-extra_fbur + 136. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer + 137. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait + 138. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nonap + 139. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-allinput + 140. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-gui + 141. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remote + 142. http://ubuntuforums.org/showthread.php?t=1223490 + 143. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-threads + 144. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect + 145. http://bugs.freedesktop.org/show_bug.cgi?id=21454 + 146. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-repeat + 147. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clip + 148. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 149. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 150. http://www.virtualgl.org/ + 151. http://www.karlrunge.com/x11vnc/faq.html#faq-turbovnc + 152. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache_cr + 153. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache + 154. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rmflag + 155. http://sourceforge.net/projects/vencrypt/ + 156. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 157. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 158. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vencrypt + 159. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-anontls + 160. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslonly + 161. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 162. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vencrypt + 163. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-anontls + 164. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCRL + 165. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA + 166. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert + 167. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 168. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-http_oneport + 169. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir + 170. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 171. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi + 172. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf + 173. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport + 174. http://www.karlrunge.com/x11vnc/x11vnc.desktop + 175. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-o + 176. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid + 177. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reopen + 178. http://www.karlrunge.com/x11vnc/faq.html#infaq_gdm + 179. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-enc + 180. http://www.karlrunge.com/x11vnc/ssvnc.html + 181. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale + 182. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-geometry + 183. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-chatwindow + 184. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 185. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 186. http://www.karlrunge.com/x11vnc/ssvnc.html + 187. http://www.karlrunge.com/x11vnc/faq.html#faq-reverse-connect + 188. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 189. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 190. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 191. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy + 192. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssh + 193. http://www.uvnc.com/addons/repeater.html + 194. http://www.karlrunge.com/x11vnc/faq.html#faq-reverse-connect + 195. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect + 196. http://www.karlrunge.com/x11vnc/ssvnc.html + 197. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-advertise_truecolor + 198. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-finddpy + 199. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-listdpy + 200. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find 201. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 202. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 203. http://www.karlrunge.com/x11vnc/faq.html#faq-avahi - 204. http://www.avahi.org/ - 205. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi - 206. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf - 207. http://www.karlrunge.com/x11vnc/ssvnc.html - 208. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 209. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 210. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 211. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 212. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 213. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 214. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-forcedpms - 215. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clientdpms - 216. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noserverdpms - 217. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-grabalways - 218. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop - 219. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage - 220. http://www.karlrunge.com/x11vnc/faq.html#faq-beryl - 221. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir - 222. http://www.karlrunge.com/x11vnc/faq.html#faq-macosx - 223. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 224. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 225. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 226. http://www.karlrunge.com/x11vnc/faq.html#faq-reflect - 227. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect - 228. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nowireframelocal - 229. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N - 230. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodpms - 231. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xwarppointer - 232. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 233. http://www.openssl.org/ - 234. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel - 235. http://www.stunnel.org/ - 236. http://stunnel.mirt.net/ - 237. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify - 238. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert - 239. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA - 240. http://www.karlrunge.com/x11vnc/ssl.html - 241. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-https - 242. http://www.karlrunge.com/x11vnc/faq.html#infaq_ss_vncviewer - 243. http://www.karlrunge.com/x11vnc/ssvnc.html - 244. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 245. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_nis - 246. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 247. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost - 248. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel - 249. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 250. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT - 251. http://www.karlrunge.com/x11vnc/faq.html#faq-userlogin - 252. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 253. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 254. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_cmd - 255. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-passwdfile - 256. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 257. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rotate - 258. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ultrafilexfer - 259. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect_or_exit - 260. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 261. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-v, - 262. http://www.karlrunge.com/x11vnc/prevrels.html - 263. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid - 264. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache - 265. http://www.tightvnc.com/ - 266. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport - 267. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N - 268. http://www.karlrunge.com/x11vnc/x11vnc_opts.html - 269. http://www.karlrunge.com/x11vnc/faq.html#faq-passwd - 270. http://www.karlrunge.com/x11vnc/recurse_x11vnc.jpg - 271. http://www.sun.com/sunray/index.html - 272. http://www.karlrunge.com/x11vnc/sunray.html - 273. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect - 274. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe - 275. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 276. http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb - 277. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursor - 278. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-overlay - 279. http://www.karlrunge.com/x11vnc/faq.html#faq-sound - 280. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect - 281. mailto:xvml@karlrunge.com - 282. http://www.karlrunge.com/x11vnc/faq.html#faq-thanks + 202. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 203. http://www.karlrunge.com/x11vnc/faq.html#faq-xrandr + 204. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-autoport + 205. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ping + 206. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_all + 207. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb + 208. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-viewers + 209. http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching + 210. http://www.karlrunge.com/x11vnc/ssvnc.html + 211. http://www.karlrunge.com/x11vnc/ssvnc.html#ycrop + 212. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 213. http://www.ultravnc.com/ + 214. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users + 215. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 216. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 217. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 218. http://www.karlrunge.com/x11vnc/faq.html#faq-avahi + 219. http://www.avahi.org/ + 220. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi + 221. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf + 222. http://www.karlrunge.com/x11vnc/ssvnc.html + 223. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 224. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 225. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 226. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 227. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 228. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 229. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-forcedpms + 230. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clientdpms + 231. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noserverdpms + 232. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-grabalways + 233. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop + 234. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage + 235. http://www.karlrunge.com/x11vnc/faq.html#faq-beryl + 236. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir + 237. http://www.karlrunge.com/x11vnc/faq.html#faq-macosx + 238. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 239. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 240. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 241. http://www.karlrunge.com/x11vnc/faq.html#faq-reflect + 242. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect + 243. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nowireframelocal + 244. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N + 245. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodpms + 246. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xwarppointer + 247. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 248. http://www.openssl.org/ + 249. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel + 250. http://www.stunnel.org/ + 251. http://stunnel.mirt.net/ + 252. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 253. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert + 254. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA + 255. http://www.karlrunge.com/x11vnc/ssl.html + 256. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-https + 257. http://www.karlrunge.com/x11vnc/faq.html#infaq_ss_vncviewer + 258. http://www.karlrunge.com/x11vnc/ssvnc.html + 259. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 260. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_nis + 261. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 262. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost + 263. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel + 264. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 265. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT + 266. http://www.karlrunge.com/x11vnc/faq.html#faq-userlogin + 267. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 268. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 269. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_cmd + 270. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-passwdfile + 271. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 272. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rotate + 273. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ultrafilexfer + 274. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect_or_exit + 275. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 276. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-v, + 277. http://www.karlrunge.com/x11vnc/prevrels.html + 278. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid + 279. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache + 280. http://www.tightvnc.com/ + 281. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport + 282. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N + 283. http://www.karlrunge.com/x11vnc/x11vnc_opts.html + 284. http://www.karlrunge.com/x11vnc/faq.html#faq-passwd + 285. http://www.karlrunge.com/x11vnc/recurse_x11vnc.jpg + 286. http://www.sun.com/sunray/index.html + 287. http://www.karlrunge.com/x11vnc/sunray.html + 288. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect + 289. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe + 290. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 291. http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb + 292. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursor + 293. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-overlay + 294. http://www.karlrunge.com/x11vnc/faq.html#faq-sound + 295. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect + 296. mailto:xvml@karlrunge.com + 297. http://www.karlrunge.com/x11vnc/faq.html#faq-thanks ======================================================================= http://www.karlrunge.com/x11vnc/faq.html: @@ -5141,10 +5189,10 @@ exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -find -env FD_XDM=1 xauth data (the above example does the latter.) If applicable (-unixpw mode), the program is run as the Unix user name who logged in. - On Linux if the virtual terminal is known the program should append - ",VT=n" to the DISPLAY line; a chvt n will be attempted automatically. - Or if you only know the X server process ID and suspect a chvt will be - needed append ",XPID=n". + On Linux if the virtual terminal is known the program appends ",VT=n" + to the DISPLAY line; a chvt n will be attempted automatically. Or if + only X server process ID is known it appends ",XPID=n" (a chvt will be + attempted by x11vnc.) Tip: Note that the [427]-find option is an alias for "-display WAIT:cmd=FINDDISPLAY". Use it! @@ -5205,8 +5253,8 @@ xpw= So an inetd(8) example might look like: 5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd \ - -o /var/log/x11vnc.log -http -ssl SAVE -unixpw -users unixpw= \ - -display WAIT:cmd=FINDCREATEDISPLAY -prog /usr/local/bin/x11vnc + -o /var/log/x11vnc.log -http -prog /usr/local/bin/x11vnc \ + -ssl SAVE -unixpw -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY Where the very long lines have been split. This will allow direct SSL (e.g. [437]ss_vncviewer) access and also Java Web browers access via: @@ -5218,7 +5266,9 @@ xpw= Tip: Note that [439]-svc is a short hand for the long "-ssl SAVE -unixpw -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY" part. Unlike -create, this alias also sets up SSL encryption and Unix - password login. + password login. The above example then simplifies to: +5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd \ + -o /var/log/x11vnc.log -http -prog /usr/local/bin/x11vnc -svc Tip: In addition to the usual unixpw parameters, the user can specify after his username (following a ":" see [440]-display WAIT for @@ -5247,11 +5297,15 @@ service x11vnc wait = no user = root server = /usr/local/bin/x11vnc - server_args = -inetd -o /var/log/x11vnc.log -http -ssl SAVE -unixpw - -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY -prog /usr/local/bin/x11vnc + server_args = -inetd -o /var/log/x11vnc.log -http -prog /usr/local/ +bin/x11vnc -ssl SAVE -unixpw -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY disable = no } + Or more simply the server_args becomes: + server_args = -inetd -o /var/log/x11vnc.log -http -prog /usr/local/ +bin/x11vnc -svc + To print out the script in this case use "-display WAIT:cmd=FINDCREATEDISPLAY-print". To change the preference of Xservers and which to try list them, e.g.: "-display @@ -8343,14 +8397,51 @@ rm -f $tmp Q-119: Does the Clipboard/Selection get transferred between the vncviewer and the X display? - As of Jan/2004 x11vnc supports the "CutText" part of the rfb protocol. - Furthermore, x11vnc is able to hold the PRIMARY and CLIPBOARD - selection (Xvnc does not seem to do this.) If you don't want the - Clipboard/Selection exchanged use the [694]-nosel option. If you don't - want the PRIMARY selection to be polled for changes use the - [695]-noprimary option. (with a similar thing for CLIPBOARD.) You can - also fine-tune it a bit with the [696]-seldir dir option and also - [697]-input. + As of Jan/2004 x11vnc supports the "CutText" part of the RFB (aka VNC) + protocol. When text is selected/copied in the X session that x11vnc is + polling it will be sent to connected VNC viewers. And when CutText is + received from a VNC viewer then x11vnc will set the X11 selections + PRIMARY, CLIPBOARD, and CUTBUFFER0 to it. x11vnc is able to hold the + PRIMARY and CLIPBOARD selections (Xvnc does not seem to do this.) + + The X11 selections can be confusing, especially to those coming from + Windows or MacOSX where there is just a single 'Clipboard'. The X11 + CLIPBOARD selection is a lot like that of Windows and MacOSX, e.g. + highlighted text is sent to the clipboard when the user activates + "Edit -> Copy" or presses "Control+C" (and pasting it via "Edit -> + Paste" or "Control+V".) The X11 PRIMARY selection has been described + as 'for power users' or 'an Easter Egg'. As soon as text is + highlighted it is set to the PRIMARY selection and so it is + immediately ready for pasting, usually via the Middle Mouse Button or + "Shift+Insert". See [694]this jwz link for more information. + + x11vnc's default behavior is to watch both CLIPBOARD and PRIMARY and + whenever one of them changes, it sends the new text to connected + viewers. Note that since the RFB protocol only has a single "CutText" + then both selections are "merged" to some degree (and this can lead to + confusing results.) One user was confused why x11vnc was "forgetting" + his CLIPBOARD selection and the reason was he also changed PRIMARY + some time after he copied text to the clipboard. Usually an app will + set PRIMARY as soon as any text is highlighted so it easy to see how + CLIPBOARD was forgotten. Use the -noprimary described below as a + workaround. Similarly, by default when x11vnc receives CutText it sets + both CLIPBOARD and PRIMARY to it (this is probably less confusing, but + could possibly lead to some failure modes as well.) + + You may not like these defaults. Here are ways to change the behavior: + * If you don't want the Clipboard/Selection exchanged at all use the + [695]-nosel option. + * If you want changes in PRIMARY to be ignored use the + [696]-noprimary option. + * If you want changes in CLIPBOARD to be ignored use the + [697]-noclipboard option. + * If you don't want x11vnc to set PRIMARY to the "CutText" received + from viewers use the [698]-nosetprimary option. + * If you don't want x11vnc to set CLIPBOARD to the "CutText" + received from viewers use the [699]-nosetclipboard option. + + You can also fine-tune it a bit with the [700]-seldir dir option and + also [701]-input. You may need to watch out for desktop utilities such as KDE's "Klipper" that do odd things with the selection, clipboard, and @@ -8362,7 +8453,7 @@ rm -f $tmp Yes, it is possible with a number of tools that record VNC and transform it to swf format or others. One such popular tool is - [698]pyvnc2swf. There are a number of [699]tutorials (broken link?) on + [702]pyvnc2swf. There are a number of [703]tutorials (broken link?) on how to do this. Another option is to use the vnc2mpg that comes in the LibVNCServer package. An important thing to remember when doing this is that tuning @@ -8377,11 +8468,11 @@ rm -f $tmp (and Windows viewers only support filetransfer it appears... but they do work to some degree under Wine on Linux.) - The [700]SSVNC Unix VNC viewer supports UltraVNC file transfer by use + The [704]SSVNC Unix VNC viewer supports UltraVNC file transfer by use of a Java helper program. TightVNC file transfer is off by default, if you want to enable it use - the [701]-tightfilexfer option. + the [705]-tightfilexfer option. UltraVNC file transfer is off by default, to enable it use something like "-rfbversion 3.6 -permitfiletransfer" @@ -8404,7 +8495,7 @@ rm -f $tmp IMPORTANT: please understand if -ultrafilexfer or -tightfilexfer is specified and you run x11vnc as root for, say, inetd or display manager (gdm, kdm, ...) access and you do not have it switch users via - the [702]-users option, then VNC Viewers that connect are able to do + the [706]-users option, then VNC Viewers that connect are able to do filetransfer reads and writes as *root*. The UltraVNC and TightVNC settings can be toggled on and off inside @@ -8423,7 +8514,7 @@ rm -f $tmp these extensions you will need to supply this option to x11vnc: -rfbversion 3.6 - Or use [703]-ultrafilexfer which is an alias for the above option and + Or use [707]-ultrafilexfer which is an alias for the above option and "-permitfiletransfer". UltraVNC evidently treats any other RFB version number as non-UltraVNC. @@ -8435,14 +8526,14 @@ rm -f $tmp * 1/n Server Scaling * rfbEncodingUltra compression encoding - The [704]SSVNC Unix VNC viewer supports these UltraVNC extensions. + The [708]SSVNC Unix VNC viewer supports these UltraVNC extensions. - To disable SingleWindow and ServerInput use [705]-noultraext (the + To disable SingleWindow and ServerInput use [709]-noultraext (the others are managed by LibVNCServer.) See this option too: - [706]-noserverdpms. + [710]-noserverdpms. - Also, the [707]UltraVNC repeater proxy is supported for use with - reverse connections: "[708]-connect repeater://host:port+ID:NNNN". Use + Also, the [711]UltraVNC repeater proxy is supported for use with + reverse connections: "[712]-connect repeater://host:port+ID:NNNN". Use it for both plaintext and SSL connections. This mode can send any string before switching to the VNC protocol, and so could be used with other proxy/gateway tools. @@ -8453,12 +8544,12 @@ rm -f $tmp reverse vnc connection from their Unix desktop to a helpdesk operator's VNC Viewer. - Yes, UltraVNC's [709]Single Click (SC) mode can be emulated fairly + Yes, UltraVNC's [713]Single Click (SC) mode can be emulated fairly well on Unix. We use the term "helpdesk" below, but it could be any sort of remote assistance you want to set up, e.g. something for Unix-using friends - or family to use. This includes [710]Mac OS X. + or family to use. This includes [714]Mac OS X. Assume you create a helpdesk directory "hd" on your website: http://www.mysite.com/hd (any website that you can upload files to @@ -8514,7 +8605,7 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc So I guess this is about 3-4 clicks (start a terminal and paste) and pressing "Enter" instead of "single click"... - See [711]this page for some variations on this method, e.g. how to add + See [715]this page for some variations on this method, e.g. how to add a password, SSL Certificates, etc. @@ -8526,11 +8617,11 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc A bit of obscurity security could be put in with a -passwd, -rfbauth options, etc. (note that x11vnc will require a password even for - reverse connections.) More info [712]here. + reverse connections.) More info [716]here. Firewalls: If the helpdesk (you) with the vncviewer is behind a - NAT/Firewall/Router the [713]router will have to be configured to + NAT/Firewall/Router the [717]router will have to be configured to redirect a port (i.e. 5500 or maybe different one if you like) to the vncviewer machine. If the vncviewer machine also has its own host-level firewall, you will have to open up the port there as well. @@ -8540,7 +8631,7 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc configuring a router to do a port redirection (i.e. on your side, the HelpDesk.) To avoid modifying either firewall/router, one would need some public (IP address reachable on the internet) redirection/proxy - service. Perhaps such a thing exists. [714]http://sc.uvnc.com provides + service. Perhaps such a thing exists. [718]http://sc.uvnc.com provides this service for their UltraVNC Single Click users. @@ -8576,7 +8667,7 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc As of Apr/2007 x11vnc supports reverse connections in SSL and so we can do this. On the Helpdesk side (Viewer) you will need STUNNEL or - better use the [715]Enhanced TightVNC Viewer (SSVNC) package we + better use the [719]Enhanced TightVNC Viewer (SSVNC) package we provide that automates all of the SSL for you. To do this create a file named "vncs" in the website "hd" directory @@ -8606,11 +8697,11 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc with the hostnames or IP addresses customized to your case. - The only change from the "vnc" above is the addition of the [716]-ssl + The only change from the "vnc" above is the addition of the [720]-ssl option to x11vnc. This will create a temporary SSL cert: openssl(1) will need to be installed on the user's end. A fixed SSL cert file could be used to avoid this (and provide some authentication; more - info [717]here.) + info [721]here.) The naive user will be doing this: wget -qO - http://www.mysite.com/hd/vncs | sh - @@ -8619,7 +8710,7 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc But before that, the helpdesk operator needs to have "vncviewer -listen" running as before, however he needs an SSL tunnel at his end. - The easiest way to do this is use [718]Enhanced TightVNC Viewer + The easiest way to do this is use [722]Enhanced TightVNC Viewer (SSVNC). Start it, and select Options -> 'Reverse VNC Connection (-listen)'. Then UN-select 'Verify All Certs' (this can be enabled later if you want; you'll need the x11vnc SSL certificate), and click @@ -8649,7 +8740,7 @@ connect = localhost:5501 answer the prompts with whatever you want; you can take the default for all of them if you like. The openssl(1) package must be installed. - See [719]this link and [720]this one too for more info on SSL certs. + See [723]this link and [724]this one too for more info on SSL certs. This creates $HOME/.vnc/certs/server-self:mystunnel.pem, then you would change the "stunnel.cfg" to look something like: foreground = yes @@ -8670,7 +8761,7 @@ connect = localhost:5501 then all bets are off!. More SSL variations and info about certificates can be found - [721]here. + [725]here. OpenSSL libssl.so.0.9.7 problems: @@ -8680,7 +8771,7 @@ connect = localhost:5501 distros are currently a bit of a mess regarding which version of libssl is installed. - You will find the [722]details here. + You will find the [726]details here. Q-124: Can I (temporarily) mount my local (viewer-side) Windows/Samba @@ -8689,7 +8780,7 @@ connect = localhost:5501 You will have to use an external network redirection for this. Filesystem mounting is not part of the VNC protocol. - We show a simple [723]Samba example here. + We show a simple [727]Samba example here. First you will need a tunnel to redirect the SMB requests from the remote machine to the one you sitting at. We use an ssh tunnel: @@ -8729,7 +8820,7 @@ d,ip=127.0.0.1,port=1139 far-away> smbumount /home/fred/smb-haystack-pub At some point we hope to fold some automation for SMB ssh redir setup - into the [724]Enhanced TightVNC Viewer (SSVNC) package we provide (as + into the [728]Enhanced TightVNC Viewer (SSVNC) package we provide (as of Sep 2006 it is there for testing.) @@ -8739,7 +8830,7 @@ d,ip=127.0.0.1,port=1139 You will have to use an external network redirection for this. Printing is not part of the VNC protocol. - We show a simple Unix to Unix [725]CUPS example here. Non-CUPS port + We show a simple Unix to Unix [729]CUPS example here. Non-CUPS port redirections (e.g. LPD) should also be possible, but may be a bit more tricky. If you are viewing on Windows SMB and don't have a local cups server it may be trickier still (see below.) @@ -8821,7 +8912,7 @@ d,ip=127.0.0.1,port=1139 "localhost". At some point we hope to fold some automation for CUPS ssh redir setup - into the [726]Enhanced TightVNC Viewer (SSVNC) package we provide (as + into the [730]Enhanced TightVNC Viewer (SSVNC) package we provide (as of Sep 2006 it is there for testing.) @@ -8922,7 +9013,7 @@ or: the applications will fail to run because LD_PRELOAD will point to libraries of the wrong wordsize. * At some point we hope to fold some automation for esd or artsd ssh - redir setup into the [727]Enhanced TightVNC Viewer (SSVNC) package + redir setup into the [731]Enhanced TightVNC Viewer (SSVNC) package we provide (as of Sep/2006 it is there for testing.) @@ -8934,14 +9025,14 @@ or: in Solaris, see Xserver(1) for how to turn it on via +kb), and so you won't hear them if the extension is not present. - If you don't want to hear the beeps use the [728]-nobell option. If + If you don't want to hear the beeps use the [732]-nobell option. If you want to hear the audio from the remote applications, consider - trying a [729]redirector such as esd. + trying a [733]redirector such as esd. Q-128: Does x11vnc work with IPv6? - Currently the only way to do this is via [730]inetd. You configure + Currently the only way to do this is via [734]inetd. You configure x11vnc to be run from inetd or xinetd and instruct it to listen on an IPv6 address. For xinetd the setting "flags = IPv6" will be needed. @@ -8950,7 +9041,7 @@ or: connection.) Some sort of ipv4-to-ipv6 redirector tool (perhaps even a perl script) could be useful to avoid this. - Also note that not all VNC Viewers are [731]IPv6 enabled, so a + Also note that not all VNC Viewers are [735]IPv6 enabled, so a redirector could even be needed on the client side. @@ -9661,44 +9752,48 @@ References 691. http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager 692. http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager 693. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 694. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nosel - 695. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noprimary - 696. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-seldir - 697. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-input - 698. http://www.unixuser.org/~euske/vnc2swf/ - 699. http://wolphination.com/linux/2006/06/30/how-to-record-videos-of-your-desktop/ - 700. http://www.karlrunge.com/x11vnc/ssvnc.html - 701. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-tightfilexfer - 702. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users - 703. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ultrafilexfer + 694. http://www.jwz.org/doc/x-cut-and-paste.html + 695. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nosel + 696. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noprimary + 697. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noclipboard + 698. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nosetprimary + 699. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nosetclipboard + 700. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-seldir + 701. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-input + 702. http://www.unixuser.org/~euske/vnc2swf/ + 703. http://wolphination.com/linux/2006/06/30/how-to-record-videos-of-your-desktop/ 704. http://www.karlrunge.com/x11vnc/ssvnc.html - 705. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noultraext - 706. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noserverdpms - 707. http://www.uvnc.com/addons/repeater.html - 708. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 709. http://www.uvnc.com/addons/singleclick.html - 710. http://www.karlrunge.com/x11vnc/faq.html#faq-macosx - 711. http://www.karlrunge.com/x11vnc/single-click.html - 712. http://www.karlrunge.com/x11vnc/single-click.html - 713. http://www.karlrunge.com/x11vnc/index.html#firewalls - 714. http://sc.uvnc.com/ - 715. http://www.karlrunge.com/x11vnc/ssvnc.html - 716. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 717. http://www.karlrunge.com/x11vnc/single-click.html - 718. http://www.karlrunge.com/x11vnc/ssvnc.html - 719. http://www.karlrunge.com/x11vnc/single-click.html - 720. http://www.karlrunge.com/x11vnc/ssl.html + 705. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-tightfilexfer + 706. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users + 707. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ultrafilexfer + 708. http://www.karlrunge.com/x11vnc/ssvnc.html + 709. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noultraext + 710. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noserverdpms + 711. http://www.uvnc.com/addons/repeater.html + 712. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect + 713. http://www.uvnc.com/addons/singleclick.html + 714. http://www.karlrunge.com/x11vnc/faq.html#faq-macosx + 715. http://www.karlrunge.com/x11vnc/single-click.html + 716. http://www.karlrunge.com/x11vnc/single-click.html + 717. http://www.karlrunge.com/x11vnc/index.html#firewalls + 718. http://sc.uvnc.com/ + 719. http://www.karlrunge.com/x11vnc/ssvnc.html + 720. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl 721. http://www.karlrunge.com/x11vnc/single-click.html - 722. http://www.karlrunge.com/x11vnc/single-click.html#libssl-problems - 723. http://www.samba.org/ - 724. http://www.karlrunge.com/x11vnc/ssvnc.html - 725. http://www.cups.org/ - 726. http://www.karlrunge.com/x11vnc/ssvnc.html - 727. http://www.karlrunge.com/x11vnc/ssvnc.html - 728. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nobell - 729. http://www.karlrunge.com/x11vnc/faq.html#faq-sound - 730. http://www.karlrunge.com/x11vnc/faq.html#faq-inetd - 731. http://jungla.dit.upm.es/~acosta/paginas/vncIPv6.html + 722. http://www.karlrunge.com/x11vnc/ssvnc.html + 723. http://www.karlrunge.com/x11vnc/single-click.html + 724. http://www.karlrunge.com/x11vnc/ssl.html + 725. http://www.karlrunge.com/x11vnc/single-click.html + 726. http://www.karlrunge.com/x11vnc/single-click.html#libssl-problems + 727. http://www.samba.org/ + 728. http://www.karlrunge.com/x11vnc/ssvnc.html + 729. http://www.cups.org/ + 730. http://www.karlrunge.com/x11vnc/ssvnc.html + 731. http://www.karlrunge.com/x11vnc/ssvnc.html + 732. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nobell + 733. http://www.karlrunge.com/x11vnc/faq.html#faq-sound + 734. http://www.karlrunge.com/x11vnc/faq.html#faq-inetd + 735. http://jungla.dit.upm.es/~acosta/paginas/vncIPv6.html ======================================================================= http://www.karlrunge.com/x11vnc/chainingssh.html: @@ -10255,6 +10350,11 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM far-away.east:0" where ./x11vnc.crt is the copied certificate x11vnc printed out. + As fourth example, our [5]SSVNC enhanced tightvnc viewer can also use + these certificate files for server authentication. You can load them + via the SSVNC 'Certs...' dialog and set 'ServerCert' to the + certificate file you safely copied there. + Note that in principle the copying of the certificate to the client machine(s) itself could be altered in a Man-In-The-Middle attack! You can't win. It is unlikely the attacker could predict how you were @@ -10285,7 +10385,7 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM server. The ".pem" file contains both the certificate and the private key and should be kept secret. (If you don't like the default location ~/.vnc/certs, e.g. it is on an NFS share and you are worried about - local network sniffing, use the [5]-ssldir dir option to point to a + local network sniffing, use the [6]-ssldir dir option to point to a different directory.) So the next time you run "x11vnc -ssl SAVE ..." it will read the @@ -10350,7 +10450,7 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM clients will run. * One or more x11vnc server certs and keys are generated. * The x11vnc server cert is signed with the CA private key. - * x11vnc is run using the server key. (e.g. "[6]-ssl SAVE") + * x11vnc is run using the server key. (e.g. "[7]-ssl SAVE") * VNC clients (viewers) can now authenticate the x11vnc server because they have the CA certificate. @@ -10374,7 +10474,7 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM * The VNC client certs+keys are safely distributed to the corresponding client machines. * x11vnc is told to verify clients by using the CA cert. (e.g. - "[7]-sslverify CA") + "[8]-sslverify CA") * When VNC clients (viewers) connect, they must authenticate themselves to x11vnc by using their client key. @@ -10384,19 +10484,19 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM no need to keep the client key on the CA machine that generated and signed it. You can keep the client certs if you like because they are public, and they could also be used let in only a subset of all the - clients. (see [8]-sslverify) + clients. (see [9]-sslverify) _________________________________________________________________ How to do the above CA steps with x11vnc: Some utility commands are provided to ease the cert+key creation, - signing, and management: [9]-sslGenCA, [10]-sslGenCert, - [11]-sslDelCert, [12]-sslEncKey, [13]-sslCertInfo. They basically run + signing, and management: [10]-sslGenCA, [11]-sslGenCert, + [12]-sslDelCert, [13]-sslEncKey, [14]-sslCertInfo. They basically run the openssl(1) command for you to manage the certs/keys. It is required that openssl(1) is installed on the machine and available in PATH. All commands can be pointed to an alternate toplevel certificate - directory via the [14]-ssldir option if you don't want to use the + directory via the [15]-ssldir option if you don't want to use the default ~/.vnc/certs. 1) To generate your Certificate Authority (CA) cert and key run this: @@ -10408,7 +10508,7 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM ~/.vnc/certs/CA/cacert.pem (the CA public certificate) ~/.vnc/certs/CA/private/cakey.pem (the CA private key) - If you want to use a different directory use [15]-ssldir It must + If you want to use a different directory use [16]-ssldir It must supplied with all subsequent SSL utility options to point them to the correct directory. @@ -10427,7 +10527,7 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM 3) Start up x11vnc using this server key: x11vnc -ssl SAVE -display :0 ... - (SAVE corresponds to server.pem, see [16]-sslGenCert server somename + (SAVE corresponds to server.pem, see [17]-sslGenCert server somename info on creating additional server keys, server-somename.crt ...) 4) Next, safely copy the CA certificate to the VNC viewer (client) @@ -10466,9 +10566,14 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM (then point the VNC viewer to localhost:1). Here is an example for the Unix stunnel wrapper script - [17]ss_vncviewer: + [18]ss_vncviewer: ss_vncviewer -verify ./cacert.pem far-away.east:0 + Our [19]SSVNC enhanced tightvnc viewer can also use the certificate + file for server authentication. You can load it via the SSVNC + 'Certs...' dialog and set 'ServerCert' to the cacert.pem file you + safely copied there. + _________________________________________________________________ Tricks for server keys: @@ -10498,7 +10603,8 @@ NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM You don't have to use your own CA cert+key you can use a third party's. Perhaps you have a company-wide CA or you can even have your x11vnc certificate signed by a professional CA (e.g. www.thawte.com or - www.verisign.com). + www.verisign.com or perhaps the free certificate service + www.startcom.org or www.cacert.org). The advantage to doing this is that the VNC client machines will already have the CA certificates installed and you don't have to @@ -10573,19 +10679,19 @@ pem Where client.crt would be an individual client certificate; client-hash-dir a directory of file names based on md5 hashes of the - certs (see [18]-sslverify); and certs.txt signifies a single file full + certs (see [20]-sslverify); and certs.txt signifies a single file full of client certificates. Finally, connect with your VNC viewer using the key. Here is an - example for the Unix stunnel wrapper script [19]ss_vncviewer: using + example for the Unix stunnel wrapper script [21]ss_vncviewer: using client authentication (and the standard server authentication with the CA cert): ss_vncviewer -mycert ./dilbert.pem -verify ./cacert.pem far-away.east:0 - Our [20]SSVNC enhanced tightvnc viewer can also use these openssl .pem + Our [22]SSVNC enhanced tightvnc viewer can also use these openssl .pem files (you can load them via Certs... -> MyCert dialog). - It is also possible to use [21]-sslverify on a per-client key basis, + It is also possible to use [23]-sslverify on a per-client key basis, and also using self-signed client keys (x11vnc -sslGenCert client self:dilbert) @@ -10607,9 +10713,9 @@ pem sufficient and can be read by Mozilla/Firefox and Java... If you have trouble getting your Java Runtime to import and use the - cert+key, there is a workaround for the [22]SSL-enabled Java applet. + cert+key, there is a workaround for the [24]SSL-enabled Java applet. On the Web browser URL that retrieves the VNC applet, simply add a - "/?oneTimeKey=..." applet parameter (see [23]ssl-portal for more + "/?oneTimeKey=..." applet parameter (see [25]ssl-portal for more details on applet parameters; you don't need to do the full portal setup though). The value of the oneTimeKey will be the very long string that is output of the onetimekey program found in the @@ -10620,14 +10726,14 @@ pem HTTPS site via password. A cgi program then makes a one time key for the logged in user to use: it is passed back over HTTPS as the applet parameter in the URL and so cannot be sniffed. x11vnc is run to use - that key via [24]-sslverify. + that key via [26]-sslverify. Update: as of Apr 2007 in the 0.9.1 x11vnc tarball there is a new - option setting "[25]-users sslpeer=" that will do a switch user much - like [26]-unixpw does, but this time using the emailAddress field of + option setting "[27]-users sslpeer=" that will do a switch user much + like [28]-unixpw does, but this time using the emailAddress field of the Certificate subject of the verified Client. This mode requires - [27]-sslverify turned on to verify the clients via SSL. This mode can - be useful in situations using [28]-create or [29]-svc where a new X + [29]-sslverify turned on to verify the clients via SSL. This mode can + be useful in situations using [30]-create or [31]-svc where a new X server needs to be started up as the authenticated user (but unlike in -unixpw mode, the unix username is not obviously known). @@ -10635,7 +10741,7 @@ pem Additional utlities: - You can get information about your keys via [30]-sslCertInfo. These + You can get information about your keys via [32]-sslCertInfo. These lists all your keys: x11vnc -sslCertInfo list x11vnc -sslCertInfo ll @@ -10664,9 +10770,9 @@ pem More info: - See also this [31]article for some some general info and examples + See also this [33]article for some some general info and examples using stunnel and openssl on Windows with VNC. Also - [32]http://www.stunnel.org/faq/certs.html + [34]http://www.stunnel.org/faq/certs.html References @@ -10674,34 +10780,36 @@ References 2. http://stunnel.mirt.net/ 3. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-ext 4. http://www.karlrunge.com/x11vnc/ss_vncviewer - 5. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssldir - 6. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 7. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 5. http://www.karlrunge.com/x11vnc/ssvnc.html + 6. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssldir + 7. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl 8. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify - 9. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA - 10. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert - 11. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslDelCert - 12. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslEncKey - 13. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCertInfo - 14. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssldir + 9. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 10. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA + 11. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert + 12. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslDelCert + 13. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslEncKey + 14. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCertInfo 15. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssldir 16. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssldir - 17. http://www.karlrunge.com/x11vnc/ss_vncviewer - 18. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify - 19. http://www.karlrunge.com/x11vnc/ss_vncviewer - 20. http://www.karlrunge.com/x11vnc/ssvnc.html - 21. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify - 22. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-viewers - 23. http://www.karlrunge.com/x11vnc/ssl-portal.html - 24. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify - 25. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users - 26. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 27. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify - 28. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 29. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 30. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCertInfo - 31. http://www.securityfocus.com/infocus/1677 - 32. http://www.stunnel.org/faq/certs.html + 17. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssldir + 18. http://www.karlrunge.com/x11vnc/ss_vncviewer + 19. http://www.karlrunge.com/x11vnc/ssvnc.html + 20. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 21. http://www.karlrunge.com/x11vnc/ss_vncviewer + 22. http://www.karlrunge.com/x11vnc/ssvnc.html + 23. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 24. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-viewers + 25. http://www.karlrunge.com/x11vnc/ssl-portal.html + 26. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 27. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users + 28. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 29. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 30. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 31. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 32. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCertInfo + 33. http://www.securityfocus.com/infocus/1677 + 34. http://www.stunnel.org/faq/certs.html ======================================================================= http://www.karlrunge.com/x11vnc/ssl-portal.html: @@ -10709,7 +10817,8 @@ http://www.karlrunge.com/x11vnc/ssl-portal.html: _________________________________________________________________ - Using Apache as an SSL Gateway to x11vnc servers inside a firewall: + Using Apache as an SSL Gateway to multiple x11vnc servers inside a + firewall: Background: @@ -10750,10 +10859,10 @@ http://www.karlrunge.com/x11vnc/ssl-portal.html: with its -proxy option. Simpler Solutions: This apache solution may be too much for you. It is - mainly intended for automatically redirecting to multiple workstations + mainly intended for automatically redirecting to MULTIPLE workstations inside the firewall. If you only have one inside machine that you want to access, the method described here is overly complicated. See - [3]below for some simpler (non-SSH) encrypted setups. + [3]below for some simpler (and still non-SSH) encrypted setups. There are numerous ways to achieve this with Apache. We present one of the simplest ones here. @@ -10965,7 +11074,7 @@ hostname2 15 that is able to interact with the internal proxy for the VNC connection. See [10]this FAQ for more info on how this works. Note: sometimes with the Proxy case if you see 'Bad Gateway' error you will - have to wait 10 or so seconds and then his reload. This seems to be + have to wait 10 or so seconds and then hit reload. This seems to be due to having to wait for a Connection Keepalive to terminate... For completeness, the "trust" cases that skip a VNC certificate dialog @@ -11690,8 +11799,8 @@ Enhanced TightVNC Viewer (SSVNC: SSL/SSH VNC viewer) * Support for UltraVNC [26]MS-Logon authentication (NOTE: the UltraVNC MS-Logon key exchange implementation is very weak; an eavesdropper on the network can recover your Windows password - easily; you need to use an additional encrypted tunnel with - MS-Logon.) + easily in a few seconds; you need to use an additional encrypted + tunnel with MS-Logon.) * Support for symmetric encryption (including blowfish and 3des ciphers) to Non-UltraVNC Servers. Any server using the same encryption method will work, [27]e.g.: x11vnc -enc @@ -12297,9 +12406,9 @@ r IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman exchange is very weak and can be brute forced to recover - your username and password in a few hours or seconds of CPU - time. To be safe, be sure to use an additional encrypted - tunnel (e.g. SSL or SSH) for the entire VNC session. + your username and password in a few seconds of CPU time. + To be safe, be sure to use an additional encrypted tunnel + (e.g. SSL or SSH) for the entire VNC session. -chatonly Try to be a client that only does UltraVNC text chat. This mode is used by x11vnc to present a chat window on the @@ -12686,7 +12795,7 @@ x11vnc: a VNC server for real X displays Here are all of x11vnc command line options: % x11vnc -opts (see below for -help long descriptions) -x11vnc: allow VNC connections to real X11 displays. 0.9.9 lastmod: 2009-08-10 +x11vnc: allow VNC connections to real X11 displays. 0.9.9 lastmod: 2009-10-07 x11vnc options: -display disp -auth file -N @@ -12711,73 +12820,74 @@ x11vnc options: -create -xdummy -xvnc -xvnc_redirect -svc -svc_xdummy -svc_xvnc -xdmsvc -sshxdmsvc - -redirect port -display WAIT:... -vencrypt mode - -anontls mode -sslonly -dhparams file - -nossl -ssl [pem] -ssltimeout n - -sslnofail -ssldir [dir] -sslverify [path] - -sslCRL path -sslGenCA [dir] -sslGenCert type name - -sslEncKey [pem] -sslCertInfo [pem] -sslDelCert [pem] - -stunnel [pem] -stunnel3 [pem] -enc cipher:keyfile - -https [port] -httpsredir [port] -http_oneport - -ssh user@host:disp -usepw -storepasswd pass file - -nopw -accept string -afteraccept string - -gone string -users list -noshm - -flipbyteorder -onetile -solid [color] - -blackout string -xinerama -noxinerama - -xtrap -xrandr [mode] -rotate string - -padgeom WxH -o logfile -flag file - -rmflag file -rc filename -norc - -env VAR=VALUE -prog /path/to/x11vnc -h, -help - -?, -opts -V, -version -license - -dbg -q, -quiet -v, -verbose - -bg -modtweak -nomodtweak - -xkb -noxkb -capslock - -skip_lockkeys -noskip_lockkeys -skip_keycodes string - -sloppy_keys -skip_dups -noskip_dups - -add_keysyms -noadd_keysyms -clear_mods - -clear_keys -clear_all -remap string - -norepeat -repeat -nofb - -nobell -nosel -noprimary - -nosetprimary -noclipboard -nosetclipboard - -seldir string -cursor [mode] -nocursor - -cursor_drag -arrow n -noxfixes - -alphacut n -alphafrac fraction -alpharemove - -noalphablend -nocursorshape -cursorpos - -nocursorpos -xwarppointer -noxwarppointer - -buttonmap string -nodragging -ncache n - -ncache_cr -ncache_no_moveraise -ncache_no_dtchange - -ncache_no_rootpixmap -ncache_keep_anims -ncache_old_wm - -ncache_pad n -debug_ncache -wireframe [str] - -nowireframe -nowireframelocal -wirecopyrect mode - -nowirecopyrect -debug_wireframe -scrollcopyrect mode - -noscrollcopyrect -scr_area n -scr_skip list - -scr_inc list -scr_keys list -scr_term list - -scr_keyrepeat lo-hi -scr_parms string -fixscreen string - -debug_scroll -noxrecord -grab_buster - -nograb_buster -debug_grabs -debug_sel - -pointer_mode n -input_skip n -allinput - -speeds rd,bw,lat -wmdt string -debug_pointer - -debug_keyboard -defer time -wait time - -wait_ui factor -setdefer n -nowait_bog - -slow_fb time -xrefresh time -nap - -nonap -sb time -readtimeout n - -ping n -nofbpm -fbpm - -nodpms -dpms -forcedpms - -clientdpms -noserverdpms -noultraext - -chatwindow -noxdamage -xd_area A - -xd_mem f -sigpipe string -threads - -nothreads -fs f -gaps n - -grow n -fuzz n -debug_tiles - -snapfb -rawfb string -freqtab file - -pipeinput cmd -macnodim -macnosleep - -macnosaver -macnowait -macwheel n - -macnoswap -macnoresize -maciconanim n - -macmenu -macuskbd -gui [gui-opts] - -remote command -query variable -QD variable - -sync -noremote -yesremote - -unsafe -safer -privremote - -nocmds -allowedcmds list -deny_all - + -unixpw_system_greeter -redirect port -display WAIT:... + -vencrypt mode -anontls mode -sslonly + -dhparams file -nossl -ssl [pem] + -ssltimeout n -sslnofail -ssldir [dir] + -sslverify [path] -sslCRL path -sslGenCA [dir] + -sslGenCert type name -sslEncKey [pem] -sslCertInfo [pem] + -sslDelCert [pem] -stunnel [pem] -stunnel3 [pem] + -enc cipher:keyfile -https [port] -httpsredir [port] + -http_oneport -ssh user@host:disp -usepw + -storepasswd pass file -nopw -accept string + -afteraccept string -gone string -users list + -noshm -flipbyteorder -onetile + -solid [color] -blackout string -xinerama + -noxinerama -xtrap -xrandr [mode] + -rotate string -padgeom WxH -o logfile + -flag file -rmflag file -rc filename + -norc -env VAR=VALUE -prog /path/to/x11vnc + -h, -help -?, -opts -V, -version + -license -dbg -q, -quiet + -v, -verbose -bg -modtweak + -nomodtweak -xkb -noxkb + -capslock -skip_lockkeys -noskip_lockkeys + -skip_keycodes string -sloppy_keys -skip_dups + -noskip_dups -add_keysyms -noadd_keysyms + -clear_mods -clear_keys -clear_all + -remap string -norepeat -repeat + -nofb -nobell -nosel + -noprimary -nosetprimary -noclipboard + -nosetclipboard -seldir string -cursor [mode] + -nocursor -cursor_drag -arrow n + -noxfixes -alphacut n -alphafrac fraction + -alpharemove -noalphablend -nocursorshape + -cursorpos -nocursorpos -xwarppointer + -noxwarppointer -buttonmap string -nodragging + -ncache n -ncache_cr -ncache_no_moveraise + -ncache_no_dtchange -ncache_no_rootpixmap -ncache_keep_anims + -ncache_old_wm -ncache_pad n -debug_ncache + -wireframe [str] -nowireframe -nowireframelocal + -wirecopyrect mode -nowirecopyrect -debug_wireframe + -scrollcopyrect mode -noscrollcopyrect -scr_area n + -scr_skip list -scr_inc list -scr_keys list + -scr_term list -scr_keyrepeat lo-hi -scr_parms string + -fixscreen string -debug_scroll -noxrecord + -grab_buster -nograb_buster -debug_grabs + -debug_sel -pointer_mode n -input_skip n + -allinput -speeds rd,bw,lat -wmdt string + -debug_pointer -debug_keyboard -defer time + -wait time -extra_fbur n -wait_ui factor + -setdefer n -nowait_bog -slow_fb time + -xrefresh time -nap -nonap + -sb time -readtimeout n -ping n + -nofbpm -fbpm -nodpms + -dpms -forcedpms -clientdpms + -noserverdpms -noultraext -chatwindow + -noxdamage -xd_area A -xd_mem f + -sigpipe string -threads -nothreads + -fs f -gaps n -grow n + -fuzz n -debug_tiles -snapfb + -rawfb string -freqtab file -pipeinput cmd + -macnodim -macnosleep -macnosaver + -macnowait -macwheel n -macnoswap + -macnoresize -maciconanim n -macmenu + -macuskbd -gui [gui-opts] -remote command + -query variable -QD variable -sync + -query_retries str -remote_prefix str -noremote + -yesremote -unsafe -safer + -privremote -nocmds -allowedcmds list + -deny_all libvncserver options: -rfbport port TCP port for RFB protocol @@ -12811,7 +12921,7 @@ libvncserver-tight-extension options: % x11vnc -help -x11vnc: allow VNC connections to real X11 displays. 0.9.9 lastmod: 2009-08-10 +x11vnc: allow VNC connections to real X11 displays. 0.9.9 lastmod: 2009-10-07 (type "x11vnc -opts" to just list the options.) @@ -13544,7 +13654,7 @@ Options: 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 + send one before a 45 second timeout. Existing clients are view-only during this period. If the first character received is "Escape" then the @@ -13803,6 +13913,10 @@ Options: under -display WAIT:... for more details about XDM, etc configuration. + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + -sshxdmsvc Display manager Terminal services mode based on SSH. Alias for -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp -localhost. @@ -13815,6 +13929,48 @@ Options: under -display WAIT:... for more details about XDM, etc configuration. + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + +-unixpw_system_greeter Present a "Press 'Escape' for System Greeter" option + to the connecting VNC client in combined -unixpw + and xdmcp FINDCREATEDISPLAY modes (e.g. -xdmsvc). + + Normally in a -unixpw mode the VNC client must + supply a valid username and password to gain access. + However, if -unixpw_system_greeter is supplied AND + the FINDCREATEDISPLAY command matches 'xdmcp', then + the user has the option to press Escape and then get a + XDM/GDM/KDM login/greeter panel instead. They will then + supply a username and password directly to the greeter. + + Otherwise, in xdmcp FINDCREATEDISPLAY mode the user + must supply his username and password TWICE. First to + the initial unixpw login dialog, and second to the + subsequent XDM/GDM/KDM greeter. Note that if the user + re-connects and supplies his username and password in + the unixpw dialog the xdmcp greeter is skipped and + he is connected directly to his existing X session. + So the -unixpw_system_greeter option avoids the extra + password at X session creation time. + + Example: x11vnc -xdmsvc -unixpw_system_greeter + See -unixpw and -display WAIT:... for more info. + + The special options after a colon at the end of the + username (e.g. user:solid) described under -display + WAIT: are also applied in this mode if they are typed + in before the user hits Escape. The username is ignored + but the colon options are not. + + If the user pressed Escape the FINDCREATEDISPLAY command + will be run with the env. var. X11VNC_XDM_ONLY=1. + + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + -redirect port As in FINDCREATEDISPLAY-Xvnc.redirect mode except redirect immediately (i.e. without X session finding or creation) to a VNC server listening on port. You @@ -13886,12 +14042,13 @@ Options: Also in the case of -unixpw, the user logging in can place a colon at the end of her username and supply a few options: scale=, scale_cursor= (or sc=), solid - (or so), id=, clear_mods (or cm), clear_keys (or ck), - repeat, speeds= (or sp=), readtimeout= (or rd=), - rotate= (or ro=), or noncache (or nc), all 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, + (or so), id=, clear_mods (or cm), clear_keys (or + ck), clear_all (or ca), repeat, speeds= (or sp=), + readtimeout= (or rd=), viewonly (or vo), nodisplay= + (or nd=), rotate= (or ro=), or noncache (or nc), + all 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,sc=1,repeat Password: ... @@ -13903,6 +14060,9 @@ Options: your long "login:" line press the Up arrow once (before typing anything else). + In the login panel, press F1 to get a list of the + available options that you can add after the username. + Another option is "geom=WxH" or "geom=WxHxD" (or ge=). This only has an effect in FINDCREATEDISPLAY mode when a virtual X server such as Xvfb is going @@ -13978,7 +14138,9 @@ Options: ignore in the finding process. The ":" is optional. Ranges n-m e.g. 0-20 can also be supplied. This string can also be set by the connecting user via "nd=" - using "+" instead of "," + using "+" instead of "," If "nd=all" or you set + X11VNC_SKIP_DISPLAY=all then all display finding fails + as if you set X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (below.) Automatic Creation of User X Sessions: @@ -14034,6 +14196,8 @@ Options: If for some reason you do not want x11vnc to ever try to find an existing display set the env. var X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (also -env ...) + This is the same as setting X11VNC_SKIP_DISPLAY=all or + supplying "nd=all" after "username:" Use WAIT:cmd=FINDCREATEDISPLAY-print to print out the script that is used for this. @@ -14062,12 +14226,15 @@ Options: be the full path to the session/windowmanager program. More FD tricks: FD_CUPS=port or FD_CUPS=host:port - will set the cups printing environment. Similarly - for FD_ESD=port or FD_ESD=host:port for esddsp sound - redirection. FD_XDUMMY_NOROOT means the Xdummy server - does not need to be started as root (e.g. it will sudo - automatically). Set FD_EXTRA to a command to be run - a few seconds after the X server starts up. + will set the cups printing environment. Similarly for + FD_ESD=port or FD_ESD=host:port for esddsp sound + redirection. FD_XDUMMY_NOROOT means the Xdummy + server does not need to be started as root (e.g. it + will sudo automatically). Set FD_EXTRA to a command + to be run a few seconds after the X server starts up. + Set FD_TAG to be a unique name for the session, it is + set as an X property, that makes FINDDISPLAY only find + sessions with that tag value. If you want the FINDCREATEDISPLAY session to contact an XDMCP login manager (xdm/gdm/kdm) on the same machine, @@ -14147,8 +14314,9 @@ Options: Otherwise in -unixpw mode the normal login panel is provided. - You *MUST* supply the -ssl option for VeNCrypt to be - active. This option only fine-tunes its operation. + You *MUST* supply the -ssl option for VeNCrypt to + be active. The -vencrypt option only fine-tunes its + operation. -anontls mode The ANONTLS extension to the VNC protocol allows encrypted SSL/TLS connections. If the -ssl mode is @@ -14183,8 +14351,9 @@ Options: Long example: -anontls newdh:plain:support - You *MUST* supply the -ssl option for ANONTLS to be - active. This option only fine-tunes its operation. + You *MUST* supply the -ssl option for ANONTLS to + be active. The -anontls option only fine-tunes its + operation. -sslonly Same as: "-vencrypt never -anontls never" i.e. it disables the VeNCrypt and ANONTLS encryption methods @@ -14208,16 +14377,17 @@ Options: -ssl [pem] Use the openssl library (www.openssl.org) to provide a built-in encrypted SSL/TLS 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 -ssl - is prescribed. + 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 + -ssl is prescribed. See the -stunnel option below for + an alternative. The VNC Viewer-side needs to support SSL/TLS as well. See this URL and also the discussion below for ideas on how to enable SSL support for the viewer: http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tun - nel-viewers x11vnc provides an SSL enabled Java + nel-viewers . x11vnc provides an SSL enabled Java viewer applet in the classes/ssl directory (-http or -httpdir options.) The SSVNC viewer package supports SSL tunnels too. @@ -14307,6 +14477,11 @@ Options: See -ssldir below to use a directory besides the default ~/.vnc/certs + If your x11vnc binary was not compiled with OpenSSL + library support, use of the -ssl option will induce an + immediate failure and exit. For such binaries, consider + using the -stunnel option for SSL encrypted connections. + Misc Info: In temporary cert creation mode "TMP", set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc print out the entire certificate, including the PRIVATE KEY @@ -14409,7 +14584,7 @@ Options: NOTE: the following utilities, -sslGenCA, -sslGenCert, - -sslEncKey, and -sslCertInfo are provided for + -sslEncKey, -sslCertInfo, and -sslCRL are provided for completeness, but for casual usage they are overkill. They provide VNC Certificate Authority (CA) key creation @@ -14460,8 +14635,9 @@ Options: the ss_vncviewer example script in the FAQ and SSVNC.) -sslCRL path Set the Certificate Revocation Lists (CRL) to "path". + This setting applies for both -ssl and -stunnel modes. - If path is a file, the file contains one more more CRLs + If path is a file, the file contains one or more CRLs in PEM format. If path is a directory, it contains hash named files of CRLs in the usual OpenSSL manner. See the OpenSSL and stunnel(8) documentation for @@ -14473,6 +14649,10 @@ Options: The -sslCRL setting will be ignored when -sslverify is not specified. + Note that if a CRL's expiration date has passed, all + SSL connections will fail regardless of if they are + related to the subject of the CRL or not. + Only rarely will one's x11vnc -ssl infrastructure be so large that this option would be useful (since normally maintaining the contents of the -sslverify file or @@ -14584,11 +14764,13 @@ Options: Similar to -sslGenCA, 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-qualified 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. + certificate when it is created. + + Tip: if you know the fully-qualified 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 that it does not + match the hostname. You will also need to supply the CA private key passphrase to unlock the private key created from @@ -14612,14 +14794,14 @@ Options: the cert and private key. The .crt contains the certificate only. - NOTE: It is very important to know one should always + NOTE: It is very important to know one should 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 + be typed in EVERY time x11vnc or the client app is started up. Examples: @@ -14715,16 +14897,30 @@ Options: This external tunnel method was implemented prior to the integrated -ssl 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 -stunnel3 below.) + works well and avoids the requirement of linking with + the OpenSSL libraries. This mode 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 -stunnel3 + below.) [pem] is optional, use "-stunnel /path/to/stunnel.pem" 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. + See the -ssl option for more info on certificate files. + + Whether or not your stunnel has its own certificate + depends on your stunnel configuration; stunnel often + generates one at install time. See your stunnel + documentation for details. In any event, if you want to + use this certificate you must supply the full path to it + as [pem]. Note: the file may only be readable by root. + + [pem] may also be the special strings "TMP", "SAVE", + and "SAVE..." as described in the -ssl option. + If [pem] is not supplied, "SAVE" is assumed. + + Note that the VeNCrypt, ANONTLS, and "ANON" modes + are not supported in -stunnel mode. stunnel is started up as a child process of x11vnc and any SSL connections stunnel receives are decrypted and @@ -14732,22 +14928,37 @@ Options: "The SSL VNC desktop is ..." and "SSLPORT=..." are printed out at startup to indicate this. - The -localhost 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. + The -localhost option is enforced by default to avoid + people routing around the SSL channel. Use -env + STUNNEL_DISABLE_LOCALHOST=1 to disable this security + requirement. + + Set -env STUNNEL_DEBUG=1 for more debugging printout. + + Your VNC viewer will also need to be able to connect + via SSL. Unfortunately not too many do this. See the + information about SSL viewers under the -ssl option. - 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. + Also, in the x11vnc distribution, patched TightVNC + and UltraVNC Java applet jar files are provided in + the classes/ssl directory that do SSL connections. + Enable serving them with the -http, -http_ssl, -https, + or -httpdir (see the option descriptions for more info.) - Also, in the x11vnc distribution, a patched TightVNC - Java applet is provided in classes/ssl that does SSL - connections (only). + Note that for the Java viewer applet usage the + "?PORT=xxxx" in the various URLs printed at startup + will need to be supplied to the web browser to connect + properly. - 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: + Currently the automatic "single port" HTTPS mode of + -ssl is not fully supported in -stunnel mode. However, + it can be emulated via: + + % x11vnc -stunnel -http_ssl -http_oneport ... + + In general, 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: % stunnel -c -d localhost:5901 -r remotehost:5900 % vncviewer localhost:1 @@ -14757,7 +14968,8 @@ Options: and SSVNC for more examples. -stunnel3 [pem] Use version 3.x stunnel command line syntax instead of - version 4.x + version 4.x. The -http/-httpdir Java applet serving + is currently not available in this mode. -enc cipher:keyfile Use symmetric encryption with cipher "cipher" and secret key data in "keyfile". If keyfile is @@ -14776,7 +14988,7 @@ Options: Note that this mode will NOT work with the UltraVNC DSM plugins because they alter the RFB protocol in addition to tunnelling with the symmetric cipher (an unfortunate - choice of implementation). + choice of implementation...) cipher can be one of: arc4, aesv2, aes-cfb, blowfish, aes256, or 3des. See the OpenSSL documentation for @@ -14849,9 +15061,9 @@ Options: For both ways of using the viewer, you can specify the salt,ivec sizes (in GUI or, e.g. arc4@8,16). --https [port] Use a special, separate HTTPS port (-ssl mode only) - for HTTPS Java viewer applet downloading. I.e. not 5900 - and not 5800 (the defaults.) +-https [port] Use a special, separate HTTPS port (-ssl and + -stunnel modes only) for HTTPS Java viewer applet + downloading. I.e. not 5900 and not 5800 (the defaults.) BACKGROUND: In -ssl mode, it turns out you can use the single VNC port (e.g. 5900) for both VNC and HTTPS @@ -14871,6 +15083,8 @@ Options: or VNC Viewer applet. That's right 3 separate "Are you sure you want to connect?" dialogs!) + END OF BACKGROUND. + USAGE: So use the -https 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. @@ -14904,7 +15118,9 @@ Options: to include the PORT= in the browser URL, simply supply "-httpsredir" to x11vnc. --http_oneport For un-encrypted connections mode (i.e. no -ssl, + This options does not work in -stunnel mode. + +-http_oneport For UN-encrypted connections mode (i.e. no -ssl, -stunnel, or -enc options), allow the Java VNC Viewer applet to be downloaded thru the VNC port via HTTP. @@ -16288,10 +16504,21 @@ t Same as -dp and -dk, respectively. Use multiple times for more output. --defer time Time in ms to wait for updates before sending to client +-defer time Time in ms to delay sending updates to connected clients (deferUpdateTime) Default: 20 + -wait time Time in ms to pause between screen polls. Used to cut down on load. Default: 20 + +-extra_fbur n Perform extra FrameBufferUpdateRequests checks to + try to be in better sync with the client's requests. + What this does is perform extra polls of the client + socket at critical times (before '-defer' and '-wait' + calls.) The default is n=1. Set to a larger number to + insert more checks or set to n=0 to disable. A downside + of these extra calls is that more mouse input may be + processed than desired. + -wait_ui factor Factor by which to cut the -wait time if there has been recent user input (pointer or keyboard). Improves response, but increases the load whenever you @@ -16325,12 +16552,12 @@ t Default: take naps -sb time Time in seconds after NO activity (e.g. screen blank) to really throttle down the screen polls (i.e. sleep - for about 1.5 secs). Use 0 to disable. Default: 20 + for about 1.5 secs). Use 0 to disable. Default: 60 -readtimeout n Set libvncserver rfbMaxClientWait to n seconds. On slow links that take a long time to paint the first screen libvncserver may hit the timeout and drop the - connection. Default: 60 seconds. + connection. Default: 20 seconds. -ping n Send a 1x1 framebuffer update to all clients every n seconds (e.g. to try to keep a network connection alive) @@ -17103,6 +17330,28 @@ n x11vnc server as long as X permissions, etc. permit communication between the two. + FONTS: On some systems the tk fonts can be too small, + jagged, or otherwise unreadable. There are 4 env vars + you can set to be the tk font you prefer: + + X11VNC_FONT_BOLD main font for menus and buttons. + X11VNC_FONT_FIXED font for fixed width text. + + X11VNC_FONT_BOLD_SMALL tray icon font. + X11VNC_FONT_REG_SMALL tray icon menu font. + + The last two only apply for the tray icon mode. + + Here are some examples: + + -env X11VNC_FONT_BOLD='Helvetica -16 bold' + -env X11VNC_FONT_FIXED='Courier -14' + -env X11VNC_FONT_REG_SMALL='Helvetica -12' + + You can put the lines like the above (without the + quotes) in your ~/.x11vncrc file to avoid having to + specify them on the x11vnc command line. + -remote command Remotely control some aspects of an already running x11vnc server. "-R" and "-r" are aliases for "-remote". After the remote control command is @@ -17126,12 +17375,27 @@ n 'x11vnc -R shared' will enable shared connections, and 'x11vnc -R scale:3/4' will rescale the desktop. + To run a bunch of commands in a sequence use something + like: x11vnc -R 'script:firstcmd;secondcmd;...' + + Use x11vnc -R script:file=/path/to/file to read commands + from a file (can be multi-line and use the comment '#' + character in the normal way. The ';' separator must + still be used to separate each command.) + + To not try to contact another x11vnc process and instead + just run the command (or query) directly, prefix the + command with the string "DIRECT:" + The following -remote/-R commands are supported: stop terminate the server, same as "quit" "exit" or "shutdown". ping see if the x11vnc server responds. - Return is: ans=ping: + return is: ans=ping: + ping:mystring as above, but use your own unique string +. + return is: ans=ping:mystring: blacken try to push a black fb update to all clients (due to timings a client could miss it). Same as "zero", also @@ -17220,6 +17484,7 @@ n nograbptr disable -grabptr mode. grabalways enable -grabalways mode. nograbalways disable -grabalways mode. + grablocal:n set -grablocal to n. client_input:str set the K, M, B -input on a per-client basis. select which client as for disconnect, e.g. client_input:host:MB @@ -17302,6 +17567,9 @@ n nosetclipboard enable -nosetclipboard mode. setclipboard disable -nosetclipboard mode. seldir:str set -seldir to "str" + resend_cutbuffer resend the most recent CUTBUFFER0 copy + resend_clipboard resend the most recent CLIPBOARD copy + resend_primary resend the most recent PRIMARY copy cursor:mode enable -cursor "mode". show_cursor enable showing a cursor. noshow_cursor disable showing a cursor. (same as @@ -17376,8 +17644,25 @@ n nodebug_pointer disable -debug_pointer, same as "nodp" debug_keyboard enable -debug_keyboard, same as "dk" nodebug_keyboard disable -debug_keyboard, same as "nodk" + keycode:n inject keystroke 'keycode' (xmodmap -pk) + keycode:n,down inject 'keycode' (down=0,1) + keysym:str inject keystroke 'keysym' (number/name) + keysym:str,down inject 'keysym' (down=0,1) + ptr:x,y,mask inject pointer event x, y, button-mask + sleep:t sleep floating point time t. + get_xprop:p get X property named 'p'. + set_xprop:p:val set X property named 'p' to 'val'. + p -> id=NNN:p for hex/dec window id. + wininfo:id get info about X window id. use 'root' + for root window, use +id for children. + grab_state get state of pointer and keyboard grab. + pointer_pos print XQueryPointer x,y cursor position. + mouse_x print x11vnc's idea of cursor position. + mouse_y print x11vnc's idea of cursor position. + noop do nothing. defer:n set -defer to n ms,same as deferupdate:n wait:n set -wait to n ms. + extra_fbur:n set -extra_fbur to n. wait_ui:f set -wait_ui factor to f. setdefer:n set -setdefer to -2,-1,0,1, or 2. wait_bog disable -nowait_bog mode. @@ -17416,6 +17701,7 @@ n nosnapfb disable -snapfb mode. rawfb:str set -rawfb mode to "str". uinput_accel:f set uinput_accel to f. + uinput_thresh:n set uinput_thresh to n. uinput_reset:n set uinput_reset to n ms. uinput_always:n set uinput_always to 1/0. progressive:n set libvncserver -progressive slice @@ -17434,7 +17720,9 @@ n macresize disable -macnoresize mode. maciconanim:n set -maciconanim to n. macmenu enable -macmenu mode. - macnomenu disable -macnmenu mode. + macnomenu disable -macmenu mode. + macuskbd enable -macuskbd mode. + macnouskbd disable -macuskbd mode. httpport:n set -httpport to n. httpdir:dir set -httpdir to dir (and enable http). enablehttpproxy enable -enablehttpproxy mode. @@ -17470,6 +17758,100 @@ n noremote disable the -remote command processing, it cannot be turned back on. + bcx_xattach:str This remote control command is for + use with the BARCO xattach program or the x2x program. + Both of these programs are for 'pointer and keyboard' + sharing between separate X displays. In general the + two displays are usually nearby, e.g. on the same desk, + and this allows the user to share a single pointer and + keyboard between them. The user moves the mouse to + an edge and then the mouse pointer appears to 'jump' + to the other display screen. Thus it emulates what a + single X server would do for two screens (e.g. :0.0 and + :0.1) The illusion of a single Xserver with multiple + screens is achieved by forwarding events to the 2nd + one via the XTEST extension. + + What the x11vnc bcx_xattach command does is to perform + some pointer movements to try to INDUCE xattach/x2x + to 'jump' to the other display. In what follows the + 'master' display refers to the one that when it has + 'focus' it is basically doing nothing besides watching + for the mouse to go over an edge. The 'slave' + display refers to the one to which the mouse and + keyboard is redirected to once an edge in the master + has been crossed. Note that the x11vnc executing the + bcx_xattach command MUST be the one connected to the + *master* display. + + Also note that when input is being redirected (via + XTEST) from the master display to the slave display, + the master display's pointer and keyboard are *grabbed* + by xattach/x2x. x11vnc can use this info to verify that + the master/slave mode change has taken place correctly. + If you specify the "ifneeded" option (see below) + and the initial grab state is that of the desired + final state, then no pointer movements are injected + and "DONE,GRAB_OK" is returned. + + "str" must contain one of "up", "down", "left", + or "right" to indicate the direction of the 'jump'. + "str" must also contain one of "master_to_slave" + or "slave_to_master" to indicate the type of mode + change induced by the jump. Use "M2S" and "S2M" + as shorter aliases. + + "str" may be a "+" separated list of additional + tuning options. The "shift=n" option indicates an + offset shift position away from (0,0) (default 20). + "final=x+y" specifies the final position of the cursor + at the end of the normal move sequence; default 30+30. + "extra_move=x+y" means to do one more pointer move + after "final" to x+y. "dt=n" sets the sleep time + in milliseconds between pointer moves (default: 40ms) + "retry=n" specifies the maximum number of retries if + the grab state change fails. "ifneeded" means to not + apply the pointer movements if the initial grab state is + that of the desired final state. "nograbcheck" means + to not check if the grab state changed as expected and + only apply the pointer movements (default is to check + the grab states.) + + If you do not specify "up", etc., to bcx_xattach + nothing will be attempted and the command returns + the string FAIL,NO_DIRECTION_SPECIFIED. If you do + not specify "master_to_slave" or "M2S", etc., to + bcx_xattach nothing will be attempted and the command + returns the string FAIL,NO_MODE_CHANGE_SPECIFIED. + + Otherwise, the returned string will contain "DONE". + It will be "DONE,GRAB_OK" if the grab state changed + as expected (or if "ifneeded" was supplied and + the initial grab state was already the desired + one.) If the initial grab state was incorrect, + but the final grab state was correct then it is + "DONE,GRAB_FAIL_INIT". If the initial grab state + was correct, but the final grab state was incorrect + then it is "DONE,GRAB_FAIL_FINAL". If both are + incorrect it will be "DONE,GRAB_FAIL". Under grab + failure the string will be followed by ":p1,k1-p2,k2" + where p1,k1 indicates the initial pointer and keyboard + grab states and p2,k2 the final ones. If GRAB_FAIL or + GRAB_FAIL_FINAL occurs, the action will be retried up + to 3 times; trying to reset the state and sleeping a + bit between each try. Set retry=n to adjust the number + of retries, zero to disable retries. + + Examples: + -R bcx_xattach:down+M2S + -R bcx_xattach:up+S2M + -R bcx_xattach:up+S2M+nograbcheck+dt=30 + -R bcx_xattach:down+M2S+extra_move=100+100 + + or use -Q instead of -R to retrieve the result text. + + End of the bcx_xattach:str description. + The vncconnect(1) command from standard VNC distributions may also be used if string is prefixed with "cmd=" E.g. 'vncconnect cmd=stop'. Under some @@ -17498,7 +17880,8 @@ n query straight to the X11VNC_REMOTE property or connect file use "qry=..." instead of "cmd=..." - ans= stop quit exit shutdown ping blacken zero + ans= stop quit exit shutdown ping resend_cutbuffer + resend_clipboard resend_primary blacken zero refresh reset close disconnect id sid waitmapped nowaitmapped clip flashcmap noflashcmap shiftcmap truecolor notruecolor overlay nooverlay overlay_cursor @@ -17509,7 +17892,7 @@ n once timeout tightfilexfer notightfilexfer ultrafilexfer noultrafilexfer rfbversion deny lock nodeny unlock avahi mdns zeroconf noavahi nomdns nozeroconf connect - proxy allowonce allow localhost nolocalhost listen + proxy allowonce allow localhost nolocalhost listen lookup nolookup accept afteraccept gone shm noshm flipbyteorder noflipbyteorder onetile noonetile solid_color solid nosolid blackout xinerama noxinerama @@ -17519,10 +17902,10 @@ n sloppy_keys nosloppy_keys skip_dups noskip_dups add_keysyms noadd_keysyms clear_mods noclear_mods clear_keys noclear_keys clear_all clear_locks keystate - remap repeat norepeat fb nofb bell nobell sel nosel - primary noprimary setprimary nosetprimary clipboard - noclipboard setclipboard nosetclipboard seldir - cursorshape nocursorshape cursorpos nocursorpos + remap repeat norepeat fb nofb bell nobell sendbell + sel nosel primary noprimary setprimary nosetprimary + clipboard noclipboard setclipboard nosetclipboard + seldir cursorshape nocursorshape cursorpos nocursorpos cursor_drag nocursor_drag cursor show_cursor noshow_cursor nocursor arrow xfixes noxfixes xdamage noxdamage xd_area xd_mem alphacut alphafrac alpharemove @@ -17538,16 +17921,18 @@ n nowireframe nowf wireframelocal wfl nowireframelocal nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area scr_skip scr_inc scr_keys scr_term scr_keyrepeat - scr_parms scrollcopyrect scr noscrollcopyrect noscr - fixscreen noxrecord xrecord reset_record pointer_mode pm - input_skip allinput noallinput input grabkbd nograbkbd - grabptr nograbptr grabalways nograbalways grablocal - client_input ssltimeout speeds wmdt debug_pointer dp - nodebug_pointer nodp debug_keyboard dk nodebug_keyboard - nodk keycode deferupdate defer setdefer wait_ui - wait_bog nowait_bog slow_fb xrefresh wait readtimeout - nap nonap sb screen_blank fbpm nofbpm dpms nodpms - clientdpms noclientdpms forcedpms noforcedpms + scr_parms scrollcopyrect scr noscrollcopyrect + noscr fixscreen noxrecord xrecord reset_record + pointer_mode pm input_skip allinput noallinput input + grabkbd nograbkbd grabptr nograbptr grabalways + nograbalways grablocal client_input ssltimeout + speeds wmdt debug_pointer dp nodebug_pointer nodp + debug_keyboard dk nodebug_keyboard nodk keycode + keysym ptr sleep get_xprop set_xprop wininfo + bcx_xattach deferupdate defer setdefer extra_fbur + wait_ui wait_bog nowait_bog slow_fb xrefresh wait + readtimeout nap nonap sb screen_blank fbpm nofbpm dpms + nodpms clientdpms noclientdpms forcedpms noforcedpms noserverdpms serverdpms noultraext ultraext chatwindow nochatwindow chaton chatoff fs gaps grow fuzz snapfb nosnapfb rawfb uinput_accel uinput_thresh uinput_reset @@ -17565,21 +17950,23 @@ n macnoresize macresize nomacnoresize maciconanim macmenu macnomenu nomacmenu macuskbd nomacuskbd noremote - aro= noop display vncdisplay desktopname guess_desktop - http_url auth xauth users rootshift clipshift scale_str - scaled_x scaled_y scale_numer scale_denom scale_fac_x + aro= noop display vncdisplay autoport loop loopbg + desktopname guess_desktop http_url auth xauth + users rootshift clipshift scale_str scaled_x + scaled_y scale_numer scale_denom scale_fac_x scale_fac_y scaling_blend scaling_nomult4 scaling_pad scaling_interpolate inetd privremote unsafe safer nocmds passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem sslverify stunnel stunnel_pem https httpsredir - usepw using_shm logfile o flag rc norc h help V version - lastmod bg sigpipe threads readrate netrate netlatency - pipeinput clients client_count pid ext_xtest ext_xtrap - ext_xrecord ext_xkb ext_xshm ext_xinerama ext_overlay - ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons - button_mask mouse_x mouse_y bpp depth indexed_color - dpy_x dpy_y wdpy_x wdpy_y off_x off_y cdpy_x cdpy_y - coff_x coff_y rfbauth passwd viewpasswd + usepw using_shm logfile o flag rmflag rc norc h help + V version lastmod bg sigpipe threads readrate netrate + netlatency pipeinput clients client_count pid ext_xtest + ext_xtrap ext_xrecord ext_xkb ext_xshm ext_xinerama + ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin + num_buttons button_mask mouse_x mouse_y grab_state + pointer_pos bpp depth indexed_color dpy_x dpy_y wdpy_x + wdpy_y off_x off_y cdpy_x cdpy_y coff_x coff_y rfbauth + passwd viewpasswd -QD variable Just like -query variable, but returns the default value for that parameter (no running x11vnc server @@ -17599,10 +17986,43 @@ n the -query request is processed in the normal way. This allows for a reliable way to see if the -remote command was processed by querying for any new settings. - Note however that there is timeout of a few seconds so - if the x11vnc takes longer than that to process the - requests the requester will think that a failure has - taken place. + Note however that there is timeout of a few seconds + (see the next paragraph) so if the x11vnc takes longer + than that to process the requests the requester will + think that a failure has taken place. + + The default is to wait 3.5 seconds. Or if cmd=stop + only 1.0 seconds. If cmd matches 'script:' then it + will wait up to 10.0 seconds. Set X11VNC_SYNC_TIMEOUT + to the number of seconds you want it to wait. + +-query_retries str If a query fails to get a response from an x11vnc + server, retry up to n times. "str" is specified as + n[:t][/match] Optionally the delay between tries may + be specified by "t" a floating point time (default + 0.5 seconds.) Note: the response is not checked for + validity or whether it corresponds to the query sent. + The query "ping:mystring" may be used to help uniquely + identify the query. Optionally, a matching string after + a "/" will be used to check the result text. Up to + n retries will take place until the matching string is + found in the output text. If the match string is never + found the program's exit code is 1; if the match is + found it exits with 0. Note that there may be stdout + printed for each retry (i.e. multiple lines printed + out to stdout.) + Example: -query_retries 4:1.5/grab_state + +-remote_prefix str Enable a remote-control communication channel for + connected VNC clients. str is a non-empty string. If a + VNC client sends rfbCutText having the prefix "str" + then the part after it is processed as though it were + sent via 'x11vnc -remote ...'. If it begins with + neither 'cmd=' nor 'qry=' then 'qry=' is assumed. + Any corresponding output text for that remote control + command is sent back to all client as rfbCutText. + The returned output is also prefixed with "str". + Example: -remote_prefix DO_THIS: -noremote Do not process any remote control commands or queries. -yesremote Do process remote control commands or queries. diff --git a/x11vnc/connections.c b/x11vnc/connections.c index 20defff..942b715 100644 --- a/x11vnc/connections.c +++ b/x11vnc/connections.c @@ -48,9 +48,11 @@ so, delete this exception statement from your version. #include "sslhelper.h" #include "xwrappers.h" #include "xevents.h" +#include "win_utils.h" #include "macosx.h" #include "macosxCG.h" #include "userinput.h" +#include "pointer.h" /* * routines for handling incoming, outgoing, etc connections @@ -93,6 +95,11 @@ int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, int len, FILE *output); int check_access(char *addr); void client_set_net(rfbClientPtr client); +char *get_xprop(char *prop, Window win); +int set_xprop(char *prop, Window win, char *value); +char *bcx_xattach(char *str, int *pg_init, int *kg_init); +void grab_state(int *ptr_grabbed, int *kbd_grabbed); +char *wininfo(Window win, int show_children); static rfbClientPtr *client_match(char *str); static void free_client_data(rfbClientPtr client); @@ -606,7 +613,7 @@ int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, int j, k = -1; if (0) fprintf(stderr, "line: %s", line); /* take care to handle embedded nulls */ - for (j=0; j < sizeof(line); j++) { + for (j=0; j < (int) sizeof(line); j++) { if (line[j] != '\0') { k = j; } @@ -2756,6 +2763,503 @@ void read_x11vnc_remote_prop(int nomsg) { #endif /* NO_X11 */ } +void grab_state(int *ptr_grabbed, int *kbd_grabbed) { + int rcp, rck; + double t0, t1; + double ta, tb, tc; + *ptr_grabbed = -1; + *kbd_grabbed = -1; + + if (!dpy) { + return; + } + *ptr_grabbed = 0; + *kbd_grabbed = 0; + +#if !NO_X11 + X_LOCK; + + XSync(dpy, False); + + ta = t0 = dnow(); + + rcp = XGrabPointer(dpy, window, False, 0, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + XUngrabPointer(dpy, CurrentTime); + + tb = dnow(); + + rck = XGrabKeyboard(dpy, window, False, GrabModeAsync, GrabModeAsync, CurrentTime); + XUngrabKeyboard(dpy, CurrentTime); + + tc = dnow(); + + XSync(dpy, False); + + t1 = dnow(); + + X_UNLOCK; + if (rcp == AlreadyGrabbed || rcp == GrabFrozen) { + *ptr_grabbed = 1; + } + if (rck == AlreadyGrabbed || rck == GrabFrozen) { + *kbd_grabbed = 1; + } + rfbLog("grab_state: checked %d,%d in %.6f sec (%.6f %.6f)\n", + *ptr_grabbed, *kbd_grabbed, t1-t0, tb-ta, tc-tb); +#endif +} + +static void pmove(int x, int y) { + if (x < 0 || y < 0) { + rfbLog("pmove: skipping negative x or y: %d %d\n", x, y); + return; + } + rfbLog("pmove: x y: %d %d\n", x, y); + pointer(0, x, y, NULL); + XFlush_wr(dpy); +} + + +char *bcx_xattach(char *str, int *pg_init, int *kg_init) { + int grab_check = 1; + int shift = 20; + int final_x = 30, final_y = 30; + int extra_x = -1, extra_y = -1; + int t1, t2, dt = 40 * 1000; + int ifneeded = 0; + char *dir = "none", *flip = "none", *q; + int pg1, kg1, pg2, kg2; + char _bcx_res[128]; + + /* str:[up,down,left,right]+nograbcheck+shift=n+final=x+y+extra_move=x+y+[master_to_slave,slave_to_master,M2S,S2M]+dt=n+retry=n+ifneeded */ + + if (strstr(str, "up")) { + dir = "up"; + } else if (strstr(str, "down")) { + dir = "down"; + } else if (strstr(str, "left")) { + dir = "left"; + } else if (strstr(str, "right")) { + dir = "right"; + } else { + return strdup("FAIL,NO_DIRECTION_SPECIFIED"); + } + + if (strstr(str, "master_to_slave") || strstr(str, "M2S")) { + flip = "M2S"; + } else if (strstr(str, "slave_to_master") || strstr(str, "S2M")) { + flip = "S2M"; + } else { + return strdup("FAIL,NO_MODE_CHANGE_SPECIFIED"); + } + + if (strstr(str, "nograbcheck")) { + grab_check = 0; + } + if (strstr(str, "ifneeded")) { + ifneeded = 1; + } + q = strstr(str, "shift="); + if (q && sscanf(q, "shift=%d", &t1) == 1) { + shift = t1; + } + q = strstr(str, "final="); + if (q && sscanf(q, "final=%d+%d", &t1, &t2) == 2) { + final_x = t1; + final_y = t2; + } + q = strstr(str, "extra_move="); + if (q && sscanf(q, "extra_move=%d+%d", &t1, &t2) == 2) { + extra_x = t1; + extra_y = t2; + } + q = strstr(str, "dt="); + if (q && sscanf(q, "dt=%d", &t1) == 1) { + dt = t1 * 1000; + } + + if (grab_check) { + int read_init = 0; + + if (*pg_init >=0 && *kg_init >=0) { + pg1 = *pg_init; + kg1 = *kg_init; + read_init = 1; + } else { + grab_state(&pg1, &kg1); + read_init = 0; + } + + if (!strcmp(flip, "M2S")) { + if (ifneeded && pg1 == 1 && kg1 == 1) { + rfbLog("bcx_xattach: M2S grab state is already what we want, skipping moves: %d,%d\n", pg1, kg1); + return strdup("DONE,GRAB_OK"); + } + } else if (!strcmp(flip, "S2M")) { + if (ifneeded && pg1 == 0 && kg1 == 0) { + rfbLog("bcx_xattach: S2M grab state is already what we want, skipping moves: %d,%d\n", pg1, kg1); + return strdup("DONE,GRAB_OK"); + } + } + + if (read_init) { + ; + } else if (!strcmp(flip, "M2S")) { + if (pg1 != 0 || kg1 != 0) { + rfbLog("bcx_xattach: M2S init grab state incorrect: %d,%d\n", pg1, kg1); + usleep(2*dt); + grab_state(&pg1, &kg1); + rfbLog("bcx_xattach: slept and retried, grab is now: %d,%d\n", pg1, kg1); + } + } else if (!strcmp(flip, "S2M")) { + if (pg1 != 1 || kg1 != 1) { + rfbLog("bcx_xattach: S2M init grab state incorrect: %d,%d\n", pg1, kg1); + usleep(2*dt); + grab_state(&pg1, &kg1); + rfbLog("bcx_xattach: slept and retried, grab is now: %d,%d\n", pg1, kg1); + } + } + if (!read_init) { + *pg_init = pg1; + *kg_init = kg1; + } + } + + /* + * A guide for BARCO xattach: + * + * For -cursor_rule 'b(0):%:t(1),t(1):%:b(0)' + * down+M2S up+S2M + * For -cursor_rule 'r(0):%:l(1),l(1):%:r(0)' + * right+M2S left+S2M + * + * For -cursor_rule 't(0):%:b(1),b(1):%:t(0)' + * up+M2S down+S2M + * For -cursor_rule 'l(0):%:r(1),r(1):%:l(0)' + * left+M2S right+S2M + * For -cursor_rule 'l(0):%:r(1),r(1):%:l(0),r(0):%:l(1),l(1):%:r(0)' + * left+M2S right+S2M (we used to do both 'right') + */ + + if (!strcmp(flip, "M2S")) { + if (!strcmp(dir, "up")) { + pmove(shift, 0); /* go to top edge */ + usleep(dt); + pmove(shift+1, 0); /* move 1 for MotionNotify */ + } else if (!strcmp(dir, "down")) { + pmove(shift, dpy_y-1); /* go to bottom edge */ + usleep(dt); + pmove(shift+1, dpy_y-1); /* move 1 for MotionNotify */ + } else if (!strcmp(dir, "left")) { + pmove(0, shift); /* go to left edge */ + usleep(dt); + pmove(0, shift+1); /* move 1 for MotionNotify */ + } else if (!strcmp(dir, "right")) { + pmove(dpy_x-1, shift); /* go to right edge */ + usleep(dt); + pmove(dpy_x-1, shift+1); /* move 1 for Motion Notify */ + } + } else if (!strcmp(flip, "S2M")) { + int dts = dt/2; + if (!strcmp(dir, "up")) { + pmove(shift, 2); /* Approach top edge in 3 moves. 1st move */ + usleep(dts); + pmove(shift, 1); /* 2nd move */ + usleep(dts); + pmove(shift, 0); /* 3rd move */ + usleep(dts); + pmove(shift+1, 0); /* move 1 for MotionNotify */ + usleep(dts); + pmove(shift+1, dpy_y-2); /* go to height-2 for extra pixel (slave y now == 0?) */ + usleep(dts); + pmove(shift, dpy_y-2); /* move 1 for MotionNotify */ + usleep(dts); + pmove(shift, 1); /* go to 1 to be sure slave y == 0 */ + usleep(dts); + pmove(shift+1, 1); /* move 1 for MotionNotify */ + } else if (!strcmp(dir, "down")) { + pmove(shift, dpy_y-3); /* Approach bottom edge in 3 moves. 1st move */ + usleep(dts); + pmove(shift, dpy_y-2); /* 2nd move */ + usleep(dts); + pmove(shift, dpy_y-1); /* 3rd move */ + usleep(dts); + pmove(shift+1, dpy_y-1); /* move 1 for MotionNotify */ + usleep(dts); + pmove(shift+1, 1); /* go to 1 for extra pixel (slave y now == dpy_y-1?) */ + usleep(dts); + pmove(shift, 1); /* move 1 for MotionNotify */ + usleep(dts); + pmove(shift, dpy_y-2); /* go to dpy_y-2 to be sure slave y == dpy_y-1 */ + usleep(dts); + pmove(shift+1, dpy_y-2); /* move 1 for MotionNotify */ + } else if (!strcmp(dir, "left")) { + pmove(2, shift); /* Approach left edge in 3 moves. 1st move */ + usleep(dts); + pmove(1, shift); /* 2nd move */ + usleep(dts); + pmove(0, shift); /* 3rd move */ + usleep(dts); + pmove(0, shift+1); /* move 1 for MotionNotify */ + usleep(dts); + pmove(dpy_x-2, shift+1); /* go to width-2 for extra pixel (slave x now == 0?) */ + usleep(dts); + pmove(dpy_x-2, shift); /* move 1 for MotionNotify */ + usleep(dts); + pmove(1, shift); /* go to 1 to be sure slave x == 0 */ + usleep(dts); + pmove(1, shift+1); /* move 1 for MotionNotify */ + } else if (!strcmp(dir, "right")) { + pmove(dpy_x-3, shift); /* Approach right edge in 3 moves. 1st move */ + usleep(dts); + pmove(dpy_x-2, shift); /* 2nd move */ + usleep(dts); + pmove(dpy_x-1, shift); /* 3rd move */ + usleep(dts); + pmove(dpy_x-1, shift+1); /* move 1 for MotionNotify */ + usleep(dts); + pmove(1, shift+1); /* go to 1 to extra pixel (slave x now == dpy_x-1?) */ + usleep(dts); + pmove(1, shift); /* move 1 for MotionNotify */ + usleep(dts); + pmove(dpy_x-2, shift); /* go to dpy_x-2 to be sure slave x == dpy_x-1 */ + usleep(dts); + pmove(dpy_x-2, shift+1); /* move 1 for MotionNotify */ + } + } + + usleep(dt); + pmove(final_x, final_y); + usleep(dt); + + if (extra_x >= 0 && extra_y >= 0) { + pmove(extra_x, extra_y); + usleep(dt); + } + + strcpy(_bcx_res, "DONE"); + + if (grab_check) { + char st[64]; + + usleep(3*dt); + grab_state(&pg2, &kg2); + + if (!strcmp(flip, "M2S")) { + if (pg2 != 1 || kg2 != 1) { + rfbLog("bcx_xattach: M2S fini grab state incorrect: %d,%d\n", pg2, kg2); + usleep(2*dt); + grab_state(&pg2, &kg2); + rfbLog("bcx_xattach: slept and retried, grab is now: %d,%d\n", pg2, kg2); + } + } else if (!strcmp(flip, "S2M")) { + if (pg2 != 0 || kg2 != 0) { + rfbLog("bcx_xattach: S2M fini grab state incorrect: %d,%d\n", pg2, kg2); + usleep(2*dt); + grab_state(&pg2, &kg2); + rfbLog("bcx_xattach: slept and retried, grab is now: %d,%d\n", pg2, kg2); + } + } + + sprintf(st, ":%d,%d-%d,%d", pg1, kg1, pg2, kg2); + + if (getenv("GRAB_CHECK_LOOP")) { + int i, n = atoi(getenv("GRAB_CHECK_LOOP")); + rfbLog("grab st: %s\n", st); + for (i=0; i < n; i++) { + usleep(dt); + grab_state(&pg2, &kg2); + sprintf(st, ":%d,%d-%d,%d", pg1, kg1, pg2, kg2); + rfbLog("grab st: %s\n", st); + } + } + + if (!strcmp(flip, "M2S")) { + if (pg1 == 0 && kg1 == 0 && pg2 == 1 && kg2 == 1) { + strcat(_bcx_res, ",GRAB_OK"); + } else { + rfbLog("bcx_xattach: M2S grab state incorrect: %d,%d -> %d,%d\n", pg1, kg1, pg2, kg2); + strcat(_bcx_res, ",GRAB_FAIL"); + if (pg2 == 1 && kg2 == 1) { + strcat(_bcx_res, "_INIT"); + } else if (pg1 == 0 && kg1 == 0) { + strcat(_bcx_res, "_FINAL"); + } + strcat(_bcx_res, st); + } + } else if (!strcmp(flip, "S2M")) { + if (pg1 == 1 && kg1 == 1 && pg2 == 0 && kg2 == 0) { + strcat(_bcx_res, ",GRAB_OK"); + } else { + rfbLog("bcx_xattach: S2M grab state incorrect: %d,%d -> %d,%d\n", pg1, kg1, pg2, kg2); + strcat(_bcx_res, ",GRAB_FAIL"); + if (pg2 == 0 && kg2 == 0) { + strcat(_bcx_res, "_INIT"); + } else if (pg1 == 1 && kg1 == 1) { + strcat(_bcx_res, "_FINAL"); + } + strcat(_bcx_res, st); + } + } + } + return strdup(_bcx_res); +} + +int set_xprop(char *prop, Window win, char *value) { + int rc = -1; +#if !NO_X11 + Atom aprop; + + RAWFB_RET(rc) + + if (!prop || !value) { + return rc; + } + if (win == None) { + win = rootwin; + } + aprop = XInternAtom(dpy, prop, False); + rc = XChangeProperty(dpy, win, aprop, XA_STRING, 8, + PropModeReplace, (unsigned char *)value, strlen(value)); + return rc; +#else + RAWFB_RET(rc) + if (!prop || !win || !value) {} + return rc; +#endif /* NO_X11 */ +} + +char *get_xprop(char *prop, Window win) { +#if NO_X11 + RAWFB_RET(NULL) + if (!prop || !win) {} + return NULL; +#else + Atom type, aprop; + int format, slen, dlen; + unsigned long nitems = 0, bytes_after = 0; + unsigned char* data = NULL; + char get_str[VNC_CONNECT_MAX+1]; + + RAWFB_RET(NULL) + + if (prop == NULL || !strcmp(prop, "")) { + return NULL; + } + if (win == None) { + win = rootwin; + } + aprop = XInternAtom(dpy, prop, True); + if (aprop == None) { + return NULL; + } + + get_str[0] = '\0'; + slen = 0; + + /* read the property value into get_str: */ + do { + if (XGetWindowProperty(dpy, win, aprop, nitems/4, + VNC_CONNECT_MAX/16, False, AnyPropertyType, &type, + &format, &nitems, &bytes_after, &data) == Success) { + + dlen = nitems * (format/8); + if (slen + dlen > VNC_CONNECT_MAX) { + /* too big */ + rfbLog("get_xprop: warning: truncating large '%s'" + " string > %d bytes.\n", prop, VNC_CONNECT_MAX); + XFree_wr(data); + break; + } + memcpy(get_str+slen, data, dlen); + slen += dlen; + get_str[slen] = '\0'; + XFree_wr(data); + } + } while (bytes_after > 0); + + get_str[VNC_CONNECT_MAX] = '\0'; + rfbLog("get_prop: read: '%s' = '%s'\n", prop, get_str); + + return strdup(get_str); +#endif /* NO_X11 */ +} + +static char _win_fmt[1000]; + +static char *win_fmt(Window win, XWindowAttributes a) { + memset(_win_fmt, 0, sizeof(_win_fmt)); + sprintf(_win_fmt, "0x%lx:%dx%dx%d+%d+%d-map:%d-bw:%d-cl:%d-vis:%d-bs:%d/%d", + win, a.width, a.height, a.depth, a.x, a.y, a.map_state, a.border_width, a.class, + (int) ((a.visual)->visualid), a.backing_store, a.save_under); + return _win_fmt; +} + +char *wininfo(Window win, int show_children) { +#if NO_X11 + RAWFB_RET(NULL) + if (!win || !show_children) {} + return NULL; +#else + XWindowAttributes attr; + int n, size = X11VNC_REMOTE_MAX; + char get_str[X11VNC_REMOTE_MAX+1]; + unsigned int nchildren; + Window rr, pr, *children; + + RAWFB_RET(NULL) + + if (win == None) { + return strdup("None"); + } + + X_LOCK; + if (!valid_window(win, &attr, 1)) { + X_UNLOCK; + return strdup("Invalid"); + } + get_str[0] = '\0'; + + if (show_children) { + XQueryTree_wr(dpy, win, &rr, &pr, &children, &nchildren); + } else { + nchildren = 1; + children = (Window *) calloc(2 * sizeof(Window), 1); + children[0] = win; + } + for (n=0; n < nchildren; n++) { + char tmp[32]; + char *str = "Invalid"; + Window w = children[n]; + if (valid_window(w, &attr, 1)) { + if (!show_children) { + str = win_fmt(w, attr); + } else { + sprintf(tmp, "0x%lx", w); + str = tmp; + } + } + if (strlen(get_str) + 1 + strlen(str) >= size) { + break; + } + if (n > 0) { + strcat(get_str, ","); + } + strcat(get_str, str); + } + get_str[size] = '\0'; + if (!show_children) { + free(children); + } else if (nchildren) { + XFree_wr(children); + } + rfbLog("wininfo computed: %s\n", get_str); + X_UNLOCK; + + return strdup(get_str); +#endif /* NO_X11 */ +} + /* * check if client_connect has been set, if so make the reverse connections. */ @@ -3082,6 +3586,8 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { return(RFB_CLIENT_REFUSE); } + /* We will RFB_CLIENT_ACCEPT or RFB_CLIENT_ON_HOLD from here on. */ + if (passwdfile) { if (strstr(passwdfile, "read:") == passwdfile || strstr(passwdfile, "cmd:") == passwdfile) { @@ -3137,7 +3643,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { cd->cmp_bytes_sent = 0; cd->raw_bytes_sent = 0; - rfbLog("incr accepted_client for %s:%d.\n", client->host, get_remote_port(client->sock)); + rfbLog("incr accepted_client for %s:%d sock=%d\n", client->host, get_remote_port(client->sock), client->sock); accepted_client++; last_client = time(NULL); @@ -3204,7 +3710,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { unixpw_login_viewonly = 1; client->viewOnly = FALSE; } - unixpw_last_try_time = time(NULL); + unixpw_last_try_time = time(NULL) + 10; unixpw_screen(1); unixpw_keystroke(0, 0, 1); @@ -3403,11 +3909,16 @@ void check_new_clients(void) { int run_after_accept = 0; if (unixpw_in_progress) { + static double lping = 0.0; + if (lping < dnow() + 5) { + mark_rect_as_modified(0, 0, 1, 1, 1); + lping = dnow(); + } if (unixpw_client && unixpw_client->viewOnly) { unixpw_login_viewonly = 1; unixpw_client->viewOnly = FALSE; } - if (time(NULL) > unixpw_last_try_time + 25) { + if (time(NULL) > unixpw_last_try_time + 45) { rfbLog("unixpw_deny: timed out waiting for reply.\n"); unixpw_deny(); } diff --git a/x11vnc/connections.h b/x11vnc/connections.h index 6a135e2..25a2027 100644 --- a/x11vnc/connections.h +++ b/x11vnc/connections.h @@ -72,5 +72,10 @@ extern int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *in int len, FILE *output); extern int check_access(char *addr); extern void client_set_net(rfbClientPtr client); +extern char *get_xprop(char *prop, Window win); +extern int set_xprop(char *prop, Window win, char *value); +extern char *bcx_xattach(char *str, int *pg_init, int *kg_init); +extern void grab_state(int *ptr_grabbed, int *kbd_grabbed); +extern char *wininfo(Window win, int show_children); #endif /* _X11VNC_CONNECTIONS_H */ diff --git a/x11vnc/enc.h b/x11vnc/enc.h index aa8b57b..26e3c01 100644 --- a/x11vnc/enc.h +++ b/x11vnc/enc.h @@ -71,7 +71,8 @@ so, delete this exception statement from your version. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; version 2 of the License, or (at + * your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/x11vnc/help.c b/x11vnc/help.c index ff697af..d16f98a 100644 --- a/x11vnc/help.c +++ b/x11vnc/help.c @@ -793,7 +793,7 @@ void print_help(int mode) { " presented to the user on a black screen inside the\n" " vncviewer. The connection is dropped if the user fails\n" " to supply the correct password in 3 tries or does not\n" -" send one before a 25 second timeout. Existing clients\n" +" send one before a 45 second timeout. Existing clients\n" " are view-only during this period.\n" "\n" " If the first character received is \"Escape\" then the\n" @@ -1052,6 +1052,10 @@ void print_help(int mode) { " under -display WAIT:... for more details about XDM,\n" " etc configuration.\n" "\n" +" Remember to enable XDMCP in the xdm-config, gdm.conf,\n" +" or kdmrc configuration file. See -display WAIT: for\n" +" more info.\n" +"\n" "-sshxdmsvc Display manager Terminal services mode based on SSH.\n" " Alias for -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp\n" " -localhost.\n" @@ -1064,6 +1068,48 @@ void print_help(int mode) { " under -display WAIT:... for more details about XDM,\n" " etc configuration.\n" "\n" +" Remember to enable XDMCP in the xdm-config, gdm.conf,\n" +" or kdmrc configuration file. See -display WAIT: for\n" +" more info.\n" +"\n" +"-unixpw_system_greeter Present a \"Press 'Escape' for System Greeter\" option\n" +" to the connecting VNC client in combined -unixpw\n" +" and xdmcp FINDCREATEDISPLAY modes (e.g. -xdmsvc).\n" +"\n" +" Normally in a -unixpw mode the VNC client must\n" +" supply a valid username and password to gain access.\n" +" However, if -unixpw_system_greeter is supplied AND\n" +" the FINDCREATEDISPLAY command matches 'xdmcp', then\n" +" the user has the option to press Escape and then get a\n" +" XDM/GDM/KDM login/greeter panel instead. They will then\n" +" supply a username and password directly to the greeter.\n" +"\n" +" Otherwise, in xdmcp FINDCREATEDISPLAY mode the user\n" +" must supply his username and password TWICE. First to\n" +" the initial unixpw login dialog, and second to the\n" +" subsequent XDM/GDM/KDM greeter. Note that if the user\n" +" re-connects and supplies his username and password in\n" +" the unixpw dialog the xdmcp greeter is skipped and\n" +" he is connected directly to his existing X session.\n" +" So the -unixpw_system_greeter option avoids the extra\n" +" password at X session creation time.\n" +"\n" +" Example: x11vnc -xdmsvc -unixpw_system_greeter\n" +" See -unixpw and -display WAIT:... for more info.\n" +"\n" +" The special options after a colon at the end of the\n" +" username (e.g. user:solid) described under -display\n" +" WAIT: are also applied in this mode if they are typed\n" +" in before the user hits Escape. The username is ignored\n" +" but the colon options are not.\n" +"\n" +" If the user pressed Escape the FINDCREATEDISPLAY command\n" +" will be run with the env. var. X11VNC_XDM_ONLY=1.\n" +"\n" +" Remember to enable XDMCP in the xdm-config, gdm.conf,\n" +" or kdmrc configuration file. See -display WAIT: for\n" +" more info.\n" +"\n" "-redirect port As in FINDCREATEDISPLAY-Xvnc.redirect mode except\n" " redirect immediately (i.e. without X session finding\n" " or creation) to a VNC server listening on port. You\n" @@ -1135,12 +1181,13 @@ void print_help(int mode) { " Also in the case of -unixpw, the user logging in can\n" " place a colon at the end of her username and supply\n" " a few options: scale=, scale_cursor= (or sc=), solid\n" -" (or so), id=, clear_mods (or cm), clear_keys (or ck),\n" -" repeat, speeds= (or sp=), readtimeout= (or rd=),\n" -" rotate= (or ro=), or noncache (or nc), all separated by\n" -" commas if there is more than one. After the user logs\n" -" in successfully, these options will be applied to the\n" -" VNC screen. For example,\n" +" (or so), id=, clear_mods (or cm), clear_keys (or\n" +" ck), clear_all (or ca), repeat, speeds= (or sp=),\n" +" readtimeout= (or rd=), viewonly (or vo), nodisplay=\n" +" (or nd=), rotate= (or ro=), or noncache (or nc),\n" +" all separated by commas if there is more than one.\n" +" After the user logs in successfully, these options will\n" +" be applied to the VNC screen. For example,\n" "\n" " login: fred:scale=3/4,sc=1,repeat\n" " Password: ...\n" @@ -1152,6 +1199,9 @@ void print_help(int mode) { " your long \"login:\" line press the Up arrow once\n" " (before typing anything else).\n" "\n" +" In the login panel, press F1 to get a list of the\n" +" available options that you can add after the username.\n" +"\n" " Another option is \"geom=WxH\" or \"geom=WxHxD\" (or\n" " ge=). This only has an effect in FINDCREATEDISPLAY\n" " mode when a virtual X server such as Xvfb is going\n" @@ -1226,7 +1276,9 @@ void print_help(int mode) { " ignore in the finding process. The \":\" is optional.\n" " Ranges n-m e.g. 0-20 can also be supplied. This string\n" " can also be set by the connecting user via \"nd=\"\n" -" using \"+\" instead of \",\"\n" +" using \"+\" instead of \",\" If \"nd=all\" or you set\n" +" X11VNC_SKIP_DISPLAY=all then all display finding fails\n" +" as if you set X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (below.)\n" "\n" " Automatic Creation of User X Sessions:\n" "\n" @@ -1282,6 +1334,8 @@ void print_help(int mode) { " If for some reason you do not want x11vnc to ever\n" " try to find an existing display set the env. var\n" " X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (also -env ...)\n" +" This is the same as setting X11VNC_SKIP_DISPLAY=all or\n" +" supplying \"nd=all\" after \"username:\"\n" "\n" " Use WAIT:cmd=FINDCREATEDISPLAY-print to print out the\n" " script that is used for this.\n" @@ -1310,12 +1364,15 @@ void print_help(int mode) { " be the full path to the session/windowmanager program.\n" "\n" " More FD tricks: FD_CUPS=port or FD_CUPS=host:port\n" -" will set the cups printing environment. Similarly\n" -" for FD_ESD=port or FD_ESD=host:port for esddsp sound\n" -" redirection. FD_XDUMMY_NOROOT means the Xdummy server\n" -" does not need to be started as root (e.g. it will sudo\n" -" automatically). Set FD_EXTRA to a command to be run\n" -" a few seconds after the X server starts up.\n" +" will set the cups printing environment. Similarly for\n" +" FD_ESD=port or FD_ESD=host:port for esddsp sound\n" +" redirection. FD_XDUMMY_NOROOT means the Xdummy\n" +" server does not need to be started as root (e.g. it\n" +" will sudo automatically). Set FD_EXTRA to a command\n" +" to be run a few seconds after the X server starts up.\n" +" Set FD_TAG to be a unique name for the session, it is\n" +" set as an X property, that makes FINDDISPLAY only find\n" +" sessions with that tag value.\n" "\n" " If you want the FINDCREATEDISPLAY session to contact an\n" " XDMCP login manager (xdm/gdm/kdm) on the same machine,\n" @@ -1395,8 +1452,9 @@ void print_help(int mode) { " Otherwise in -unixpw mode the normal login panel is\n" " provided.\n" "\n" -" You *MUST* supply the -ssl option for VeNCrypt to be\n" -" active. This option only fine-tunes its operation.\n" +" You *MUST* supply the -ssl option for VeNCrypt to\n" +" be active. The -vencrypt option only fine-tunes its\n" +" operation.\n" "\n" "-anontls mode The ANONTLS extension to the VNC protocol allows\n" " encrypted SSL/TLS connections. If the -ssl mode is\n" @@ -1431,8 +1489,9 @@ void print_help(int mode) { "\n" " Long example: -anontls newdh:plain:support\n" "\n" -" You *MUST* supply the -ssl option for ANONTLS to be\n" -" active. This option only fine-tunes its operation.\n" +" You *MUST* supply the -ssl option for ANONTLS to\n" +" be active. The -anontls option only fine-tunes its\n" +" operation.\n" "\n" "-sslonly Same as: \"-vencrypt never -anontls never\" i.e. it\n" " disables the VeNCrypt and ANONTLS encryption methods\n" @@ -1456,16 +1515,17 @@ void print_help(int mode) { "\n" "-ssl [pem] Use the openssl library (www.openssl.org) to provide a\n" " built-in encrypted SSL/TLS tunnel between VNC viewers\n" -" and x11vnc. This requires libssl support to be compiled\n" -" into x11vnc at build time. If x11vnc is not built\n" -" with libssl support it will exit immediately when -ssl\n" -" is prescribed.\n" +" and x11vnc. This requires libssl support to be\n" +" compiled into x11vnc at build time. If x11vnc is not\n" +" built with libssl support it will exit immediately when\n" +" -ssl is prescribed. See the -stunnel option below for\n" +" an alternative.\n" "\n" " The VNC Viewer-side needs to support SSL/TLS as well.\n" " See this URL and also the discussion below for\n" " ideas on how to enable SSL support for the viewer:\n" " http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tun\n" -" nel-viewers x11vnc provides an SSL enabled Java\n" +" nel-viewers . x11vnc provides an SSL enabled Java\n" " viewer applet in the classes/ssl directory (-http or\n" " -httpdir options.) The SSVNC viewer package supports\n" " SSL tunnels too.\n" @@ -1555,6 +1615,11 @@ void print_help(int mode) { " See -ssldir below to use a directory besides the\n" " default ~/.vnc/certs\n" "\n" +" If your x11vnc binary was not compiled with OpenSSL\n" +" library support, use of the -ssl option will induce an\n" +" immediate failure and exit. For such binaries, consider\n" +" using the -stunnel option for SSL encrypted connections.\n" +"\n" " Misc Info: In temporary cert creation mode \"TMP\", set\n" " the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc print\n" " out the entire certificate, including the PRIVATE KEY\n" @@ -1657,7 +1722,7 @@ void print_help(int mode) { "\n" "\n" " NOTE: the following utilities, -sslGenCA, -sslGenCert,\n" -" -sslEncKey, and -sslCertInfo are provided for\n" +" -sslEncKey, -sslCertInfo, and -sslCRL are provided for\n" " completeness, but for casual usage they are overkill.\n" "\n" " They provide VNC Certificate Authority (CA) key creation\n" @@ -1708,8 +1773,9 @@ void print_help(int mode) { " the ss_vncviewer example script in the FAQ and SSVNC.)\n" "\n" "-sslCRL path Set the Certificate Revocation Lists (CRL) to \"path\".\n" +" This setting applies for both -ssl and -stunnel modes.\n" "\n" -" If path is a file, the file contains one more more CRLs\n" +" If path is a file, the file contains one or more CRLs\n" " in PEM format. If path is a directory, it contains\n" " hash named files of CRLs in the usual OpenSSL manner.\n" " See the OpenSSL and stunnel(8) documentation for\n" @@ -1721,6 +1787,10 @@ void print_help(int mode) { " The -sslCRL setting will be ignored when -sslverify is\n" " not specified.\n" "\n" +" Note that if a CRL's expiration date has passed, all\n" +" SSL connections will fail regardless of if they are\n" +" related to the subject of the CRL or not.\n" +"\n" " Only rarely will one's x11vnc -ssl infrastructure be so\n" " large that this option would be useful (since normally\n" " maintaining the contents of the -sslverify file or\n" @@ -1832,11 +1902,13 @@ void print_help(int mode) { "\n" " Similar to -sslGenCA, you will be prompted to fill\n" " in some information that will be recorded in the\n" -" certificate when it is created. Tip: if you know\n" -" the fully-qualified hostname other people will be\n" -" connecting to you can use that as the CommonName \"CN\"\n" -" to avoid some applications (e.g. web browsers and java\n" -" plugin) complaining it does not match the hostname.\n" +" certificate when it is created.\n" +"\n" +" Tip: if you know the fully-qualified hostname other\n" +" people will be connecting to, you can use that as the\n" +" CommonName \"CN\" to avoid some applications (e.g. web\n" +" browsers and java plugin) complaining that it does not\n" +" match the hostname.\n" "\n" " You will also need to supply the CA private key\n" " passphrase to unlock the private key created from\n" @@ -1860,14 +1932,14 @@ void print_help(int mode) { " the cert and private key. The .crt contains the\n" " certificate only.\n" "\n" -" NOTE: It is very important to know one should always\n" +" NOTE: It is very important to know one should\n" " generate new keys with a passphrase. Otherwise if an\n" " untrusted user steals the key file he could use it to\n" " masquerade as the x11vnc server (or VNC viewer client).\n" " You will be prompted whether to encrypt the key with\n" " a passphrase or not. It is recommended that you do.\n" " One inconvenience to a passphrase is that it must\n" -" be suppled every time x11vnc or the client app is\n" +" be typed in EVERY time x11vnc or the client app is\n" " started up.\n" "\n" " Examples:\n" @@ -1964,16 +2036,30 @@ void print_help(int mode) { "\n" " This external tunnel method was implemented prior to the\n" " integrated -ssl encryption described above. It still\n" -" works well. This requires stunnel to be installed\n" -" on the system and available via PATH (n.b. stunnel is\n" -" often installed in sbin directories). Version 4.x of\n" -" stunnel is assumed (but see -stunnel3 below.)\n" +" works well and avoids the requirement of linking with\n" +" the OpenSSL libraries. This mode requires stunnel\n" +" to be installed on the system and available via PATH\n" +" (n.b. stunnel is often installed in sbin directories).\n" +" Version 4.x of stunnel is assumed (but see -stunnel3\n" +" below.)\n" "\n" " [pem] is optional, use \"-stunnel /path/to/stunnel.pem\"\n" " to specify a PEM certificate file to pass to stunnel.\n" -" Whether one is needed or not depends on your stunnel\n" -" configuration. stunnel often generates one at install\n" -" time. See the stunnel documentation for details.\n" +" See the -ssl option for more info on certificate files.\n" +"\n" +" Whether or not your stunnel has its own certificate\n" +" depends on your stunnel configuration; stunnel often\n" +" generates one at install time. See your stunnel\n" +" documentation for details. In any event, if you want to\n" +" use this certificate you must supply the full path to it\n" +" as [pem]. Note: the file may only be readable by root.\n" +"\n" +" [pem] may also be the special strings \"TMP\", \"SAVE\",\n" +" and \"SAVE...\" as described in the -ssl option.\n" +" If [pem] is not supplied, \"SAVE\" is assumed.\n" +"\n" +" Note that the VeNCrypt, ANONTLS, and \"ANON\" modes\n" +" are not supported in -stunnel mode.\n" "\n" " stunnel is started up as a child process of x11vnc and\n" " any SSL connections stunnel receives are decrypted and\n" @@ -1981,22 +2067,37 @@ void print_help(int mode) { " \"The SSL VNC desktop is ...\" and \"SSLPORT=...\"\n" " are printed out at startup to indicate this.\n" "\n" -" The -localhost option is enforced by default\n" -" to avoid people routing around the SSL channel.\n" -" Set STUNNEL_DISABLE_LOCALHOST=1 before starting x11vnc\n" -" to disable the requirement.\n" +" The -localhost option is enforced by default to avoid\n" +" people routing around the SSL channel. Use -env\n" +" STUNNEL_DISABLE_LOCALHOST=1 to disable this security\n" +" requirement.\n" +"\n" +" Set -env STUNNEL_DEBUG=1 for more debugging printout.\n" +"\n" +" Your VNC viewer will also need to be able to connect\n" +" via SSL. Unfortunately not too many do this. See the\n" +" information about SSL viewers under the -ssl option.\n" "\n" -" Your VNC viewer will also need to be able to connect via\n" -" SSL. Unfortunately not too many do this. UltraVNC has\n" -" an encryption plugin but it does not seem to be SSL.\n" +" Also, in the x11vnc distribution, patched TightVNC\n" +" and UltraVNC Java applet jar files are provided in\n" +" the classes/ssl directory that do SSL connections.\n" +" Enable serving them with the -http, -http_ssl, -https,\n" +" or -httpdir (see the option descriptions for more info.)\n" "\n" -" Also, in the x11vnc distribution, a patched TightVNC\n" -" Java applet is provided in classes/ssl that does SSL\n" -" connections (only).\n" +" Note that for the Java viewer applet usage the\n" +" \"?PORT=xxxx\" in the various URLs printed at startup\n" +" will need to be supplied to the web browser to connect\n" +" properly.\n" "\n" -" It is also not too difficult to set up an stunnel or\n" -" other SSL tunnel on the viewer side. A simple example\n" -" on Unix using stunnel 3.x is:\n" +" Currently the automatic \"single port\" HTTPS mode of\n" +" -ssl is not fully supported in -stunnel mode. However,\n" +" it can be emulated via:\n" +"\n" +" %% x11vnc -stunnel -http_ssl -http_oneport ...\n" +"\n" +" In general, it is also not too difficult to set up\n" +" an stunnel or other SSL tunnel on the viewer side.\n" +" A simple example on Unix using stunnel 3.x is:\n" "\n" " %% stunnel -c -d localhost:5901 -r remotehost:5900\n" " %% vncviewer localhost:1\n" @@ -2006,7 +2107,8 @@ void print_help(int mode) { " and SSVNC for more examples.\n" "\n" "-stunnel3 [pem] Use version 3.x stunnel command line syntax instead of\n" -" version 4.x\n" +" version 4.x. The -http/-httpdir Java applet serving\n" +" is currently not available in this mode.\n" "\n" "-enc cipher:keyfile Use symmetric encryption with cipher \"cipher\"\n" " and secret key data in \"keyfile\". If keyfile is\n" @@ -2025,7 +2127,7 @@ void print_help(int mode) { " Note that this mode will NOT work with the UltraVNC DSM\n" " plugins because they alter the RFB protocol in addition\n" " to tunnelling with the symmetric cipher (an unfortunate\n" -" choice of implementation).\n" +" choice of implementation...)\n" "\n" " cipher can be one of: arc4, aesv2, aes-cfb, blowfish,\n" " aes256, or 3des. See the OpenSSL documentation for\n" @@ -2098,9 +2200,9 @@ void print_help(int mode) { " For both ways of using the viewer, you can specify the\n" " salt,ivec sizes (in GUI or, e.g. arc4@8,16).\n" "\n" -"-https [port] Use a special, separate HTTPS port (-ssl mode only)\n" -" for HTTPS Java viewer applet downloading. I.e. not 5900\n" -" and not 5800 (the defaults.)\n" +"-https [port] Use a special, separate HTTPS port (-ssl and\n" +" -stunnel modes only) for HTTPS Java viewer applet\n" +" downloading. I.e. not 5900 and not 5800 (the defaults.)\n" "\n" " BACKGROUND: In -ssl mode, it turns out you can use the\n" " single VNC port (e.g. 5900) for both VNC and HTTPS\n" @@ -2120,6 +2222,8 @@ void print_help(int mode) { " or VNC Viewer applet. That's right 3 separate \"Are\n" " you sure you want to connect?\" dialogs!)\n" "\n" +" END OF BACKGROUND.\n" +"\n" " USAGE: So use the -https option to provide a separate,\n" " more reliable HTTPS port that x11vnc will listen on. If\n" " [port] is not provided (or is 0), one is autoselected.\n" @@ -2153,7 +2257,9 @@ void print_help(int mode) { " to include the PORT= in the browser URL, simply supply\n" " \"-httpsredir\" to x11vnc.\n" "\n" -"-http_oneport For un-encrypted connections mode (i.e. no -ssl,\n" +" This options does not work in -stunnel mode.\n" +"\n" +"-http_oneport For UN-encrypted connections mode (i.e. no -ssl,\n" " -stunnel, or -enc options), allow the Java VNC Viewer\n" " applet to be downloaded thru the VNC port via HTTP.\n" "\n" @@ -3537,10 +3643,21 @@ void print_help(int mode) { " Same as -dp and -dk, respectively. Use multiple\n" " times for more output.\n" "\n" -"-defer time Time in ms to wait for updates before sending to client\n" +"-defer time Time in ms to delay sending updates to connected clients\n" " (deferUpdateTime) Default: %d\n" +"\n" "-wait time Time in ms to pause between screen polls. Used to cut\n" " down on load. Default: %d\n" +"\n" +"-extra_fbur n Perform extra FrameBufferUpdateRequests checks to\n" +" try to be in better sync with the client's requests.\n" +" What this does is perform extra polls of the client\n" +" socket at critical times (before '-defer' and '-wait'\n" +" calls.) The default is n=1. Set to a larger number to\n" +" insert more checks or set to n=0 to disable. A downside\n" +" of these extra calls is that more mouse input may be\n" +" processed than desired.\n" +"\n" "-wait_ui factor Factor by which to cut the -wait time if there\n" " has been recent user input (pointer or keyboard).\n" " Improves response, but increases the load whenever you\n" @@ -4350,6 +4467,28 @@ void print_help(int mode) { " x11vnc server as long as X permissions, etc. permit\n" " communication between the two.\n" "\n" +" FONTS: On some systems the tk fonts can be too small,\n" +" jagged, or otherwise unreadable. There are 4 env vars\n" +" you can set to be the tk font you prefer:\n" +"\n" +" X11VNC_FONT_BOLD main font for menus and buttons.\n" +" X11VNC_FONT_FIXED font for fixed width text.\n" +"\n" +" X11VNC_FONT_BOLD_SMALL tray icon font.\n" +" X11VNC_FONT_REG_SMALL tray icon menu font.\n" +"\n" +" The last two only apply for the tray icon mode.\n" +"\n" +" Here are some examples:\n" +"\n" +" -env X11VNC_FONT_BOLD='Helvetica -16 bold'\n" +" -env X11VNC_FONT_FIXED='Courier -14'\n" +" -env X11VNC_FONT_REG_SMALL='Helvetica -12'\n" +"\n" +" You can put the lines like the above (without the\n" +" quotes) in your ~/.x11vncrc file to avoid having to\n" +" specify them on the x11vnc command line.\n" +"\n" "-remote command Remotely control some aspects of an already running\n" " x11vnc server. \"-R\" and \"-r\" are aliases for\n" " \"-remote\". After the remote control command is\n" @@ -4373,12 +4512,26 @@ void print_help(int mode) { " 'x11vnc -R shared' will enable shared connections, and\n" " 'x11vnc -R scale:3/4' will rescale the desktop.\n" "\n" +" To run a bunch of commands in a sequence use something\n" +" like: x11vnc -R 'script:firstcmd;secondcmd;...'\n" +"\n" +" Use x11vnc -R script:file=/path/to/file to read commands\n" +" from a file (can be multi-line and use the comment '#'\n" +" character in the normal way. The ';' separator must\n" +" still be used to separate each command.)\n" +"\n" +" To not try to contact another x11vnc process and instead\n" +" just run the command (or query) directly, prefix the\n" +" command with the string \"DIRECT:\"\n" +"\n" " The following -remote/-R commands are supported:\n" "\n" " stop terminate the server, same as \"quit\"\n" " \"exit\" or \"shutdown\".\n" " ping see if the x11vnc server responds.\n" -" Return is: ans=ping:\n" +" return is: ans=ping:\n" +" ping:mystring as above, but use your own unique string.\n" +" return is: ans=ping:mystring:\n" " blacken try to push a black fb update to all\n" " clients (due to timings a client\n" " could miss it). Same as \"zero\", also\n" @@ -4473,6 +4626,7 @@ void print_help(int mode) { " nograbptr disable -grabptr mode.\n" " grabalways enable -grabalways mode.\n" " nograbalways disable -grabalways mode.\n" +" grablocal:n set -grablocal to n.\n" " client_input:str set the K, M, B -input on a per-client\n" " basis. select which client as for\n" " disconnect, e.g. client_input:host:MB\n" @@ -4558,6 +4712,9 @@ void print_help(int mode) { " nosetclipboard enable -nosetclipboard mode.\n" " setclipboard disable -nosetclipboard mode.\n" " seldir:str set -seldir to \"str\"\n" +" resend_cutbuffer resend the most recent CUTBUFFER0 copy\n" +" resend_clipboard resend the most recent CLIPBOARD copy\n" +" resend_primary resend the most recent PRIMARY copy\n" " cursor:mode enable -cursor \"mode\".\n" " show_cursor enable showing a cursor.\n" " noshow_cursor disable showing a cursor. (same as\n" @@ -4630,8 +4787,25 @@ void print_help(int mode) { " nodebug_pointer disable -debug_pointer, same as \"nodp\"\n" " debug_keyboard enable -debug_keyboard, same as \"dk\"\n" " nodebug_keyboard disable -debug_keyboard, same as \"nodk\"\n" +" keycode:n inject keystroke 'keycode' (xmodmap -pk)\n" +" keycode:n,down inject 'keycode' (down=0,1)\n" +" keysym:str inject keystroke 'keysym' (number/name)\n" +" keysym:str,down inject 'keysym' (down=0,1)\n" +" ptr:x,y,mask inject pointer event x, y, button-mask\n" +" sleep:t sleep floating point time t.\n" +" get_xprop:p get X property named 'p'.\n" +" set_xprop:p:val set X property named 'p' to 'val'.\n" +" p -> id=NNN:p for hex/dec window id.\n" +" wininfo:id get info about X window id. use 'root'\n" +" for root window, use +id for children.\n" +" grab_state get state of pointer and keyboard grab.\n" +" pointer_pos print XQueryPointer x,y cursor position.\n" +" mouse_x print x11vnc's idea of cursor position.\n" +" mouse_y print x11vnc's idea of cursor position.\n" +" noop do nothing.\n" " defer:n set -defer to n ms,same as deferupdate:n\n" " wait:n set -wait to n ms.\n" +" extra_fbur:n set -extra_fbur to n.\n" " wait_ui:f set -wait_ui factor to f.\n" " setdefer:n set -setdefer to -2,-1,0,1, or 2.\n" " wait_bog disable -nowait_bog mode.\n" @@ -4670,6 +4844,7 @@ void print_help(int mode) { " nosnapfb disable -snapfb mode.\n" " rawfb:str set -rawfb mode to \"str\".\n" " uinput_accel:f set uinput_accel to f.\n" +" uinput_thresh:n set uinput_thresh to n.\n" " uinput_reset:n set uinput_reset to n ms.\n" " uinput_always:n set uinput_always to 1/0.\n" " progressive:n set libvncserver -progressive slice\n" @@ -4687,7 +4862,9 @@ void print_help(int mode) { " macresize disable -macnoresize mode.\n" " maciconanim:n set -maciconanim to n.\n" " macmenu enable -macmenu mode.\n" -" macnomenu disable -macnmenu mode.\n" +" macnomenu disable -macmenu mode.\n" +" macuskbd enable -macuskbd mode.\n" +" macnouskbd disable -macuskbd mode.\n" /* access */ " httpport:n set -httpport to n.\n" " httpdir:dir set -httpdir to dir (and enable http).\n" @@ -4724,6 +4901,100 @@ void print_help(int mode) { " noremote disable the -remote command processing,\n" " it cannot be turned back on.\n" "\n" +" bcx_xattach:str This remote control command is for\n" +" use with the BARCO xattach program or the x2x program.\n" +" Both of these programs are for 'pointer and keyboard'\n" +" sharing between separate X displays. In general the\n" +" two displays are usually nearby, e.g. on the same desk,\n" +" and this allows the user to share a single pointer and\n" +" keyboard between them. The user moves the mouse to\n" +" an edge and then the mouse pointer appears to 'jump'\n" +" to the other display screen. Thus it emulates what a\n" +" single X server would do for two screens (e.g. :0.0 and\n" +" :0.1) The illusion of a single Xserver with multiple\n" +" screens is achieved by forwarding events to the 2nd\n" +" one via the XTEST extension.\n" +"\n" +" What the x11vnc bcx_xattach command does is to perform\n" +" some pointer movements to try to INDUCE xattach/x2x\n" +" to 'jump' to the other display. In what follows the\n" +" 'master' display refers to the one that when it has\n" +" 'focus' it is basically doing nothing besides watching\n" +" for the mouse to go over an edge. The 'slave'\n" +" display refers to the one to which the mouse and\n" +" keyboard is redirected to once an edge in the master\n" +" has been crossed. Note that the x11vnc executing the\n" +" bcx_xattach command MUST be the one connected to the\n" +" *master* display.\n" +"\n" +" Also note that when input is being redirected (via\n" +" XTEST) from the master display to the slave display,\n" +" the master display's pointer and keyboard are *grabbed*\n" +" by xattach/x2x. x11vnc can use this info to verify that\n" +" the master/slave mode change has taken place correctly.\n" +" If you specify the \"ifneeded\" option (see below)\n" +" and the initial grab state is that of the desired\n" +" final state, then no pointer movements are injected\n" +" and \"DONE,GRAB_OK\" is returned.\n" +"\n" +" \"str\" must contain one of \"up\", \"down\", \"left\",\n" +" or \"right\" to indicate the direction of the 'jump'.\n" +" \"str\" must also contain one of \"master_to_slave\"\n" +" or \"slave_to_master\" to indicate the type of mode\n" +" change induced by the jump. Use \"M2S\" and \"S2M\"\n" +" as shorter aliases.\n" +"\n" +" \"str\" may be a \"+\" separated list of additional\n" +" tuning options. The \"shift=n\" option indicates an\n" +" offset shift position away from (0,0) (default 20).\n" +" \"final=x+y\" specifies the final position of the cursor\n" +" at the end of the normal move sequence; default 30+30.\n" +" \"extra_move=x+y\" means to do one more pointer move\n" +" after \"final\" to x+y. \"dt=n\" sets the sleep time\n" +" in milliseconds between pointer moves (default: 40ms)\n" +" \"retry=n\" specifies the maximum number of retries if\n" +" the grab state change fails. \"ifneeded\" means to not\n" +" apply the pointer movements if the initial grab state is\n" +" that of the desired final state. \"nograbcheck\" means\n" +" to not check if the grab state changed as expected and\n" +" only apply the pointer movements (default is to check\n" +" the grab states.)\n" +"\n" +" If you do not specify \"up\", etc., to bcx_xattach\n" +" nothing will be attempted and the command returns\n" +" the string FAIL,NO_DIRECTION_SPECIFIED. If you do\n" +" not specify \"master_to_slave\" or \"M2S\", etc., to\n" +" bcx_xattach nothing will be attempted and the command\n" +" returns the string FAIL,NO_MODE_CHANGE_SPECIFIED.\n" +"\n" +" Otherwise, the returned string will contain \"DONE\".\n" +" It will be \"DONE,GRAB_OK\" if the grab state changed\n" +" as expected (or if \"ifneeded\" was supplied and\n" +" the initial grab state was already the desired\n" +" one.) If the initial grab state was incorrect,\n" +" but the final grab state was correct then it is\n" +" \"DONE,GRAB_FAIL_INIT\". If the initial grab state\n" +" was correct, but the final grab state was incorrect\n" +" then it is \"DONE,GRAB_FAIL_FINAL\". If both are\n" +" incorrect it will be \"DONE,GRAB_FAIL\". Under grab\n" +" failure the string will be followed by \":p1,k1-p2,k2\"\n" +" where p1,k1 indicates the initial pointer and keyboard\n" +" grab states and p2,k2 the final ones. If GRAB_FAIL or\n" +" GRAB_FAIL_FINAL occurs, the action will be retried up\n" +" to 3 times; trying to reset the state and sleeping a\n" +" bit between each try. Set retry=n to adjust the number\n" +" of retries, zero to disable retries.\n" +"\n" +" Examples:\n" +" -R bcx_xattach:down+M2S\n" +" -R bcx_xattach:up+S2M\n" +" -R bcx_xattach:up+S2M+nograbcheck+dt=30\n" +" -R bcx_xattach:down+M2S+extra_move=100+100\n" +"\n" +" or use -Q instead of -R to retrieve the result text.\n" +"\n" +" End of the bcx_xattach:str description.\n" +"\n" " The vncconnect(1) command from standard VNC\n" " distributions may also be used if string is prefixed\n" " with \"cmd=\" E.g. 'vncconnect cmd=stop'. Under some\n" @@ -4752,7 +5023,8 @@ void print_help(int mode) { " query straight to the X11VNC_REMOTE property or connect\n" " file use \"qry=...\" instead of \"cmd=...\"\n" "\n" -" ans= stop quit exit shutdown ping blacken zero\n" +" ans= stop quit exit shutdown ping resend_cutbuffer\n" +" resend_clipboard resend_primary blacken zero\n" " refresh reset close disconnect id sid waitmapped\n" " nowaitmapped clip flashcmap noflashcmap shiftcmap\n" " truecolor notruecolor overlay nooverlay overlay_cursor\n" @@ -4763,7 +5035,7 @@ void print_help(int mode) { " once timeout tightfilexfer notightfilexfer ultrafilexfer\n" " noultrafilexfer rfbversion deny lock nodeny unlock\n" " avahi mdns zeroconf noavahi nomdns nozeroconf connect\n" -" proxy allowonce allow localhost nolocalhost listen\n" +" proxy allowonce allow localhost nolocalhost listen\n" " lookup nolookup accept afteraccept gone shm noshm\n" " flipbyteorder noflipbyteorder onetile noonetile\n" " solid_color solid nosolid blackout xinerama noxinerama\n" @@ -4773,10 +5045,10 @@ void print_help(int mode) { " sloppy_keys nosloppy_keys skip_dups noskip_dups\n" " add_keysyms noadd_keysyms clear_mods noclear_mods\n" " clear_keys noclear_keys clear_all clear_locks keystate\n" -" remap repeat norepeat fb nofb bell nobell sel nosel\n" -" primary noprimary setprimary nosetprimary clipboard\n" -" noclipboard setclipboard nosetclipboard seldir\n" -" cursorshape nocursorshape cursorpos nocursorpos\n" +" remap repeat norepeat fb nofb bell nobell sendbell\n" +" sel nosel primary noprimary setprimary nosetprimary\n" +" clipboard noclipboard setclipboard nosetclipboard\n" +" seldir cursorshape nocursorshape cursorpos nocursorpos\n" " cursor_drag nocursor_drag cursor show_cursor\n" " noshow_cursor nocursor arrow xfixes noxfixes xdamage\n" " noxdamage xd_area xd_mem alphacut alphafrac alpharemove\n" @@ -4792,16 +5064,18 @@ void print_help(int mode) { " nowireframe nowf wireframelocal wfl nowireframelocal\n" " nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area\n" " scr_skip scr_inc scr_keys scr_term scr_keyrepeat\n" -" scr_parms scrollcopyrect scr noscrollcopyrect noscr\n" -" fixscreen noxrecord xrecord reset_record pointer_mode pm\n" -" input_skip allinput noallinput input grabkbd nograbkbd\n" -" grabptr nograbptr grabalways nograbalways grablocal\n" -" client_input ssltimeout speeds wmdt debug_pointer dp\n" -" nodebug_pointer nodp debug_keyboard dk nodebug_keyboard\n" -" nodk keycode deferupdate defer setdefer wait_ui\n" -" wait_bog nowait_bog slow_fb xrefresh wait readtimeout\n" -" nap nonap sb screen_blank fbpm nofbpm dpms nodpms\n" -" clientdpms noclientdpms forcedpms noforcedpms\n" +" scr_parms scrollcopyrect scr noscrollcopyrect\n" +" noscr fixscreen noxrecord xrecord reset_record\n" +" pointer_mode pm input_skip allinput noallinput input\n" +" grabkbd nograbkbd grabptr nograbptr grabalways\n" +" nograbalways grablocal client_input ssltimeout\n" +" speeds wmdt debug_pointer dp nodebug_pointer nodp\n" +" debug_keyboard dk nodebug_keyboard nodk keycode\n" +" keysym ptr sleep get_xprop set_xprop wininfo\n" +" bcx_xattach deferupdate defer setdefer extra_fbur\n" +" wait_ui wait_bog nowait_bog slow_fb xrefresh wait\n" +" readtimeout nap nonap sb screen_blank fbpm nofbpm dpms\n" +" nodpms clientdpms noclientdpms forcedpms noforcedpms\n" " noserverdpms serverdpms noultraext ultraext chatwindow\n" " nochatwindow chaton chatoff fs gaps grow fuzz snapfb\n" " nosnapfb rawfb uinput_accel uinput_thresh uinput_reset\n" @@ -4819,21 +5093,23 @@ void print_help(int mode) { " macnoresize macresize nomacnoresize maciconanim macmenu\n" " macnomenu nomacmenu macuskbd nomacuskbd noremote\n" "\n" -" aro= noop display vncdisplay desktopname guess_desktop\n" -" http_url auth xauth users rootshift clipshift scale_str\n" -" scaled_x scaled_y scale_numer scale_denom scale_fac_x\n" +" aro= noop display vncdisplay autoport loop loopbg\n" +" desktopname guess_desktop http_url auth xauth\n" +" users rootshift clipshift scale_str scaled_x\n" +" scaled_y scale_numer scale_denom scale_fac_x\n" " scale_fac_y scaling_blend scaling_nomult4 scaling_pad\n" " scaling_interpolate inetd privremote unsafe safer\n" " nocmds passwdfile unixpw unixpw_nis unixpw_list ssl\n" " ssl_pem sslverify stunnel stunnel_pem https httpsredir\n" -" usepw using_shm logfile o flag rc norc h help V version\n" -" lastmod bg sigpipe threads readrate netrate netlatency\n" -" pipeinput clients client_count pid ext_xtest ext_xtrap\n" -" ext_xrecord ext_xkb ext_xshm ext_xinerama ext_overlay\n" -" ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons\n" -" button_mask mouse_x mouse_y bpp depth indexed_color\n" -" dpy_x dpy_y wdpy_x wdpy_y off_x off_y cdpy_x cdpy_y\n" -" coff_x coff_y rfbauth passwd viewpasswd\n" +" usepw using_shm logfile o flag rmflag rc norc h help\n" +" V version lastmod bg sigpipe threads readrate netrate\n" +" netlatency pipeinput clients client_count pid ext_xtest\n" +" ext_xtrap ext_xrecord ext_xkb ext_xshm ext_xinerama\n" +" ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin\n" +" num_buttons button_mask mouse_x mouse_y grab_state\n" +" pointer_pos bpp depth indexed_color dpy_x dpy_y wdpy_x\n" +" wdpy_y off_x off_y cdpy_x cdpy_y coff_x coff_y rfbauth\n" +" passwd viewpasswd\n" "\n" "-QD variable Just like -query variable, but returns the default\n" " value for that parameter (no running x11vnc server\n" @@ -4853,10 +5129,43 @@ void print_help(int mode) { " the -query request is processed in the normal way.\n" " This allows for a reliable way to see if the -remote\n" " command was processed by querying for any new settings.\n" -" Note however that there is timeout of a few seconds so\n" -" if the x11vnc takes longer than that to process the\n" -" requests the requester will think that a failure has\n" -" taken place.\n" +" Note however that there is timeout of a few seconds\n" +" (see the next paragraph) so if the x11vnc takes longer\n" +" than that to process the requests the requester will\n" +" think that a failure has taken place.\n" +"\n" +" The default is to wait 3.5 seconds. Or if cmd=stop\n" +" only 1.0 seconds. If cmd matches 'script:' then it\n" +" will wait up to 10.0 seconds. Set X11VNC_SYNC_TIMEOUT\n" +" to the number of seconds you want it to wait.\n" +"\n" +"-query_retries str If a query fails to get a response from an x11vnc\n" +" server, retry up to n times. \"str\" is specified as\n" +" n[:t][/match] Optionally the delay between tries may\n" +" be specified by \"t\" a floating point time (default\n" +" 0.5 seconds.) Note: the response is not checked for\n" +" validity or whether it corresponds to the query sent.\n" +" The query \"ping:mystring\" may be used to help uniquely\n" +" identify the query. Optionally, a matching string after\n" +" a \"/\" will be used to check the result text. Up to\n" +" n retries will take place until the matching string is\n" +" found in the output text. If the match string is never\n" +" found the program's exit code is 1; if the match is\n" +" found it exits with 0. Note that there may be stdout\n" +" printed for each retry (i.e. multiple lines printed\n" +" out to stdout.)\n" +" Example: -query_retries 4:1.5/grab_state\n" +"\n" +"-remote_prefix str Enable a remote-control communication channel for\n" +" connected VNC clients. str is a non-empty string. If a\n" +" VNC client sends rfbCutText having the prefix \"str\"\n" +" then the part after it is processed as though it were\n" +" sent via 'x11vnc -remote ...'. If it begins with\n" +" neither 'cmd=' nor 'qry=' then 'qry=' is assumed.\n" +" Any corresponding output text for that remote control\n" +" command is sent back to all client as rfbCutText.\n" +" The returned output is also prefixed with \"str\".\n" +" Example: -remote_prefix DO_THIS:\n" "\n" "-noremote Do not process any remote control commands or queries.\n" "-yesremote Do process remote control commands or queries.\n" @@ -4936,6 +5245,7 @@ void print_help(int mode) { int w = 23; char tmp[100]; if (p[0] == '-') { + memset(tmp, 0, sizeof(tmp)); strncpy(tmp, p, w); fprintf(stderr, " %s", tmp); l++; @@ -4981,8 +5291,8 @@ void print_help(int mode) { waitms, wait_ui, take_naps ? "take naps":"no naps", - rfbMaxClientWait/1000, screen_blank, + rfbMaxClientWait/1000, watch_fbpm ? "-nofbpm":"-fbpm", watch_dpms ? "-nodpms":"-dpms", xdamage_max_area, NSCAN, xdamage_memory, diff --git a/x11vnc/keyboard.c b/x11vnc/keyboard.c index c6dec3c..9aee9ca 100644 --- a/x11vnc/keyboard.c +++ b/x11vnc/keyboard.c @@ -2045,7 +2045,7 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, * why nothing needs to be done with the modifier, see below. * * sentmods[] is the corresponding keycode to use - * to acheive the needmods[] requirement for the bit. + * to achieve the needmods[] requirement for the bit. */ for (i=0; i<8; i++) { @@ -2780,6 +2780,11 @@ void get_allowed_input(rfbClientPtr client, allowed_input_t *input) { input->files = 0; if (! client) { + input->keystroke = 1; + input->motion = 1; + input->button = 1; + input->clipboard = 1; + input->files = 1; return; } diff --git a/x11vnc/options.c b/x11vnc/options.c index e25e530..2003225 100644 --- a/x11vnc/options.c +++ b/x11vnc/options.c @@ -55,6 +55,8 @@ int unixpw = 0; /* -unixpw */ int unixpw_nis = 0; /* -unixpw_nis */ char *unixpw_list = NULL; char *unixpw_cmd = NULL; +int unixpw_system_greeter = 0; +int unixpw_system_greeter_active = 0; int use_stunnel = 0; /* -stunnel */ int stunnel_port = 0; char *stunnel_pem = NULL; @@ -70,6 +72,8 @@ int vencrypt_enable_plain_login = 0; int anontls_mode = ANONTLS_SUPPORT; int create_fresh_dhparams = 0; char *dhparams_file = NULL; +int http_try_it = 0; +int stunnel_http_port = 0; int https_port_num = -1; int https_port_redir = 0; char *ssl_verify = NULL; @@ -112,6 +116,8 @@ int deny_all = 0; /* global locking of new clients */ #define REMOTE_DEFAULT 1 #endif int accept_remote_cmds = REMOTE_DEFAULT; /* -noremote */ +char *remote_prefix = NULL; +int remote_direct = 0; int query_default = 0; int safe_remote_only = 1; /* -unsafe */ int priv_remote = 0; /* -privremote */ @@ -402,6 +408,7 @@ double wait_ui = 2.0; double slow_fb = 0.0; double xrefresh = 0.0; int wait_bog = 1; +int extra_fbur = 1; int defer_update = 20; /* deferUpdateTime ms to wait before sends. */ int set_defer = 1; int got_defer = 0; diff --git a/x11vnc/options.h b/x11vnc/options.h index bdd5945..e6dea7a 100644 --- a/x11vnc/options.h +++ b/x11vnc/options.h @@ -55,6 +55,8 @@ extern int unixpw; extern int unixpw_nis; extern char *unixpw_list; extern char *unixpw_cmd; +extern int unixpw_system_greeter; +extern int unixpw_system_greeter_active; extern int use_stunnel; extern int stunnel_port; extern char *stunnel_pem; @@ -70,6 +72,8 @@ extern int vencrypt_enable_plain_login; extern int anontls_mode; extern int create_fresh_dhparams; extern char *dhparams_file; +extern int http_try_it; +extern int stunnel_http_port; extern int https_port_num; extern int https_port_redir; extern char *ssl_verify; @@ -100,6 +104,8 @@ extern int connect_once; extern int got_connect_once; extern int deny_all; extern int accept_remote_cmds; +extern char *remote_prefix; +extern int remote_direct; extern int query_default; extern int safe_remote_only; extern int priv_remote; @@ -307,6 +313,7 @@ extern double wait_ui; extern double slow_fb; extern double xrefresh; extern int wait_bog; +extern int extra_fbur; extern int defer_update; extern int set_defer; extern int got_defer; diff --git a/x11vnc/params.h b/x11vnc/params.h index 78772f1..9495c11 100644 --- a/x11vnc/params.h +++ b/x11vnc/params.h @@ -63,8 +63,8 @@ so, delete this exception statement from your version. #define FB_REQ 0x4 #define VNC_CONNECT_MAX 16384 -#define X11VNC_REMOTE_MAX 16384 -#define PROP_MAX (131072L) +#define X11VNC_REMOTE_MAX 65536 +#define PROP_MAX (262144L) #define MAXN 256 diff --git a/x11vnc/remote.c b/x11vnc/remote.c index d5ae366..3c6b42d 100644 --- a/x11vnc/remote.c +++ b/x11vnc/remote.c @@ -76,6 +76,7 @@ static void if_8bpp_do_new_fb(void); static void reset_httpport(int old, int new); static void reset_rfbport(int old, int new) ; +char *query_result = NULL; /* * for the wild-n-crazy -remote/-R interface. @@ -83,6 +84,11 @@ static void reset_rfbport(int old, int new) ; int send_remote_cmd(char *cmd, int query, int wait) { FILE *in = NULL; + if (query_result != NULL) { + free(query_result); + query_result = NULL; + } + if (client_connect_file) { umask(077); in = fopen(client_connect_file, "w"); @@ -118,13 +124,26 @@ int send_remote_cmd(char *cmd, int query, int wait) { if (query || wait) { char line[X11VNC_REMOTE_MAX]; - int rc=1, i=0, max=70, ms_sl=50; + int rc=1, i=0, max=140, ms_sl=25; if (!strcmp(cmd, "cmd=stop")) { - max = 20; + max = 40; + } + if (strstr(cmd, "script:")) { + max = 400; + } + if (strstr(cmd, "bcx_xattach:")) { + max = 400; + } + if (getenv("X11VNC_SYNC_TIMEOUT")) { + max = (int) ((1000. * atof(getenv("X11VNC_SYNC_TIMEOUT")))/ms_sl); } for (i=0; ihttpDir = http_dir; rfbHttpInitSockets(screen); + if (screen->httpPort != 0 && screen->httpListenSock < 0) { + rfbLog("http_connections: failed to listen on http port: %d\n", screen->httpPort); + clean_up_exit(1); + } } } else { rfbLog("http_connections: turning off http service.\n"); @@ -474,6 +525,9 @@ static void reset_httpport(int old, int new) { rfbLog("reset_httpport: setting httpport %d -> %d.\n", old == -1 ? hp : old, hp); rfbHttpInitSockets(screen); + if (screen->httpPort != 0 && screen->httpListenSock < 0) { + rfbLog("reset_httpport: failed to listen on http port: %d\n", screen->httpPort); + } } } @@ -699,16 +753,95 @@ char *process_remote_cmd(char *cmd, int stringonly) { } } + strcpy(buf, ""); if (strstr(cmd, "cmd=") == cmd) { p += strlen("cmd="); + if (strstr(p, "script:") == p) { + char *s, *q, **pieces, tmp[1024]; + int k = 0, n = 0, dp = 1; + + p += strlen("script:"); + + if (strstr(p, "file=") == p) { + FILE *f; + struct stat sbuf; + + p += strlen("file="); + + rfbLog("reading script from file '%s'\n", p); + + if (stat(p, &sbuf) != 0) { + rfbLogPerror("stat"); + return NULL; + } + + f = fopen(p, "r"); + if (f == NULL) { + rfbLogPerror("fopen"); + return NULL; + } + + p = (char *) calloc(sbuf.st_size + 1, 1); + dp = 0; + while (fgets(tmp, 1024, f) != NULL) { + char *c = strchr(tmp, '#'); + if (c) *c = '\0'; + if (strlen(p) + strlen(tmp) > sbuf.st_size) { + break; + } + strcat(p, tmp); + } + fclose(f); + } + + pieces = (char **) malloc(strlen(p) * sizeof(char *)); + if (dp) { + s = strdup(p); + } else { + s = p; + } + q = strtok(s, ";"); + + while (q) { + char *t = lblanks(q); + if (strstr(t, "cmd=") != t && strstr(t, "qry=") != t) { + strcpy(tmp, "cmd="); + } else { + strcpy(tmp, ""); + } + strncat(tmp, t, 1000); + pieces[n] = strdup(tmp); + n++; + q = strtok(NULL, ";"); + } + free(s); + + for (k=0; k < n; k++) { + char *c = pieces[k]; + char *t = c + strlen(c) - 1; /* shortest is "cmd=" */ + while (isspace((unsigned char) (*t))) { + *t = '\0'; + if (t <= c) break; + t--; + } + if (k < n - 1) { + process_remote_cmd(c, 1); + } else { + process_remote_cmd(c, 0); + } + } + for (k=0; k= X11VNC_REMOTE_MAX - 1) { @@ -797,6 +930,11 @@ char *process_remote_cmd(char *cmd, int stringonly) { /* * Maybe add: passwdfile logfile bg rfbauth passwd... */ + if (!strcmp(p, "")) { /* skip-cmd-list */ + NOTAPP + rfbLog("remote_cmd: empty command.\n"); + goto done; + } if (strstr(p, "CR:") == p) { /* skip-cmd-list */ /* CR:WxH+X+Y,dx,dy */ int w, h, x, y, dx, dy; @@ -829,7 +967,8 @@ char *process_remote_cmd(char *cmd, int stringonly) { close_all_clients(); goto done; } - if (!strcmp(p, "ping")) { + if (!strcmp(p, "ping") + || strstr(p, "ping:") == p) { /* skip-cmd-list */ query = 1; if (rfb_desktop_name) { snprintf(buf, bufn, "ans=%s:%s", p, rfb_desktop_name); @@ -839,6 +978,21 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto qry; goto done; } + if (!strcmp(p, "resend_cutbuffer")) { + NOTAPP + resend_selection("cutbuffer"); + goto done; + } + if (!strcmp(p, "resend_clipboard")) { + NOTAPP + resend_selection("clipboard"); + goto done; + } + if (!strcmp(p, "resend_primary")) { + NOTAPP + resend_selection("primary"); + goto done; + } if (!strcmp(p, "blacken") || !strcmp(p, "zero")) { NOTAPP push_black_screen(4); @@ -911,7 +1065,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto qry; } p += strlen("id:"); - if (*p == '\0' || !strcmp("root", p)) { + if (*p == '\0' || !strcmp("root", p)) { /* skip-cmd-list */ /* back to root win */ twin = 0x0; ok = 1; @@ -953,7 +1107,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto qry; } p += strlen("sid:"); - if (*p == '\0' || !strcmp("root", p)) { + if (*p == '\0' || !strcmp("root", p)) { /* skip-cmd-list */ /* back to root win */ twin = 0x0; ok = 1; @@ -1513,7 +1667,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { free(connect_proxy); connect_proxy = NULL; } - if (!strcmp(p, "") || !strcasecmp(p, "none")) { + if (!strcmp(p, "") || !strcasecmp(p, "none")) { /* skip-cmd-list */ rfbLog("remote_cmd: disabled -proxy\n"); } else { connect_proxy = strdup(p); @@ -3749,7 +3903,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto qry; } p += strlen("input:"); - if (allowed_input_str && !strcmp(p, allowed_input_str)) { + if (allowed_input_str && !strcmp(p, allowed_input_str)) { /* skip-cmd-list */ doit = 0; } rfbLog("remote_cmd: setting input %s\n", p); @@ -3957,28 +4111,260 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto done; } if (strstr(p, "keycode") == p) { - int kc; + int kc, down = -1; + char *c; NOTAPP COLON_CHECK("keycode:") p += strlen("keycode:"); kc = atoi(p); if (kc < 0) kc = 0; kc = kc % 256; - rfbLog("remote_cmd: insert keycode %d\n", kc); + c = strchr(p, ','); + if (c) down = atoi(c+1); + rfbLog("remote_cmd: insert keycode %d down=%d\n", kc, down); if (macosx_console) { #ifdef MACOSX - macosxCG_keycode_inject(1, kc); - usleep(100*1000); - macosxCG_keycode_inject(0, kc); + if (down == -1) { + macosxCG_keycode_inject(1, kc); + usleep(50*1000); + macosxCG_keycode_inject(0, kc); + } else { + macosxCG_keycode_inject(down, kc); + } #endif } else { - XTestFakeKeyEvent_wr(dpy, kc, 1, CurrentTime); - usleep(100*1000); - XTestFakeKeyEvent_wr(dpy, kc, 0, CurrentTime); + if (down == -1) { + XTestFakeKeyEvent_wr(dpy, kc, 1, CurrentTime); + usleep(50*1000); + XTestFakeKeyEvent_wr(dpy, kc, 0, CurrentTime); + } else { + XTestFakeKeyEvent_wr(dpy, kc, down, CurrentTime); + } } goto done; } + if (strstr(p, "keysym") == p) { + int down = -1; + unsigned int in; + KeySym ks; + char *c, *str; + NOTAPP + COLON_CHECK("keysym:") + p += strlen("keysym:"); + + c = strchr(p, ','); + if (c) { + down = atoi(c+1); + *c = '\0'; + } + + if (sscanf(p, "0x%x", &in) == 1) { + ks = (KeySym) in; + } else if (sscanf(p, "%u", &in) == 1) { + ks = (KeySym) in; + } else if ((ks = XStringToKeysym(p)) != NoSymbol) { + ; + } else { + rfbLog("remote_cmd: bad keysym: %s\n", p); + goto done; + } + str = XKeysymToString(ks); + str = str ? str : "NoSymbol"; + rfbLog("remote_cmd: insert keysym %s 0x%x '%s' down=%d\n", p, ks, str, down); + if (down == -1) { + keyboard(1, ks, NULL); + usleep(50*1000); + keyboard(0, ks, NULL); + } else { + keyboard(down, ks, NULL); + } + goto done; + } + if (strstr(p, "ptr") == p) { + int x, y, m = 0; + NOTAPP + COLON_CHECK("ptr:") + p += strlen("ptr:"); + rfbLog("remote_cmd: insert pointer event: %s\n", p); + if (sscanf(p, "%d,%d,%d", &x, &y, &m) == 3) { + pointer(m, x, y, NULL); + } else if (sscanf(p, "%d,%d", &x, &y) == 2) { + pointer(m, x, y, NULL); + } else { + rfbLog("remote_cmd: bad ptr:x,y,mask\n"); + } + + goto done; + } + if (strstr(p, "sleep") == p) { + NOTAPP + COLON_CHECK("sleep:") + p += strlen("sleep:"); + rfbLog("remote_cmd: sleeping: %s\n", p); + usleep((int) (1.0e+6 * atof(p))); + rfbLog("remote_cmd: done sleeping.\n"); + goto done; + } + if (strstr(p, "get_xprop") == p) { + char *res; + unsigned long id; + Window win = None; /* None implies root in get_xprop() */ + + /* note we force query and assume the colon is there. */ + query = 1; + if (strstr(p, "get_xprop:") != p) { /* skip-cmd-list */ + snprintf(buf, bufn, "ans=%s:N/A", p); + goto qry; + } + p += strlen("get_xprop:"); + + if (strstr(p, "id=") == p) { /* skip-cmd-list */ + p += strlen("id="); + if (scan_hexdec(p, &id)) { + win = (Window) id; + } + if (strchr(p, ':')) { + p = strchr(p, ':') + 1; + } + } + + res = get_xprop(p, win); + if (res == NULL) { + res = strdup("NULL"); + } + snprintf(buf, bufn, "ans=get_xprop:%s:%s", p, res); + free(res); + + goto qry; + } + if (strstr(p, "set_xprop") == p) { + char *q; + int rc = -2; + unsigned long id; + Window win = None; /* None implies root in set_xprop() */ + + /* note we force query and assume the colon is there. */ + query = 1; + if (strstr(p, "set_xprop:") != p) { /* skip-cmd-list */ + snprintf(buf, bufn, "ans=%s:N/A", p); + goto qry; + } + p += strlen("set_xprop:"); + + if (strstr(p, "id=") == p) { /* skip-cmd-list */ + p += strlen("id="); + if (scan_hexdec(p, &id)) { + win = (Window) id; + } + if (strchr(p, ':')) { + p = strchr(p, ':') + 1; + } + } + + q = strchr(p, ':'); + if (q) { + *q = '\0'; + rc = set_xprop(p, win, q+1); + *q = ':'; + } + snprintf(buf, bufn, "ans=set_xprop:%s:%d", p, rc); + + goto qry; + } + if (strstr(p, "wininfo") == p) { + char *res, *t = ""; + unsigned long id; + Window win = None; + int show_children = 0; + + /* note we force query and assume the colon is there. */ + query = 1; + if (strstr(p, "wininfo:") != p) { /* skip-cmd-list */ + snprintf(buf, bufn, "ans=%s:N/A", p); + goto qry; + } + p += strlen("wininfo:"); + + if (p[0] == '+') { + show_children = 1; + t = "+"; + p++; + } + if (!strcmp(p, "root")) { /* skip-cmd-list */ + win = rootwin; + } else if (scan_hexdec(p, &id)) { + win = (Window) id; + } + + res = wininfo(win, show_children); + if (res == NULL) { + res = strdup("NULL"); + } + snprintf(buf, bufn, "ans=wininfo:%s%s:%s", t, p, res); + free(res); + + goto qry; + } + if (strstr(p, "bcx_xattach") == p) { + char *res; + int pg_init = -1, kg_init = -1; + int try = 0, max_tries = 4; + + /* note we force query and assume the colon is there. */ + query = 1; + if (strstr(p, "bcx_xattach:") != p) { /* skip-cmd-list */ + snprintf(buf, bufn, "ans=%s:N/A", p); + goto qry; + } + p += strlen("bcx_xattach:"); + + if (strstr(p, "retry=")) { /* skip-cmd-list */ + int n; + char *q = strstr(p, "retry="); /* skip-cmd-list */ + if (sscanf(q, "retry=%d", &n) == 1) { + if (n < 0) n = 0; + max_tries = 1 + n; + } + } + + try_again: + + res = bcx_xattach(p, &pg_init, &kg_init); + try++; + if (res == NULL) { + res = strdup("NULL"); + } else if (strstr(res, "GRAB_FAIL_INIT")) { + rfbLog("bcx_xattach: failed grab check for '%s': %s. Final state OK, not Retrying.\n", p, res); + } else if (strstr(res, "GRAB_FAIL") && try < max_tries) { + rfbLog("bcx_xattach: failed grab check for '%s': %s. Retrying[%d]...\n", p, res, try); + free(res); + pointer(0, dpy_x/2 + try, dpy_y/2 + try, NULL); + XFlush_wr(dpy); +#if !NO_X11 + if (dpy) { + if (try == 2) { + XSync(dpy, False); + } else if (try == 3) { + XSync(dpy, True); + } + } +#endif + if (try == 1) { + usleep(250*1000); + } else if (try <= 4) { + usleep(try*400*1000); + } else { + usleep(4*500*1000); + } + goto try_again; + } + + snprintf(buf, bufn, "ans=bcx_xattach:%s:%s", p, res); + free(res); + + goto qry; + } if (strstr(p, "deferupdate") == p) { int d; COLON_CHECK("deferupdate:") @@ -4032,6 +4418,17 @@ char *process_remote_cmd(char *cmd, int stringonly) { rfbLog("remote_cmd: setting set_defer to %d\n", set_defer); goto done; } + if (strstr(p, "extra_fbur") == p) { + COLON_CHECK("extra_fbur:") + if (query) { + snprintf(buf, bufn, "ans=%s%s%d", p, co, extra_fbur); + goto qry; + } + p += strlen("extra_fbur:"); + extra_fbur = atoi(p); + rfbLog("remote_cmd: setting extra_fbur to %d\n", extra_fbur); + goto done; + } if (strstr(p, "wait_ui") == p) { double w; COLON_CHECK("wait_ui:") @@ -5169,6 +5566,11 @@ char *process_remote_cmd(char *cmd, int stringonly) { NONUL(guess_desktop())); goto qry; } + if (!strcmp(p, "guess_dbus")) { + snprintf(buf, bufn, "aro=%s:%s", p, + NONUL(dbus_session())); + goto qry; + } if (!strcmp(p, "http_url")) { if (!screen) { snprintf(buf, bufn, "aro=%s:", p); @@ -5448,6 +5850,38 @@ char *process_remote_cmd(char *cmd, int stringonly) { snprintf(buf, bufn, "aro=%s:%d", p, cursor_y); goto qry; } + if (!strcmp(p, "grab_state")) { + int ptr_grabbed, kbd_grabbed; + + grab_state(&ptr_grabbed, &kbd_grabbed); + snprintf(buf, bufn, "aro=%s:%d,%d", p, ptr_grabbed, kbd_grabbed); + rfbLog("remote_cmd: ptr,kbd: %s\n", buf); + goto qry; + } + + if (!strcmp(p, "pointer_pos")) { + int px = -1, py = -1; + int wx, wy; + unsigned int m; + Window r, c; + + + snprintf(buf, bufn, "aro=%s:%d,%d", p, px, py); + if (!dpy) { + goto qry; + } +#if NO_X11 + goto qry; +#else + X_LOCK; + XQueryPointer_wr(dpy, rootwin, &r, &c, &px, &py, &wx, &wy, &m); + X_UNLOCK; +#endif + + snprintf(buf, bufn, "aro=%s:%d,%d", p, px, py); + rfbLog("remote_cmd: pointer_pos: %s\n", buf); + goto qry; + } if (!strcmp(p, "bpp")) { snprintf(buf, bufn, "aro=%s:%d", p, bpp); goto qry; diff --git a/x11vnc/remote.h b/x11vnc/remote.h index ee064d3..14e7261 100644 --- a/x11vnc/remote.h +++ b/x11vnc/remote.h @@ -44,4 +44,7 @@ extern void http_connections(int on); extern int remote_control_access_ok(void); extern char *process_remote_cmd(char *cmd, int stringonly); +extern char *query_result; + + #endif /* _X11VNC_REMOTE_H */ diff --git a/x11vnc/screen.c b/x11vnc/screen.c index 71f4462..6a9a5fe 100644 --- a/x11vnc/screen.c +++ b/x11vnc/screen.c @@ -1179,6 +1179,8 @@ static char* vnc_reflect_get_password(rfbClient* client) { char *q, *p, *str = getenv("X11VNC_REFLECT_PASSWORD"); int len = 110; + if (client) {} + if (str) { len += 2*strlen(str); } @@ -2846,11 +2848,17 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { /* n.b. samplesPerPixel (set = 1 here) seems to be unused. */ if (create_screen) { - if (use_openssl) { - openssl_init(0); - } else if (use_stunnel) { + if (use_stunnel) { setup_stunnel(0, argc, argv); } + if (use_openssl) { + if (use_stunnel && enc_str && !strcmp(enc_str, "none")) { + /* emulating HTTPS oneport */ + ; + } else { + openssl_init(0); + } + } screen = rfbGetScreen(argc, argv, width, height, bits_per_color, 1, fb_bpp/8); if (screen && http_dir) { @@ -3367,6 +3375,10 @@ void announce(int lport, int ssl, char *iface) { char *host = this_host(); char *tvdt; + if (remote_direct) { + return; + } + if (! ssl) { tvdt = "The VNC desktop is: "; } else { @@ -3422,12 +3434,12 @@ void announce(int lport, int ssl, char *iface) { } } -static void announce_http(int lport, int ssl, char *iface) { +static void announce_http(int lport, int ssl, char *iface, char *extra) { char *host = this_host(); char *jvu; - if (enc_str && !strcmp(enc_str, "none")) { + if (enc_str && !strcmp(enc_str, "none") && !use_stunnel) { jvu = "Java viewer URL: http"; } else if (ssl == 1) { jvu = "Java SSL viewer URL: https"; @@ -3442,44 +3454,91 @@ static void announce_http(int lport, int ssl, char *iface) { } if (host != NULL) { if (! inetd) { - fprintf(stderr, "%s://%s:%d/\n", jvu, host, lport); - if (screen && enc_str && !strcmp(enc_str, "none")) { - fprintf(stderr, "%s://%s:%d/\n", jvu, host, screen->port); + fprintf(stderr, "%s://%s:%d/%s\n", jvu, host, lport, extra); + } + } +} + +void do_announce_http(void) { + if (!screen) { + return; + } + if (remote_direct) { + return; + } + + if (screen->httpListenSock > -1 && screen->httpPort) { + int enc_none = (enc_str && !strcmp(enc_str, "none")); + char *SPORT = " (single port)"; + if (use_openssl && ! enc_none) { + announce_http(screen->port, 1, listen_str, SPORT); + if (https_port_num >= 0) { + announce_http(https_port_num, 1, + listen_str, ""); + } + announce_http(screen->httpPort, 2, listen_str, ""); + } else if (use_stunnel) { + char pmsg[100]; + pmsg[0] = '\0'; + if (stunnel_port) { + sprintf(pmsg, "?PORT=%d", stunnel_port); + } + announce_http(screen->httpPort, 2, listen_str, pmsg); + if (stunnel_http_port > 0) { + announce_http(stunnel_http_port, 1, NULL, pmsg); + } + if (enc_none) { + strcat(pmsg, SPORT); + announce_http(stunnel_port, 1, NULL, pmsg); + } + } else { + announce_http(screen->httpPort, 0, listen_str, ""); + if (enc_none) { + announce_http(screen->port, 1, NULL, SPORT); } } } } +void do_mention_java_urls(void) { + if (! quiet && screen) { + if (screen->httpListenSock > -1 && screen->httpPort) { + rfbLog("\n"); + rfbLog("The URLs printed out below ('Java ... viewer URL') can\n"); + rfbLog("be used for Java enabled Web browser connections.\n"); + if (!stunnel_port && enc_str && !strcmp(enc_str, "none")) { + ; + } else if (use_openssl || stunnel_port) { + rfbLog("Here are some additional possibilities:\n"); + rfbLog("\n"); + rfbLog("https://host:port/proxy.vnc (MUST be used if Web Proxy used)\n"); + rfbLog("\n"); + rfbLog("https://host:port/ultra.vnc (Use UltraVNC Java Viewer)\n"); + rfbLog("https://host:port/ultraproxy.vnc (Web Proxy with UltraVNC)\n"); + rfbLog("https://host:port/ultrasigned.vnc (Signed UltraVNC Filexfer)\n"); + rfbLog("\n"); + rfbLog("Where you replace \"host:port\" with that printed below, or\n"); + rfbLog("whatever is needed to reach the host e.g. Internet IP number\n"); + rfbLog("\n"); + rfbLog("Append ?GET=1 to a URL for faster loading.\n"); + } + } + rfbLog("\n"); + } +} + void set_vnc_desktop_name(void) { sprintf(vnc_desktop_name, "unknown"); if (inetd) { sprintf(vnc_desktop_name, "%s/inetd-no-further-clients", this_host()); } + if (remote_direct) { + return; + } if (screen->port) { - if (! quiet) { - if (screen->httpListenSock > -1 && screen->httpPort) { - rfbLog("\n"); - rfbLog("The URLs printed out below ('Java ... viewer URL') can\n"); - rfbLog("be used for Java enabled Web browser connections.\n"); - if (enc_str && !strcmp(enc_str, "none")) { - ; - } else if (use_openssl || stunnel_port) { - rfbLog("Here are some additional possibilities:\n"); - rfbLog("\n"); - rfbLog("https://host:port/proxy.vnc (MUST be used if Web Proxy used)\n"); - rfbLog("\n"); - rfbLog("https://host:port/ultra.vnc (Use UltraVNC Java Viewer)\n"); - rfbLog("https://host:port/ultraproxy.vnc (Web Proxy with UltraVNC)\n"); - rfbLog("https://host:port/ultrasigned.vnc (Signed UltraVNC Filexfer)\n"); - rfbLog("\n"); - rfbLog("Where you replace \"host:port\" with that printed below, or\n"); - rfbLog("whatever is needed to reach the host e.g. Internet IP number\n"); - } - } - rfbLog("\n"); - } + do_mention_java_urls(); if (use_openssl) { announce(screen->port, 1, listen_str); @@ -3489,24 +3548,8 @@ void set_vnc_desktop_name(void) { if (stunnel_port) { announce(stunnel_port, 1, NULL); } - if (screen->httpListenSock > -1 && screen->httpPort) { - if (use_openssl) { - if (enc_str && !strcmp(enc_str, "none")) { - ; - } else { - announce_http(screen->port, 1, listen_str); - } - if (https_port_num >= 0) { - announce_http(https_port_num, 1, - listen_str); - } - announce_http(screen->httpPort, 2, listen_str); - } else if (use_stunnel) { - announce_http(screen->httpPort, 2, listen_str); - } else { - announce_http(screen->httpPort, 0, listen_str); - } - } + + do_announce_http(); fflush(stderr); if (inetd) { @@ -3954,13 +3997,19 @@ void watch_loop(void) { * see quickly (just 1 rfbPE will likely * only process the subsequent "up" event) */ - if (tm < last_keyboard_time + 0.16) { + if (tm < last_keyboard_time + 0.20) { rfbPE(0); rfbPE(0); rfbPE(-1); rfbPE(0); rfbPE(0); } else { + if (extra_fbur > 0) { + int i; + for (i=0; i < extra_fbur; i++) { + rfbPE(0); + } + } rfbPE(-1); } if (x11vnc_current < last_new_client + 0.5) { @@ -4126,6 +4175,7 @@ void watch_loop(void) { } else { static double last_dt = 0.0; double xdamage_thrash = 0.4; + static int tilecut = -1; check_cursor_changes(); @@ -4176,8 +4226,15 @@ void watch_loop(void) { last_dt = dt; } + if (tilecut < 0) { + if (getenv("TILECUT")) { + tilecut = atoi(getenv("TILECUT")); + } + if (tilecut < 0) tilecut = 4; + } + if ((debug_tiles || debug_scroll > 1 || debug_wireframe > 1) - && (tile_diffs > 4 || debug_tiles > 1)) { + && (tile_diffs > tilecut || debug_tiles > 1)) { double rate = (tile_x * tile_y * bpp/8 * tile_diffs) / dt; fprintf(stderr, "============================= TILES: %d dt: %.4f" " t: %.4f %.2f MB/s nap_ok: %d\n", tile_diffs, dt, @@ -4188,13 +4245,33 @@ void watch_loop(void) { /* sleep a bit to lessen load */ wait = choose_delay(dt); + if (urgent_update) { ; } else if (wait > 2*waitms) { /* bog case, break it up */ nap_sleep(wait, 10); } else { + double t1, t2; + int idt; + if (extra_fbur > 0) { + int i; + for (i=0; i <= extra_fbur; i++) { + int r = rfbPE(0); + if (!r) break; + } + } + + /* sometimes the sleep is too short, so measure it: */ + t1 = dnow(); usleep(wait * 1000); + t2 = dnow(); + + idt = (int) (1000. * (t2 - t1)); + if (idt > 0 && idt < wait) { + /* try to sleep the remainder */ + usleep((wait - idt) * 1000); + } } cnt++; diff --git a/x11vnc/selection.c b/x11vnc/selection.c index c751a91..0df29eb 100644 --- a/x11vnc/selection.c +++ b/x11vnc/selection.c @@ -64,6 +64,7 @@ void selection_request(XEvent *ev, char *type); int check_sel_direction(char *dir, char *label, char *sel, int len); void cutbuffer_send(void); void selection_send(XEvent *ev); +void resend_selection(char *type); /* @@ -76,6 +77,9 @@ void selection_send(XEvent *ev); static char cutbuffer_str[PROP_MAX+1]; static char primary_str[PROP_MAX+1]; static char clipboard_str[PROP_MAX+1]; +static int cutbuffer_len = 0; +static int primary_len = 0; +static int clipboard_len = 0; /* * An X11 (not VNC) client on the local display has requested the selection @@ -346,7 +350,7 @@ void cutbuffer_send(void) { if (!screen) { return; } - len = strlen(cutbuffer_str); + cutbuffer_len = len = strlen(cutbuffer_str); if (check_sel_direction("send", "cutbuffer_send", cutbuffer_str, len)) { rfbSendServerCutText(screen, cutbuffer_str, len); } @@ -492,6 +496,49 @@ if (debug_sel) fprintf(stderr, "selection_send: data: '%s' dlen: %d nitems: %lu } len = newlen; + if (ev->xselection.selection == XA_PRIMARY) { + primary_len = len; + } else if (clipboard_atom && ev->xselection.selection == clipboard_atom) { + clipboard_len = len; + } + if (check_sel_direction("send", "selection_send", selection_str, len)) { + rfbSendServerCutText(screen, selection_str, len); + } +#endif /* NO_X11 */ +} + +void resend_selection(char *type) { +#if NO_X11 + RAWFB_RET_VOID + if (!type) {} + return; +#else + char *selection_str = ""; + int len = 0; + + RAWFB_RET_VOID + + if (! all_clients_initialized()) { + rfbLog("selection_send: no send: uninitialized clients\n"); + return; /* some clients initializing, cannot send */ + } + if (unixpw_in_progress) { + return; + } + if (!screen) { + return; + } + + if (!strcmp(type, "cutbuffer")) { + selection_str = cutbuffer_str; + len = cutbuffer_len; + } else if (!strcmp(type, "clipboard")) { + selection_str = clipboard_str; + len = clipboard_len; + } else if (!strcmp(type, "primary")) { + selection_str = primary_str; + len = primary_len; + } if (check_sel_direction("send", "selection_send", selection_str, len)) { rfbSendServerCutText(screen, selection_str, len); } diff --git a/x11vnc/selection.h b/x11vnc/selection.h index d467bd0..9e0a182 100644 --- a/x11vnc/selection.h +++ b/x11vnc/selection.h @@ -50,5 +50,6 @@ extern void selection_request(XEvent *ev, char *type); extern int check_sel_direction(char *dir, char *label, char *sel, int len); extern void cutbuffer_send(void); extern void selection_send(XEvent *ev); +extern void resend_selection(char *type); #endif /* _X11VNC_SELECTION_H */ diff --git a/x11vnc/solid.c b/x11vnc/solid.c index 53cb0c2..a6500d8 100644 --- a/x11vnc/solid.c +++ b/x11vnc/solid.c @@ -37,9 +37,11 @@ so, delete this exception statement from your version. #include "xwrappers.h" #include "connections.h" #include "cleanup.h" +#include "xevents.h" char *guess_desktop(void); void solid_bg(int restore); +char *dbus_session(void); static void usr_bin_path(int restore); @@ -550,31 +552,104 @@ static void solid_cde(char *color) { #endif /* NO_X11 */ } +static char _dbus_str[1100]; + +char *dbus_session(void) { + char *dbus_env = getenv("DBUS_SESSION_BUS_ADDRESS"); + char tmp[1000]; + + if (dbus_env != NULL && strlen(dbus_env) > 0) { + return ""; + } +#if NO_X11 + return ""; +#else + { + Atom dbus_prop; + Window r, w, *children; + unsigned int ui; + int rc, i; + + memset(_dbus_str, 0, sizeof(_dbus_str)); + + X_LOCK; + dbus_prop = XInternAtom(dpy, "_DBUS_SESSION_BUS_ADDRESS", True); + X_UNLOCK; + if (dbus_prop == None) { + return ""; + } + + X_LOCK; + memset(tmp, 0, sizeof(tmp)); + get_prop(tmp, sizeof(tmp)-1, dbus_prop, None); + X_UNLOCK; + if (strcmp(tmp, "")) { + if (!strchr(tmp, '\'')) { + sprintf(_dbus_str, "env DBUS_SESSION_BUS_ADDRESS='%s'", tmp); + return _dbus_str; + } + } + + X_LOCK; + rc = XQueryTree_wr(dpy, rootwin, &r, &w, &children, &ui); + X_UNLOCK; + if (!rc || children == NULL || ui == 0) { + return ""; + } + for (i=0; i < ui; i++) { + X_LOCK; + memset(tmp, 0, sizeof(tmp)); + get_prop(tmp, sizeof(tmp)-1, dbus_prop, children[i]); + X_UNLOCK; + + if (strcmp(tmp, "")) { + if (!strchr(tmp, '\'')) { + sprintf(_dbus_str, "env DBUS_SESSION_BUS_ADDRESS='%s'", tmp); + break; + } + } + } + X_LOCK; + XFree_wr(children); + X_UNLOCK; + + return _dbus_str; + } +#endif +} + static void solid_gnome(char *color) { #if NO_X11 RAWFB_RET_VOID if (!color) {} return; #else - char get_color[] = "gconftool-2 --get " + char get_color[] = "%s gconftool-2 --get " "/desktop/gnome/background/primary_color"; - char set_color[] = "gconftool-2 --set " - "/desktop/gnome/background/primary_color --type string '%s'"; - char get_option[] = "gconftool-2 --get " + char set_color[] = "%s gconftool-2 --set --type string " + "/desktop/gnome/background/primary_color '%s'"; + char get_option[] = "%s gconftool-2 --get " "/desktop/gnome/background/picture_options"; - char set_option[] = "gconftool-2 --set " - "/desktop/gnome/background/picture_options --type string '%s'"; + char set_option[] = "%s gconftool-2 --set --type string " + "/desktop/gnome/background/picture_options '%s'"; #if 0 - char get_filename[] = "gconftool-2 --get " + char get_shading[] = "%s gconftool-2 --get " + "/desktop/gnome/background/color_shading_type"; + char set_shading[] = "%s gconftool-2 --set --type string " + "/desktop/gnome/background/color_shading_type '%s'"; + char get_filename[] = "%s gconftool-2 --get " "/desktop/gnome/background/picture_filename"; - char set_filename[] = "gconftool-2 --set " - "/desktop/gnome/background/picture_filename --type string '%s'"; + char set_filename[] = "%s gconftool-2 --set --type string " + "/desktop/gnome/background/picture_filename '%s'"; #endif static char *orig_color = NULL; static char *orig_option = NULL; - char *cmd; + char *cmd, *dbus = ""; RAWFB_RET_VOID + + dbus = dbus_session(); + rfbLog("guessed dbus: %s\n", dbus); if (! color) { if (! orig_color) { @@ -591,14 +666,12 @@ static void solid_gnome(char *color) { rfbLog("invalid option: %s\n", orig_option); return; } - cmd = (char *) malloc(strlen(set_option) - 2 + - strlen(orig_option) + 1); - sprintf(cmd, set_option, orig_option); + cmd = (char *) malloc(strlen(set_option) - 2 + strlen(orig_option) + strlen(dbus) + 1); + sprintf(cmd, set_option, dbus, orig_option); dt_cmd(cmd); free(cmd); - cmd = (char *) malloc(strlen(set_color) - 2 + - strlen(orig_color) + 1); - sprintf(cmd, set_color, orig_color); + cmd = (char *) malloc(strlen(set_color) - 2 + strlen(orig_color) + strlen(dbus) + 1); + sprintf(cmd, set_color, dbus, orig_color); dt_cmd(cmd); free(cmd); return; @@ -607,7 +680,10 @@ static void solid_gnome(char *color) { if (! orig_color) { char *q; if (cmd_ok("dt")) { - orig_color = strdup(cmd_output(get_color)); + cmd = (char *) malloc(strlen(get_color) + strlen(dbus) + 1); + sprintf(cmd, get_color, dbus); + orig_color = strdup(cmd_output(cmd)); + free(cmd); } else { orig_color = ""; } @@ -621,7 +697,10 @@ static void solid_gnome(char *color) { if (! orig_option) { char *q; if (cmd_ok("dt")) { - orig_option = strdup(cmd_output(get_option)); + cmd = (char *) malloc(strlen(get_option) + strlen(dbus) + 1); + sprintf(cmd, get_option, dbus); + orig_option = strdup(cmd_output(cmd)); + free(cmd); } else { orig_color = ""; } @@ -636,19 +715,19 @@ static void solid_gnome(char *color) { rfbLog("invalid color: %s\n", color); return; } - cmd = (char *) malloc(strlen(set_color) + strlen(color) + 1); - sprintf(cmd, set_color, color); + cmd = (char *) malloc(strlen(set_color) + strlen(color) + strlen(dbus) + 1); + sprintf(cmd, set_color, dbus, color); dt_cmd(cmd); free(cmd); - cmd = (char *) malloc(strlen(set_option) + strlen("none") + 1); - sprintf(cmd, set_option, "none"); + cmd = (char *) malloc(strlen(set_option) + strlen("none") + strlen(dbus) + 1); + sprintf(cmd, set_option, dbus, "none"); dt_cmd(cmd); free(cmd); #if 0 cmd = (char *) malloc(strlen(set_filename) + strlen("none") + 1); - sprintf(cmd, set_filename, "none"); + sprintf(cmd, set_filename, dbus, "none"); dt_cmd(cmd); free(cmd); #endif diff --git a/x11vnc/solid.h b/x11vnc/solid.h index 5fffdbf..8ade2f9 100644 --- a/x11vnc/solid.h +++ b/x11vnc/solid.h @@ -39,6 +39,7 @@ extern char *guess_desktop(void); extern unsigned long get_pixel(char *color); extern XImage *solid_image(char *color); extern void solid_bg(int restore); +extern char *dbus_session(void); extern XImage *solid_root(char *color); extern void kde_no_animate(int restore); extern void gnome_no_animate(void); diff --git a/x11vnc/sslcmds.c b/x11vnc/sslcmds.c index 2fb248b..5a4e027 100644 --- a/x11vnc/sslcmds.c +++ b/x11vnc/sslcmds.c @@ -49,7 +49,7 @@ so, delete this exception statement from your version. void check_stunnel(void); -int start_stunnel(int stunnel_port, int x11vnc_port); +int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport); void stop_stunnel(void); void setup_stunnel(int rport, int *argc, char **argv); char *get_Cert_dir(char *cdir_in, char **tmp_in); @@ -86,14 +86,14 @@ void check_stunnel(void) { } } -int start_stunnel(int stunnel_port, int x11vnc_port) { +int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport) { #ifdef SSLCMDS char extra[] = ":/usr/sbin:/usr/local/sbin:/dist/sbin"; char *path, *p, *exe; char *stunnel_path = NULL; struct stat verify_buf; struct stat crl_buf; - int status; + int status, tmp_pem = 0; if (stunnel_pid) { stop_stunnel(); @@ -167,9 +167,33 @@ int start_stunnel(int stunnel_port, int x11vnc_port) { " saved PEM.\n"); clean_up_exit(1); } + } else if (!stunnel_pem) { + stunnel_pem = create_tmp_pem(NULL, 0); + if (! stunnel_pem) { + rfbLog("start_stunnel: could not create temporary," + " self-signed PEM.\n"); + clean_up_exit(1); + } + tmp_pem = 1; + if (getenv("X11VNC_SHOW_TMP_PEM")) { + FILE *in = fopen(stunnel_pem, "r"); + if (in != NULL) { + char line[128]; + fprintf(stderr, "\n"); + while (fgets(line, 128, in) != NULL) { + fprintf(stderr, "%s", line); + } + fprintf(stderr, "\n"); + fclose(in); + } + } } if (ssl_verify) { + char *file = get_ssl_verify_file(ssl_verify); + if (file) { + ssl_verify = file; + } if (stat(ssl_verify, &verify_buf) != 0) { rfbLog("stunnel: %s does not exist.\n", ssl_verify); clean_up_exit(1); @@ -245,6 +269,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) { if (! in) { exit(1); } + fprintf(in, "foreground = yes\n"); fprintf(in, "pid =\n"); if (stunnel_pem) { @@ -263,7 +288,6 @@ int start_stunnel(int stunnel_port, int x11vnc_port) { } else { fprintf(in, "CAfile = %s\n", ssl_verify); } - /* XXX double check -v 2 */ fprintf(in, "verify = 2\n"); } fprintf(in, ";debug = 7\n\n"); @@ -271,8 +295,24 @@ int start_stunnel(int stunnel_port, int x11vnc_port) { fprintf(in, "accept = %d\n", stunnel_port); fprintf(in, "connect = %d\n", x11vnc_port); + if (hport > 0 && x11vnc_hport > 0) { + fprintf(in, "\n[x11vnc_http]\n"); + fprintf(in, "accept = %d\n", hport); + fprintf(in, "connect = %d\n", x11vnc_hport); + } + fflush(in); rewind(in); + + if (getenv("STUNNEL_DEBUG")) { + char line[1000]; + fprintf(stderr, "\nstunnel config contents:\n\n"); + while (fgets(line, sizeof(line), in) != NULL) { + fprintf(stderr, "%s", line); + } + fprintf(stderr, "\n"); + rewind(in); + } sprintf(fd, "%d", fileno(in)); execlp(stunnel_path, stunnel_path, "-fd", fd, (char *) NULL); @@ -280,9 +320,21 @@ int start_stunnel(int stunnel_port, int x11vnc_port) { } free(exe); - usleep(500 * 1000); + usleep(750 * 1000); waitpid(stunnel_pid, &status, WNOHANG); + + if (ssl_verify && strstr(ssl_verify, "/sslverify-tmp-load-")) { + /* temporary file */ + usleep(1000 * 1000); + unlink(ssl_verify); + } + if (tmp_pem) { + /* temporary cert */ + usleep(1500 * 1000); + unlink(stunnel_pem); + } + if (kill(stunnel_pid, 0) != 0) { waitpid(stunnel_pid, &status, WNOHANG); stunnel_pid = 0; @@ -315,13 +367,13 @@ void stop_stunnel(void) { } void setup_stunnel(int rport, int *argc, char **argv) { - int i, xport = 0; + int i, xport = 0, hport = 0, xhport = 0; + if (! rport && argc && argv) { for (i=0; i< *argc; i++) { if (argv[i] && !strcmp(argv[i], "-rfbport")) { if (i < *argc - 1) { rport = atoi(argv[i+1]); - break; } } } @@ -340,7 +392,36 @@ void setup_stunnel(int rport, int *argc, char **argv) { goto stunnel_fail; } - if (start_stunnel(rport, xport)) { + if (https_port_num > 0) { + hport = https_port_num; + } + + if (! hport && argc && argv) { + for (i=0; i< *argc; i++) { + if (argv[i] && !strcmp(argv[i], "-httpport")) { + if (i < *argc - 1) { + hport = atoi(argv[i+1]); + } + } + } + } + + if (! hport && http_try_it) { + hport = find_free_port(rport-100, rport-1); + if (! hport) { + goto stunnel_fail; + } + } + if (hport) { + xhport = find_free_port(5850, 5899); + if (! xhport) { + goto stunnel_fail; + } + stunnel_http_port = hport; + } + + + if (start_stunnel(rport, xport, hport, xhport)) { int tweaked = 0; char tmp[30]; sprintf(tmp, "%d", xport); diff --git a/x11vnc/sslcmds.h b/x11vnc/sslcmds.h index 3256775..f8d5210 100644 --- a/x11vnc/sslcmds.h +++ b/x11vnc/sslcmds.h @@ -36,7 +36,7 @@ so, delete this exception statement from your version. /* -- sslcmds.h -- */ extern void check_stunnel(void); -extern int start_stunnel(int stunnel_port, int x11vnc_port); +extern int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport); extern void stop_stunnel(void); extern void setup_stunnel(int rport, int *argc, char **argv); extern char *get_Cert_dir(char *cdir_in, char **tmp_in); diff --git a/x11vnc/sslhelper.c b/x11vnc/sslhelper.c index 89a4da7..4c84cbc 100644 --- a/x11vnc/sslhelper.c +++ b/x11vnc/sslhelper.c @@ -73,80 +73,13 @@ char *new_dh_params = NULL; void raw_xfer(int csock, int s_in, int s_out); -#if !LIBVNCSERVER_HAVE_LIBSSL -int openssl_present(void) {return 0;} -static void badnews(void) { - use_openssl = 0; - use_stunnel = 0; - rfbLog("** not compiled with libssl OpenSSL support **\n"); - clean_up_exit(1); -} -void openssl_init(int isclient) {badnews();} -void openssl_port(void) {badnews();} -void https_port(void) {badnews();} -void check_openssl(void) {if (use_openssl) badnews();} -void check_https(void) {if (use_openssl) badnews();} -void ssl_helper_pid(pid_t pid, int sock) {badnews(); sock = pid;} -void accept_openssl(int mode, int presock) {mode = 0; presock = 0; badnews();} -char *find_openssl_bin(void) {badnews(); return NULL;} -char *get_saved_pem(char *string, int create) {badnews(); return NULL;} -#else - -/* - * This is because on older systems both zlib.h and ssl.h define - * 'free_func' nothing we do below (currently) induces an external - * dependency on 'free_func'. - */ -#define free_func my_jolly_little_free_func - -#include -#include -#include - -int openssl_present(void); -void openssl_init(int isclient); -void openssl_port(void); -void check_openssl(void); -void check_https(void); -void ssl_helper_pid(pid_t pid, int sock); -void accept_openssl(int mode, int presock); -char *find_openssl_bin(void); +/* openssl(1) pem related functions: */ char *get_saved_pem(char *string, int create); +char *find_openssl_bin(void); +char *get_ssl_verify_file(char *str_in); +char *create_tmp_pem(char *path, int prompt); -static SSL_CTX *ctx = NULL; -static RSA *rsa_512 = NULL; -static RSA *rsa_1024 = NULL; -static SSL *ssl = NULL; -static X509_STORE *revocation_store = NULL; - - -static void init_prng(void); -static void sslerrexit(void); static char *get_input(char *tag, char **in); -static char *create_tmp_pem(char *path, int prompt); -static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https); -static void ssl_xfer(int csock, int s_in, int s_out, int is_https); - -#ifndef FORK_OK -void openssl_init(int isclient) { - rfbLog("openssl_init: fork is not supported. cannot create" - " ssl helper process.\n"); - clean_up_exit(1); -} -int openssl_present(void) {return 0;} -#else -int openssl_present(void) {return 1;} - -static void sslerrexit(void) { - unsigned long err = ERR_get_error(); - - if (err) { - char str[256]; - ERR_error_string(err, str); - fprintf(stderr, "ssl error: %s\n", str); - } - clean_up_exit(1); -} char *get_saved_pem(char *save, int create) { char *s = NULL, *path, *cdir, *tmp; @@ -263,7 +196,7 @@ char *find_openssl_bin(void) { 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. (null)\n"); return NULL; } @@ -289,6 +222,7 @@ char *find_openssl_bin(void) { if (! found_openssl) { fprintf(stderr, "could not find openssl(1) program in PATH.\n"); + fprintf(stderr, "PATH=%s\n", gp); fprintf(stderr, "(also checked: %s)\n", extra); return NULL; } @@ -297,7 +231,7 @@ char *find_openssl_bin(void) { /* uses /usr/bin/openssl to create a tmp cert */ -static char *create_tmp_pem(char *pathin, int prompt) { +char *create_tmp_pem(char *pathin, int prompt) { pid_t pid, pidw; FILE *in, *out; char cnf[] = "/tmp/x11vnc-cnf.XXXXXX"; @@ -411,6 +345,10 @@ static char *create_tmp_pem(char *pathin, int prompt) { days = "30"; } +#ifndef FORK_OK + rfbLog("not compiled with fork(2)\n"); + clean_up_exit(1); +#else /* make RSA key */ pid = fork(); if (pid < 0) { @@ -476,6 +414,8 @@ static char *create_tmp_pem(char *pathin, int prompt) { fclose(out); #endif +#endif /* FORK_OK */ + unlink(cnf); free(exe); @@ -543,15 +483,22 @@ static char *create_tmp_pem(char *pathin, int prompt) { } if (show_cert) { - char cmd[100]; - if (inetd) { - sprintf(cmd, "openssl x509 -text -in '%s' 1>&2", pem); - } else { - sprintf(cmd, "openssl x509 -text -in '%s'", pem); + exe = find_openssl_bin(); + if (!exe) { + exe = strdup("openssl"); + } + if (strlen(pem) + strlen(exe) < 4000) { + char cmd[5000]; + if (inetd) { + sprintf(cmd, "%s x509 -text -in '%s' 1>&2", exe, pem); + } else { + sprintf(cmd, "%s x509 -text -in '%s'", exe, pem); + } + fprintf(stderr, "\n"); + system(cmd); + fprintf(stderr, "\n"); } - fprintf(stderr, "\n"); - system(cmd); - fprintf(stderr, "\n"); + free(exe); } if (pathin) { @@ -562,39 +509,6 @@ static char *create_tmp_pem(char *pathin, int prompt) { } } -static int pem_passwd_callback(char *buf, int size, int rwflag, - void *userdata) { - char *q, line[1024]; - - if (! buf) { - exit(1); - } - - fprintf(stderr, "\nA passphrase is needed to unlock an OpenSSL " - "private key (PEM file).\n"); - fprintf(stderr, "Enter passphrase> "); - system("stty -echo"); - if(fgets(line, 1024, stdin) == NULL) { - fprintf(stdout, "\n"); - system("stty echo"); - exit(1); - } - system("stty echo"); - fprintf(stdout, "\n\n"); - q = strrchr(line, '\n'); - if (q) { - *q = '\0'; - } - line[1024 - 1] = '\0'; - strncpy(buf, line, size); - buf[size - 1] = '\0'; - - if (0) rwflag = 0; /* compiler warning. */ - if (0) userdata = 0; /* compiler warning. */ - - return strlen(buf); -} - static int appendfile(FILE *out, char *infile) { char line[1024]; FILE *in; @@ -623,7 +537,7 @@ static int appendfile(FILE *out, char *infile) { return 1; } -static char *get_ssl_verify_file(char *str_in) { +char *get_ssl_verify_file(char *str_in) { char *p, *str, *cdir, *tmp; char *tfile, *tfile2; FILE *file; @@ -649,7 +563,7 @@ static char *get_ssl_verify_file(char *str_in) { tfile = (char *) malloc(strlen(tmp) + 1024); tfile2 = (char *) malloc(strlen(tmp) + 1024); - sprintf(tfile, "%s/sslverify-load-%d.crts.XXXXXX", tmp, getpid()); + sprintf(tfile, "%s/sslverify-tmp-load-%d.crts.XXXXXX", tmp, getpid()); fd = mkstemp(tfile); if (fd < 0) { @@ -742,6 +656,140 @@ static char *get_ssl_verify_file(char *str_in) { return tfile; } +int openssl_present(void); +void openssl_init(int isclient); +void openssl_port(void); +void https_port(void); +void check_openssl(void); +void check_https(void); +void ssl_helper_pid(pid_t pid, int sock); +void accept_openssl(int mode, int presock); + +static void lose_ram(void); +#define ABSIZE 16384 + +static int vencrypt_selected = 0; +static int anontls_selected = 0; + +/* to test no openssl libssl */ +#if 0 +#undef LIBVNCSERVER_HAVE_LIBSSL +#define LIBVNCSERVER_HAVE_LIBSSL 0 +#endif + +#if !LIBVNCSERVER_HAVE_LIBSSL + +static void badnews(char *name) { + use_openssl = 0; + use_stunnel = 0; + rfbLog("** %s: not compiled with libssl OpenSSL support **\n", name ? name : "???"); + clean_up_exit(1); +} + +int openssl_present(void) {return 0;} +void openssl_init(int isclient) {badnews("openssl_init");} + +#define SSL_ERROR_NONE 0 + +static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) { + if (enc_str != NULL) { + return 1; + } + badnews("ssl_init"); + return 0; +} + +static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { + if (enc_str != NULL && !strcmp(enc_str, "none")) { + usleep(250*1000); + rfbLog("doing '-enc none' raw transfer (no encryption)\n"); + raw_xfer(csock, s_in, s_out); + } else { + badnews("ssl_xfer"); + } +} + +#else /* LIBVNCSERVER_HAVE_LIBSSL */ + +/* + * This is because on older systems both zlib.h and ssl.h define + * 'free_func' nothing we do below (currently) induces an external + * dependency on 'free_func'. + */ +#define free_func my_jolly_little_free_func + +#include +#include +#include + +static SSL_CTX *ctx = NULL; +static RSA *rsa_512 = NULL; +static RSA *rsa_1024 = NULL; +static SSL *ssl = NULL; +static X509_STORE *revocation_store = NULL; + + +static void init_prng(void); +static void sslerrexit(void); +static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https); +static void ssl_xfer(int csock, int s_in, int s_out, int is_https); + +#ifndef FORK_OK +void openssl_init(int isclient) { + rfbLog("openssl_init: fork is not supported. cannot create" + " ssl helper process.\n"); + clean_up_exit(1); +} +int openssl_present(void) {return 0;} + +#else + +int openssl_present(void) {return 1;} + +static void sslerrexit(void) { + unsigned long err = ERR_get_error(); + + if (err) { + char str[256]; + ERR_error_string(err, str); + fprintf(stderr, "ssl error: %s\n", str); + } + clean_up_exit(1); +} + +static int pem_passwd_callback(char *buf, int size, int rwflag, + void *userdata) { + char *q, line[1024]; + + if (! buf) { + exit(1); + } + + fprintf(stderr, "\nA passphrase is needed to unlock an OpenSSL " + "private key (PEM file).\n"); + fprintf(stderr, "Enter passphrase> "); + system("stty -echo"); + if(fgets(line, 1024, stdin) == NULL) { + fprintf(stdout, "\n"); + system("stty echo"); + exit(1); + } + system("stty echo"); + fprintf(stdout, "\n\n"); + q = strrchr(line, '\n'); + if (q) { + *q = '\0'; + } + line[1024 - 1] = '\0'; + strncpy(buf, line, size); + buf[size - 1] = '\0'; + + if (0) rwflag = 0; /* compiler warning. */ + if (0) userdata = 0; /* compiler warning. */ + + return strlen(buf); +} + /* based on mod_ssl */ static int crl_callback(X509_STORE_CTX *callback_ctx) { X509_STORE_CTX store_ctx; @@ -890,9 +938,6 @@ static int verify_callback(int ok, X509_STORE_CTX *callback_ctx) { #define rfbVencryptX509Vnc 261 #define rfbVencryptX509Plain 262 -static int vencrypt_selected = 0; -static int anontls_selected = 0; - static int ssl_client_mode = 0; static int switch_to_anon_dh(void); @@ -1168,7 +1213,7 @@ void openssl_init(int isclient) { } else { SSL_CTX_set_verify(ctx, lvl, verify_callback); } - if (strstr(file, "tmp/sslverify-load-")) { + if (strstr(file, "/sslverify-tmp-load-")) { /* temporary file */ unlink(file); } @@ -1179,2810 +1224,2746 @@ void openssl_init(int isclient) { rfbLog("\n"); } -void openssl_port(void) { - int sock, shutdown = 0; - static int port = 0; - static in_addr_t iface = INADDR_ANY; - int db = 0; - - if (! screen) { - rfbLog("openssl_port: no screen!\n"); - clean_up_exit(1); - } - if (inetd) { - ssl_initialized = 1; - return; - } - - if (screen->listenSock > -1 && screen->port > 0) { - port = screen->port; - shutdown = 1; - } - if (screen->listenInterface) { - iface = screen->listenInterface; +static int read_exact(int sock, char *buf, int len) { + int n, fail = 0; + if (sock < 0) { + return 0; } - - if (shutdown) { - if (db) fprintf(stderr, "shutting down %d/%d\n", - port, screen->listenSock); -#if LIBVNCSERVER_HAS_SHUTDOWNSOCKETS - rfbShutdownSockets(screen); -#endif + while (len > 0) { + n = read(sock, buf, len); + if (n > 0) { + buf += n; + len -= n; + } else if (n == 0) { + fail = 1; + break; + } else if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + usleep(10*1000); + } else if (n < 0 && errno != EINTR) { + fail = 1; + break; + } + } + if (fail) { + return 0; + } else { + return 1; } +} - sock = rfbListenOnTCPPort(port, iface); +static int write_exact(int sock, char *buf, int len) { + int n, fail = 0; if (sock < 0) { - rfbLog("openssl_port: could not reopen port %d\n", port); - clean_up_exit(1); + return 0; } - rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock); - if (!quiet) { - announce(port, 1, NULL); + while (len > 0) { + n = write(sock, buf, len); + if (n > 0) { + buf += n; + len -= n; + } else if (n == 0) { + fail = 1; + break; + } else if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + usleep(10*1000); + } else if (n < 0 && errno != EINTR) { + fail = 1; + break; + } + } + if (fail) { + return 0; + } else { + return 1; } - openssl_sock = sock; - openssl_port_num = port; - - ssl_initialized = 1; } +/* XXX not in rfb.h: */ +void rfbClientSendString(rfbClientPtr cl, char *reason); -void https_port(void) { - int sock; - static int port = 0; - static in_addr_t iface = INADDR_ANY; - int db = 0; +static int finish_auth(rfbClientPtr client, char *type) { + int security_result, ret; - /* as openssl_port above: open a listening socket for pure https: */ - if (https_port_num < 0) { - return; - } - if (! screen) { - rfbLog("https_port: no screen!\n"); - clean_up_exit(1); - } - if (screen->listenInterface) { - iface = screen->listenInterface; - } + ret = 0; - if (https_port_num == 0) { - https_port_num = find_free_port(5801, 5851); - } - if (https_port_num <= 0) { - rfbLog("https_port: could not find port %d\n", https_port_num); - clean_up_exit(1); - } - port = https_port_num; +if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "finish_auth type=%s\n", type); - sock = rfbListenOnTCPPort(port, iface); - if (sock < 0) { - rfbLog("https_port: could not open port %d\n", port); - clean_up_exit(1); - } - if (db) fprintf(stderr, "https_port: listen on port/sock %d/%d\n", - port, sock); + if (!strcmp(type, "None")) { + security_result = 0; /* success */ + if (write_exact(client->sock, (char *) &security_result, 4)) { + ret = 1; + } + rfbLog("finish_auth: using auth 'None'\n"); + client->state = RFB_INITIALISATION; - https_sock = sock; -} + } else if (!strcmp(type, "Vnc")) { + RAND_bytes(client->authChallenge, CHALLENGESIZE); + if (write_exact(client->sock, (char *) &client->authChallenge, CHALLENGESIZE)) { + ret = 1; + } + rfbLog("finish_auth: using auth 'Vnc', sent challenge.\n"); + client->state = RFB_AUTHENTICATION; -static void lose_ram(void) { - /* - * for a forked child that will be around for a long time - * without doing exec(). we really should re-exec, but a pain - * to redo all SSL ctx. - */ - free_old_fb(); + } else if (!strcmp(type, "Plain")) { + if (!unixpw) { + rfbLog("finish_auth: *Plain not allowed outside unixpw mode.\n"); + ret = 0; + } else { + char *un, *pw; + int unlen, pwlen; - free_tiles(); -} +if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "*Plain begin: onHold=%d client=%p unixpw_client=%p\n", client->onHold, (void *) client, (void *) unixpw_client); -/* utility to keep track of existing helper processes: */ + if (!read_exact(client->sock, (char *)&unlen, 4)) goto fail; + unlen = Swap32IfLE(unlen); -void ssl_helper_pid(pid_t pid, int sock) { -# define HPSIZE 256 - static pid_t helpers[HPSIZE]; - static int sockets[HPSIZE], first = 1; - int i, empty, set, status; - static int db = 0; +if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "unlen: %d\n", unlen); - if (first) { - for (i=0; i < HPSIZE; i++) { - helpers[i] = 0; - sockets[i] = 0; - } - if (getenv("SSL_HELPER_PID_DB")) { - db = 1; - } - first = 0; - } + if (!read_exact(client->sock, (char *)&pwlen, 4)) goto fail; + pwlen = Swap32IfLE(pwlen); +if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "pwlen: %d\n", pwlen); - if (pid == 0) { - /* killall or waitall */ - for (i=0; i < HPSIZE; i++) { - if (helpers[i] == 0) { - sockets[i] = -1; - continue; - } - if (kill(helpers[i], 0) == 0) { - int kret = -2; - pid_t wret; - if (sock != -2) { - if (sockets[i] >= 0) { - close(sockets[i]); - } - kret = kill(helpers[i], SIGTERM); - if (kret == 0) { - usleep(20 * 1000); - } - } + un = (char *) malloc(unlen+1); + memset(un, 0, unlen+1); -#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID - wret = waitpid(helpers[i], &status, WNOHANG); + pw = (char *) malloc(pwlen+2); + memset(pw, 0, pwlen+2); -if (db) fprintf(stderr, "waitpid(%d)\n", helpers[i]); -if (db) fprintf(stderr, " waitret1=%d\n", wret); + if (!read_exact(client->sock, un, unlen)) goto fail; + if (!read_exact(client->sock, pw, pwlen)) goto fail; - if (kret == 0 && wret != helpers[i]) { - int k; - for (k=0; k < 10; k++) { - usleep(100 * 1000); - wret = waitpid(helpers[i], &status, WNOHANG); -if (db) fprintf(stderr, " waitret2=%d\n", wret); - if (wret == helpers[i]) { - break; - } - } - } -#endif - if (sock == -2) { - continue; +if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "*Plain: %d %d '%s' ... \n", unlen, pwlen, un); + strcat(pw, "\n"); + + if (unixpw_verify(un, pw)) { + security_result = 0; /* success */ + if (write_exact(client->sock, (char *) &security_result, 4)) { + ret = 1; + unixpw_verify_screen(un, pw); } + client->onHold = FALSE; + client->state = RFB_INITIALISATION; } - helpers[i] = 0; - sockets[i] = -1; + if (ret == 0) { + rfbClientSendString(client, "unixpw failed"); + } + + memset(un, 0, unlen+1); + memset(pw, 0, pwlen+2); + free(un); + free(pw); } - return; + } else { + rfbLog("finish_auth: unknown sub-type: %s\n", type); + ret = 0; } -if (db) fprintf(stderr, "ssl_helper_pid(%d, %d)\n", pid, sock); + fail: + return ret; +} - /* add (or delete for sock == -1) */ - set = 0; - empty = -1; - for (i=0; i < HPSIZE; i++) { - if (helpers[i] == pid) { - if (sock == -1) { -#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID - pid_t wret; - wret = waitpid(helpers[i], &status, WNOHANG); +static int finish_vencrypt_auth(rfbClientPtr client, int subtype) { -if (db) fprintf(stderr, "waitpid(%d) 2\n", helpers[i]); -if (db) fprintf(stderr, " waitret1=%d\n", wret); -#endif - helpers[i] = 0; - } - sockets[i] = sock; - set = 1; - } else if (empty == -1 && helpers[i] == 0) { - empty = i; - } - } - if (set || sock == -1) { - return; /* done */ + if (subtype == rfbVencryptTlsNone || subtype == rfbVencryptX509None) { + return finish_auth(client, "None"); + } else if (subtype == rfbVencryptTlsVnc || subtype == rfbVencryptX509Vnc) { + return finish_auth(client, "Vnc"); + } else if (subtype == rfbVencryptTlsPlain || subtype == rfbVencryptX509Plain) { + return finish_auth(client, "Plain"); + } else { + rfbLog("finish_vencrypt_auth: unknown sub-type: %d\n", subtype); + return 0; } +} - /* now try to store */ - if (empty >= 0) { - helpers[empty] = pid; - sockets[empty] = sock; - return; - } - for (i=0; i < HPSIZE; i++) { - if (helpers[i] == 0) { - continue; - } - /* clear out stale pids: */ - if (kill(helpers[i], 0) != 0) { - helpers[i] = 0; - sockets[i] = -1; - - if (empty == -1) { - empty = i; - } - } + +static int add_anon_dh(void) { + pid_t pid, pidw; + char cnf[] = "/tmp/x11vnc-dh.XXXXXX"; + char *infile = NULL; + int status, cnf_fd; + DH *dh; + BIO *bio; + FILE *in; + double ds; + /* + * These are dh parameters (prime, generator), not dh keys. + * Evidently it is ok for them to be publicly known. + * openssl dhparam -out dh.out 1024 + */ + char *fixed_dh_params = +"-----BEGIN DH PARAMETERS-----\n" +"MIGHAoGBAL28w69ZnLYBvp8R2OeqtAIms+oatY19iBL4WhGI/7H1OMmkJjIe+OHs\n" +"PXoJfe5ucrnvno7Xm+HJZYa1jnPGQuWoa/VJKXdVjYdJVNzazJKM2daKKcQA4GDc\n" +"msFS5DxLbzUR5jy1n12K3EcbvpyFqDYVTJJXm7NuNuiWRfz3wTozAgEC\n" +"-----END DH PARAMETERS-----\n"; + + if (dhparams_file != NULL) { + infile = dhparams_file; + rfbLog("add_anon_dh: using %s\n", dhparams_file); + goto readin; } - if (empty >= 0) { - helpers[empty] = pid; - sockets[empty] = sock; + + cnf_fd = mkstemp(cnf); + if (cnf_fd < 0) { + return 0; } -} + infile = cnf; -static int is_ssl_readable(int s_in, double last_https, char *last_get, - int mode) { - int nfd, db = 0; - struct timeval tv; - fd_set rd; + if (create_fresh_dhparams) { - if (getenv("ACCEPT_OPENSSL_DEBUG")) { - db = atoi(getenv("ACCEPT_OPENSSL_DEBUG")); - } + if (new_dh_params != NULL) { + write(cnf_fd, new_dh_params, strlen(new_dh_params)); + close(cnf_fd); + } else { + char *exe = find_openssl_bin(); + struct stat sbuf; - /* - * we'll do a select() on s_in for reading. this is not an - * absolute proof that SSL_read is ready (XXX use SSL utility). - */ - tv.tv_sec = 2; - tv.tv_usec = 0; + if (no_external_cmds || !cmd_ok("ssl")) { + rfbLog("add_anon_dh: cannot run external commands.\n"); + return 0; + } - if (mode == OPENSSL_INETD) { - /* - * https via inetd is icky because x11vnc is restarted - * for each socket (and some clients send requests - * rapid fire). - */ - tv.tv_sec = 6; - } + close(cnf_fd); + if (exe == NULL) { + return 0; + } + ds = dnow(); + pid = fork(); + if (pid < 0) { + return 0; + } else if (pid == 0) { + int i; + for (i=0; i<256; i++) { + if (i == 2) continue; + close(i); + } + /* rather slow at 1024 */ + execlp(exe, exe, "dhparam", "-out", cnf, "1024", (char *)0); + exit(1); + } + pidw = waitpid(pid, &status, 0); + if (pidw != pid) { + return 0; + } + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + ; + } else { + return 0; + } + rfbLog("add_anon_dh: created new DH params in %.3f secs\n", dnow() - ds); - /* - * increase the timeout if we know HTTP traffic has occurred - * recently: - */ - if (dnow() < last_https + 30.0) { - tv.tv_sec = 10; - if (last_get && strstr(last_get, "VncViewer")) { - tv.tv_sec = 5; + if (stat(cnf, &sbuf) == 0 && sbuf.st_size > 0) { + /* save it to reuse during our process's lifetime: */ + int d = open(cnf, O_RDONLY); + if (d >= 0) { + int n, len = sbuf.st_size; + new_dh_params = (char *) calloc(len+1, 1); + n = read(d, new_dh_params, len); + close(d); + if (n != len) { + free(new_dh_params); + new_dh_params = NULL; + } else if (dhret != NULL) { + d = open(dhret, O_WRONLY); + if (d >= 0) { + write(d, new_dh_params, strlen(new_dh_params)); + close(d); + } + } + } + } } + } else { + write(cnf_fd, fixed_dh_params, strlen(fixed_dh_params)); + close(cnf_fd); } - if (getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT")) { - tv.tv_sec = atoi(getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT")); - } -if (db) fprintf(stderr, "tv_sec: %d - %s\n", (int) tv.tv_sec, last_get); - - FD_ZERO(&rd); - FD_SET(s_in, &rd); - do { - nfd = select(s_in+1, &rd, NULL, NULL, &tv); - } while (nfd < 0 && errno == EINTR); + readin: - if (db) fprintf(stderr, "https nfd: %d\n", nfd); + ds = dnow(); + in = fopen(infile, "r"); - if (nfd <= 0 || ! FD_ISSET(s_in, &rd)) { + if (in == NULL) { + rfbLogPerror("fopen"); + unlink(cnf); return 0; } - return 1; -} - -#define ABSIZE 16384 -static int watch_for_http_traffic(char *buf_a, int *n_a, int raw_sock) { - int is_http, err, n, n2; - char *buf; - int db = 0; - /* - * 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 - * rest of the available data otherwise we may deadlock. - * what has been read is returned in buf_a and n_a. - * *buf_a is ABSIZE+1 long and zeroed. - */ - if (getenv("ACCEPT_OPENSSL_DEBUG")) { - db = atoi(getenv("ACCEPT_OPENSSL_DEBUG")); + bio = BIO_new_fp(in, BIO_CLOSE|BIO_FP_TEXT); + if (! bio) { + rfbLog("openssl_init: BIO_new_fp() failed.\n"); + unlink(cnf); + return 0; } - if (! buf_a || ! n_a) { + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + if (dh == NULL) { + rfbLog("openssl_init: PEM_read_bio_DHparams() failed.\n"); + unlink(cnf); + BIO_free(bio); return 0; } + BIO_free(bio); + SSL_CTX_set_tmp_dh(ctx, dh); + rfbLog("loaded Diffie Hellman %d bits, %.3fs\n", 8*DH_size(dh), dnow()-ds); + DH_free(dh); - buf = (char *) calloc((ABSIZE+1), 1); - *n_a = 0; + unlink(cnf); + return 1; +} - if (enc_str && !strcmp(enc_str, "none")) { - n = read(raw_sock, buf, 2); - err = SSL_ERROR_NONE; +static int switch_to_anon_dh(void) { + long mode; + + rfbLog("Using Anonymous Diffie-Hellman mode.\n"); + rfbLog("WARNING: Anonymous Diffie-Hellman uses encryption but is\n"); + rfbLog("WARNING: susceptible to a Man-In-The-Middle attack.\n"); + if (ssl_client_mode) { + ctx = SSL_CTX_new( SSLv23_client_method() ); } else { - n = SSL_read(ssl, buf, 2); - err = SSL_get_error(ssl, n); + ctx = SSL_CTX_new( SSLv23_server_method() ); } - - if (err != SSL_ERROR_NONE || n < 2) { - if (n > 0) { - strncpy(buf_a, buf, n); - *n_a = n; - } - if (db) fprintf(stderr, "watch_for_http_traffic ssl err: %d/%d\n", err, n); - return -1; + if (ctx == NULL) { + return 0; } - - /* look for GET, HEAD, POST, CONNECT */ - is_http = 0; - if (!strncmp("GE", buf, 2)) { - is_http = 1; - } else if (!strncmp("HE", buf, 2)) { - is_http = 1; - } else if (!strncmp("PO", buf, 2)) { - is_http = 1; - } else if (!strncmp("CO", buf, 2)) { - is_http = 1; + if (ssl_client_mode) { + return 1; } - if (db) fprintf(stderr, "watch_for_http_traffic read: '%s' %d\n", buf, n); - - /* - * better read all we can and fwd it along to avoid blocking - * in ssl_xfer(). - */ - - if (enc_str && !strcmp(enc_str, "none")) { - n2 = read(raw_sock, buf + n, ABSIZE - n); - } else { - n2 = SSL_read(ssl, buf + n, ABSIZE - n); + if (!SSL_CTX_set_cipher_list(ctx, "ADH:@STRENGTH")) { + return 0; } - if (n2 >= 0) { - n += n2; + if (!add_anon_dh()) { + return 0; } - *n_a = n; + mode = 0; + mode |= SSL_MODE_ENABLE_PARTIAL_WRITE; + mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; + SSL_CTX_set_mode(ctx, mode); - if (db) fprintf(stderr, "watch_for_http_traffic readmore: %d\n", n2); - - if (n > 0) { - memcpy(buf_a, buf, n); - } - if (db > 1) { - fprintf(stderr, "watch_for_http_traffic readmore: "); - write(2, buf_a, *n_a); - fprintf(stderr, "\n"); - } - if (db) fprintf(stderr, "watch_for_http_traffic return: %d\n", is_http); - return is_http; -} - -static int csock_timeout_sock = -1; + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); + SSL_CTX_set_timeout(ctx, 300); + SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_callback); + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); -static void csock_timeout (int sig) { - rfbLog("sig: %d, csock_timeout.\n", sig); - if (csock_timeout_sock >= 0) { - close(csock_timeout_sock); - csock_timeout_sock = -1; - } + return 1; } -#define PROXY_HACK 0 -#if PROXY_HACK +static int anontls_dialog(int s_in, int s_out) { -static int wait_conn(int sock) { - int conn; - struct sockaddr_in addr; -#ifdef __hpux - int addrlen = sizeof(addr); -#else - socklen_t addrlen = sizeof(addr); -#endif + if (s_in || s_out) {} + anontls_selected = 1; - signal(SIGALRM, csock_timeout); - csock_timeout_sock = sock; - - alarm(15); - conn = accept(sock, (struct sockaddr *)&addr, &addrlen); - alarm(0); + if (!switch_to_anon_dh()) { + rfbLog("anontls: Anonymous Diffie-Hellman failed.\n"); + return 0; + } - signal(SIGALRM, SIG_DFL); - return conn; + /* continue with SSL/TLS */ + return 1; } -/* no longer used */ - -int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie, - int mode) { - int sock1, db = 0; - char reply[] = "HTTP/1.1 200 OK\r\n" - "Content-Type: octet-stream\r\n" - "Pragma: no-cache\r\n\r\n"; - char reply0[] = "HTTP/1.0 200 OK\r\n" - "Content-Type: octet-stream\r\n" - "Content-Length: 9\r\n" - "Pragma: no-cache\r\n\r\nGO_AHEAD\n"; - - rfbLog("SSL: accept_openssl: detected https proxied connection" - " request.\n"); +/* + * Using spec: + * http://www.mail-archive.com/qemu-devel@nongnu.org/msg08681.html + */ +static int vencrypt_dialog(int s_in, int s_out) { + char buf[256], buf2[256]; + int subtypes[16]; + int n, i, ival, ok, nsubtypes = 0; - if (getenv("ACCEPT_OPENSSL_DEBUG")) { - db = atoi(getenv("ACCEPT_OPENSSL_DEBUG")); - } + vencrypt_selected = 0; - SSL_write(ssl, reply0, strlen(reply0)); - SSL_shutdown(ssl); - SSL_shutdown(ssl); - close(s_in); - close(s_out); - SSL_free(ssl); + /* send version 0.2 */ + buf[0] = 0; + buf[1] = 2; - if (mode == OPENSSL_VNC) { - listen = openssl_sock; - } else if (mode == OPENSSL_HTTPS) { - listen = https_sock; - } else { - /* inetd */ + if (!write_exact(s_out, buf, 2)) { + close(s_in); close(s_out); return 0; } - sock1 = wait_conn(listen); + /* read client version 0.2 */ + memset(buf, 0, sizeof(buf)); + if (!read_exact(s_in, buf, 2)) { + close(s_in); close(s_out); + return 0; + } + rfbLog("vencrypt: received %d.%d client version.\n", (int) buf[0], (int) buf[1]); - if (csock_timeout_sock < 0 || sock1 < 0) { - close(sock1); + /* close 0.0 */ + if (buf[0] == 0 && buf[1] == 0) { + rfbLog("vencrypt: received 0.0 version, closing connection.\n"); + close(s_in); close(s_out); return 0; } -if (db) fprintf(stderr, "got applet input sock1: %d\n", sock1); + /* accept only 0.2 */ + if (buf[0] != 0 || buf[1] != 2) { + rfbLog("vencrypt: unsupported VeNCrypt version, closing connection.\n"); + buf[0] = (char) 255; + write_exact(s_out, buf, 1); + close(s_in); close(s_out); + return 0; + } - if (! ssl_init(sock1, sock1, 0, 0.0)) { -if (db) fprintf(stderr, "ssl_init FAILED\n"); - exit(1); + /* tell them OK */ + buf[0] = 0; + if (!write_exact(s_out, buf, 1)) { + close(s_in); close(s_out); + return 0; } - SSL_write(ssl, reply, strlen(reply)); + if (getenv("X11VNC_ENABLE_VENCRYPT_PLAIN_LOGIN")) { + vencrypt_enable_plain_login = atoi(getenv("X11VNC_ENABLE_VENCRYPT_PLAIN_LOGIN")); + } - { - char *buf; - int n = 0, ptr = 0; - - buf = (char *) calloc((8192+1), 1); - while (ptr < 8192) { - n = SSL_read(ssl, buf + ptr, 8192 - ptr); - if (n > 0) { - ptr += n; + /* load our list of sub-types: */ + n = 0; + if (!ssl_verify && vencrypt_kx != VENCRYPT_NODH) { + if (screen->authPasswdData != NULL) { + subtypes[n++] = rfbVencryptTlsVnc; + } else { + if (vencrypt_enable_plain_login && unixpw) { + subtypes[n++] = rfbVencryptTlsPlain; + } else { + subtypes[n++] = rfbVencryptTlsNone; } -if (db) fprintf(stderr, "buf: '%s'\n", buf); - if (strstr(buf, "\r\n\r\n")) { - break; + } + } + if (vencrypt_kx != VENCRYPT_NOX509) { + if (screen->authPasswdData != NULL) { + subtypes[n++] = rfbVencryptX509Vnc; + } else { + if (vencrypt_enable_plain_login && unixpw) { + subtypes[n++] = rfbVencryptX509Plain; + } else { + subtypes[n++] = rfbVencryptX509None; } } } - if (cookie) { - write(vncsock, cookie, strlen(cookie)); + nsubtypes = n; + for (i = 0; i < nsubtypes; i++) { + ((uint32_t *)buf)[i] = Swap32IfLE(subtypes[i]); } - ssl_xfer(vncsock, sock1, sock1, 0); - return 1; -} -#endif /* PROXY_HACK */ + /* send number first: */ + buf2[0] = (char) nsubtypes; + if (!write_exact(s_out, buf2, 1)) { + close(s_in); close(s_out); + return 0; + } + /* and now the list: */ + if (!write_exact(s_out, buf, 4*n)) { + close(s_in); close(s_out); + return 0; + } -static int check_ssl_access(char *addr) { - static char *save_allow_once = NULL; - static time_t time_allow_once = 0; + /* read client's selection: */ + if (!read_exact(s_in, (char *)&ival, 4)) { + close(s_in); close(s_out); + return 0; + } + ival = Swap32IfLE(ival); - /* due to "Fetch Cert" activities for SSL really need to "allow twice" */ - if (allow_once != NULL) { - save_allow_once = strdup(allow_once); - time_allow_once = time(NULL); - } else if (save_allow_once != NULL) { - if (getenv("X11VNC_NO_SSL_ALLOW_TWICE")) { - ; - } else if (time(NULL) < time_allow_once + 30) { - /* give them 30 secs to check and save the fetched cert. */ - allow_once = save_allow_once; - rfbLog("SSL: Permitting 30 sec grace period for allowonce.\n"); - rfbLog("SSL: Set X11VNC_NO_SSL_ALLOW_TWICE=1 to disable.\n"); + /* zero means no dice: */ + if (ival == 0) { + rfbLog("vencrypt: client selected no sub-type, closing connection.\n"); + close(s_in); close(s_out); + return 0; + } + + /* check if he selected a valid one: */ + ok = 0; + for (i = 0; i < nsubtypes; i++) { + if (ival == subtypes[i]) { + ok = 1; } - save_allow_once = NULL; - time_allow_once = 0; } - return check_access(addr); -} + if (!ok) { + rfbLog("vencrypt: client selected invalid sub-type: %d\n", ival); + close(s_in); close(s_out); + return 0; + } else { + char *st = "unknown!!"; + if (ival == rfbVencryptTlsNone) st = "rfbVencryptTlsNone"; + if (ival == rfbVencryptTlsVnc) st = "rfbVencryptTlsVnc"; + if (ival == rfbVencryptTlsPlain) st = "rfbVencryptTlsPlain"; + if (ival == rfbVencryptX509None) st = "rfbVencryptX509None"; + if (ival == rfbVencryptX509Vnc) st = "rfbVencryptX509Vnc"; + if (ival == rfbVencryptX509Plain) st = "rfbVencryptX509Plain"; + rfbLog("vencrypt: client selected sub-type: %d (%s)\n", ival, st); + } -static int write_exact(int sock, char *buf, int len); -static int read_exact(int sock, char *buf, int len); + vencrypt_selected = ival; -/* XXX not in rfb.h: */ -void rfbClientSendString(rfbClientPtr cl, char *reason); + /* not documented in spec, send OK: */ + buf[0] = 1; + if (!write_exact(s_out, buf, 1)) { + close(s_in); close(s_out); + return 0; + } -static int finish_auth(rfbClientPtr client, char *type) { - int security_result, ret; + if (vencrypt_selected == rfbVencryptTlsNone || + vencrypt_selected == rfbVencryptTlsVnc || + vencrypt_selected == rfbVencryptTlsPlain) { + /* these modes are Anonymous Diffie-Hellman */ + if (!switch_to_anon_dh()) { + rfbLog("vencrypt: Anonymous Diffie-Hellman failed.\n"); + return 0; + } + } - ret = 0; + /* continue with SSL/TLS */ + return 1; +} -if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "finish_auth type=%s\n", type); +static int check_vnc_tls_mode(int s_in, int s_out, double last_https) { + double waited = 0.0, waitmax = 1.4, dt = 0.01, start = dnow(); + struct timeval tv; + int input = 0, i, n, ok; + int major, minor, sectype = -1; + char *proto = "RFB 003.008\n"; + char *stype = "unknown"; + char buf[256]; + + vencrypt_selected = 0; + anontls_selected = 0; - if (!strcmp(type, "None")) { - security_result = 0; /* success */ - if (write_exact(client->sock, (char *) &security_result, 4)) { - ret = 1; + if (vencrypt_mode == VENCRYPT_NONE && anontls_mode == ANONTLS_NONE) { + /* only normal SSL */ + return 1; + } + if (ssl_client_mode) { + if (vencrypt_mode == VENCRYPT_FORCE || anontls_mode == ANONTLS_FORCE) { + rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/ANONTLS_FORCE in client\n"); + rfbLog("check_vnc_tls_mode: connect mode.\n"); + /* this is OK, continue on below for dialog. */ + } else { + /* otherwise we must assume normal SSL (we send client hello) */ + return 1; } - rfbLog("finish_auth: using auth 'None'\n"); - client->state = RFB_INITIALISATION; + } + if (ssl_verify && vencrypt_mode != VENCRYPT_FORCE && anontls_mode == ANONTLS_FORCE) { + rfbLog("check_vnc_tls_mode: Cannot use ANONTLS_FORCE with -sslverify (Anon DH only)\n"); + /* fallback to normal SSL */ + return 1; + } - } else if (!strcmp(type, "Vnc")) { - RAND_bytes(client->authChallenge, CHALLENGESIZE); - if (write_exact(client->sock, (char *) &client->authChallenge, CHALLENGESIZE)) { - ret = 1; - } - rfbLog("finish_auth: using auth 'Vnc', sent challenge.\n"); - client->state = RFB_AUTHENTICATION; - - } else if (!strcmp(type, "Plain")) { - if (!unixpw) { - rfbLog("finish_auth: *Plain not allowed outside unixpw mode.\n"); - ret = 0; - } else { - char *un, *pw; - int unlen, pwlen; + if (last_https > 0.0) { + double now = dnow(); + if (now < last_https + 5.0) { + waitmax = 20.0; + } else if (now < last_https + 15.0) { + waitmax = 10.0; + } else if (now < last_https + 30.0) { + waitmax = 5.0; + } else if (now < last_https + 60.0) { + waitmax = 2.5; + } + } -if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "*Plain begin: onHold=%d client=%p unixpw_client=%p\n", client->onHold, (void *) client, (void *) unixpw_client); + while (waited < waitmax) { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(s_in, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + select(s_in+1, &rfds, NULL, NULL, &tv); + if (FD_ISSET(s_in, &rfds)) { + input = 1; + break; + } + usleep((int) (1000 * 1000 * dt)); + waited += dt; + } + rfbLog("check_vnc_tls_mode: waited: %f / %.2f input: %s\n", + dnow() - start, waitmax, input ? "SSL Handshake" : "(future) RFB Handshake"); - if (!read_exact(client->sock, (char *)&unlen, 4)) goto fail; - unlen = Swap32IfLE(unlen); + if (input) { + /* got SSL client hello, can only assume normal SSL */ + if (vencrypt_mode == VENCRYPT_FORCE || anontls_mode == ANONTLS_FORCE) { + rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/ANONTLS_FORCE prevents normal SSL\n"); + return 0; + } + return 1; + } -if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "unlen: %d\n", unlen); + /* send RFB 003.008 -- there is no turning back from this point... */ + if (!write_exact(s_out, proto, strlen(proto))) { + close(s_in); close(s_out); + return 0; + } - if (!read_exact(client->sock, (char *)&pwlen, 4)) goto fail; - pwlen = Swap32IfLE(pwlen); + memset(buf, 0, sizeof(buf)); + if (!read_exact(s_in, buf, 12)) { + close(s_in); close(s_out); + return 0; + } -if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "pwlen: %d\n", pwlen); + if (sscanf(buf, "RFB %03d.%03d\n", &major, &minor) != 2) { + int i; + rfbLog("check_vnc_tls_mode: abnormal handshake: '%s'\nbytes: ", buf); + for (i=0; i < 12; i++) { + fprintf(stderr, "%d.", (unsigned char) buf[i]); + } + fprintf(stderr, "\n"); + close(s_in); close(s_out); + return 0; + } + rfbLog("check_vnc_tls_mode: version: %d.%d\n", major, minor); + if (major != 3 || minor < 8) { + rfbLog("check_vnc_tls_mode: invalid version: '%s'\n", buf); + close(s_in); close(s_out); + return 0; + } - un = (char *) malloc(unlen+1); - memset(un, 0, unlen+1); + n = 1; + if (vencrypt_mode == VENCRYPT_FORCE) { + buf[n++] = rfbSecTypeVencrypt; + } else if (anontls_mode == ANONTLS_FORCE && !ssl_verify) { + buf[n++] = rfbSecTypeAnonTls; + } else if (vencrypt_mode == VENCRYPT_SOLE) { + buf[n++] = rfbSecTypeVencrypt; + } else if (anontls_mode == ANONTLS_SOLE && !ssl_verify) { + buf[n++] = rfbSecTypeAnonTls; + } else { + if (vencrypt_mode == VENCRYPT_SUPPORT) { + buf[n++] = rfbSecTypeVencrypt; + } + if (anontls_mode == ANONTLS_SUPPORT && !ssl_verify) { + buf[n++] = rfbSecTypeAnonTls; + } + } - pw = (char *) malloc(pwlen+2); - memset(pw, 0, pwlen+2); + n--; + buf[0] = (char) n; + if (!write_exact(s_out, buf, n+1)) { + close(s_in); close(s_out); + return 0; + } + if (0) fprintf(stderr, "wrote[%d] %d %d %d\n", n, buf[0], buf[1], buf[2]); - if (!read_exact(client->sock, un, unlen)) goto fail; - if (!read_exact(client->sock, pw, pwlen)) goto fail; + buf[0] = 0; + if (!read_exact(s_in, buf, 1)) { + close(s_in); close(s_out); + return 0; + } -if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "*Plain: %d %d '%s' ... \n", unlen, pwlen, un); - strcat(pw, "\n"); + if (buf[0] == rfbSecTypeVencrypt) stype = "VeNCrypt"; + if (buf[0] == rfbSecTypeAnonTls) stype = "ANONTLS"; - if (unixpw_verify(un, pw)) { - security_result = 0; /* success */ - if (write_exact(client->sock, (char *) &security_result, 4)) { - ret = 1; - unixpw_verify_screen(un, pw); - } - client->onHold = FALSE; - client->state = RFB_INITIALISATION; - } - if (ret == 0) { - rfbClientSendString(client, "unixpw failed"); - } + rfbLog("check_vnc_tls_mode: reply: %d (%s)\n", (int) buf[0], stype); - memset(un, 0, unlen+1); - memset(pw, 0, pwlen+2); - free(un); - free(pw); + ok = 0; + for (i=1; i < n+1; i++) { + if (buf[0] == buf[i]) { + ok = 1; } - } else { - rfbLog("finish_auth: unknown sub-type: %s\n", type); - ret = 0; + } + if (!ok) { + char *msg = "check_vnc_tls_mode: invalid security-type"; + int len = strlen(msg); + rfbLog("%s: %d\n", msg, (int) buf[0]); + ((uint32_t *)buf)[0] = Swap32IfLE(len); + write_exact(s_out, buf, 4); + write_exact(s_out, msg, strlen(msg)); + close(s_in); close(s_out); + return 0; } - fail: - return ret; -} - -static int finish_vencrypt_auth(rfbClientPtr client, int subtype) { + sectype = (int) buf[0]; - if (subtype == rfbVencryptTlsNone || subtype == rfbVencryptX509None) { - return finish_auth(client, "None"); - } else if (subtype == rfbVencryptTlsVnc || subtype == rfbVencryptX509Vnc) { - return finish_auth(client, "Vnc"); - } else if (subtype == rfbVencryptTlsPlain || subtype == rfbVencryptX509Plain) { - return finish_auth(client, "Plain"); + if (sectype == rfbSecTypeVencrypt) { + return vencrypt_dialog(s_in, s_out); + } else if (sectype == rfbSecTypeAnonTls) { + return anontls_dialog(s_in, s_out); } else { - rfbLog("finish_vencrypt_auth: unknown sub-type: %d\n", subtype); return 0; } } +static void pr_ssl_info(int verb) { + SSL_CIPHER *c; + SSL_SESSION *s; + char *proto = "unknown"; -void accept_openssl(int mode, int presock) { - int sock = -1, listen = -1, cport, csock, vsock; - int peerport = 0; - int status, n, i, db = 0; - struct sockaddr_in addr; -#ifdef __hpux - int addrlen = sizeof(addr); -#else - socklen_t addrlen = sizeof(addr); -#endif - rfbClientPtr client; - pid_t pid; - char uniq[] = "_evilrats_"; - char cookie[256], rcookie[256], *name = NULL; - int vencrypt_sel = 0; - int anontls_sel = 0; - static double last_https = 0.0; - static char last_get[256]; - static int first = 1; - unsigned char *rb; - - openssl_last_helper_pid = 0; + if (verb) {} - /* zero buffers for use below. */ - for (i=0; i<256; i++) { - if (first) { - last_get[i] = '\0'; - } - cookie[i] = '\0'; - rcookie[i] = '\0'; + if (ssl == NULL) { + return; } - first = 0; + c = SSL_get_current_cipher(ssl); + s = SSL_get_session(ssl); - if (getenv("ACCEPT_OPENSSL_DEBUG")) { - db = atoi(getenv("ACCEPT_OPENSSL_DEBUG")); + if (s == NULL) { + proto = "nosession"; + } else if (s->ssl_version == SSL2_VERSION) { + proto = "SSLv2"; + } else if (s->ssl_version == SSL3_VERSION) { + proto = "SSLv3"; + } else if (s->ssl_version == TLS1_VERSION) { + proto = "TLSv1"; } + if (c != NULL) { + rfbLog("SSL: ssl_helper[%d]: Cipher: %s %s Proto: %s\n", getpid(), + SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c), proto); + } else { + rfbLog("SSL: ssl_helper[%d]: Proto: %s\n", getpid(), + proto); + } +} - /* do INETD, VNC, or HTTPS cases (result is client socket or pipe) */ - if (mode == OPENSSL_INETD) { - ssl_initialized = 1; +static void ssl_timeout (int sig) { + int i; + rfbLog("sig: %d, ssl_init[%d] timed out.\n", sig, getpid()); + for (i=0; i < 256; i++) { + close(i); + } + exit(1); +} - } else if (mode == OPENSSL_VNC) { - sock = accept(openssl_sock, (struct sockaddr *)&addr, &addrlen); - if (sock < 0) { - rfbLog("SSL: accept_openssl: accept connection failed\n"); - rfbLogPerror("accept"); - if (ssl_no_fail) { - clean_up_exit(1); - } - return; - } - listen = openssl_sock; +static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) { + unsigned char *sid = (unsigned char *) "x11vnc SID"; + char *name = NULL; + int peerport = 0; + int db = 0, rc, err; + int ssock = s_in; + double start = dnow(); + int timeout = 20; - } else if (mode == OPENSSL_REVERSE) { - sock = presock; - if (sock < 0) { - rfbLog("SSL: accept_openssl: connection failed\n"); - if (ssl_no_fail) { - clean_up_exit(1); - } - return; - } - listen = -1; - - } else if (mode == OPENSSL_HTTPS) { - sock = accept(https_sock, (struct sockaddr *)&addr, &addrlen); - if (sock < 0) { - rfbLog("SSL: accept_openssl: accept connection failed\n"); - rfbLogPerror("accept"); - if (ssl_no_fail) { - clean_up_exit(1); - } - return; - } - listen = https_sock; + if (enc_str != NULL) { + return 1; } - if (db) fprintf(stderr, "SSL: accept_openssl: sock: %d\n", sock); - - if (openssl_last_ip) { - free(openssl_last_ip); - openssl_last_ip = NULL; + if (getenv("SSL_DEBUG")) { + db = atoi(getenv("SSL_DEBUG")); } - if (mode == OPENSSL_INETD) { - openssl_last_ip = get_remote_host(fileno(stdin)); - } else { - openssl_last_ip = get_remote_host(sock); + if (getenv("SSL_INIT_TIMEOUT")) { + timeout = atoi(getenv("SSL_INIT_TIMEOUT")); } + if (db) fprintf(stderr, "ssl_init: %d/%d\n", s_in, s_out); - if (!check_ssl_access(openssl_last_ip)) { - rfbLog("SSL: accept_openssl: denying client %s\n", openssl_last_ip); - rfbLog("SSL: accept_openssl: does not match -allow (or other reason).\n"); - close(sock); - sock = -1; - if (ssl_no_fail) { - clean_up_exit(1); - } - return; + if (skip_vnc_tls) { + rfbLog("SSL: ssl_helper[%d]: HTTPS mode, skipping check_vnc_tls_mode()\n", + getpid()); + } else if (!check_vnc_tls_mode(s_in, s_out, last_https)) { + return 0; } - /* now make a listening socket for child to connect back to us by: */ - - cport = find_free_port(20000, 0); - if (! cport) { - rfbLog("SSL: accept_openssl: could not find open port.\n"); - close(sock); - if (mode == OPENSSL_INETD || ssl_no_fail) { - clean_up_exit(1); - } - return; + ssl = SSL_new(ctx); + if (ssl == NULL) { + fprintf(stderr, "SSL_new failed\n"); + return 0; } - if (db) fprintf(stderr, "accept_openssl: cport: %d\n", cport); + if (db > 1) fprintf(stderr, "ssl_init: 1\n"); - csock = rfbListenOnTCPPort(cport, htonl(INADDR_LOOPBACK)); + SSL_set_session_id_context(ssl, sid, strlen((char *)sid)); - if (csock < 0) { - rfbLog("SSL: accept_openssl: could not listen on port %d.\n", - cport); - close(sock); - if (mode == OPENSSL_INETD || ssl_no_fail) { - clean_up_exit(1); + if (s_in == s_out) { + if (! SSL_set_fd(ssl, ssock)) { + fprintf(stderr, "SSL_set_fd failed\n"); + return 0; } - return; - } - if (db) fprintf(stderr, "accept_openssl: csock: %d\n", csock); - - fflush(stderr); - - /* - * make a simple cookie to id the child socket, not foolproof - * but hard to guess exactly (just worrying about local lusers - * here, since we use INADDR_LOOPBACK). - */ - rb = (unsigned char *) calloc(6, 1); - RAND_bytes(rb, 6); - sprintf(cookie, "RB=%d%d%d%d%d%d/%f%f/%p", - rb[0], rb[1], rb[2], rb[3], rb[4], rb[5], - dnow() - x11vnc_start, x11vnc_start, (void *)rb); - - if (mode != OPENSSL_INETD) { - name = get_remote_host(sock); - peerport = get_remote_port(sock); } else { - openssl_last_ip = get_remote_host(fileno(stdin)); - peerport = get_remote_port(fileno(stdin)); - if (openssl_last_ip) { - name = strdup(openssl_last_ip); - } else { - name = strdup("unknown"); + if (! SSL_set_rfd(ssl, s_in)) { + fprintf(stderr, "SSL_set_rfd failed\n"); + return 0; } - } - if (name) { - if (mode == OPENSSL_INETD) { - rfbLog("SSL: (inetd) spawning helper process " - "to handle: %s:%d\n", name, peerport); - } else { - rfbLog("SSL: spawning helper process to handle: " - "%s:%d\n", name, peerport); + if (! SSL_set_wfd(ssl, s_out)) { + fprintf(stderr, "SSL_set_wfd failed\n"); + return 0; } - free(name); - name = NULL; - } - - if (certret) { - free(certret); - } - if (certret_str) { - free(certret_str); - certret_str = NULL; } - certret = strdup("/tmp/x11vnc-certret.XXXXXX"); - omode = umask(077); - certret_fd = mkstemp(certret); - umask(omode); - if (certret_fd < 0) { - free(certret); - certret = NULL; - certret_fd = -1; - } - - if (dhret) { - free(dhret); - } - if (dhret_str) { - free(dhret_str); - dhret_str = NULL; - } - dhret = strdup("/tmp/x11vnc-dhret.XXXXXX"); - omode = umask(077); - dhret_fd = mkstemp(dhret); - umask(omode); - if (dhret_fd < 0) { - free(dhret); - dhret = NULL; - dhret_fd = -1; - } - - /* now fork the child to handle the SSL: */ - pid = fork(); + if (db > 1) fprintf(stderr, "ssl_init: 2\n"); - if (pid > 0) { - rfbLog("SSL: helper for peerport %d is pid %d: \n", - peerport, (int) pid); + if (ssl_client_mode) { + SSL_set_connect_state(ssl); + } else { + SSL_set_accept_state(ssl); } - if (pid < 0) { - rfbLog("SSL: accept_openssl: could not fork.\n"); - rfbLogPerror("fork"); - close(sock); - close(csock); - if (mode == OPENSSL_INETD || ssl_no_fail) { - clean_up_exit(1); - } - return; - - } else if (pid == 0) { - int s_in, s_out, httpsock = -1; - int vncsock; - int i, have_httpd = 0; - int f_in = fileno(stdin); - int f_out = fileno(stdout); - int skip_vnc_tls = mode == OPENSSL_HTTPS ? 1 : 0; + if (db > 1) fprintf(stderr, "ssl_init: 3\n"); - if (db) fprintf(stderr, "helper pid in: %d %d %d %d\n", f_in, f_out, sock, listen); + name = get_remote_host(ssock); + peerport = get_remote_port(ssock); - /* reset all handlers to default (no interrupted() calls) */ - unset_signals(); + if (db > 1) fprintf(stderr, "ssl_init: 4\n"); - /* close all non-essential fd's */ - for (i=0; i<256; i++) { - if (mode == OPENSSL_INETD) { - if (i == f_in || i == f_out) { - continue; - } - } - if (i == sock) { - continue; - } - if (i == 2) { - continue; - } - close(i); - } + while (1) { - /* - * sadly, we are a long lived child and so the large - * framebuffer memory areas will soon differ from parent. - * try to free as much as possible. - */ - lose_ram(); + signal(SIGALRM, ssl_timeout); + alarm(timeout); - /* now connect back to parent socket: */ - vncsock = rfbConnectToTcpAddr("127.0.0.1", cport); - if (vncsock < 0) { - rfbLog("SSL: ssl_helper[%d]: could not connect" - " back to: %d\n", getpid(), cport); - rfbLog("SSL: ssl_helper[%d]: exit case 1 (no local vncsock)\n", getpid()); - exit(1); + if (ssl_client_mode) { + if (db) fprintf(stderr, "calling SSL_connect...\n"); + rc = SSL_connect(ssl); + } else { + if (db) fprintf(stderr, "calling SSL_accept...\n"); + rc = SSL_accept(ssl); } - if (db) fprintf(stderr, "vncsock %d\n", vncsock); + err = SSL_get_error(ssl, rc); - /* try to initialize SSL with the remote client */ + alarm(0); + signal(SIGALRM, SIG_DFL); - if (mode == OPENSSL_INETD) { - s_in = fileno(stdin); - s_out = fileno(stdout); + if (ssl_client_mode) { + if (db) fprintf(stderr, "SSL_connect %d/%d\n", rc, err); } else { - s_in = s_out = sock; + if (db) fprintf(stderr, "SSL_accept %d/%d\n", rc, err); } + if (err == SSL_ERROR_NONE) { + break; + } else if (err == SSL_ERROR_WANT_READ) { - if (! ssl_init(s_in, s_out, skip_vnc_tls, last_https)) { - close(vncsock); - rfbLog("SSL: ssl_helper[%d]: exit case 2 (ssl_init failed)\n", getpid()); - exit(1); - } + if (db) fprintf(stderr, "got SSL_ERROR_WANT_READ\n"); + rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n", + getpid(), name, peerport); + pr_ssl_info(1); + return 0; + + } else if (err == SSL_ERROR_WANT_WRITE) { - if (vencrypt_selected != 0) { - char *tbuf; - tbuf = (char *) malloc(strlen(cookie) + 100); - sprintf(tbuf, "%s,VENCRYPT=%d,%s", uniq, vencrypt_selected, cookie); - write(vncsock, tbuf, strlen(cookie)); - goto wrote_cookie; - } else if (anontls_selected != 0) { - char *tbuf; - tbuf = (char *) malloc(strlen(cookie) + 100); - sprintf(tbuf, "%s,ANONTLS=%d,%s", uniq, anontls_selected, cookie); - write(vncsock, tbuf, strlen(cookie)); - goto wrote_cookie; - } + if (db) fprintf(stderr, "got SSL_ERROR_WANT_WRITE\n"); + rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n", + getpid(), name, peerport); + pr_ssl_info(1); + return 0; - /* - * things get messy below since we are trying to do - * *both* VNC and Java applet httpd through the same - * SSL socket. - */ + } else if (err == SSL_ERROR_SYSCALL) { - if (! screen) { - close(vncsock); - exit(1); - } - if (screen->httpListenSock >= 0 && screen->httpPort > 0) { - have_httpd = 1; - } - if (screen->httpListenSock == -2) { - have_httpd = 1; - } - if (mode == OPENSSL_HTTPS && ! have_httpd) { - rfbLog("SSL: accept_openssl[%d]: no httpd socket for " - "-https mode\n", getpid()); - close(vncsock); - rfbLog("SSL: ssl_helper[%d]: exit case 3 (no httpd sock)\n", getpid()); - exit(1); - } + if (db) fprintf(stderr, "got SSL_ERROR_SYSCALL\n"); + rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n", + getpid(), name, peerport); + pr_ssl_info(1); + return 0; - if (have_httpd) { - int n = 0, is_http = 0; - int hport = screen->httpPort; - char *iface = NULL; - char *buf, *tbuf; + } else if (err == SSL_ERROR_ZERO_RETURN) { - buf = (char *) calloc((ABSIZE+1), 1); - tbuf = (char *) calloc((2*ABSIZE+1), 1); + if (db) fprintf(stderr, "got SSL_ERROR_ZERO_RETURN\n"); + rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n", + getpid(), name, peerport); + pr_ssl_info(1); + return 0; - if (mode == OPENSSL_HTTPS) { - /* - * for this mode we know it is HTTP traffic - * so we skip trying to guess. - */ - is_http = 1; - n = 0; - goto connect_to_httpd; - } + } else if (rc < 0) { + unsigned long err; + int cnt = 0; - /* - * Check if there is stuff to read from remote end - * if so it is likely a GET or HEAD. - */ - if (! is_ssl_readable(s_in, last_https, last_get, - mode)) { - goto write_cookie; + rfbLog("SSL: ssl_helper[%d]: SSL_accept() *FATAL: %d SSL FAILED\n", getpid(), rc); + while ((err = ERR_get_error()) != 0) { + rfbLog("SSL: %s\n", ERR_error_string(err, NULL)); + if (cnt++ > 100) { + break; + } } - - /* - * read first 2 bytes to try to guess. sadly, - * the user is often pondering a "non-verified - * cert" dialog for a long time before the GET - * is ever sent. So often we timeout here. - */ + pr_ssl_info(1); + return 0; - if (db) fprintf(stderr, "watch_for_http_traffic\n"); + } else if (dnow() > start + 3.0) { - is_http = watch_for_http_traffic(buf, &n, s_in); + rfbLog("SSL: ssl_helper[%d]: timeout looping SSL_accept() " + "fatal.\n", getpid()); + pr_ssl_info(1); + return 0; - if (is_http < 0 || is_http == 0) { - /* - * error or http not detected, fall back - * to normal VNC socket. - */ - if (db) fprintf(stderr, "is_http err: %d n: %d\n", is_http, n); - write(vncsock, cookie, strlen(cookie)); - if (n > 0) { - write(vncsock, buf, n); - } - goto wrote_cookie; + } else { + BIO *bio = SSL_get_rbio(ssl); + if (bio == NULL) { + rfbLog("SSL: ssl_helper[%d]: ssl BIO is null. " + "fatal.\n", getpid()); + pr_ssl_info(1); + return 0; } + if (BIO_eof(bio)) { + rfbLog("SSL: ssl_helper[%d]: ssl BIO is EOF. " + "fatal.\n", getpid()); + pr_ssl_info(1); + return 0; + } + } + usleep(10 * 1000); + } - if (db) fprintf(stderr, "is_http: %d n: %d\n", - is_http, n); - if (db) fprintf(stderr, "buf: '%s'\n", buf); - - if (strstr(buf, "/request.https.vnc.connection")) { - char reply[] = "HTTP/1.0 200 OK\r\n" - "Content-Type: octet-stream\r\n" - "Connection: Keep-Alive\r\n" - "Pragma: no-cache\r\n\r\n"; - /* - * special case proxy coming thru https - * instead of a direct SSL connection. - */ - rfbLog("Handling VNC request via https GET. [%d]\n", getpid()); - rfbLog("-- %s\n", buf); + if (ssl_client_mode) { + rfbLog("SSL: ssl_helper[%d]: SSL_connect() succeeded for: %s:%d\n", getpid(), name, peerport); + } else { + rfbLog("SSL: ssl_helper[%d]: SSL_accept() succeeded for: %s:%d\n", getpid(), name, peerport); + } - if (strstr(buf, "/reverse.proxy")) { - char *buf2; - int n, ptr; - SSL_write(ssl, reply, strlen(reply)); - - buf2 = (char *) calloc((8192+1), 1); - n = 0; - ptr = 0; - while (ptr < 8192) { - n = SSL_read(ssl, buf2 + ptr, 1); - if (n > 0) { - ptr += n; - } - if (db) fprintf(stderr, "buf2: '%s'\n", buf2); + pr_ssl_info(0); - if (strstr(buf2, "\r\n\r\n")) { - break; - } - } - free(buf2); + if (SSL_get_verify_result(ssl) == X509_V_OK) { + X509 *x; + FILE *cr = NULL; + if (certret != NULL) { + cr = fopen(certret, "w"); + } + + x = SSL_get_peer_certificate(ssl); + if (x == NULL) { + rfbLog("SSL: ssl_helper[%d]: accepted client %s x509 peer cert is null\n", getpid(), name); + if (cr != NULL) { + fprintf(cr, "NOCERT\n"); + fclose(cr); + } + } else { + rfbLog("SSL: ssl_helper[%d]: accepted client %s x509 cert is:\n", getpid(), name); +#if LIBVNCSERVER_HAVE_X509_PRINT_EX_FP + X509_print_ex_fp(stderr, x, 0, XN_FLAG_MULTILINE); +#endif + if (cr != NULL) { +#if LIBVNCSERVER_HAVE_X509_PRINT_EX_FP + X509_print_ex_fp(cr, x, 0, XN_FLAG_MULTILINE); +#else + rfbLog("** not compiled with libssl X509_print_ex_fp() function **\n"); + if (users_list && strstr(users_list, "sslpeer=")) { + rfbLog("** -users sslpeer= will not work! **\n"); } - goto write_cookie; +#endif + fclose(cr); + } + } + } + free(name); - } else if (strstr(buf, "/check.https.proxy.connection")) { - char reply[] = "HTTP/1.0 200 OK\r\n" - "Connection: close\r\n" - "Content-Type: octet-stream\r\n" - "Pragma: no-cache\r\n\r\n"; + return 1; +} - rfbLog("Handling Check HTTPS request via https GET. [%d]\n", getpid()); - rfbLog("-- %s\n", buf); +static void symmetric_encryption_xfer(int csock, int s_in, int s_out); - SSL_write(ssl, reply, strlen(reply)); - SSL_shutdown(ssl); +static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { + int dbxfer = 0, db = 0, check_pending, fdmax, nfd, n, i, err; + char cbuf[ABSIZE], sbuf[ABSIZE]; + int cptr, sptr, c_rd, c_wr, s_rd, s_wr; + fd_set rd, wr; + struct timeval tv; + int ssock, cnt = 0, ndata = 0; - strcpy(tbuf, uniq); - strcat(tbuf, cookie); - write(vncsock, tbuf, strlen(tbuf)); - close(vncsock); + /* + * we want to switch to a longer timeout for long term VNC + * connections (in case the network is not working for periods of + * time), but we also want the timeout shorter at the beginning + * in case the client went away. + */ + double start, now; + int tv_https_early = 60; + int tv_https_later = 20; + int tv_vnc_early = 40; + int tv_vnc_later = 43200; /* was 300, stunnel: 43200 */ + int tv_cutover = 70; + int tv_closing = 60; + int tv_use; - rfbLog("SSL: ssl_helper[%d]: exit case 4 (check.https.proxy.connection)\n", getpid()); - exit(0); - } - connect_to_httpd: + if (dbxfer) { + raw_xfer(csock, s_in, s_out); + return; + } + if (enc_str != NULL) { + if (!strcmp(enc_str, "none")) { + usleep(250*1000); + rfbLog("doing '-enc none' raw transfer (no encryption)\n"); + raw_xfer(csock, s_in, s_out); + } else { + symmetric_encryption_xfer(csock, s_in, s_out); + } + return; + } - /* - * Here we go... no turning back. we have to - * send failure to parent and close socket to have - * http processed at all in a timely fashion... - */ + if (getenv("SSL_DEBUG")) { + db = atoi(getenv("SSL_DEBUG")); + } - /* send the failure tag: */ - strcpy(tbuf, uniq); + if (db) fprintf(stderr, "ssl_xfer begin\n"); - if (https_port_redir < 0 || (strstr(buf, "PORT=") || strstr(buf, "port="))) { - char *q = strstr(buf, "Host:"); - int fport = 443, match = 0; - char num[16]; + start = dnow(); + if (is_https) { + tv_use = tv_https_early; + } else { + tv_use = tv_vnc_early; + } + - if (q && strstr(q, "\n")) { - q += strlen("Host:") + 1; - while (*q != '\n') { - int p; - if (*q == ':' && sscanf(q, ":%d", &p) == 1) { - if (p > 0 && p < 65536) { - fport = p; - match = 1; - break; - } - } - q++; - } - } - if (!match || !https_port_redir) { - int p; - if (sscanf(buf, "PORT=%d,", &p) == 1) { - if (p > 0 && p < 65536) { - fport = p; - } - } else if (sscanf(buf, "port=%d,", &p) == 1) { - if (p > 0 && p < 65536) { - fport = p; - } - } - } - sprintf(num, "HP=%d,", fport); - strcat(tbuf, num); - } + /* + * csock: clear text socket with libvncserver. "C" + * ssock: ssl data socket with remote vnc viewer. "S" + * + * to cover inetd mode, we have s_in and s_out, but in non-inetd + * mode they both ssock. + * + * cbuf[] is data from csock that we have read but not passed on to ssl + * sbuf[] is data from ssl that we have read but not passed on to csock + */ + for (i=0; i s_in) { + ssock = s_out; + } else { + ssock = s_in; + } - if (strstr(buf, "HTTP/") != NULL) { - char *q, *str; - /* - * Also send back the GET line for heuristics. - * (last_https, get file). - */ - str = strdup(buf); - q = strstr(str, "HTTP/"); - if (q != NULL) { - *q = '\0'; - strcat(tbuf, str); - } - free(str); - } + if (csock > ssock) { + fdmax = csock; + } else { + fdmax = ssock; + } - /* - * Also send the cookie to pad out the number of - * bytes to more than the parent wants to read. - * Since this is the failure case, it does not - * matter that we send more than strlen(cookie). + c_rd = 1; /* clear text (libvncserver) socket open for reading */ + c_wr = 1; /* clear text (libvncserver) socket open for writing */ + s_rd = 1; /* ssl data (remote client) socket open for reading */ + s_wr = 1; /* ssl data (remote client) socket open for writing */ + + cptr = 0; /* offsets into ABSIZE buffers */ + sptr = 0; + + if (vencrypt_selected > 0 || anontls_selected > 0) { + char tmp[16]; + /* read and discard the extra RFB version */ + memset(tmp, 0, sizeof(tmp)); + read(csock, tmp, 12); + if (0) fprintf(stderr, "extra: %s\n", tmp); + } + + while (1) { + int c_to_s, s_to_c, closing; + + if ( s_wr && (c_rd || cptr > 0) ) { + /* + * S is writable and + * C is readable or some cbuf data remaining */ - strcat(tbuf, cookie); - write(vncsock, tbuf, strlen(tbuf)); + c_to_s = 1; + } else { + c_to_s = 0; + } - usleep(150*1000); - if (db) fprintf(stderr, "close vncsock: %d\n", vncsock); - close(vncsock); + if ( c_wr && (s_rd || sptr > 0) ) { + /* + * C is writable and + * S is readable or some sbuf data remaining + */ + s_to_c = 1; + } else { + s_to_c = 0; + } - /* now, finally, connect to the libvncserver httpd: */ - if (screen->listenInterface == htonl(INADDR_ANY) || - screen->listenInterface == htonl(INADDR_NONE)) { - iface = "127.0.0.1"; - } else { - struct in_addr in; - in.s_addr = screen->listenInterface; - iface = inet_ntoa(in); - } - if (iface == NULL || !strcmp(iface, "")) { - iface = "127.0.0.1"; - } - if (db) fprintf(stderr, "iface: %s:%d\n", iface, hport); - usleep(150*1000); + if (! c_to_s && ! s_to_c) { + /* + * nothing can be sent either direction. + * break out of the loop to finish all work. + */ + break; + } + cnt++; - httpsock = rfbConnectToTcpAddr(iface, hport); + /* set up the fd sets for the two sockets for read & write: */ - if (httpsock < 0) { - /* UGH, after all of that! */ - rfbLog("Could not connect to httpd socket!\n"); - rfbLog("SSL: ssl_helper[%d]: exit case 5.\n", getpid()); - exit(1); + FD_ZERO(&rd); + + if (c_rd && cptr < ABSIZE) { + /* we could read more from C since cbuf is not full */ + FD_SET(csock, &rd); + } + if (s_rd) { + /* + * we could read more from S since sbuf not full, + * OR ssl is waiting for more BIO to be able to + * read and we have some C data still buffered. + */ + if (sptr < ABSIZE || (cptr > 0 && SSL_want_read(ssl))) { + FD_SET(s_in, &rd); } - if (db) fprintf(stderr, "ssl_helper[%d]: httpsock: %d %d\n", - getpid(), httpsock, n); + } + + FD_ZERO(&wr); + if (c_wr && sptr > 0) { + /* we could write more to C since sbuf is not empty */ + FD_SET(csock, &wr); + } + if (s_wr) { /* - * send what we read to httpd, and then connect - * the rest of the SSL session to it: + * we could write more to S since cbuf not empty, + * OR ssl is waiting for more BIO to be able + * write and we haven't filled up sbuf yet. */ - if (n > 0) { - if (db) fprintf(stderr, "sending http buffer httpsock: %d\n'%s'\n", httpsock, buf); - write(httpsock, buf, n); + if (cptr > 0 || (sptr < ABSIZE && SSL_want_write(ssl))) { + FD_SET(s_out, &wr); } - ssl_xfer(httpsock, s_in, s_out, is_http); - rfbLog("SSL: ssl_helper[%d]: exit case 6 (https ssl_xfer done)\n", getpid()); - exit(0); } - /* - * ok, back from the above https mess, simply send the - * cookie back to the parent (who will attach us to - * libvncserver), and connect the rest of the SSL session - * to it. - */ - write_cookie: - write(vncsock, cookie, strlen(cookie)); + now = dnow(); + if (tv_cutover && now > start + tv_cutover) { + rfbLog("SSL: ssl_xfer[%d]: tv_cutover: %d\n", getpid(), + tv_cutover); + tv_cutover = 0; + if (is_https) { + tv_use = tv_https_later; + } else { + tv_use = tv_vnc_later; + } + /* try to clean out some zombies if we can. */ + ssl_helper_pid(0, -2); + } + if (ssl_timeout_secs > 0) { + tv_use = ssl_timeout_secs; + } - wrote_cookie: - ssl_xfer(vncsock, s_in, s_out, 0); + if ( (s_rd && c_rd) || cptr || sptr) { + closing = 0; + } else { + closing = 1; + tv_use = tv_closing; + } - rfbLog("SSL: ssl_helper[%d]: exit case 7 (ssl_xfer done)\n", getpid()); - exit(0); - } - /* parent here */ + tv.tv_sec = tv_use; + tv.tv_usec = 0; - if (mode != OPENSSL_INETD) { - close(sock); - } - if (db) fprintf(stderr, "helper process is: %d\n", pid); + /* do the select, repeat if interrupted */ + do { + if (ssl_timeout_secs == 0) { + nfd = select(fdmax+1, &rd, &wr, NULL, NULL); + } else { + nfd = select(fdmax+1, &rd, &wr, NULL, &tv); + } + } while (nfd < 0 && errno == EINTR); - /* accept connection from our child. */ - signal(SIGALRM, csock_timeout); - csock_timeout_sock = csock; - alarm(20); + if (db > 1) fprintf(stderr, "nfd: %d\n", nfd); - vsock = accept(csock, (struct sockaddr *)&addr, &addrlen); +if (0) fprintf(stderr, "nfd[%d]: %d w/r csock: %d %d s_in: %d %d\n", getpid(), nfd, FD_ISSET(csock, &wr), FD_ISSET(csock, &rd), FD_ISSET(s_out, &wr), FD_ISSET(s_in, &rd)); - alarm(0); - signal(SIGALRM, SIG_DFL); - close(csock); + if (nfd < 0) { + rfbLog("SSL: ssl_xfer[%d]: select error: %d\n", getpid(), nfd); + perror("select"); + /* connection finished */ + goto done; + } + if (nfd == 0) { + if (!closing && tv_cutover && ndata > 25000) { + static int cn = 0; + /* probably ok, early windows iconify */ + if (cn++ < 2) { + rfbLog("SSL: ssl_xfer[%d]: early time" + "out: %d\n", getpid(), ndata); + } + continue; + } + rfbLog("SSL: ssl_xfer[%d]: connection timedout. %d tv_use: %d\n", + getpid(), ndata, tv_use); + /* connection finished */ + goto done; + } - if (vsock < 0) { - rfbLog("SSL: accept_openssl: connection from ssl_helper[%d] FAILED.\n", pid); - rfbLogPerror("accept"); + /* used to see if SSL_pending() should be checked: */ + check_pending = 0; +/* AUDIT */ - kill(pid, SIGTERM); - waitpid(pid, &status, WNOHANG); - if (mode == OPENSSL_INETD || ssl_no_fail) { - clean_up_exit(1); - } - if (certret_fd >= 0) { - close(certret_fd); - certret_fd = -1; - } - if (certret) { - unlink(certret); - } - if (dhret_fd >= 0) { - close(dhret_fd); - dhret_fd = -1; - } - if (dhret) { - unlink(dhret); - } - return; - } - if (db) fprintf(stderr, "accept_openssl: vsock: %d\n", vsock); + if (c_wr && FD_ISSET(csock, &wr)) { - n = read(vsock, rcookie, strlen(cookie)); - if (n < 0 && errno != 0) { - rfbLogPerror("read"); - } + /* try to write some of our sbuf to C: */ + n = write(csock, sbuf, sptr); - if (certret) { - struct stat sbuf; - sbuf.st_size = 0; - if (certret_fd >= 0 && stat(certret, &sbuf) == 0 && sbuf.st_size > 0) { - certret_str = (char *) calloc(sbuf.st_size+1, 1); - read(certret_fd, certret_str, sbuf.st_size); - close(certret_fd); - certret_fd = -1; - } - if (certret_fd >= 0) { - close(certret_fd); - certret_fd = -1; - } - unlink(certret); - if (certret_str && strstr(certret_str, "NOCERT") == certret_str) { - free(certret_str); - certret_str = NULL; - } - if (0 && certret_str) { - fprintf(stderr, "certret_str[%d]:\n%s\n", (int) sbuf.st_size, certret_str); - } - } + if (n < 0) { + if (errno != EINTR) { + /* connection finished */ + goto done; + } + /* proceed */ + } else if (n == 0) { + /* connection finished XXX double check */ + goto done; + } else { + /* shift over the data in sbuf by n */ + memmove(sbuf, sbuf + n, sptr - n); + if (sptr == ABSIZE) { + check_pending = 1; + } + sptr -= n; - if (dhret) { - struct stat sbuf; - sbuf.st_size = 0; - if (dhret_fd >= 0 && stat(dhret, &sbuf) == 0 && sbuf.st_size > 0) { - dhret_str = (char *) calloc(sbuf.st_size+1, 1); - read(dhret_fd, dhret_str, sbuf.st_size); - close(dhret_fd); - dhret_fd = -1; - } - if (dhret_fd >= 0) { - close(dhret_fd); - dhret_fd = -1; - } - unlink(dhret); - if (dhret_str && strstr(dhret_str, "NOCERT") == dhret_str) { - free(dhret_str); - dhret_str = NULL; - } - if (dhret_str) { - if (new_dh_params == NULL) { - fprintf(stderr, "dhret_str[%d]:\n%s\n", (int) sbuf.st_size, dhret_str); - new_dh_params = strdup(dhret_str); + if (! s_rd && sptr == 0) { + /* finished sending last of sbuf */ + shutdown(csock, SHUT_WR); + c_wr = 0; + } + ndata += n; } } - } - if (0) { - fprintf(stderr, "rcookie: %s\n", rcookie); - fprintf(stderr, "cookie: %s\n", cookie); - } + if (s_wr) { + if ((cptr > 0 && FD_ISSET(s_out, &wr)) || + (SSL_want_read(ssl) && FD_ISSET(s_in, &rd))) { - if (strstr(rcookie, uniq) == rcookie) { - char *q = strstr(rcookie, "RB="); - if (q && strstr(cookie, q) == cookie) { - vencrypt_sel = 0; - anontls_sel = 0; - q = strstr(rcookie, "VENCRYPT="); - if (q && sscanf(q, "VENCRYPT=%d,", &vencrypt_sel) == 1) { - if (vencrypt_sel != 0) { - rfbLog("SSL: VENCRYPT mode=%d accepted.\n", vencrypt_sel); - goto accept_client; - } - } - q = strstr(rcookie, "ANONTLS="); - if (q && sscanf(q, "ANONTLS=%d,", &anontls_sel) == 1) { - if (anontls_sel != 0) { - rfbLog("SSL: ANONTLS mode=%d accepted.\n", anontls_sel); - goto accept_client; + /* try to write some of our cbuf to S: */ + + n = SSL_write(ssl, cbuf, cptr); + err = SSL_get_error(ssl, n); + + if (err == SSL_ERROR_NONE) { + /* shift over the data in cbuf by n */ + memmove(cbuf, cbuf + n, cptr - n); + cptr -= n; + + if (! c_rd && cptr == 0 && s_wr) { + /* finished sending last cbuf */ + SSL_shutdown(ssl); + s_wr = 0; + } + ndata += n; + + } else if (err == SSL_ERROR_WANT_WRITE + || err == SSL_ERROR_WANT_READ + || err == SSL_ERROR_WANT_X509_LOOKUP) { + + ; /* proceed */ + + } else if (err == SSL_ERROR_SYSCALL) { + if (n < 0 && errno != EINTR) { + /* connection finished */ + goto done; + } + /* proceed */ + } else if (err == SSL_ERROR_ZERO_RETURN) { + /* S finished */ + s_rd = 0; + s_wr = 0; + } else if (err == SSL_ERROR_SSL) { + /* connection finished */ + goto done; } } } - } - if (n != (int) strlen(cookie) || strncmp(cookie, rcookie, n)) { - rfbLog("SSL: accept_openssl: cookie from ssl_helper[%d] FAILED. %d\n", pid, n); - if (db) fprintf(stderr, "'%s'\n'%s'\n", cookie, rcookie); - close(vsock); + if (c_rd && FD_ISSET(csock, &rd)) { - if (strstr(rcookie, uniq) == rcookie) { - int i; - rfbLog("SSL: BUT WAIT! HTTPS for helper process[%d] succeeded. Good.\n", pid); - if (mode != OPENSSL_HTTPS) { - last_https = dnow(); - for (i=0; i<256; i++) { - last_get[i] = '\0'; - } - strncpy(last_get, rcookie, 100); - if (db) fprintf(stderr, "last_get: '%s'\n", last_get); - } - if (rcookie && strstr(rcookie, "VncViewer.class")) { - rfbLog("\n"); - rfbLog("***********************************************************\n"); - rfbLog("SSL: WARNING CLIENT ASKED FOR NONEXISTENT 'VncViewer.class'\n"); - rfbLog("SSL: USER NEEDS TO **RESTART** HIS WEB BROWSER.\n"); - rfbLog("***********************************************************\n"); - rfbLog("\n"); - } - ssl_helper_pid(pid, -2); - if (https_port_redir) { - double start; - int origport = screen->port; - int useport = screen->port; - int saw_httpsock = 0; - /* to expand $PORT correctly in index.vnc */ - if (https_port_redir < 0) { - char *q = strstr(rcookie, "HP="); - if (q) { - int p; - if (sscanf(q, "HP=%d,", &p) == 1) { - useport = p; - } - } - } else { - useport = https_port_redir; - } - screen->port = useport; - if (origport != useport) { - rfbLog("SSL: -httpsredir guess port: %d\n", screen->port); - } + /* try to read some data from C into our cbuf */ - start = dnow(); - while (dnow() < start + 10.0) { - if (screen->httpSock >= 0) saw_httpsock = 1; - rfbPE(10000); - usleep(10000); - if (screen->httpSock >= 0) saw_httpsock = 1; - waitpid(pid, &status, WNOHANG); - if (kill(pid, 0) != 0) { - rfbPE(10000); - rfbPE(10000); - break; - } - if (saw_httpsock && screen->httpSock < 0) { - rfbLog("SSL: httpSock for helper[%d] went away\n", pid); - rfbPE(10000); - rfbPE(10000); - break; - } + n = read(csock, cbuf + cptr, ABSIZE - cptr); + + if (n < 0) { + if (errno != EINTR) { + /* connection finished */ + goto done; } - screen->port = origport; - rfbLog("SSL: guessing child helper[%d] https finished. dt=%.6f\n", - pid, dnow() - start); - ssl_helper_pid(0, -2); - if (mode == OPENSSL_INETD) { - clean_up_exit(1); + /* proceed */ + } else if (n == 0) { + /* C is EOF */ + c_rd = 0; + if (cptr == 0 && s_wr) { + /* and no more in cbuf to send */ + SSL_shutdown(ssl); + s_wr = 0; } - } else if (mode == OPENSSL_INETD) { - double start; - int saw_httpsock = 0; + } else { + /* good */ - /* to expand $PORT correctly in index.vnc */ - if (screen->port == 0) { - int fd = fileno(stdin); - if (getenv("X11VNC_INETD_PORT")) { - screen->port = atoi(getenv( - "X11VNC_INETD_PORT")); - } else { - int tport = get_local_port(fd); - if (tport > 0) { - screen->port = tport; + cptr += n; + ndata += n; + } + } + + if (s_rd) { + if ((sptr < ABSIZE && FD_ISSET(s_in, &rd)) || + (SSL_want_write(ssl) && FD_ISSET(s_out, &wr)) || + (check_pending && SSL_pending(ssl))) { + + /* try to read some data from S into our sbuf */ + + n = SSL_read(ssl, sbuf + sptr, ABSIZE - sptr); + err = SSL_get_error(ssl, n); + + if (err == SSL_ERROR_NONE) { + /* good */ + + sptr += n; + ndata += n; + + } else if (err == SSL_ERROR_WANT_WRITE + || err == SSL_ERROR_WANT_READ + || err == SSL_ERROR_WANT_X509_LOOKUP) { + + ; /* proceed */ + + } else if (err == SSL_ERROR_SYSCALL) { + if (n < 0) { + if(errno != EINTR) { + /* connection finished */ + goto done; } + /* proceed */ + } else { + /* S finished */ + s_rd = 0; + s_wr = 0; } - } - rfbLog("SSL: screen->port %d\n", screen->port); - - /* kludge for https fetch via inetd */ - start = dnow(); - while (dnow() < start + 10.0) { - if (screen->httpSock >= 0) saw_httpsock = 1; - rfbPE(10000); - usleep(10000); - if (screen->httpSock >= 0) saw_httpsock = 1; - waitpid(pid, &status, WNOHANG); - if (kill(pid, 0) != 0) { - rfbPE(10000); - rfbPE(10000); - break; + } else if (err == SSL_ERROR_ZERO_RETURN) { + /* S is EOF */ + s_rd = 0; + if (cptr == 0 && s_wr) { + /* and no more in cbuf to send */ + SSL_shutdown(ssl); + s_wr = 0; } - if (saw_httpsock && screen->httpSock < 0) { - rfbLog("SSL: httpSock for helper[%d] went away\n", pid); - rfbPE(10000); - rfbPE(10000); - break; + if (sptr == 0 && c_wr) { + /* and no more in sbuf to send */ + shutdown(csock, SHUT_WR); + c_wr = 0; } + } else if (err == SSL_ERROR_SSL) { + /* connection finished */ + goto done; } - rfbLog("SSL: OPENSSL_INETD guessing " - "child helper[%d] https finished. dt=%.6f\n", - pid, dnow() - start); - ssl_helper_pid(0, -2); - clean_up_exit(1); } - /* this will actually only get earlier https */ - ssl_helper_pid(0, -2); - return; } - kill(pid, SIGTERM); - waitpid(pid, &status, WNOHANG); - if (mode == OPENSSL_INETD || ssl_no_fail) { - clean_up_exit(1); - } - return; } - accept_client: + done: + rfbLog("SSL: ssl_xfer[%d]: closing sockets %d, %d, %d\n", + getpid(), csock, s_in, s_out); + close(csock); + close(s_in); + close(s_out); + return; +} + +#define MSZ 4096 +static void init_prng(void) { + int db = 0, bytes, ubytes, fd; + char file[MSZ], dtmp[100]; + unsigned int sr; + + RAND_file_name(file, MSZ); + + rfbLog("RAND_file_name: %s\n", file); + + bytes = RAND_load_file(file, -1); + if (db) fprintf(stderr, "bytes read: %d\n", bytes); + + ubytes = RAND_load_file("/dev/urandom", 64); + bytes += ubytes; + if (db) fprintf(stderr, "bytes read: %d / %d\n", bytes, ubytes); + + /* mix in more predictable stuff as well for fallback */ + sprintf(dtmp, "/tmp/p%.8f.XXXXXX", dnow()); + fd = mkstemp(dtmp); + RAND_add(dtmp, strlen(dtmp), 0); + if (fd >= 0) { + close(fd); + unlink(dtmp); + } + sprintf(dtmp, "%d-%.8f", (int) getpid(), dnow()); + RAND_add(dtmp, strlen(dtmp), 0); + + if (!RAND_status()) { + ubytes = -1; + rfbLog("calling RAND_poll()\n"); + RAND_poll(); + } + + RAND_bytes((unsigned char *)&sr, 4); + srand(sr); + + if (bytes > 0) { + if (! quiet) { + rfbLog("initialized PRNG with %d random bytes.\n", + bytes); + } + if (ubytes > 32 && rnow() < 0.25) { + RAND_write_file(file); + } + return; + } - if (db) fprintf(stderr, "accept_openssl: cookie good: %s\n", cookie); + bytes += RAND_load_file("/dev/random", 8); + if (db) fprintf(stderr, "bytes read: %d\n", bytes); + RAND_poll(); - rfbLog("SSL: handshake with helper process[%d] succeeded.\n", pid); + if (! quiet) { + rfbLog("initialized PRNG with %d random bytes.\n", bytes); + } +} +#endif /* FORK_OK */ +#endif /* LIBVNCSERVER_HAVE_LIBSSL */ - openssl_last_helper_pid = pid; - ssl_helper_pid(pid, vsock); +void check_openssl(void) { + fd_set fds; + struct timeval tv; + int nfds; + static time_t last_waitall = 0; + static double last_check = 0.0; + double now; - if (vnc_redirect) { - vnc_redirect_sock = vsock; - openssl_last_helper_pid = 0; + if (! use_openssl) { return; } - client = create_new_client(vsock, 0); - openssl_last_helper_pid = 0; - - if (client) { - if (db) fprintf(stderr, "accept_openssl: client %p\n", (void *) client); - if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) screen->newClientHook); - if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) new_client); - if (mode == OPENSSL_INETD) { - inetd_client = client; - client->clientGoneHook = client_gone; - } - if (openssl_last_ip && - strpbrk(openssl_last_ip, "0123456789") == openssl_last_ip) { - client->host = strdup(openssl_last_ip); - } - if (vencrypt_sel != 0) { - client->protocolMajorVersion = 3; - client->protocolMinorVersion = 8; - if (!finish_vencrypt_auth(client, vencrypt_sel)) { - rfbCloseClient(client); - client = NULL; - } - } else if (anontls_sel != 0) { - client->protocolMajorVersion = 3; - client->protocolMinorVersion = 8; - rfbAuthNewClient(client); - } - if (use_threads && client != NULL) { - rfbStartOnHoldClient(client); - } - /* try to get RFB proto done now. */ - progress_client(); - } else { - rfbLog("SSL: accept_openssl: rfbNewClient failed.\n"); - close(vsock); + if (time(NULL) > last_waitall + 120) { + last_waitall = time(NULL); + ssl_helper_pid(0, -2); /* waitall */ + } - kill(pid, SIGTERM); - waitpid(pid, &status, WNOHANG); - if (mode == OPENSSL_INETD || ssl_no_fail) { - clean_up_exit(1); - } + if (openssl_sock < 0) { return; } -} -static int read_exact(int sock, char *buf, int len) { - int n, fail = 0; - if (sock < 0) { - return 0; - } - while (len > 0) { - n = read(sock, buf, len); - if (n > 0) { - buf += n; - len -= n; - } else if (n == 0) { - fail = 1; - break; - } else if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { - usleep(10*1000); - } else if (n < 0 && errno != EINTR) { - fail = 1; - break; - } - } - if (fail) { - return 0; - } else { - return 1; + now = dnow(); + if (now < last_check + 0.5) { + return; } -} + last_check = now; -static int write_exact(int sock, char *buf, int len) { - int n, fail = 0; - if (sock < 0) { - return 0; - } - while (len > 0) { - n = write(sock, buf, len); - if (n > 0) { - buf += n; - len -= n; - } else if (n == 0) { - fail = 1; - break; - } else if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { - usleep(10*1000); - } else if (n < 0 && errno != EINTR) { - fail = 1; - break; - } - } - if (fail) { - return 0; - } else { - return 1; + FD_ZERO(&fds); + FD_SET(openssl_sock, &fds); + + tv.tv_sec = 0; + tv.tv_usec = 0; + + nfds = select(openssl_sock+1, &fds, NULL, NULL, &tv); + + if (nfds <= 0) { + return; } + + rfbLog("SSL: accept_openssl(OPENSSL_VNC)\n"); + accept_openssl(OPENSSL_VNC, -1); } -static int add_anon_dh(void) { - pid_t pid, pidw; - char cnf[] = "/tmp/x11vnc-dh.XXXXXX"; - char *infile = NULL; - int status, cnf_fd; - DH *dh; - BIO *bio; - FILE *in; - double ds; - /* - * These are dh parameters (prime, generator), not dh keys. - * Evidently it is ok for them to be publicly known. - * openssl dhparam -out dh.out 1024 - */ - char *fixed_dh_params = -"-----BEGIN DH PARAMETERS-----\n" -"MIGHAoGBAL28w69ZnLYBvp8R2OeqtAIms+oatY19iBL4WhGI/7H1OMmkJjIe+OHs\n" -"PXoJfe5ucrnvno7Xm+HJZYa1jnPGQuWoa/VJKXdVjYdJVNzazJKM2daKKcQA4GDc\n" -"msFS5DxLbzUR5jy1n12K3EcbvpyFqDYVTJJXm7NuNuiWRfz3wTozAgEC\n" -"-----END DH PARAMETERS-----\n"; +void check_https(void) { + fd_set fds; + struct timeval tv; + int nfds; + static double last_check = 0.0; + double now; - if (dhparams_file != NULL) { - infile = dhparams_file; - rfbLog("add_anon_dh: using %s\n", dhparams_file); - goto readin; + if (! use_openssl || https_sock < 0) { + return; } - cnf_fd = mkstemp(cnf); - if (cnf_fd < 0) { - return 0; + now = dnow(); + if (now < last_check + 0.5) { + return; } - infile = cnf; + last_check = now; - if (create_fresh_dhparams) { + FD_ZERO(&fds); + FD_SET(https_sock, &fds); - if (new_dh_params != NULL) { - write(cnf_fd, new_dh_params, strlen(new_dh_params)); - close(cnf_fd); - } else { - char *exe = find_openssl_bin(); - struct stat sbuf; + tv.tv_sec = 0; + tv.tv_usec = 0; - if (no_external_cmds || !cmd_ok("ssl")) { - rfbLog("add_anon_dh: cannot run external commands.\n"); - return 0; - } + nfds = select(https_sock+1, &fds, NULL, NULL, &tv); - close(cnf_fd); - if (exe == NULL) { - return 0; - } - ds = dnow(); - pid = fork(); - if (pid < 0) { - return 0; - } else if (pid == 0) { - int i; - for (i=0; i<256; i++) { - if (i == 2) continue; - close(i); - } - /* rather slow at 1024 */ - execlp(exe, exe, "dhparam", "-out", cnf, "1024", (char *)0); - exit(1); - } - pidw = waitpid(pid, &status, 0); - if (pidw != pid) { - return 0; - } - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - ; - } else { - return 0; - } - rfbLog("add_anon_dh: created new DH params in %.3f secs\n", dnow() - ds); + if (nfds <= 0) { + return; + } + rfbLog("SSL: accept_openssl(OPENSSL_HTTPS)\n"); + accept_openssl(OPENSSL_HTTPS, -1); +} - if (stat(cnf, &sbuf) == 0 && sbuf.st_size > 0) { - /* save it to reuse during our process's lifetime: */ - int d = open(cnf, O_RDONLY); - if (d >= 0) { - int n, len = sbuf.st_size; - new_dh_params = (char *) calloc(len+1, 1); - n = read(d, new_dh_params, len); - close(d); - if (n != len) { - free(new_dh_params); - new_dh_params = NULL; - } else if (dhret != NULL) { - d = open(dhret, O_WRONLY); - if (d >= 0) { - write(d, new_dh_params, strlen(new_dh_params)); - close(d); - } - } - } - } - } - } else { - write(cnf_fd, fixed_dh_params, strlen(fixed_dh_params)); - close(cnf_fd); +void openssl_port(void) { + int sock, shutdown = 0; + static int port = 0; + static in_addr_t iface = INADDR_ANY; + int db = 0; + + if (! screen) { + rfbLog("openssl_port: no screen!\n"); + clean_up_exit(1); + } + if (inetd) { + ssl_initialized = 1; + return; } - readin: + if (screen->listenSock > -1 && screen->port > 0) { + port = screen->port; + shutdown = 1; + } + if (screen->listenInterface) { + iface = screen->listenInterface; + } - ds = dnow(); - in = fopen(infile, "r"); + if (shutdown) { + if (db) fprintf(stderr, "shutting down %d/%d\n", + port, screen->listenSock); +#if LIBVNCSERVER_HAS_SHUTDOWNSOCKETS + rfbShutdownSockets(screen); +#endif + } - if (in == NULL) { - rfbLogPerror("fopen"); - unlink(cnf); - return 0; + if (port <= 0) { + rfbLog("openssl_port: could not obtain listening port %d\n", port); + clean_up_exit(1); } - bio = BIO_new_fp(in, BIO_CLOSE|BIO_FP_TEXT); - if (! bio) { - rfbLog("openssl_init: BIO_new_fp() failed.\n"); - unlink(cnf); - return 0; + sock = rfbListenOnTCPPort(port, iface); + if (sock < 0) { + rfbLog("openssl_port: could not reopen port %d\n", port); + clean_up_exit(1); } - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - if (dh == NULL) { - rfbLog("openssl_init: PEM_read_bio_DHparams() failed.\n"); - unlink(cnf); - BIO_free(bio); - return 0; + rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock); + if (!quiet) { + announce(port, 1, NULL); } - BIO_free(bio); - SSL_CTX_set_tmp_dh(ctx, dh); - rfbLog("loaded Diffie Hellman %d bits, %.3fs\n", 8*DH_size(dh), dnow()-ds); - DH_free(dh); + openssl_sock = sock; + openssl_port_num = port; - unlink(cnf); - return 1; + ssl_initialized = 1; } -static int switch_to_anon_dh(void) { - long mode; - - rfbLog("Using Anonymous Diffie-Hellman mode.\n"); - rfbLog("WARNING: Anonymous Diffie-Hellman uses encryption but is\n"); - rfbLog("WARNING: susceptible to a Man-In-The-Middle attack.\n"); - if (ssl_client_mode) { - ctx = SSL_CTX_new( SSLv23_client_method() ); - } else { - ctx = SSL_CTX_new( SSLv23_server_method() ); +void https_port(void) { + int sock; + static int port = 0; + static in_addr_t iface = INADDR_ANY; + int db = 0; + + /* as openssl_port above: open a listening socket for pure https: */ + if (https_port_num < 0) { + return; } - if (ctx == NULL) { - return 0; + if (! screen) { + rfbLog("https_port: no screen!\n"); + clean_up_exit(1); } - if (ssl_client_mode) { - return 1; + if (screen->listenInterface) { + iface = screen->listenInterface; } - if (!SSL_CTX_set_cipher_list(ctx, "ADH:@STRENGTH")) { - return 0; + + if (https_port_num == 0) { + https_port_num = find_free_port(5801, 5851); } - if (!add_anon_dh()) { - return 0; + if (https_port_num <= 0) { + rfbLog("https_port: could not find port %d\n", https_port_num); + clean_up_exit(1); } + port = https_port_num; - mode = 0; - mode |= SSL_MODE_ENABLE_PARTIAL_WRITE; - mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; - SSL_CTX_set_mode(ctx, mode); - - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); - SSL_CTX_set_timeout(ctx, 300); - SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_callback); - SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); - - return 1; -} - -static int anontls_dialog(int s_in, int s_out) { - - if (s_in || s_out) {} - anontls_selected = 1; - - if (!switch_to_anon_dh()) { - rfbLog("anontls: Anonymous Diffie-Hellman failed.\n"); - return 0; + if (port <= 0) { + rfbLog("https_port: could not obtain listening port %d\n", port); + clean_up_exit(1); + } + sock = rfbListenOnTCPPort(port, iface); + if (sock < 0) { + rfbLog("https_port: could not open port %d\n", port); + clean_up_exit(1); } + if (db) fprintf(stderr, "https_port: listen on port/sock %d/%d\n", + port, sock); - /* continue with SSL/TLS */ - return 1; + https_sock = sock; } -/* - * Using spec: - * http://www.mail-archive.com/qemu-devel@nongnu.org/msg08681.html - */ -static int vencrypt_dialog(int s_in, int s_out) { - char buf[256], buf2[256]; - int subtypes[16]; - int n, i, ival, ok, nsubtypes = 0; +static void lose_ram(void) { + /* + * for a forked child that will be around for a long time + * without doing exec(). we really should re-exec, but a pain + * to redo all SSL ctx. + */ + free_old_fb(); - vencrypt_selected = 0; + free_tiles(); +} - /* send version 0.2 */ - buf[0] = 0; - buf[1] = 2; +/* utility to keep track of existing helper processes: */ - if (!write_exact(s_out, buf, 2)) { - close(s_in); close(s_out); - return 0; - } +void ssl_helper_pid(pid_t pid, int sock) { +# define HPSIZE 256 + static pid_t helpers[HPSIZE]; + static int sockets[HPSIZE], first = 1; + int i, empty, set, status; + static int db = 0; - /* read client version 0.2 */ - memset(buf, 0, sizeof(buf)); - if (!read_exact(s_in, buf, 2)) { - close(s_in); close(s_out); - return 0; + if (first) { + for (i=0; i < HPSIZE; i++) { + helpers[i] = 0; + sockets[i] = 0; + } + if (getenv("SSL_HELPER_PID_DB")) { + db = 1; + } + first = 0; } - rfbLog("vencrypt: received %d.%d client version.\n", (int) buf[0], (int) buf[1]); - /* close 0.0 */ - if (buf[0] == 0 && buf[1] == 0) { - rfbLog("vencrypt: received 0.0 version, closing connection.\n"); - close(s_in); close(s_out); - return 0; - } - /* accept only 0.2 */ - if (buf[0] != 0 || buf[1] != 2) { - rfbLog("vencrypt: unsupported VeNCrypt version, closing connection.\n"); - buf[0] = (char) 255; - write_exact(s_out, buf, 1); - close(s_in); close(s_out); - return 0; - } + if (pid == 0) { + /* killall or waitall */ + for (i=0; i < HPSIZE; i++) { + if (helpers[i] == 0) { + sockets[i] = -1; + continue; + } + if (kill(helpers[i], 0) == 0) { + int kret = -2; + pid_t wret; + if (sock != -2) { + if (sockets[i] >= 0) { + close(sockets[i]); + } + kret = kill(helpers[i], SIGTERM); + if (kret == 0) { + usleep(20 * 1000); + } + } - /* tell them OK */ - buf[0] = 0; - if (!write_exact(s_out, buf, 1)) { - close(s_in); close(s_out); - return 0; - } +#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID + wret = waitpid(helpers[i], &status, WNOHANG); - if (getenv("X11VNC_ENABLE_VENCRYPT_PLAIN_LOGIN")) { - vencrypt_enable_plain_login = atoi(getenv("X11VNC_ENABLE_VENCRYPT_PLAIN_LOGIN")); - } +if (db) fprintf(stderr, "waitpid(%d)\n", helpers[i]); +if (db) fprintf(stderr, " waitret1=%d\n", wret); - /* load our list of sub-types: */ - n = 0; - if (!ssl_verify && vencrypt_kx != VENCRYPT_NODH) { - if (screen->authPasswdData != NULL) { - subtypes[n++] = rfbVencryptTlsVnc; - } else { - if (vencrypt_enable_plain_login && unixpw) { - subtypes[n++] = rfbVencryptTlsPlain; - } else { - subtypes[n++] = rfbVencryptTlsNone; - } - } - } - if (vencrypt_kx != VENCRYPT_NOX509) { - if (screen->authPasswdData != NULL) { - subtypes[n++] = rfbVencryptX509Vnc; - } else { - if (vencrypt_enable_plain_login && unixpw) { - subtypes[n++] = rfbVencryptX509Plain; - } else { - subtypes[n++] = rfbVencryptX509None; + if (kret == 0 && wret != helpers[i]) { + int k; + for (k=0; k < 10; k++) { + usleep(100 * 1000); + wret = waitpid(helpers[i], &status, WNOHANG); +if (db) fprintf(stderr, " waitret2=%d\n", wret); + if (wret == helpers[i]) { + break; + } + } + } +#endif + if (sock == -2) { + continue; + } } + helpers[i] = 0; + sockets[i] = -1; } + return; } - nsubtypes = n; - for (i = 0; i < nsubtypes; i++) { - ((uint32_t *)buf)[i] = Swap32IfLE(subtypes[i]); - } - - /* send number first: */ - buf2[0] = (char) nsubtypes; - if (!write_exact(s_out, buf2, 1)) { - close(s_in); close(s_out); - return 0; - } - /* and now the list: */ - if (!write_exact(s_out, buf, 4*n)) { - close(s_in); close(s_out); - return 0; - } - - /* read client's selection: */ - if (!read_exact(s_in, (char *)&ival, 4)) { - close(s_in); close(s_out); - return 0; - } - ival = Swap32IfLE(ival); +if (db) fprintf(stderr, "ssl_helper_pid(%d, %d)\n", pid, sock); - /* zero means no dice: */ - if (ival == 0) { - rfbLog("vencrypt: client selected no sub-type, closing connection.\n"); - close(s_in); close(s_out); - return 0; - } + /* add (or delete for sock == -1) */ + set = 0; + empty = -1; + for (i=0; i < HPSIZE; i++) { + if (helpers[i] == pid) { + if (sock == -1) { +#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID + pid_t wret; + wret = waitpid(helpers[i], &status, WNOHANG); - /* check if he selected a valid one: */ - ok = 0; - for (i = 0; i < nsubtypes; i++) { - if (ival == subtypes[i]) { - ok = 1; +if (db) fprintf(stderr, "waitpid(%d) 2\n", helpers[i]); +if (db) fprintf(stderr, " waitret1=%d\n", wret); +#endif + helpers[i] = 0; + } + sockets[i] = sock; + set = 1; + } else if (empty == -1 && helpers[i] == 0) { + empty = i; } } - - if (!ok) { - rfbLog("vencrypt: client selected invalid sub-type: %d\n", ival); - close(s_in); close(s_out); - return 0; - } else { - char *st = "unknown!!"; - if (ival == rfbVencryptTlsNone) st = "rfbVencryptTlsNone"; - if (ival == rfbVencryptTlsVnc) st = "rfbVencryptTlsVnc"; - if (ival == rfbVencryptTlsPlain) st = "rfbVencryptTlsPlain"; - if (ival == rfbVencryptX509None) st = "rfbVencryptX509None"; - if (ival == rfbVencryptX509Vnc) st = "rfbVencryptX509Vnc"; - if (ival == rfbVencryptX509Plain) st = "rfbVencryptX509Plain"; - rfbLog("vencrypt: client selected sub-type: %d (%s)\n", ival, st); + if (set || sock == -1) { + return; /* done */ } - vencrypt_selected = ival; - - /* not documented in spec, send OK: */ - buf[0] = 1; - if (!write_exact(s_out, buf, 1)) { - close(s_in); close(s_out); - return 0; + /* now try to store */ + if (empty >= 0) { + helpers[empty] = pid; + sockets[empty] = sock; + return; } - - if (vencrypt_selected == rfbVencryptTlsNone || - vencrypt_selected == rfbVencryptTlsVnc || - vencrypt_selected == rfbVencryptTlsPlain) { - /* these modes are Anonymous Diffie-Hellman */ - if (!switch_to_anon_dh()) { - rfbLog("vencrypt: Anonymous Diffie-Hellman failed.\n"); - return 0; + for (i=0; i < HPSIZE; i++) { + if (helpers[i] == 0) { + continue; + } + /* clear out stale pids: */ + if (kill(helpers[i], 0) != 0) { + helpers[i] = 0; + sockets[i] = -1; + + if (empty == -1) { + empty = i; + } } } - - /* continue with SSL/TLS */ - return 1; + if (empty >= 0) { + helpers[empty] = pid; + sockets[empty] = sock; + } } -static int check_vnc_tls_mode(int s_in, int s_out, double last_https) { - double waited = 0.0, waitmax = 1.4, dt = 0.01, start = dnow(); +static int is_ssl_readable(int s_in, double last_https, char *last_get, + int mode) { + int nfd, db = 0; struct timeval tv; - int input = 0, i, n, ok; - int major, minor, sectype = -1; - char *proto = "RFB 003.008\n"; - char *stype = "unknown"; - char buf[256]; - - vencrypt_selected = 0; - anontls_selected = 0; + fd_set rd; - if (vencrypt_mode == VENCRYPT_NONE && anontls_mode == ANONTLS_NONE) { - /* only normal SSL */ - return 1; - } - if (ssl_client_mode) { - if (vencrypt_mode == VENCRYPT_FORCE || anontls_mode == ANONTLS_FORCE) { - rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/ANONTLS_FORCE in client\n"); - rfbLog("check_vnc_tls_mode: connect mode.\n"); - /* this is OK, continue on below for dialog. */ - } else { - /* otherwise we must assume normal SSL (we send client hello) */ - return 1; - } - } - if (ssl_verify && vencrypt_mode != VENCRYPT_FORCE && anontls_mode == ANONTLS_FORCE) { - rfbLog("check_vnc_tls_mode: Cannot use ANONTLS_FORCE with -sslverify (Anon DH only)\n"); - /* fallback to normal SSL */ - return 1; + if (getenv("ACCEPT_OPENSSL_DEBUG")) { + db = atoi(getenv("ACCEPT_OPENSSL_DEBUG")); } - if (last_https > 0.0) { - double now = dnow(); - if (now < last_https + 5.0) { - waitmax = 20.0; - } else if (now < last_https + 15.0) { - waitmax = 10.0; - } else if (now < last_https + 30.0) { - waitmax = 5.0; - } else if (now < last_https + 60.0) { - waitmax = 2.5; - } - } + /* + * we'll do a select() on s_in for reading. this is not an + * absolute proof that SSL_read is ready (XXX use SSL utility). + */ + tv.tv_sec = 2; + tv.tv_usec = 0; - while (waited < waitmax) { - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(s_in, &rfds); - tv.tv_sec = 0; - tv.tv_usec = 0; - select(s_in+1, &rfds, NULL, NULL, &tv); - if (FD_ISSET(s_in, &rfds)) { - input = 1; - break; - } - usleep((int) (1000 * 1000 * dt)); - waited += dt; + if (mode == OPENSSL_INETD) { + /* + * https via inetd is icky because x11vnc is restarted + * for each socket (and some clients send requests + * rapid fire). + */ + tv.tv_sec = 6; } - rfbLog("check_vnc_tls_mode: waited: %f / %.2f input: %s\n", - dnow() - start, waitmax, input ? "SSL Handshake" : "(future) RFB Handshake"); - if (input) { - /* got SSL client hello, can only assume normal SSL */ - if (vencrypt_mode == VENCRYPT_FORCE || anontls_mode == ANONTLS_FORCE) { - rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/ANONTLS_FORCE prevents normal SSL\n"); - return 0; + /* + * increase the timeout if we know HTTP traffic has occurred + * recently: + */ + if (dnow() < last_https + 30.0) { + tv.tv_sec = 10; + if (last_get && strstr(last_get, "VncViewer")) { + tv.tv_sec = 5; } - return 1; } - - /* send RFB 003.008 -- there is no turning back from this point... */ - if (!write_exact(s_out, proto, strlen(proto))) { - close(s_in); close(s_out); - return 0; - } - - memset(buf, 0, sizeof(buf)); - if (!read_exact(s_in, buf, 12)) { - close(s_in); close(s_out); - return 0; + if (getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT")) { + tv.tv_sec = atoi(getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT")); } +if (db) fprintf(stderr, "tv_sec: %d - %s\n", (int) tv.tv_sec, last_get); - if (sscanf(buf, "RFB %03d.%03d\n", &major, &minor) != 2) { - int i; - rfbLog("check_vnc_tls_mode: abnormal handshake: '%s'\nbytes: ", buf); - for (i=0; i < 12; i++) { - fprintf(stderr, "%d.", (unsigned char) buf[i]); - } - fprintf(stderr, "\n"); - close(s_in); close(s_out); - return 0; - } - rfbLog("check_vnc_tls_mode: version: %d.%d\n", major, minor); - if (major != 3 || minor < 8) { - rfbLog("check_vnc_tls_mode: invalid version: '%s'\n", buf); - close(s_in); close(s_out); - return 0; - } + FD_ZERO(&rd); + FD_SET(s_in, &rd); - n = 1; - if (vencrypt_mode == VENCRYPT_FORCE) { - buf[n++] = rfbSecTypeVencrypt; - } else if (anontls_mode == ANONTLS_FORCE && !ssl_verify) { - buf[n++] = rfbSecTypeAnonTls; - } else if (vencrypt_mode == VENCRYPT_SOLE) { - buf[n++] = rfbSecTypeVencrypt; - } else if (anontls_mode == ANONTLS_SOLE && !ssl_verify) { - buf[n++] = rfbSecTypeAnonTls; - } else { - if (vencrypt_mode == VENCRYPT_SUPPORT) { - buf[n++] = rfbSecTypeVencrypt; - } - if (anontls_mode == ANONTLS_SUPPORT && !ssl_verify) { - buf[n++] = rfbSecTypeAnonTls; - } - } + do { + nfd = select(s_in+1, &rd, NULL, NULL, &tv); + } while (nfd < 0 && errno == EINTR); - n--; - buf[0] = (char) n; - if (!write_exact(s_out, buf, n+1)) { - close(s_in); close(s_out); + if (db) fprintf(stderr, "https nfd: %d\n", nfd); + + if (nfd <= 0 || ! FD_ISSET(s_in, &rd)) { return 0; } - if (0) fprintf(stderr, "wrote[%d] %d %d %d\n", n, buf[0], buf[1], buf[2]); + return 1; +} - buf[0] = 0; - if (!read_exact(s_in, buf, 1)) { - close(s_in); close(s_out); +static int watch_for_http_traffic(char *buf_a, int *n_a, int raw_sock) { + int is_http, err, n, n2; + char *buf; + int db = 0; + /* + * 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 + * rest of the available data otherwise we may deadlock. + * what has been read is returned in buf_a and n_a. + * *buf_a is ABSIZE+1 long and zeroed. + */ + if (getenv("ACCEPT_OPENSSL_DEBUG")) { + db = atoi(getenv("ACCEPT_OPENSSL_DEBUG")); + } + if (! buf_a || ! n_a) { return 0; } - if (buf[0] == rfbSecTypeVencrypt) stype = "VeNCrypt"; - if (buf[0] == rfbSecTypeAnonTls) stype = "ANONTLS"; + buf = (char *) calloc((ABSIZE+1), 1); + *n_a = 0; - rfbLog("check_vnc_tls_mode: reply: %d (%s)\n", (int) buf[0], stype); + if (enc_str && !strcmp(enc_str, "none")) { + n = read(raw_sock, buf, 2); + err = SSL_ERROR_NONE; + } else { +#if LIBVNCSERVER_HAVE_LIBSSL + n = SSL_read(ssl, buf, 2); + err = SSL_get_error(ssl, n); +#else + err = n = 0; + badnews("1 in watch_for_http_traffic"); +#endif + } - ok = 0; - for (i=1; i < n+1; i++) { - if (buf[0] == buf[i]) { - ok = 1; + if (err != SSL_ERROR_NONE || n < 2) { + if (n > 0) { + strncpy(buf_a, buf, n); + *n_a = n; } + if (db) fprintf(stderr, "watch_for_http_traffic ssl err: %d/%d\n", err, n); + return -1; } - if (!ok) { - char *msg = "check_vnc_tls_mode: invalid security-type"; - int len = strlen(msg); - rfbLog("%s: %d\n", msg, (int) buf[0]); - ((uint32_t *)buf)[0] = Swap32IfLE(len); - write_exact(s_out, buf, 4); - write_exact(s_out, msg, strlen(msg)); - close(s_in); close(s_out); - return 0; + + /* look for GET, HEAD, POST, CONNECT */ + is_http = 0; + if (!strncmp("GE", buf, 2)) { + is_http = 1; + } else if (!strncmp("HE", buf, 2)) { + is_http = 1; + } else if (!strncmp("PO", buf, 2)) { + is_http = 1; + } else if (!strncmp("CO", buf, 2)) { + is_http = 1; } + if (db) fprintf(stderr, "watch_for_http_traffic read: '%s' %d\n", buf, n); - sectype = (int) buf[0]; + /* + * better read all we can and fwd it along to avoid blocking + * in ssl_xfer(). + */ - if (sectype == rfbSecTypeVencrypt) { - return vencrypt_dialog(s_in, s_out); - } else if (sectype == rfbSecTypeAnonTls) { - return anontls_dialog(s_in, s_out); + if (enc_str && !strcmp(enc_str, "none")) { + n2 = read(raw_sock, buf + n, ABSIZE - n); } else { - return 0; +#if LIBVNCSERVER_HAVE_LIBSSL + n2 = SSL_read(ssl, buf + n, ABSIZE - n); +#else + n2 = 0; + badnews("2 in watch_for_http_traffic"); +#endif + } + if (n2 >= 0) { + n += n2; } -} -static void pr_ssl_info(int verb) { - SSL_CIPHER *c; - SSL_SESSION *s; - char *proto = "unknown"; + *n_a = n; - if (verb) {} + if (db) fprintf(stderr, "watch_for_http_traffic readmore: %d\n", n2); - if (ssl == NULL) { - return; + if (n > 0) { + memcpy(buf_a, buf, n); } - c = SSL_get_current_cipher(ssl); - s = SSL_get_session(ssl); - - if (s == NULL) { - proto = "nosession"; - } else if (s->ssl_version == SSL2_VERSION) { - proto = "SSLv2"; - } else if (s->ssl_version == SSL3_VERSION) { - proto = "SSLv3"; - } else if (s->ssl_version == TLS1_VERSION) { - proto = "TLSv1"; + if (db > 1) { + fprintf(stderr, "watch_for_http_traffic readmore: "); + write(2, buf_a, *n_a); + fprintf(stderr, "\n"); } - if (c != NULL) { - rfbLog("SSL: ssl_helper[%d]: Cipher: %s %s Proto: %s\n", getpid(), - SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c), proto); - } else { - rfbLog("SSL: ssl_helper[%d]: Proto: %s\n", getpid(), - proto); + if (db) fprintf(stderr, "watch_for_http_traffic return: %d\n", is_http); + return is_http; +} + +static int csock_timeout_sock = -1; + +static void csock_timeout (int sig) { + rfbLog("sig: %d, csock_timeout.\n", sig); + if (csock_timeout_sock >= 0) { + close(csock_timeout_sock); + csock_timeout_sock = -1; } } -static void ssl_timeout (int sig) { - int i; - rfbLog("sig: %d, ssl_init[%d] timed out.\n", sig, getpid()); - for (i=0; i < 256; i++) { - close(i); +static int check_ssl_access(char *addr) { + static char *save_allow_once = NULL; + static time_t time_allow_once = 0; + + /* due to "Fetch Cert" activities for SSL really need to "allow twice" */ + if (allow_once != NULL) { + save_allow_once = strdup(allow_once); + time_allow_once = time(NULL); + } else if (save_allow_once != NULL) { + if (getenv("X11VNC_NO_SSL_ALLOW_TWICE")) { + ; + } else if (time(NULL) < time_allow_once + 30) { + /* give them 30 secs to check and save the fetched cert. */ + allow_once = save_allow_once; + rfbLog("SSL: Permitting 30 sec grace period for allowonce.\n"); + rfbLog("SSL: Set X11VNC_NO_SSL_ALLOW_TWICE=1 to disable.\n"); + } + save_allow_once = NULL; + time_allow_once = 0; } - exit(1); + + return check_access(addr); } -static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) { - unsigned char *sid = (unsigned char *) "x11vnc SID"; - char *name = NULL; +void accept_openssl(int mode, int presock) { + int sock = -1, listen = -1, cport, csock, vsock; int peerport = 0; - int db = 0, rc, err; - int ssock = s_in; - double start = dnow(); - int timeout = 20; + int status, n, i, db = 0; + struct sockaddr_in addr; +#ifdef __hpux + int addrlen = sizeof(addr); +#else + socklen_t addrlen = sizeof(addr); +#endif + rfbClientPtr client; + pid_t pid; + char uniq[] = "_evilrats_"; + char cookie[256], rcookie[256], *name = NULL; + int vencrypt_sel = 0; + int anontls_sel = 0; + static double last_https = 0.0; + static char last_get[256]; + static int first = 1; + unsigned char *rb; - if (enc_str != NULL) { - return 1; - } - if (getenv("SSL_DEBUG")) { - db = atoi(getenv("SSL_DEBUG")); - } - if (getenv("SSL_INIT_TIMEOUT")) { - timeout = atoi(getenv("SSL_INIT_TIMEOUT")); +#if !LIBVNCSERVER_HAVE_LIBSSL + if (enc_str == NULL || strcmp(enc_str, "none")) { + badnews("0 accept_openssl"); } - if (db) fprintf(stderr, "ssl_init: %d/%d\n", s_in, s_out); +#endif - if (skip_vnc_tls) { - rfbLog("SSL: ssl_helper[%d]: HTTPS mode, skipping check_vnc_tls_mode()\n", - getpid()); - } else if (!check_vnc_tls_mode(s_in, s_out, last_https)) { - return 0; + openssl_last_helper_pid = 0; + + /* zero buffers for use below. */ + for (i=0; i<256; i++) { + if (first) { + last_get[i] = '\0'; + } + cookie[i] = '\0'; + rcookie[i] = '\0'; } + first = 0; - ssl = SSL_new(ctx); - if (ssl == NULL) { - fprintf(stderr, "SSL_new failed\n"); - return 0; + if (getenv("ACCEPT_OPENSSL_DEBUG")) { + db = atoi(getenv("ACCEPT_OPENSSL_DEBUG")); } - if (db > 1) fprintf(stderr, "ssl_init: 1\n"); - SSL_set_session_id_context(ssl, sid, strlen((char *)sid)); + /* do INETD, VNC, or HTTPS cases (result is client socket or pipe) */ + if (mode == OPENSSL_INETD) { + ssl_initialized = 1; - if (s_in == s_out) { - if (! SSL_set_fd(ssl, ssock)) { - fprintf(stderr, "SSL_set_fd failed\n"); - return 0; + } else if (mode == OPENSSL_VNC) { + sock = accept(openssl_sock, (struct sockaddr *)&addr, &addrlen); + if (sock < 0) { + rfbLog("SSL: accept_openssl: accept connection failed\n"); + rfbLogPerror("accept"); + if (ssl_no_fail) { + clean_up_exit(1); + } + return; } - } else { - if (! SSL_set_rfd(ssl, s_in)) { - fprintf(stderr, "SSL_set_rfd failed\n"); - return 0; + listen = openssl_sock; + + } else if (mode == OPENSSL_REVERSE) { + sock = presock; + if (sock < 0) { + rfbLog("SSL: accept_openssl: connection failed\n"); + if (ssl_no_fail) { + clean_up_exit(1); + } + return; } - if (! SSL_set_wfd(ssl, s_out)) { - fprintf(stderr, "SSL_set_wfd failed\n"); - return 0; + listen = -1; + + } else if (mode == OPENSSL_HTTPS) { + sock = accept(https_sock, (struct sockaddr *)&addr, &addrlen); + if (sock < 0) { + rfbLog("SSL: accept_openssl: accept connection failed\n"); + rfbLogPerror("accept"); + if (ssl_no_fail) { + clean_up_exit(1); + } + return; } + listen = https_sock; } - if (db > 1) fprintf(stderr, "ssl_init: 2\n"); + if (db) fprintf(stderr, "SSL: accept_openssl: sock: %d\n", sock); - if (ssl_client_mode) { - SSL_set_connect_state(ssl); + if (openssl_last_ip) { + free(openssl_last_ip); + openssl_last_ip = NULL; + } + if (mode == OPENSSL_INETD) { + openssl_last_ip = get_remote_host(fileno(stdin)); } else { - SSL_set_accept_state(ssl); + openssl_last_ip = get_remote_host(sock); } - if (db > 1) fprintf(stderr, "ssl_init: 3\n"); - - name = get_remote_host(ssock); - peerport = get_remote_port(ssock); - - if (db > 1) fprintf(stderr, "ssl_init: 4\n"); - - while (1) { - - signal(SIGALRM, ssl_timeout); - alarm(timeout); - - if (ssl_client_mode) { - if (db) fprintf(stderr, "calling SSL_connect...\n"); - rc = SSL_connect(ssl); - } else { - if (db) fprintf(stderr, "calling SSL_accept...\n"); - rc = SSL_accept(ssl); + if (!check_ssl_access(openssl_last_ip)) { + rfbLog("SSL: accept_openssl: denying client %s\n", openssl_last_ip); + rfbLog("SSL: accept_openssl: does not match -allow (or other reason).\n"); + close(sock); + sock = -1; + if (ssl_no_fail) { + clean_up_exit(1); } - err = SSL_get_error(ssl, rc); + return; + } - alarm(0); - signal(SIGALRM, SIG_DFL); + /* now make a listening socket for child to connect back to us by: */ - if (ssl_client_mode) { - if (db) fprintf(stderr, "SSL_connect %d/%d\n", rc, err); - } else { - if (db) fprintf(stderr, "SSL_accept %d/%d\n", rc, err); + cport = find_free_port(20000, 0); + if (! cport) { + rfbLog("SSL: accept_openssl: could not find open port.\n"); + close(sock); + if (mode == OPENSSL_INETD || ssl_no_fail) { + clean_up_exit(1); } - if (err == SSL_ERROR_NONE) { - break; - } else if (err == SSL_ERROR_WANT_READ) { - - if (db) fprintf(stderr, "got SSL_ERROR_WANT_READ\n"); - rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n", - getpid(), name, peerport); - pr_ssl_info(1); - return 0; - - } else if (err == SSL_ERROR_WANT_WRITE) { + return; + } + if (db) fprintf(stderr, "accept_openssl: cport: %d\n", cport); - if (db) fprintf(stderr, "got SSL_ERROR_WANT_WRITE\n"); - rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n", - getpid(), name, peerport); - pr_ssl_info(1); - return 0; + csock = rfbListenOnTCPPort(cport, htonl(INADDR_LOOPBACK)); - } else if (err == SSL_ERROR_SYSCALL) { + if (csock < 0) { + rfbLog("SSL: accept_openssl: could not listen on port %d.\n", + cport); + close(sock); + if (mode == OPENSSL_INETD || ssl_no_fail) { + clean_up_exit(1); + } + return; + } + if (db) fprintf(stderr, "accept_openssl: csock: %d\n", csock); - if (db) fprintf(stderr, "got SSL_ERROR_SYSCALL\n"); - rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n", - getpid(), name, peerport); - pr_ssl_info(1); - return 0; + fflush(stderr); - } else if (err == SSL_ERROR_ZERO_RETURN) { + /* + * make a simple cookie to id the child socket, not foolproof + * but hard to guess exactly (just worrying about local lusers + * here, since we use INADDR_LOOPBACK). + */ + rb = (unsigned char *) calloc(6, 1); +#if LIBVNCSERVER_HAVE_LIBSSL + RAND_bytes(rb, 6); +#endif + sprintf(cookie, "RB=%d%d%d%d%d%d/%f%f/%p", + rb[0], rb[1], rb[2], rb[3], rb[4], rb[5], + dnow() - x11vnc_start, x11vnc_start, (void *)rb); - if (db) fprintf(stderr, "got SSL_ERROR_ZERO_RETURN\n"); - rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n", - getpid(), name, peerport); - pr_ssl_info(1); - return 0; + if (mode != OPENSSL_INETD) { + name = get_remote_host(sock); + peerport = get_remote_port(sock); + } else { + openssl_last_ip = get_remote_host(fileno(stdin)); + peerport = get_remote_port(fileno(stdin)); + if (openssl_last_ip) { + name = strdup(openssl_last_ip); + } else { + name = strdup("unknown"); + } + } + if (name) { + if (mode == OPENSSL_INETD) { + rfbLog("SSL: (inetd) spawning helper process " + "to handle: %s:%d\n", name, peerport); + } else { + rfbLog("SSL: spawning helper process to handle: " + "%s:%d\n", name, peerport); + } + free(name); + name = NULL; + } - } else if (rc < 0) { - unsigned long err; - int cnt = 0; + if (certret) { + free(certret); + } + if (certret_str) { + free(certret_str); + certret_str = NULL; + } + certret = strdup("/tmp/x11vnc-certret.XXXXXX"); + omode = umask(077); + certret_fd = mkstemp(certret); + umask(omode); + if (certret_fd < 0) { + free(certret); + certret = NULL; + certret_fd = -1; + } - rfbLog("SSL: ssl_helper[%d]: SSL_accept() *FATAL: %d SSL FAILED\n", getpid(), rc); - while ((err = ERR_get_error()) != 0) { - rfbLog("SSL: %s\n", ERR_error_string(err, NULL)); - if (cnt++ > 100) { - break; - } - } - pr_ssl_info(1); - return 0; + if (dhret) { + free(dhret); + } + if (dhret_str) { + free(dhret_str); + dhret_str = NULL; + } + dhret = strdup("/tmp/x11vnc-dhret.XXXXXX"); + omode = umask(077); + dhret_fd = mkstemp(dhret); + umask(omode); + if (dhret_fd < 0) { + free(dhret); + dhret = NULL; + dhret_fd = -1; + } - } else if (dnow() > start + 3.0) { + /* now fork the child to handle the SSL: */ + pid = fork(); - rfbLog("SSL: ssl_helper[%d]: timeout looping SSL_accept() " - "fatal.\n", getpid()); - pr_ssl_info(1); - return 0; + if (pid > 0) { + rfbLog("SSL: helper for peerport %d is pid %d: \n", + peerport, (int) pid); + } - } else { - BIO *bio = SSL_get_rbio(ssl); - if (bio == NULL) { - rfbLog("SSL: ssl_helper[%d]: ssl BIO is null. " - "fatal.\n", getpid()); - pr_ssl_info(1); - return 0; - } - if (BIO_eof(bio)) { - rfbLog("SSL: ssl_helper[%d]: ssl BIO is EOF. " - "fatal.\n", getpid()); - pr_ssl_info(1); - return 0; - } + if (pid < 0) { + rfbLog("SSL: accept_openssl: could not fork.\n"); + rfbLogPerror("fork"); + close(sock); + close(csock); + if (mode == OPENSSL_INETD || ssl_no_fail) { + clean_up_exit(1); } - usleep(10 * 1000); - } + return; - if (ssl_client_mode) { - rfbLog("SSL: ssl_helper[%d]: SSL_connect() succeeded for: %s:%d\n", getpid(), name, peerport); - } else { - rfbLog("SSL: ssl_helper[%d]: SSL_accept() succeeded for: %s:%d\n", getpid(), name, peerport); - } + } else if (pid == 0) { + int s_in, s_out, httpsock = -1; + int vncsock; + int i, have_httpd = 0; + int f_in = fileno(stdin); + int f_out = fileno(stdout); + int skip_vnc_tls = mode == OPENSSL_HTTPS ? 1 : 0; - pr_ssl_info(0); + if (db) fprintf(stderr, "helper pid in: %d %d %d %d\n", f_in, f_out, sock, listen); - if (SSL_get_verify_result(ssl) == X509_V_OK) { - X509 *x; - FILE *cr = NULL; - if (certret != NULL) { - cr = fopen(certret, "w"); - } - - x = SSL_get_peer_certificate(ssl); - if (x == NULL) { - rfbLog("SSL: ssl_helper[%d]: accepted client %s x509 peer cert is null\n", getpid(), name); - if (cr != NULL) { - fprintf(cr, "NOCERT\n"); - fclose(cr); - } - } else { - rfbLog("SSL: ssl_helper[%d]: accepted client %s x509 cert is:\n", getpid(), name); -#if LIBVNCSERVER_HAVE_X509_PRINT_EX_FP - X509_print_ex_fp(stderr, x, 0, XN_FLAG_MULTILINE); -#endif - if (cr != NULL) { -#if LIBVNCSERVER_HAVE_X509_PRINT_EX_FP - X509_print_ex_fp(cr, x, 0, XN_FLAG_MULTILINE); -#else - rfbLog("** not compiled with libssl X509_print_ex_fp() function **\n"); - if (users_list && strstr(users_list, "sslpeer=")) { - rfbLog("** -users sslpeer= will not work! **\n"); + /* reset all handlers to default (no interrupted() calls) */ + unset_signals(); + + /* close all non-essential fd's */ + for (i=0; i<256; i++) { + if (mode == OPENSSL_INETD) { + if (i == f_in || i == f_out) { + continue; } -#endif - fclose(cr); } + if (i == sock) { + continue; + } + if (i == 2) { + continue; + } + close(i); } - } - free(name); - - return 1; -} -static void symmetric_encryption_xfer(int csock, int s_in, int s_out); + /* + * sadly, we are a long lived child and so the large + * framebuffer memory areas will soon differ from parent. + * try to free as much as possible. + */ + lose_ram(); -static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { - int dbxfer = 0, db = 0, check_pending, fdmax, nfd, n, i, err; - char cbuf[ABSIZE], sbuf[ABSIZE]; - int cptr, sptr, c_rd, c_wr, s_rd, s_wr; - fd_set rd, wr; - struct timeval tv; - int ssock, cnt = 0, ndata = 0; + /* now connect back to parent socket: */ + vncsock = rfbConnectToTcpAddr("127.0.0.1", cport); + if (vncsock < 0) { + rfbLog("SSL: ssl_helper[%d]: could not connect" + " back to: %d\n", getpid(), cport); + rfbLog("SSL: ssl_helper[%d]: exit case 1 (no local vncsock)\n", getpid()); + exit(1); + } + if (db) fprintf(stderr, "vncsock %d\n", vncsock); - /* - * we want to switch to a longer timeout for long term VNC - * connections (in case the network is not working for periods of - * time), but we also want the timeout shorter at the beginning - * in case the client went away. - */ - double start, now; - int tv_https_early = 60; - int tv_https_later = 20; - int tv_vnc_early = 40; - int tv_vnc_later = 43200; /* was 300, stunnel: 43200 */ - int tv_cutover = 70; - int tv_closing = 60; - int tv_use; + /* try to initialize SSL with the remote client */ - if (dbxfer) { - raw_xfer(csock, s_in, s_out); - return; - } - if (enc_str != NULL) { - if (!strcmp(enc_str, "none")) { - usleep(250*1000); - rfbLog("doing '-enc none' raw transfer (no encryption)\n"); - raw_xfer(csock, s_in, s_out); + if (mode == OPENSSL_INETD) { + s_in = fileno(stdin); + s_out = fileno(stdout); } else { - symmetric_encryption_xfer(csock, s_in, s_out); + s_in = s_out = sock; } - return; - } - - if (getenv("SSL_DEBUG")) { - db = atoi(getenv("SSL_DEBUG")); - } - - if (db) fprintf(stderr, "ssl_xfer begin\n"); - start = dnow(); - if (is_https) { - tv_use = tv_https_early; - } else { - tv_use = tv_vnc_early; - } - + if (! ssl_init(s_in, s_out, skip_vnc_tls, last_https)) { + close(vncsock); + rfbLog("SSL: ssl_helper[%d]: exit case 2 (ssl_init failed)\n", getpid()); + exit(1); + } - /* - * csock: clear text socket with libvncserver. "C" - * ssock: ssl data socket with remote vnc viewer. "S" - * - * to cover inetd mode, we have s_in and s_out, but in non-inetd - * mode they both ssock. - * - * cbuf[] is data from csock that we have read but not passed on to ssl - * sbuf[] is data from ssl that we have read but not passed on to csock - */ - for (i=0; i s_in) { - ssock = s_out; - } else { - ssock = s_in; - } + if (vencrypt_selected != 0) { + char *tbuf; + tbuf = (char *) malloc(strlen(cookie) + 100); + sprintf(tbuf, "%s,VENCRYPT=%d,%s", uniq, vencrypt_selected, cookie); + write(vncsock, tbuf, strlen(cookie)); + goto wrote_cookie; + } else if (anontls_selected != 0) { + char *tbuf; + tbuf = (char *) malloc(strlen(cookie) + 100); + sprintf(tbuf, "%s,ANONTLS=%d,%s", uniq, anontls_selected, cookie); + write(vncsock, tbuf, strlen(cookie)); + goto wrote_cookie; + } - if (csock > ssock) { - fdmax = csock; - } else { - fdmax = ssock; - } + /* + * things get messy below since we are trying to do + * *both* VNC and Java applet httpd through the same + * SSL socket. + */ - c_rd = 1; /* clear text (libvncserver) socket open for reading */ - c_wr = 1; /* clear text (libvncserver) socket open for writing */ - s_rd = 1; /* ssl data (remote client) socket open for reading */ - s_wr = 1; /* ssl data (remote client) socket open for writing */ + if (! screen) { + close(vncsock); + exit(1); + } + if (screen->httpListenSock >= 0 && screen->httpPort > 0) { + have_httpd = 1; + } + if (screen->httpListenSock == -2) { + have_httpd = 1; + } + if (mode == OPENSSL_HTTPS && ! have_httpd) { + rfbLog("SSL: accept_openssl[%d]: no httpd socket for " + "-https mode\n", getpid()); + close(vncsock); + rfbLog("SSL: ssl_helper[%d]: exit case 3 (no httpd sock)\n", getpid()); + exit(1); + } - cptr = 0; /* offsets into ABSIZE buffers */ - sptr = 0; + if (have_httpd) { + int n = 0, is_http = 0; + int hport = screen->httpPort; + char *iface = NULL; + char *buf, *tbuf; - if (vencrypt_selected > 0 || anontls_selected > 0) { - char tmp[16]; - /* read and discard the extra RFB version */ - memset(tmp, 0, sizeof(tmp)); - read(csock, tmp, 12); - if (0) fprintf(stderr, "extra: %s\n", tmp); - } + buf = (char *) calloc((ABSIZE+1), 1); + tbuf = (char *) calloc((2*ABSIZE+1), 1); - while (1) { - int c_to_s, s_to_c, closing; + if (mode == OPENSSL_HTTPS) { + /* + * for this mode we know it is HTTP traffic + * so we skip trying to guess. + */ + is_http = 1; + n = 0; + goto connect_to_httpd; + } - if ( s_wr && (c_rd || cptr > 0) ) { + /* + * Check if there is stuff to read from remote end + * if so it is likely a GET or HEAD. + */ + if (! is_ssl_readable(s_in, last_https, last_get, + mode)) { + goto write_cookie; + } + /* - * S is writable and - * C is readable or some cbuf data remaining + * read first 2 bytes to try to guess. sadly, + * the user is often pondering a "non-verified + * cert" dialog for a long time before the GET + * is ever sent. So often we timeout here. */ - c_to_s = 1; - } else { - c_to_s = 0; - } - if ( c_wr && (s_rd || sptr > 0) ) { - /* - * C is writable and - * S is readable or some sbuf data remaining - */ - s_to_c = 1; - } else { - s_to_c = 0; - } + if (db) fprintf(stderr, "watch_for_http_traffic\n"); + + is_http = watch_for_http_traffic(buf, &n, s_in); + + if (is_http < 0 || is_http == 0) { + /* + * error or http not detected, fall back + * to normal VNC socket. + */ + if (db) fprintf(stderr, "is_http err: %d n: %d\n", is_http, n); + write(vncsock, cookie, strlen(cookie)); + if (n > 0) { + write(vncsock, buf, n); + } + goto wrote_cookie; + } + + if (db) fprintf(stderr, "is_http: %d n: %d\n", + is_http, n); + if (db) fprintf(stderr, "buf: '%s'\n", buf); + + if (strstr(buf, "/request.https.vnc.connection")) { + char reply[] = "HTTP/1.0 200 OK\r\n" + "Content-Type: octet-stream\r\n" + "Connection: Keep-Alive\r\n" + "Pragma: no-cache\r\n\r\n"; + /* + * special case proxy coming thru https + * instead of a direct SSL connection. + */ + rfbLog("Handling VNC request via https GET. [%d]\n", getpid()); + rfbLog("-- %s\n", buf); + + if (strstr(buf, "/reverse.proxy")) { + char *buf2; + int n, ptr; +#if !LIBVNCSERVER_HAVE_LIBSSL + write(s_out, reply, strlen(reply)); +#else + SSL_write(ssl, reply, strlen(reply)); +#endif + + buf2 = (char *) calloc((8192+1), 1); + n = 0; + ptr = 0; + while (ptr < 8192) { +#if !LIBVNCSERVER_HAVE_LIBSSL + n = read(s_in, buf2 + ptr, 1); +#else + n = SSL_read(ssl, buf2 + ptr, 1); +#endif + if (n > 0) { + ptr += n; + } + if (db) fprintf(stderr, "buf2: '%s'\n", buf2); + + if (strstr(buf2, "\r\n\r\n")) { + break; + } + } + free(buf2); + } + goto write_cookie; - if (! c_to_s && ! s_to_c) { - /* - * nothing can be sent either direction. - * break out of the loop to finish all work. - */ - break; - } - cnt++; + } else if (strstr(buf, "/check.https.proxy.connection")) { + char reply[] = "HTTP/1.0 200 OK\r\n" + "Connection: close\r\n" + "Content-Type: octet-stream\r\n" + "Pragma: no-cache\r\n\r\n"; - /* set up the fd sets for the two sockets for read & write: */ + rfbLog("Handling Check HTTPS request via https GET. [%d]\n", getpid()); + rfbLog("-- %s\n", buf); - FD_ZERO(&rd); +#if !LIBVNCSERVER_HAVE_LIBSSL + write(s_out, reply, strlen(reply)); +#else + SSL_write(ssl, reply, strlen(reply)); + SSL_shutdown(ssl); +#endif - if (c_rd && cptr < ABSIZE) { - /* we could read more from C since cbuf is not full */ - FD_SET(csock, &rd); - } - if (s_rd) { - /* - * we could read more from S since sbuf not full, - * OR ssl is waiting for more BIO to be able to - * read and we have some C data still buffered. - */ - if (sptr < ABSIZE || (cptr > 0 && SSL_want_read(ssl))) { - FD_SET(s_in, &rd); + strcpy(tbuf, uniq); + strcat(tbuf, cookie); + write(vncsock, tbuf, strlen(tbuf)); + close(vncsock); + + rfbLog("SSL: ssl_helper[%d]: exit case 4 (check.https.proxy.connection)\n", getpid()); + exit(0); } - } - - FD_ZERO(&wr); + connect_to_httpd: - if (c_wr && sptr > 0) { - /* we could write more to C since sbuf is not empty */ - FD_SET(csock, &wr); - } - if (s_wr) { /* - * we could write more to S since cbuf not empty, - * OR ssl is waiting for more BIO to be able - * write and we haven't filled up sbuf yet. + * Here we go... no turning back. we have to + * send failure to parent and close socket to have + * http processed at all in a timely fashion... */ - if (cptr > 0 || (sptr < ABSIZE && SSL_want_write(ssl))) { - FD_SET(s_out, &wr); - } - } - - now = dnow(); - if (tv_cutover && now > start + tv_cutover) { - rfbLog("SSL: ssl_xfer[%d]: tv_cutover: %d\n", getpid(), - tv_cutover); - tv_cutover = 0; - if (is_https) { - tv_use = tv_https_later; - } else { - tv_use = tv_vnc_later; - } - /* try to clean out some zombies if we can. */ - ssl_helper_pid(0, -2); - } - if (ssl_timeout_secs > 0) { - tv_use = ssl_timeout_secs; - } - if ( (s_rd && c_rd) || cptr || sptr) { - closing = 0; - } else { - closing = 1; - tv_use = tv_closing; - } + /* send the failure tag: */ + strcpy(tbuf, uniq); - tv.tv_sec = tv_use; - tv.tv_usec = 0; + if (https_port_redir < 0 || (strstr(buf, "PORT=") || strstr(buf, "port="))) { + char *q = strstr(buf, "Host:"); + int fport = 443, match = 0; + char num[16]; - /* do the select, repeat if interrupted */ - do { - if (ssl_timeout_secs == 0) { - nfd = select(fdmax+1, &rd, &wr, NULL, NULL); - } else { - nfd = select(fdmax+1, &rd, &wr, NULL, &tv); + if (q && strstr(q, "\n")) { + q += strlen("Host:") + 1; + while (*q != '\n') { + int p; + if (*q == ':' && sscanf(q, ":%d", &p) == 1) { + if (p > 0 && p < 65536) { + fport = p; + match = 1; + break; + } + } + q++; + } + } + if (!match || !https_port_redir) { + int p; + if (sscanf(buf, "PORT=%d,", &p) == 1) { + if (p > 0 && p < 65536) { + fport = p; + } + } else if (sscanf(buf, "port=%d,", &p) == 1) { + if (p > 0 && p < 65536) { + fport = p; + } + } + } + sprintf(num, "HP=%d,", fport); + strcat(tbuf, num); } - } while (nfd < 0 && errno == EINTR); - if (db > 1) fprintf(stderr, "nfd: %d\n", nfd); - -if (0) fprintf(stderr, "nfd[%d]: %d w/r csock: %d %d s_in: %d %d\n", getpid(), nfd, FD_ISSET(csock, &wr), FD_ISSET(csock, &rd), FD_ISSET(s_out, &wr), FD_ISSET(s_in, &rd)); - - if (nfd < 0) { - rfbLog("SSL: ssl_xfer[%d]: select error: %d\n", getpid(), nfd); - perror("select"); - /* connection finished */ - goto done; - } - - if (nfd == 0) { - if (!closing && tv_cutover && ndata > 25000) { - static int cn = 0; - /* probably ok, early windows iconify */ - if (cn++ < 2) { - rfbLog("SSL: ssl_xfer[%d]: early time" - "out: %d\n", getpid(), ndata); + if (strstr(buf, "HTTP/") != NULL) { + char *q, *str; + /* + * Also send back the GET line for heuristics. + * (last_https, get file). + */ + str = strdup(buf); + q = strstr(str, "HTTP/"); + if (q != NULL) { + *q = '\0'; + strcat(tbuf, str); } - continue; + free(str); } - rfbLog("SSL: ssl_xfer[%d]: connection timedout. %d tv_use: %d\n", - getpid(), ndata, tv_use); - /* connection finished */ - goto done; - } - - /* used to see if SSL_pending() should be checked: */ - check_pending = 0; -/* AUDIT */ - if (c_wr && FD_ISSET(csock, &wr)) { + /* + * Also send the cookie to pad out the number of + * bytes to more than the parent wants to read. + * Since this is the failure case, it does not + * matter that we send more than strlen(cookie). + */ + strcat(tbuf, cookie); + write(vncsock, tbuf, strlen(tbuf)); - /* try to write some of our sbuf to C: */ - n = write(csock, sbuf, sptr); + usleep(150*1000); + if (db) fprintf(stderr, "close vncsock: %d\n", vncsock); + close(vncsock); - if (n < 0) { - if (errno != EINTR) { - /* connection finished */ - goto done; - } - /* proceed */ - } else if (n == 0) { - /* connection finished XXX double check */ - goto done; + /* now, finally, connect to the libvncserver httpd: */ + if (screen->listenInterface == htonl(INADDR_ANY) || + screen->listenInterface == htonl(INADDR_NONE)) { + iface = "127.0.0.1"; } else { - /* shift over the data in sbuf by n */ - memmove(sbuf, sbuf + n, sptr - n); - if (sptr == ABSIZE) { - check_pending = 1; - } - sptr -= n; + struct in_addr in; + in.s_addr = screen->listenInterface; + iface = inet_ntoa(in); + } + if (iface == NULL || !strcmp(iface, "")) { + iface = "127.0.0.1"; + } + if (db) fprintf(stderr, "iface: %s:%d\n", iface, hport); + usleep(150*1000); - if (! s_rd && sptr == 0) { - /* finished sending last of sbuf */ - shutdown(csock, SHUT_WR); - c_wr = 0; - } - ndata += n; + httpsock = rfbConnectToTcpAddr(iface, hport); + + if (httpsock < 0) { + /* UGH, after all of that! */ + rfbLog("Could not connect to httpd socket!\n"); + rfbLog("SSL: ssl_helper[%d]: exit case 5.\n", getpid()); + exit(1); + } + if (db) fprintf(stderr, "ssl_helper[%d]: httpsock: %d %d\n", + getpid(), httpsock, n); + + /* + * send what we read to httpd, and then connect + * the rest of the SSL session to it: + */ + if (n > 0) { + if (db) fprintf(stderr, "sending http buffer httpsock: %d\n'%s'\n", httpsock, buf); + write(httpsock, buf, n); } + ssl_xfer(httpsock, s_in, s_out, is_http); + rfbLog("SSL: ssl_helper[%d]: exit case 6 (https ssl_xfer done)\n", getpid()); + exit(0); } - if (s_wr) { - if ((cptr > 0 && FD_ISSET(s_out, &wr)) || - (SSL_want_read(ssl) && FD_ISSET(s_in, &rd))) { + /* + * ok, back from the above https mess, simply send the + * cookie back to the parent (who will attach us to + * libvncserver), and connect the rest of the SSL session + * to it. + */ + write_cookie: + write(vncsock, cookie, strlen(cookie)); + + wrote_cookie: + ssl_xfer(vncsock, s_in, s_out, 0); - /* try to write some of our cbuf to S: */ + rfbLog("SSL: ssl_helper[%d]: exit case 7 (ssl_xfer done)\n", getpid()); + exit(0); + } + /* parent here */ - n = SSL_write(ssl, cbuf, cptr); - err = SSL_get_error(ssl, n); + if (mode != OPENSSL_INETD) { + close(sock); + } + if (db) fprintf(stderr, "helper process is: %d\n", pid); - if (err == SSL_ERROR_NONE) { - /* shift over the data in cbuf by n */ - memmove(cbuf, cbuf + n, cptr - n); - cptr -= n; + /* accept connection from our child. */ + signal(SIGALRM, csock_timeout); + csock_timeout_sock = csock; + alarm(20); - if (! c_rd && cptr == 0 && s_wr) { - /* finished sending last cbuf */ - SSL_shutdown(ssl); - s_wr = 0; - } - ndata += n; + vsock = accept(csock, (struct sockaddr *)&addr, &addrlen); - } else if (err == SSL_ERROR_WANT_WRITE - || err == SSL_ERROR_WANT_READ - || err == SSL_ERROR_WANT_X509_LOOKUP) { + alarm(0); + signal(SIGALRM, SIG_DFL); + close(csock); - ; /* proceed */ - } else if (err == SSL_ERROR_SYSCALL) { - if (n < 0 && errno != EINTR) { - /* connection finished */ - goto done; - } - /* proceed */ - } else if (err == SSL_ERROR_ZERO_RETURN) { - /* S finished */ - s_rd = 0; - s_wr = 0; - } else if (err == SSL_ERROR_SSL) { - /* connection finished */ - goto done; - } - } + if (vsock < 0) { + rfbLog("SSL: accept_openssl: connection from ssl_helper[%d] FAILED.\n", pid); + rfbLogPerror("accept"); + + kill(pid, SIGTERM); + waitpid(pid, &status, WNOHANG); + if (mode == OPENSSL_INETD || ssl_no_fail) { + clean_up_exit(1); + } + if (certret_fd >= 0) { + close(certret_fd); + certret_fd = -1; + } + if (certret) { + unlink(certret); + } + if (dhret_fd >= 0) { + close(dhret_fd); + dhret_fd = -1; + } + if (dhret) { + unlink(dhret); } + return; + } + if (db) fprintf(stderr, "accept_openssl: vsock: %d\n", vsock); - if (c_rd && FD_ISSET(csock, &rd)) { + n = read(vsock, rcookie, strlen(cookie)); + if (n < 0 && errno != 0) { + rfbLogPerror("read"); + } + if (certret) { + struct stat sbuf; + sbuf.st_size = 0; + if (certret_fd >= 0 && stat(certret, &sbuf) == 0 && sbuf.st_size > 0) { + certret_str = (char *) calloc(sbuf.st_size+1, 1); + read(certret_fd, certret_str, sbuf.st_size); + close(certret_fd); + certret_fd = -1; + } + if (certret_fd >= 0) { + close(certret_fd); + certret_fd = -1; + } + unlink(certret); + if (certret_str && strstr(certret_str, "NOCERT") == certret_str) { + free(certret_str); + certret_str = NULL; + } + if (0 && certret_str) { + fprintf(stderr, "certret_str[%d]:\n%s\n", (int) sbuf.st_size, certret_str); + } + } - /* try to read some data from C into our cbuf */ + if (dhret) { + struct stat sbuf; + sbuf.st_size = 0; + if (dhret_fd >= 0 && stat(dhret, &sbuf) == 0 && sbuf.st_size > 0) { + dhret_str = (char *) calloc(sbuf.st_size+1, 1); + read(dhret_fd, dhret_str, sbuf.st_size); + close(dhret_fd); + dhret_fd = -1; + } + if (dhret_fd >= 0) { + close(dhret_fd); + dhret_fd = -1; + } + unlink(dhret); + if (dhret_str && strstr(dhret_str, "NOCERT") == dhret_str) { + free(dhret_str); + dhret_str = NULL; + } + if (dhret_str) { + if (new_dh_params == NULL) { + fprintf(stderr, "dhret_str[%d]:\n%s\n", (int) sbuf.st_size, dhret_str); + new_dh_params = strdup(dhret_str); + } + } + } - n = read(csock, cbuf + cptr, ABSIZE - cptr); + if (0) { + fprintf(stderr, "rcookie: %s\n", rcookie); + fprintf(stderr, "cookie: %s\n", cookie); + } - if (n < 0) { - if (errno != EINTR) { - /* connection finished */ - goto done; + if (strstr(rcookie, uniq) == rcookie) { + char *q = strstr(rcookie, "RB="); + if (q && strstr(cookie, q) == cookie) { + vencrypt_sel = 0; + anontls_sel = 0; + q = strstr(rcookie, "VENCRYPT="); + if (q && sscanf(q, "VENCRYPT=%d,", &vencrypt_sel) == 1) { + if (vencrypt_sel != 0) { + rfbLog("SSL: VENCRYPT mode=%d accepted.\n", vencrypt_sel); + goto accept_client; } - /* proceed */ - } else if (n == 0) { - /* C is EOF */ - c_rd = 0; - if (cptr == 0 && s_wr) { - /* and no more in cbuf to send */ - SSL_shutdown(ssl); - s_wr = 0; + } + q = strstr(rcookie, "ANONTLS="); + if (q && sscanf(q, "ANONTLS=%d,", &anontls_sel) == 1) { + if (anontls_sel != 0) { + rfbLog("SSL: ANONTLS mode=%d accepted.\n", anontls_sel); + goto accept_client; } - } else { - /* good */ - - cptr += n; - ndata += n; } } + } - if (s_rd) { - if ((sptr < ABSIZE && FD_ISSET(s_in, &rd)) || - (SSL_want_write(ssl) && FD_ISSET(s_out, &wr)) || - (check_pending && SSL_pending(ssl))) { - - /* try to read some data from S into our sbuf */ - - n = SSL_read(ssl, sbuf + sptr, ABSIZE - sptr); - err = SSL_get_error(ssl, n); - - if (err == SSL_ERROR_NONE) { - /* good */ + if (n != (int) strlen(cookie) || strncmp(cookie, rcookie, n)) { + rfbLog("SSL: accept_openssl: cookie from ssl_helper[%d] FAILED. %d\n", pid, n); + if (db) fprintf(stderr, "'%s'\n'%s'\n", cookie, rcookie); + close(vsock); - sptr += n; - ndata += n; + if (strstr(rcookie, uniq) == rcookie) { + int i; + rfbLog("SSL: BUT WAIT! HTTPS for helper process[%d] succeeded. Good.\n", pid); + if (mode != OPENSSL_HTTPS) { + last_https = dnow(); + for (i=0; i<256; i++) { + last_get[i] = '\0'; + } + strncpy(last_get, rcookie, 100); + if (db) fprintf(stderr, "last_get: '%s'\n", last_get); + } + if (rcookie && strstr(rcookie, "VncViewer.class")) { + rfbLog("\n"); + rfbLog("***********************************************************\n"); + rfbLog("SSL: WARNING CLIENT ASKED FOR NONEXISTENT 'VncViewer.class'\n"); + rfbLog("SSL: USER NEEDS TO **RESTART** HIS WEB BROWSER.\n"); + rfbLog("***********************************************************\n"); + rfbLog("\n"); + } + ssl_helper_pid(pid, -2); - } else if (err == SSL_ERROR_WANT_WRITE - || err == SSL_ERROR_WANT_READ - || err == SSL_ERROR_WANT_X509_LOOKUP) { + if (https_port_redir) { + double start; + int origport = screen->port; + int useport = screen->port; + int saw_httpsock = 0; + /* to expand $PORT correctly in index.vnc */ + if (https_port_redir < 0) { + char *q = strstr(rcookie, "HP="); + if (q) { + int p; + if (sscanf(q, "HP=%d,", &p) == 1) { + useport = p; + } + } + } else { + useport = https_port_redir; + } + screen->port = useport; + if (origport != useport) { + rfbLog("SSL: -httpsredir guess port: %d\n", screen->port); + } - ; /* proceed */ + start = dnow(); + while (dnow() < start + 10.0) { + if (screen->httpSock >= 0) saw_httpsock = 1; + rfbPE(10000); + usleep(10000); + if (screen->httpSock >= 0) saw_httpsock = 1; + waitpid(pid, &status, WNOHANG); + if (kill(pid, 0) != 0) { + rfbPE(10000); + rfbPE(10000); + break; + } + if (saw_httpsock && screen->httpSock < 0) { + rfbLog("SSL: httpSock for helper[%d] went away\n", pid); + rfbPE(10000); + rfbPE(10000); + break; + } + } + screen->port = origport; + rfbLog("SSL: guessing child helper[%d] https finished. dt=%.6f\n", + pid, dnow() - start); + ssl_helper_pid(0, -2); + if (mode == OPENSSL_INETD) { + clean_up_exit(1); + } + } else if (mode == OPENSSL_INETD) { + double start; + int saw_httpsock = 0; - } else if (err == SSL_ERROR_SYSCALL) { - if (n < 0) { - if(errno != EINTR) { - /* connection finished */ - goto done; - } - /* proceed */ + /* to expand $PORT correctly in index.vnc */ + if (screen->port == 0) { + int fd = fileno(stdin); + if (getenv("X11VNC_INETD_PORT")) { + screen->port = atoi(getenv( + "X11VNC_INETD_PORT")); } else { - /* S finished */ - s_rd = 0; - s_wr = 0; + int tport = get_local_port(fd); + if (tport > 0) { + screen->port = tport; + } } - } else if (err == SSL_ERROR_ZERO_RETURN) { - /* S is EOF */ - s_rd = 0; - if (cptr == 0 && s_wr) { - /* and no more in cbuf to send */ - SSL_shutdown(ssl); - s_wr = 0; + } + rfbLog("SSL: screen->port %d\n", screen->port); + + /* kludge for https fetch via inetd */ + start = dnow(); + while (dnow() < start + 10.0) { + if (screen->httpSock >= 0) saw_httpsock = 1; + rfbPE(10000); + usleep(10000); + if (screen->httpSock >= 0) saw_httpsock = 1; + waitpid(pid, &status, WNOHANG); + if (kill(pid, 0) != 0) { + rfbPE(10000); + rfbPE(10000); + break; } - if (sptr == 0 && c_wr) { - /* and no more in sbuf to send */ - shutdown(csock, SHUT_WR); - c_wr = 0; + if (saw_httpsock && screen->httpSock < 0) { + rfbLog("SSL: httpSock for helper[%d] went away\n", pid); + rfbPE(10000); + rfbPE(10000); + break; } - } else if (err == SSL_ERROR_SSL) { - /* connection finished */ - goto done; } + rfbLog("SSL: OPENSSL_INETD guessing " + "child helper[%d] https finished. dt=%.6f\n", + pid, dnow() - start); + ssl_helper_pid(0, -2); + clean_up_exit(1); } + /* this will actually only get earlier https */ + ssl_helper_pid(0, -2); + return; + } + kill(pid, SIGTERM); + waitpid(pid, &status, WNOHANG); + if (mode == OPENSSL_INETD || ssl_no_fail) { + clean_up_exit(1); } - } - - done: - rfbLog("SSL: ssl_xfer[%d]: closing sockets %d, %d, %d\n", - getpid(), csock, s_in, s_out); - close(csock); - close(s_in); - close(s_out); - return; -} - -void check_openssl(void) { - fd_set fds; - struct timeval tv; - int nfds; - static time_t last_waitall = 0; - static double last_check = 0.0; - double now; - - if (! use_openssl) { - return; - } - - if (time(NULL) > last_waitall + 120) { - last_waitall = time(NULL); - ssl_helper_pid(0, -2); /* waitall */ - } - - if (openssl_sock < 0) { - return; - } - - now = dnow(); - if (now < last_check + 0.5) { - return; - } - last_check = now; - - FD_ZERO(&fds); - FD_SET(openssl_sock, &fds); - - tv.tv_sec = 0; - tv.tv_usec = 0; - - nfds = select(openssl_sock+1, &fds, NULL, NULL, &tv); - - if (nfds <= 0) { - return; - } - - rfbLog("SSL: accept_openssl(OPENSSL_VNC)\n"); - accept_openssl(OPENSSL_VNC, -1); -} - -void check_https(void) { - fd_set fds; - struct timeval tv; - int nfds; - static double last_check = 0.0; - double now; - - if (! use_openssl || https_sock < 0) { return; } - now = dnow(); - if (now < last_check + 0.5) { - return; - } - last_check = now; + accept_client: - FD_ZERO(&fds); - FD_SET(https_sock, &fds); + if (db) fprintf(stderr, "accept_openssl: cookie good: %s\n", cookie); - tv.tv_sec = 0; - tv.tv_usec = 0; + rfbLog("SSL: handshake with helper process[%d] succeeded.\n", pid); - nfds = select(https_sock+1, &fds, NULL, NULL, &tv); + openssl_last_helper_pid = pid; + ssl_helper_pid(pid, vsock); - if (nfds <= 0) { + if (vnc_redirect) { + vnc_redirect_sock = vsock; + openssl_last_helper_pid = 0; return; } - rfbLog("SSL: accept_openssl(OPENSSL_HTTPS)\n"); - accept_openssl(OPENSSL_HTTPS, -1); -} - -#define MSZ 4096 -static void init_prng(void) { - int db = 0, bytes, ubytes, fd; - char file[MSZ], dtmp[100]; - unsigned int sr; - - RAND_file_name(file, MSZ); - - rfbLog("RAND_file_name: %s\n", file); - - bytes = RAND_load_file(file, -1); - if (db) fprintf(stderr, "bytes read: %d\n", bytes); - - ubytes = RAND_load_file("/dev/urandom", 64); - bytes += ubytes; - if (db) fprintf(stderr, "bytes read: %d / %d\n", bytes, ubytes); - - /* mix in more predictable stuff as well for fallback */ - sprintf(dtmp, "/tmp/p%.8f.XXXXXX", dnow()); - fd = mkstemp(dtmp); - RAND_add(dtmp, strlen(dtmp), 0); - if (fd >= 0) { - close(fd); - unlink(dtmp); - } - sprintf(dtmp, "%d-%.8f", (int) getpid(), dnow()); - RAND_add(dtmp, strlen(dtmp), 0); - if (!RAND_status()) { - ubytes = -1; - rfbLog("calling RAND_poll()\n"); - RAND_poll(); - } - - RAND_bytes((unsigned char *)&sr, 4); - srand(sr); + client = create_new_client(vsock, 0); + openssl_last_helper_pid = 0; - if (bytes > 0) { - if (! quiet) { - rfbLog("initialized PRNG with %d random bytes.\n", - bytes); + if (client) { + if (db) fprintf(stderr, "accept_openssl: client %p\n", (void *) client); + if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) screen->newClientHook); + if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) new_client); + if (mode == OPENSSL_INETD) { + inetd_client = client; + client->clientGoneHook = client_gone; } - if (ubytes > 32 && rnow() < 0.25) { - RAND_write_file(file); + if (openssl_last_ip && + strpbrk(openssl_last_ip, "0123456789") == openssl_last_ip) { + client->host = strdup(openssl_last_ip); } - return; - } - - bytes += RAND_load_file("/dev/random", 8); - if (db) fprintf(stderr, "bytes read: %d\n", bytes); - RAND_poll(); + if (vencrypt_sel != 0) { + client->protocolMajorVersion = 3; + client->protocolMinorVersion = 8; +#if LIBVNCSERVER_HAVE_LIBSSL + if (!finish_vencrypt_auth(client, vencrypt_sel)) { + rfbCloseClient(client); + client = NULL; + } +#else + badnews("3 accept_openssl"); +#endif + } else if (anontls_sel != 0) { + client->protocolMajorVersion = 3; + client->protocolMinorVersion = 8; + rfbAuthNewClient(client); + } + if (use_threads && client != NULL) { + rfbStartOnHoldClient(client); + } + /* try to get RFB proto done now. */ + progress_client(); + } else { + rfbLog("SSL: accept_openssl: rfbNewClient failed.\n"); + close(vsock); - if (! quiet) { - rfbLog("initialized PRNG with %d random bytes.\n", bytes); + kill(pid, SIGTERM); + waitpid(pid, &status, WNOHANG); + if (mode == OPENSSL_INETD || ssl_no_fail) { + clean_up_exit(1); + } + return; } } -#endif /* FORK_OK */ -#endif /* LIBVNCSERVER_HAVE_LIBSSL */ void raw_xfer(int csock, int s_in, int s_out) { char buf0[8192]; diff --git a/x11vnc/sslhelper.h b/x11vnc/sslhelper.h index ce4c9ec..92011ba 100644 --- a/x11vnc/sslhelper.h +++ b/x11vnc/sslhelper.h @@ -62,6 +62,8 @@ extern void ssl_helper_pid(pid_t pid, int sock); extern void accept_openssl(int mode, int presock); extern char *find_openssl_bin(void); extern char *get_saved_pem(char *string, int create); +extern char *get_ssl_verify_file(char *str_in); +extern char *create_tmp_pem(char *path, int prompt); #endif /* _X11VNC_SSLHELPER_H */ diff --git a/x11vnc/ssltools.h b/x11vnc/ssltools.h index 5518533..6635bdf 100644 --- a/x11vnc/ssltools.h +++ b/x11vnc/ssltools.h @@ -271,13 +271,13 @@ char genCA[] = " -keyout \"$DIR/CA/private/cakey.pem\" \\\n" " -out \"$DIR/CA/cacert.pem\"\n" "\n" -"chmod go-rwx \"$DIR/CA/private/cakey.pem\"\n" -"\n" "if [ $? != 0 ]; then\n" " echo \"openssl failed.\"\n" " exit 1\n" "fi\n" "\n" +"chmod go-rwx \"$DIR/CA/private/cakey.pem\"\n" +"\n" "echo \"\"\n" "echo \"----------------------------------------------------------------------\"\n" "echo \"Your public x11vnc CA cert is:\"\n" @@ -785,6 +785,10 @@ char find_display[] = " set -xv\n" "fi\n" "\n" +"if [ \"X$X11VNC_SKIP_DISPLAY\" = \"Xall\" ]; then\n" +" exit 1\n" +"fi\n" +"\n" "PATH=$PATH:/bin:/usr/bin:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/ucb\n" "export PATH\n" "\n" @@ -1439,7 +1443,11 @@ char create_display[] = " return\n" " fi\n" " if [ \"X$have_gnome_session\" != \"X\" -a \"X$FD_SESS\" = \"Xgnome\" ]; then\n" -" echo \"$have_gnome_session\"\n" +" if [ \"X$have_dbus_launch\" != \"X\" ]; then\n" +" echo \"$have_dbus_launch --exit-with-session $have_gnome_session\"\n" +" else\n" +" echo \"$have_gnome_session\"\n" +" fi\n" " return\n" " elif [ \"X$have_startkde\" != \"X\" -a \"X$FD_SESS\" = \"Xkde\" ]; then\n" " echo \"$have_startkde\"\n" @@ -1692,8 +1700,10 @@ char create_display[] = " DISPLAY=:$N\n" " export DISPLAY\n" " stmp=\"\"\n" +" noxauth=\"\"\n" " if [ \"X$have_root\" != \"X\" -a \"X$USER\" != \"Xroot\" ]; then\n" " sess=\"env DISPLAY=:$N $sess\"\n" +" noxauth=\"1\"\n" " fi\n" "\n" " redir_daemon=\"\"\n" @@ -1706,27 +1716,34 @@ char create_display[] = " touch $stmp\n" " chmod 755 $stmp || exit 1\n" " echo \"#!/bin/sh\" > $stmp\n" +" #echo \"(id; env; env | grep XAUTHORITY | sed -e 's/XAUTHORITY=//' | xargs ls -l) > /tmp/ENV.OUT.$$\" >> $stmp\n" +" if [ \"X$noxauth\" = \"X1\" ]; then\n" +" echo \"unset XAUTHORITY\" >> $stmp\n" +" fi\n" " echo \"$sess\" >> $stmp\n" " echo \"sleep 1\" >> $stmp\n" " echo \"rm -f $stmp\" >> $stmp\n" " sess=$stmp\n" " rmf=\"$stmp\"\n" " fi\n" +"\n" " if [ \"X$have_root\" != \"X\" -a \"X$USER\" != \"Xroot\" ]; then\n" -" ctmp=/tmp/.xat$$`random`\n" -" ctmp=`mytmp \"$ctmp\"`\n" -" touch $ctmp\n" -" chmod 644 $ctmp || exit 1\n" -" $have_xauth -f $authfile nextract - :$N > $ctmp\n" -" su - $USER -c \"$have_xauth nmerge - < $ctmp\" 1>&2\n" -" $have_xauth -f $authfile nextract - `hostname`:$N > $ctmp\n" -" su - $USER -c \"$have_xauth nmerge - < $ctmp\" 1>&2\n" -" rm -f $ctmp\n" +" ctmp1=/tmp/.xat1_$$`random`\n" +" ctmp1=`mytmp \"$ctmp1\"`\n" +" ctmp2=/tmp/.xat2_$$`random`\n" +" ctmp2=`mytmp \"$ctmp2\"`\n" +" touch $ctmp1 $ctmp2\n" +" $have_xauth -f $authfile nextract - :$N > $ctmp1\n" +" $have_xauth -f $authfile nextract - `hostname`:$N > $ctmp2\n" +" chown $USER $ctmp1 $ctmp2\n" +" (unset XAUTHORITY; su - $USER -c \"$have_xauth nmerge - < $ctmp1\" 1>&2)\n" +" (unset XAUTHORITY; su - $USER -c \"$have_xauth nmerge - < $ctmp2\" 1>&2)\n" +" rm -f $ctmp1 $ctmp2\n" " XAUTHORITY=$authfile\n" " export XAUTHORITY\n" " sess=\"/bin/su - $USER -c $sess\"\n" " else\n" -" $have_xauth -f $authfile nextract - :$N | $have_xauth nmerge -\n" +" $have_xauth -f $authfile nextract - :$N | $have_xauth nmerge -\n" " $have_xauth -f $authfile nextract - `hostname`:$N | $have_xauth nmerge -\n" " fi\n" "\n" @@ -1742,7 +1759,12 @@ char create_display[] = " # we cannot use -nolisten tcp\n" " echo \"$* -once -query localhost $FD_OPTS\" 1>&2\n" " if [ \"X$have_root\" != \"X\" ]; then\n" -" $have_nohup $* -once -query localhost $FD_OPTS 1>&2 &\n" +" if [ -r $authfile ]; then\n" +" $have_nohup $* -once -query localhost -auth $authfile $FD_OPTS 1>&2 &\n" +" else\n" +" # why did we have this?\n" +" $have_nohup $* -once -query localhost $FD_OPTS 1>&2 &\n" +" fi\n" " else\n" " if [ \"X$ns\" = \"X0\" ]; then\n" " $have_nohup sh -c \"$* -once -query localhost -auth $authfile $FD_OPTS\" 1>&2 &\n" @@ -1754,10 +1776,10 @@ char create_display[] = " pid=$!\n" " sleep 10\n" " elif [ \"X$have_startx\" != \"X\" -o \"X$have_xinit\" != \"X\" ]; then\n" -" if [ \"X$have_startx\" != \"X\" ]; then\n" -" sxcmd=$have_startx\n" -" else\n" +" if [ \"X$have_xinit\" != \"X\" ]; then\n" " sxcmd=$have_xinit\n" +" else\n" +" sxcmd=$have_startx\n" " fi\n" " echo \"$sxcmd $sess -- $* $nolisten -auth $authfile $FD_OPTS\" 1>&2\n" " if [ \"X$have_root\" != \"X\" ]; then\n" @@ -1924,12 +1946,18 @@ char create_display[] = " sarg=\"screen\"\n" " fi\n" " fi\n" -" # remember to put server args after sarg ... to work on Solaris 9 and 10.\n" +" margs=\"+kb\"\n" +"\n" +" # currently not enabled in Xvfb's we see.\n" +"# if $have_Xvfb -extension MOOMOO 2>&1 | grep -w RANDR >/dev/null; then\n" +"# margs=\"$margs +extension RANDR\"\n" +"# fi\n" +"\n" " if [ $depth -ge 16 ]; then\n" -" server $have_Xvfb :$N $sarg 0 ${geom}x${depth} +kb -cc 4\n" -" else\n" -" server $have_Xvfb :$N $sarg 0 ${geom}x${depth} +kb\n" +" # avoid DirectColor for default visual:\n" +" margs=\"$margs -cc 4\"\n" " fi\n" +" server $have_Xvfb :$N $sarg 0 ${geom}x${depth} $margs\n" "\n" " if [ \"X$result\" = \"X1\" -a \"X$have_xmodmap\" != \"X\" ]; then\n" " if [ \"X$have_root\" = \"X\" ]; then\n" @@ -2030,6 +2058,10 @@ char create_display[] = " cook=`cookie`\n" " $have_xauth -f $tmp add :$N . $cook 1>&2\n" " $have_xauth -f $tmp add `hostname`:$N . $cook 1>&2\n" +" if [ \"X$CREATE_DISPLAY_EXEC\" != \"X\" ]; then\n" +" ls -l $tmp 1>&2\n" +" $have_xauth -f $tmp list 1>&2\n" +" fi\n" " echo \"$tmp\"\n" "}\n" "\n" @@ -2117,7 +2149,7 @@ char create_display[] = " USER=`whoami`\n" "fi\n" "\n" -"PATH=$PATH:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/dt/bin:/opt/kde3/bin:/opt/gnome/bin:/usr/bin:/bin:/usr/sfw/bin\n" +"PATH=$PATH:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/dt/bin:/opt/kde4/bin:/opt/kde3/bin:/opt/gnome/bin:/usr/bin:/bin:/usr/sfw/bin\n" "\n" "have_root=\"\"\n" "id0=`id`\n" @@ -2130,7 +2162,7 @@ char create_display[] = " p_ok=1\n" "fi\n" "\n" -"for prog in startx xinit xdm gdm kdm xterm Xdummy Xvfb Xvnc xauth xdpyinfo mcookie md5sum xmodmap startkde gnome-session blackbox fvwm2 mwm openbox twm windowmaker wmaker enlightenment metacity X Xorg XFree86 Xsun Xsession dtwm netstat nohup esddsp konsole gnome-terminal perl startxfce4 startxfce\n" +"for prog in startx xinit xdm gdm kdm xterm Xdummy Xvfb Xvnc xauth xdpyinfo mcookie md5sum xmodmap startkde dbus-launch gnome-session blackbox fvwm2 mwm openbox twm windowmaker wmaker enlightenment metacity X Xorg XFree86 Xsun Xsession dtwm netstat nohup esddsp konsole gnome-terminal x-terminal-emulator perl startxfce4 startxfce\n" "do\n" " p2=`echo \"$prog\" | sed -e 's/-/_/g'`\n" " eval \"have_$p2=''\"\n" @@ -2148,10 +2180,12 @@ char create_display[] = " fi\n" "done\n" "if [ \"X$have_xterm\" = \"X\" ]; then\n" -" if [ \"X$have_konsole\" != \"X\" ]; then\n" -" have_xterm=$have_konsole\n" -" elif [ \"X$have_gnome_terminal\" != \"X\" ]; then\n" +" if [ \"X$have_gnome_terminal\" != \"X\" ]; then\n" " have_xterm=$have_gnome_terminal\n" +" elif [ \"X$have_konsole\" != \"X\" ]; then\n" +" have_xterm=$have_konsole\n" +" elif [ \"X$have_x_terminal_emulator\" != \"X\" ]; then\n" +" have_xterm=$have_x_terminal_emulator\n" " fi\n" "fi\n" "\n" @@ -2182,9 +2216,15 @@ char create_display[] = " if echo \"$curr_try\" | egrep '[+.-]xdmcp' > /dev/null; then\n" " use_xdmcp_query=1\n" " fi\n" +"\n" +" if [ \"X$X11VNC_XDM_ONLY\" = \"X1\" -a \"X$use_xdmcp_query\" = \"X0\" ]; then\n" +" echo \"SKIPPING NON-XDMCP item '$curr_try' in X11VNC_XDM_ONLY=1 mode.\" 1>&2\n" +" continue\n" +" fi\n" +" \n" " curr_try=`echo \"$curr_try\" | sed -e 's/[+.-]xdmcp//'`\n" " curr_try=`echo \"$curr_try\" | sed -e 's/[+.-]redirect//'`\n" -" \n" +"\n" " if echo \"$curr_try\" | grep -i '^Xdummy\\>' > /dev/null; then\n" " try_Xdummy\n" " elif echo \"$curr_try\" | grep -i '^Xvfb\\>' > /dev/null; then\n" diff --git a/x11vnc/tkx11vnc b/x11vnc/tkx11vnc index ddb96a2..d34bf94 100755 --- a/x11vnc/tkx11vnc +++ b/x11vnc/tkx11vnc @@ -413,6 +413,7 @@ Tuning gaps: grow: fuzz: + extra_fbur: wait_ui: setdefer: nowait_bog @@ -749,7 +750,8 @@ more) via Properties -> Advanced -> Actions -> Quit non-standard listening port use \"host:port\". Pressing \"OK\" will initiate the reverse - connection. Use a blank hostname to skip it. + connection. Use a blank hostname to skip it, or + delete (\"X-out\") the window. " @@ -2985,7 +2987,12 @@ proc all_query_vars {} { } set cache_all_query_vars $qry -#puts $qry + global env + if [info exists env(TKX11VNC_PRINT_ALL_VARS)] { + puts "--------------- BEGIN ALL VARS ---------------" + puts $qry + puts "--------------- END ALL VARS ---------------" + } return $qry } @@ -6261,11 +6268,11 @@ proc run_remote_cmd_via_sock {opts} { } if {$db} {puts stderr "run_remote_cmd_via_sock: $docmd \"$str\""} - puts $client_sock $str + catch {puts $client_sock $str} if {$db} {puts stderr "run_remote_cmd_via_sock: flush"} - flush $client_sock + catch {flush $client_sock} if {$db} {puts stderr "run_remote_cmd_via_sock: gets"} - gets $client_sock res + catch {gets $client_sock res} if {$db} {puts stderr "run_remote_cmd_via_sock: \"$res\""} set res [string trim $res] @@ -6535,18 +6542,18 @@ proc do_port_prompt {} { } else { frame .pp.f -bd 1 -relief ridge -pady 2 } - label .pp.f.l -text "Port: " - entry .pp.f.e -width 8 -textvariable port_set + label .pp.f.l -text "Port: " -font $bfont + entry .pp.f.e -width 8 -textvariable port_set -font $ffont global enable_ssl; set enable_ssl 0 if [info exists env(X11VNC_SSL_ENABLED)] { set enable_ssl 1 } - checkbutton .pp.f.ssl -relief raised -pady 3 -padx 3 -text "Enable SSL" -variable enable_ssl + checkbutton .pp.f.ssl -relief raised -pady 3 -padx 3 -text "Enable SSL" -variable enable_ssl -font $bfont global localhost; set localhost 0 if [info exists env(X11VNC_LOCALHOST_ENABLED)] { set localhost 1 } - checkbutton .pp.f.loc -relief raised -pady 3 -padx 3 -text "Listen on localhost" -variable localhost + checkbutton .pp.f.loc -relief raised -pady 3 -padx 3 -text "Listen on localhost" -variable localhost -font $bfont pack .pp.f.l .pp.f.e -side left pack .pp.f.loc .pp.f.ssl -side right @@ -6559,15 +6566,15 @@ proc do_port_prompt {} { if [info exists env(X11VNC_FILETRANSFER_ENABLED)] { set file_transfer $env(X11VNC_FILETRANSFER_ENABLED) } - label .pp.t.l -text "File Transfer: " - radiobutton .pp.t.none -text "None" -variable file_transfer -value "none" - radiobutton .pp.t.ultra -text "UltraVNC" -variable file_transfer -value "ultra" - radiobutton .pp.t.tight -text "TightVNC" -variable file_transfer -value "tight" + label .pp.t.l -text "File Transfer: " -font $bfont + radiobutton .pp.t.none -text "None" -variable file_transfer -value "none" -font $bfont + radiobutton .pp.t.ultra -text "UltraVNC" -variable file_transfer -value "ultra" -font $bfont + radiobutton .pp.t.tight -text "TightVNC" -variable file_transfer -value "tight" -font $bfont pack .pp.t.l .pp.t.none .pp.t.ultra .pp.t.tight -side left frame .pp.o -bd 1 -relief ridge - button .pp.o.ok -text "OK" -command "set port_reply 1; destroy .pp" - button .pp.o.cancel -text "Cancel" -command "set port_reply 0; destroy .pp" + button .pp.o.ok -text "OK" -command "set port_reply 1; destroy .pp" -font $bfont + button .pp.o.cancel -text "Cancel" -command "set port_reply 0; destroy .pp" -font $bfont pack .pp.o.ok .pp.o.cancel -side left -fill x -expand 1 pack .pp.m -side top -fill x -expand 1 pack .pp.f .pp.t .pp.o -side top -fill x @@ -6794,6 +6801,24 @@ set sfont "-adobe-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*" set snfont "-adobe-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*" set ffont "fixed" +set got_helv 0 +catch { + foreach fam [font families] { + if {$fam == "helvetica"} { + set got_helv 1 + } + if {$fam == "Helvetica"} { + set got_helv 1 + } + } +} + +if {$got_helv} { + set bfont "Helvetica -12 bold" + set sfont "Helvetica -10 bold" + set snfont "Helvetica -10" +} + set ls "" catch {set ls [font metrics $bfont -linespace]} if {$ls != "" && $ls > 14} { @@ -6914,11 +6939,6 @@ if {"$argv" == "-spit"} { puts ";" exit 0 } -if {"$argv" == "-portprompt"} { - do_port_prompt - exit 0 -} - set_view_variable "full" @@ -6977,6 +6997,19 @@ if {[info exists env(X11VNC_GUI_PARAMS)]} { set x11vnc_gui_params "" } +if {[info exists env(X11VNC_FONT_BOLD)]} { + set bfont $env(X11VNC_FONT_BOLD) +} +if {[info exists env(X11VNC_FONT_BOLD_SMALL)]} { + set sfont $env(X11VNC_FONT_BOLD_SMALL) +} +if {[info exists env(X11VNC_FONT_REG_SMALL)]} { + set snfont $env(X11VNC_FONT_REG_SMALL) +} +if {[info exists env(X11VNC_FONT_FIXED)]} { + set ffont $env(X11VNC_FONT_FIXED) +} + if {[info exists env(X11VNC_CONNECT_FILE)]} { set x11vnc_connect_file $env(X11VNC_CONNECT_FILE); } else { @@ -7086,6 +7119,11 @@ if {[regexp -nocase {Darwin} $osname]} { set bfont {system} } +if {"$argv" == "-portprompt"} { + do_port_prompt + exit 0 +} + #puts [exec env] #puts "x11vnc_xdisplay: $x11vnc_xdisplay" diff --git a/x11vnc/tkx11vnc.h b/x11vnc/tkx11vnc.h index 49b25a3..8180fe2 100644 --- a/x11vnc/tkx11vnc.h +++ b/x11vnc/tkx11vnc.h @@ -424,6 +424,7 @@ char gui_code[] = ""; " gaps:\n" " grow:\n" " fuzz:\n" +" extra_fbur:\n" " wait_ui:\n" " setdefer:\n" " nowait_bog\n" @@ -760,7 +761,8 @@ char gui_code[] = ""; " non-standard listening port use \\\"host:port\\\".\n" "\n" " Pressing \\\"OK\\\" will initiate the reverse\n" -" connection. Use a blank hostname to skip it.\n" +" connection. Use a blank hostname to skip it, or\n" +" delete (\\\"X-out\\\") the window.\n" " \n" "\"\n" "\n" @@ -2996,7 +2998,12 @@ char gui_code[] = ""; " }\n" " set cache_all_query_vars $qry\n" "\n" -"#puts $qry\n" +" global env\n" +" if [info exists env(TKX11VNC_PRINT_ALL_VARS)] {\n" +" puts \"--------------- BEGIN ALL VARS ---------------\"\n" +" puts $qry\n" +" puts \"--------------- END ALL VARS ---------------\"\n" +" }\n" "\n" " return $qry\n" "}\n" @@ -6272,11 +6279,11 @@ char gui_code[] = ""; " }\n" "\n" " if {$db} {puts stderr \"run_remote_cmd_via_sock: $docmd \\\"$str\\\"\"}\n" -" puts $client_sock $str\n" +" catch {puts $client_sock $str}\n" " if {$db} {puts stderr \"run_remote_cmd_via_sock: flush\"}\n" -" flush $client_sock\n" +" catch {flush $client_sock}\n" " if {$db} {puts stderr \"run_remote_cmd_via_sock: gets\"}\n" -" gets $client_sock res\n" +" catch {gets $client_sock res}\n" " if {$db} {puts stderr \"run_remote_cmd_via_sock: \\\"$res\\\"\"}\n" " set res [string trim $res]\n" "\n" @@ -6546,18 +6553,18 @@ char gui_code[] = ""; " } else {\n" " frame .pp.f -bd 1 -relief ridge -pady 2\n" " }\n" -" label .pp.f.l -text \"Port: \"\n" -" entry .pp.f.e -width 8 -textvariable port_set\n" +" label .pp.f.l -text \"Port: \" -font $bfont\n" +" entry .pp.f.e -width 8 -textvariable port_set -font $ffont\n" " global enable_ssl; set enable_ssl 0\n" " if [info exists env(X11VNC_SSL_ENABLED)] {\n" " set enable_ssl 1\n" " }\n" -" checkbutton .pp.f.ssl -relief raised -pady 3 -padx 3 -text \"Enable SSL\" -variable enable_ssl\n" +" checkbutton .pp.f.ssl -relief raised -pady 3 -padx 3 -text \"Enable SSL\" -variable enable_ssl -font $bfont\n" " global localhost; set localhost 0\n" " if [info exists env(X11VNC_LOCALHOST_ENABLED)] {\n" " set localhost 1\n" " }\n" -" checkbutton .pp.f.loc -relief raised -pady 3 -padx 3 -text \"Listen on localhost\" -variable localhost\n" +" checkbutton .pp.f.loc -relief raised -pady 3 -padx 3 -text \"Listen on localhost\" -variable localhost -font $bfont\n" " pack .pp.f.l .pp.f.e -side left\n" " pack .pp.f.loc .pp.f.ssl -side right\n" "\n" @@ -6570,15 +6577,15 @@ char gui_code[] = ""; " if [info exists env(X11VNC_FILETRANSFER_ENABLED)] {\n" " set file_transfer $env(X11VNC_FILETRANSFER_ENABLED)\n" " }\n" -" label .pp.t.l -text \"File Transfer: \"\n" -" radiobutton .pp.t.none -text \"None\" -variable file_transfer -value \"none\"\n" -" radiobutton .pp.t.ultra -text \"UltraVNC\" -variable file_transfer -value \"ultra\"\n" -" radiobutton .pp.t.tight -text \"TightVNC\" -variable file_transfer -value \"tight\"\n" +" label .pp.t.l -text \"File Transfer: \" -font $bfont\n" +" radiobutton .pp.t.none -text \"None\" -variable file_transfer -value \"none\" -font $bfont\n" +" radiobutton .pp.t.ultra -text \"UltraVNC\" -variable file_transfer -value \"ultra\" -font $bfont\n" +" radiobutton .pp.t.tight -text \"TightVNC\" -variable file_transfer -value \"tight\" -font $bfont\n" " pack .pp.t.l .pp.t.none .pp.t.ultra .pp.t.tight -side left\n" "\n" " frame .pp.o -bd 1 -relief ridge\n" -" button .pp.o.ok -text \"OK\" -command \"set port_reply 1; destroy .pp\"\n" -" button .pp.o.cancel -text \"Cancel\" -command \"set port_reply 0; destroy .pp\"\n" +" button .pp.o.ok -text \"OK\" -command \"set port_reply 1; destroy .pp\" -font $bfont\n" +" button .pp.o.cancel -text \"Cancel\" -command \"set port_reply 0; destroy .pp\" -font $bfont\n" " pack .pp.o.ok .pp.o.cancel -side left -fill x -expand 1\n" " pack .pp.m -side top -fill x -expand 1 \n" " pack .pp.f .pp.t .pp.o -side top -fill x\n" @@ -6805,6 +6812,24 @@ char gui_code[] = ""; "set snfont \"-adobe-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*\"\n" "set ffont \"fixed\"\n" "\n" +"set got_helv 0\n" +"catch {\n" +" foreach fam [font families] {\n" +" if {$fam == \"helvetica\"} {\n" +" set got_helv 1\n" +" }\n" +" if {$fam == \"Helvetica\"} {\n" +" set got_helv 1\n" +" }\n" +" }\n" +"}\n" +"\n" +"if {$got_helv} {\n" +" set bfont \"Helvetica -12 bold\"\n" +" set sfont \"Helvetica -10 bold\"\n" +" set snfont \"Helvetica -10\"\n" +"}\n" +"\n" "set ls \"\"\n" "catch {set ls [font metrics $bfont -linespace]}\n" "if {$ls != \"\" && $ls > 14} {\n" @@ -6925,11 +6950,6 @@ char gui_code[] = ""; " puts \";\"\n" " exit 0\n" "}\n" -"if {\"$argv\" == \"-portprompt\"} {\n" -" do_port_prompt\n" -" exit 0\n" -"}\n" -"\n" "\n" "set_view_variable \"full\"\n" "\n" @@ -6988,6 +7008,19 @@ char gui_code[] = ""; " set x11vnc_gui_params \"\"\n" "}\n" "\n" +"if {[info exists env(X11VNC_FONT_BOLD)]} {\n" +" set bfont $env(X11VNC_FONT_BOLD)\n" +"}\n" +"if {[info exists env(X11VNC_FONT_BOLD_SMALL)]} {\n" +" set sfont $env(X11VNC_FONT_BOLD_SMALL)\n" +"}\n" +"if {[info exists env(X11VNC_FONT_REG_SMALL)]} {\n" +" set snfont $env(X11VNC_FONT_REG_SMALL)\n" +"}\n" +"if {[info exists env(X11VNC_FONT_FIXED)]} {\n" +" set ffont $env(X11VNC_FONT_FIXED)\n" +"}\n" +"\n" "if {[info exists env(X11VNC_CONNECT_FILE)]} {\n" " set x11vnc_connect_file $env(X11VNC_CONNECT_FILE);\n" "} else {\n" @@ -7097,6 +7130,11 @@ char gui_code[] = ""; " set bfont {system}\n" "}\n" "\n" +"if {\"$argv\" == \"-portprompt\"} {\n" +" do_port_prompt\n" +" exit 0\n" +"}\n" +"\n" "#puts [exec env]\n" "#puts \"x11vnc_xdisplay: $x11vnc_xdisplay\"\n" "\n" diff --git a/x11vnc/unixpw.c b/x11vnc/unixpw.c index 5ba3879..3f26319 100644 --- a/x11vnc/unixpw.c +++ b/x11vnc/unixpw.c @@ -96,7 +96,7 @@ void unixpw_accept(char *user); void unixpw_deny(void); void unixpw_msg(char *msg, int delay); int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int nodisp); -int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n, int nodisp); +int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n); int crypt_verify(char *user, char *pass); int cmd_verify(char *user, char *pass); void unixpw_verify_screen(char *user, char *pass); @@ -119,6 +119,237 @@ char *keep_unixpw_user = NULL; char *keep_unixpw_pass = NULL; char *keep_unixpw_opts = NULL; +/////// +static unsigned char default6x13FontData[2899]={ +0x00,0x00,0xA8,0x00,0x88,0x00,0x88,0x00,0x88,0x00,0xA8,0x00,0x00, /* 0 */ +0x00,0x00,0x00,0x00,0x20,0x70,0xF8,0x70,0x20,0x00,0x00,0x00,0x00, /* 1 */ +0xA8,0x54,0xA8,0x54,0xA8,0x54,0xA8,0x54,0xA8,0x54,0xA8,0x54,0xA8, /* 2 */ +0x00,0x00,0xA0,0xA0,0xE0,0xA0,0xA0,0x38,0x10,0x10,0x10,0x00,0x00, /* 3 */ +0x00,0x00,0xE0,0x80,0xC0,0x80,0xB8,0x20,0x30,0x20,0x20,0x00,0x00, /* 4 */ +0x00,0x00,0x60,0x80,0x80,0x60,0x30,0x28,0x30,0x28,0x28,0x00,0x00, /* 5 */ +0x00,0x00,0x80,0x80,0x80,0xE0,0x38,0x20,0x30,0x20,0x20,0x00,0x00, /* 6 */ +0x00,0x00,0x30,0x48,0x48,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 7 */ +0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0xF8,0x00,0x00,0x00, /* 8 */ +0x00,0x00,0x90,0xD0,0xB0,0x90,0x20,0x20,0x20,0x20,0x38,0x00,0x00, /* 9 */ +0x00,0x00,0xA0,0xA0,0xA0,0x40,0x40,0x38,0x10,0x10,0x10,0x00,0x00, /* 10 */ +0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, /* 11 */ +0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0x20,0x20, /* 12 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x20,0x20,0x20,0x20,0x20,0x20, /* 13 */ +0x20,0x20,0x20,0x20,0x20,0x20,0x3C,0x00,0x00,0x00,0x00,0x00,0x00, /* 14 */ +0x20,0x20,0x20,0x20,0x20,0x20,0xFC,0x20,0x20,0x20,0x20,0x20,0x20, /* 15 */ +0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16 */ +0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 17 */ +0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00, /* 18 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x00,0x00,0x00, /* 19 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, /* 20 */ +0x20,0x20,0x20,0x20,0x20,0x20,0x3C,0x20,0x20,0x20,0x20,0x20,0x20, /* 21 */ +0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x20,0x20,0x20,0x20,0x20,0x20, /* 22 */ +0x20,0x20,0x20,0x20,0x20,0x20,0xFC,0x00,0x00,0x00,0x00,0x00,0x00, /* 23 */ +0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x20,0x20,0x20,0x20,0x20,0x20, /* 24 */ +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, /* 25 */ +0x00,0x00,0x00,0x18,0x60,0x80,0x60,0x18,0x00,0xF8,0x00,0x00,0x00, /* 26 */ +0x00,0x00,0x00,0xC0,0x30,0x08,0x30,0xC0,0x00,0xF8,0x00,0x00,0x00, /* 27 */ +0x00,0x00,0x00,0x00,0x00,0xF8,0x50,0x50,0x50,0x50,0x50,0x00,0x00, /* 28 */ +0x00,0x00,0x00,0x00,0x00,0x08,0xF8,0x20,0xF8,0x80,0x00,0x00,0x00, /* 29 */ +0x00,0x00,0x30,0x48,0x40,0x40,0xE0,0x40,0x40,0x48,0xB0,0x00,0x00, /* 30 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00, /* 31 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32 */ +0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, /* 33 */ +0x00,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 34 */ +0x00,0x00,0x00,0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00,0x00,0x00, /* 35 */ +0x00,0x00,0x20,0x78,0xA0,0xA0,0x70,0x28,0x28,0xF0,0x20,0x00,0x00, /* 36 */ +0x00,0x00,0x48,0xA8,0x50,0x10,0x20,0x40,0x50,0xA8,0x90,0x00,0x00, /* 37 */ +0x00,0x00,0x00,0x40,0xA0,0xA0,0x40,0xA0,0x98,0x90,0x68,0x00,0x00, /* 38 */ +0x00,0x00,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 39 */ +0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x00, /* 40 */ +0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40,0x00, /* 41 */ +0x00,0x00,0x00,0x20,0xA8,0xF8,0x70,0xF8,0xA8,0x20,0x00,0x00,0x00, /* 42 */ +0x00,0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00,0x00,0x00, /* 43 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x20,0x40,0x00, /* 44 */ +0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, /* 45 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x70,0x20,0x00, /* 46 */ +0x00,0x00,0x08,0x08,0x10,0x10,0x20,0x40,0x40,0x80,0x80,0x00,0x00, /* 47 */ +0x00,0x00,0x20,0x50,0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00,0x00, /* 48 */ +0x00,0x00,0x20,0x60,0xA0,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00, /* 49 */ +0x00,0x00,0x70,0x88,0x88,0x08,0x10,0x20,0x40,0x80,0xF8,0x00,0x00, /* 50 */ +0x00,0x00,0xF8,0x08,0x10,0x20,0x70,0x08,0x08,0x88,0x70,0x00,0x00, /* 51 */ +0x00,0x00,0x10,0x10,0x30,0x50,0x50,0x90,0xF8,0x10,0x10,0x00,0x00, /* 52 */ +0x00,0x00,0xF8,0x80,0x80,0xB0,0xC8,0x08,0x08,0x88,0x70,0x00,0x00, /* 53 */ +0x00,0x00,0x70,0x88,0x80,0x80,0xF0,0x88,0x88,0x88,0x70,0x00,0x00, /* 54 */ +0x00,0x00,0xF8,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00,0x00, /* 55 */ +0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x88,0x70,0x00,0x00, /* 56 */ +0x00,0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x08,0x88,0x70,0x00,0x00, /* 57 */ +0x00,0x00,0x00,0x00,0x20,0x70,0x20,0x00,0x00,0x20,0x70,0x20,0x00, /* 58 */ +0x00,0x00,0x00,0x00,0x20,0x70,0x20,0x00,0x00,0x30,0x20,0x40,0x00, /* 59 */ +0x00,0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00,0x00, /* 60 */ +0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, /* 61 */ +0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00,0x00, /* 62 */ +0x00,0x00,0x70,0x88,0x88,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00, /* 63 */ +0x00,0x00,0x70,0x88,0x88,0x98,0xA8,0xA8,0xB0,0x80,0x78,0x00,0x00, /* 64 */ +0x00,0x00,0x20,0x50,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00,0x00, /* 65 */ +0x00,0x00,0xF0,0x48,0x48,0x48,0x70,0x48,0x48,0x48,0xF0,0x00,0x00, /* 66 */ +0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x80,0x80,0x88,0x70,0x00,0x00, /* 67 */ +0x00,0x00,0xF0,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0xF0,0x00,0x00, /* 68 */ +0x00,0x00,0xF8,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0xF8,0x00,0x00, /* 69 */ +0x00,0x00,0xF8,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0x80,0x00,0x00, /* 70 */ +0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x98,0x88,0x88,0x70,0x00,0x00, /* 71 */ +0x00,0x00,0x88,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x88,0x00,0x00, /* 72 */ +0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 73 */ +0x00,0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x00, /* 74 */ +0x00,0x00,0x88,0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x88,0x00,0x00, /* 75 */ +0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00,0x00, /* 76 */ +0x00,0x00,0x88,0x88,0xD8,0xA8,0xA8,0x88,0x88,0x88,0x88,0x00,0x00, /* 77 */ +0x00,0x00,0x88,0xC8,0xC8,0xA8,0xA8,0x98,0x98,0x88,0x88,0x00,0x00, /* 78 */ +0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 79 */ +0x00,0x00,0xF0,0x88,0x88,0x88,0xF0,0x80,0x80,0x80,0x80,0x00,0x00, /* 80 */ +0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0xA8,0x70,0x08,0x00, /* 81 */ +0x00,0x00,0xF0,0x88,0x88,0x88,0xF0,0xA0,0x90,0x88,0x88,0x00,0x00, /* 82 */ +0x00,0x00,0x70,0x88,0x80,0x80,0x70,0x08,0x08,0x88,0x70,0x00,0x00, /* 83 */ +0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, /* 84 */ +0x00,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 85 */ +0x00,0x00,0x88,0x88,0x88,0x88,0x50,0x50,0x50,0x20,0x20,0x00,0x00, /* 86 */ +0x00,0x00,0x88,0x88,0x88,0x88,0xA8,0xA8,0xA8,0xA8,0x50,0x00,0x00, /* 87 */ +0x00,0x00,0x88,0x88,0x50,0x50,0x20,0x50,0x50,0x88,0x88,0x00,0x00, /* 88 */ +0x00,0x00,0x88,0x88,0x50,0x50,0x20,0x20,0x20,0x20,0x20,0x00,0x00, /* 89 */ +0x00,0x00,0xF8,0x08,0x10,0x10,0x20,0x40,0x40,0x80,0xF8,0x00,0x00, /* 90 */ +0x00,0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, /* 91 */ +0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x10,0x08,0x08,0x00,0x00, /* 92 */ +0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, /* 93 */ +0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 94 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00, /* 95 */ +0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 96 */ +0x00,0x00,0x00,0x00,0x00,0x70,0x08,0x78,0x88,0x98,0x68,0x00,0x00, /* 97 */ +0x00,0x00,0x80,0x80,0x80,0xF0,0x88,0x88,0x88,0x88,0xF0,0x00,0x00, /* 98 */ +0x00,0x00,0x00,0x00,0x00,0x70,0x88,0x80,0x80,0x88,0x70,0x00,0x00, /* 99 */ +0x00,0x00,0x08,0x08,0x08,0x78,0x88,0x88,0x88,0x88,0x78,0x00,0x00, /* 100 */ +0x00,0x00,0x00,0x00,0x00,0x70,0x88,0xF8,0x80,0x88,0x70,0x00,0x00, /* 101 */ +0x00,0x00,0x30,0x48,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x00,0x00, /* 102 */ +0x00,0x00,0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x88,0x70, /* 103 */ +0x00,0x00,0x80,0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x88,0x00,0x00, /* 104 */ +0x00,0x00,0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 105 */ +0x00,0x00,0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x90,0x90,0x60, /* 106 */ +0x00,0x00,0x80,0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00,0x00, /* 107 */ +0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 108 */ +0x00,0x00,0x00,0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x88,0x00,0x00, /* 109 */ +0x00,0x00,0x00,0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x88,0x00,0x00, /* 110 */ +0x00,0x00,0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 111 */ +0x00,0x00,0x00,0x00,0x00,0xF0,0x88,0x88,0x88,0xF0,0x80,0x80,0x80, /* 112 */ +0x00,0x00,0x00,0x00,0x00,0x78,0x88,0x88,0x88,0x78,0x08,0x08,0x08, /* 113 */ +0x00,0x00,0x00,0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x80,0x00,0x00, /* 114 */ +0x00,0x00,0x00,0x00,0x00,0x70,0x88,0x60,0x10,0x88,0x70,0x00,0x00, /* 115 */ +0x00,0x00,0x00,0x40,0x40,0xF0,0x40,0x40,0x40,0x48,0x30,0x00,0x00, /* 116 */ +0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x98,0x68,0x00,0x00, /* 117 */ +0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x00,0x00, /* 118 */ +0x00,0x00,0x00,0x00,0x00,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00,0x00, /* 119 */ +0x00,0x00,0x00,0x00,0x00,0x88,0x50,0x20,0x20,0x50,0x88,0x00,0x00, /* 120 */ +0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x08,0x88,0x70, /* 121 */ +0x00,0x00,0x00,0x00,0x00,0xF8,0x10,0x20,0x40,0x80,0xF8,0x00,0x00, /* 122 */ +0x00,0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, /* 123 */ +0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, /* 124 */ +0x00,0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0,0x00, /* 125 */ +0x00,0x00,0x48,0xA8,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 126 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160 */ +0x00,0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, /* 161 */ +0x00,0x00,0x20,0x70,0xA8,0xA0,0xA0,0xA8,0x70,0x20,0x00,0x00,0x00, /* 162 */ +0x00,0x00,0x30,0x48,0x40,0x40,0xE0,0x40,0x40,0x48,0xB0,0x00,0x00, /* 163 */ +0x00,0x00,0x00,0x00,0x88,0x70,0x50,0x50,0x70,0x88,0x00,0x00,0x00, /* 164 */ +0x00,0x00,0x88,0x88,0x50,0x50,0xF8,0x20,0xF8,0x20,0x20,0x00,0x00, /* 165 */ +0x00,0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00,0x00, /* 166 */ +0x00,0x30,0x48,0x40,0x30,0x48,0x48,0x30,0x08,0x48,0x30,0x00,0x00, /* 167 */ +0x00,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168 */ +0x00,0x70,0x88,0xA8,0xD8,0xC8,0xD8,0xA8,0x88,0x70,0x00,0x00,0x00, /* 169 */ +0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x00,0xF8,0x00,0x00,0x00,0x00, /* 170 */ +0x00,0x00,0x00,0x00,0x28,0x50,0xA0,0xA0,0x50,0x28,0x00,0x00,0x00, /* 171 */ +0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x08,0x08,0x00,0x00,0x00,0x00, /* 172 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00, /* 173 */ +0x00,0x70,0x88,0xE8,0xD8,0xD8,0xE8,0xD8,0x88,0x70,0x00,0x00,0x00, /* 174 */ +0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 175 */ +0x00,0x00,0x30,0x48,0x48,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176 */ +0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0xF8,0x00,0x00,0x00, /* 177 */ +0x00,0x40,0xA0,0x20,0x40,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 178 */ +0x00,0x40,0xA0,0x40,0x20,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 179 */ +0x00,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 180 */ +0x00,0x00,0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x98,0xE8,0x80,0x80, /* 181 */ +0x00,0x00,0x78,0xE8,0xE8,0xE8,0xE8,0x68,0x28,0x28,0x28,0x00,0x00, /* 182 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00, /* 183 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x20, /* 184 */ +0x00,0x40,0xC0,0x40,0x40,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 185 */ +0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00,0xF8,0x00,0x00,0x00,0x00, /* 186 */ +0x00,0x00,0x00,0x00,0xA0,0x50,0x28,0x28,0x50,0xA0,0x00,0x00,0x00, /* 187 */ +0x00,0x40,0xC0,0x40,0x40,0xE0,0x08,0x18,0x28,0x38,0x08,0x00,0x00, /* 188 */ +0x00,0x40,0xC0,0x40,0x40,0xE0,0x10,0x28,0x08,0x10,0x38,0x00,0x00, /* 189 */ +0x00,0x40,0xA0,0x40,0x20,0xA0,0x48,0x18,0x28,0x38,0x08,0x00,0x00, /* 190 */ +0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x80,0x88,0x88,0x70,0x00,0x00, /* 191 */ +0x00,0x40,0x20,0x00,0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00,0x00, /* 192 */ +0x00,0x10,0x20,0x00,0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00,0x00, /* 193 */ +0x00,0x30,0x48,0x00,0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00,0x00, /* 194 */ +0x00,0x28,0x50,0x00,0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00,0x00, /* 195 */ +0x00,0x50,0x50,0x00,0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00,0x00, /* 196 */ +0x00,0x20,0x50,0x20,0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00,0x00, /* 197 */ +0x00,0x00,0x58,0xA0,0xA0,0xA0,0xB0,0xE0,0xA0,0xA0,0xB8,0x00,0x00, /* 198 */ +0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x80,0x80,0x88,0x70,0x20,0x40, /* 199 */ +0x00,0x40,0x20,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00,0x00, /* 200 */ +0x00,0x10,0x20,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00,0x00, /* 201 */ +0x00,0x30,0x48,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00,0x00, /* 202 */ +0x00,0x50,0x50,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00,0x00, /* 203 */ +0x00,0x40,0x20,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 204 */ +0x00,0x10,0x20,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 205 */ +0x00,0x30,0x48,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 206 */ +0x00,0x50,0x50,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 207 */ +0x00,0x00,0xF0,0x48,0x48,0x48,0xE8,0x48,0x48,0x48,0xF0,0x00,0x00, /* 208 */ +0x00,0x28,0x50,0x00,0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00,0x00, /* 209 */ +0x00,0x40,0x20,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 210 */ +0x00,0x10,0x20,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 211 */ +0x00,0x30,0x48,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 212 */ +0x00,0x28,0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 213 */ +0x00,0x50,0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 214 */ +0x00,0x00,0x00,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,0x00, /* 215 */ +0x00,0x08,0x70,0x98,0x98,0xA8,0xA8,0xA8,0xC8,0xC8,0x70,0x80,0x00, /* 216 */ +0x00,0x40,0x20,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 217 */ +0x00,0x10,0x20,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 218 */ +0x00,0x30,0x48,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 219 */ +0x00,0x50,0x50,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 220 */ +0x00,0x10,0x20,0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00,0x00, /* 221 */ +0x00,0x00,0x80,0xF0,0x88,0x88,0x88,0xF0,0x80,0x80,0x80,0x00,0x00, /* 222 */ +0x00,0x00,0x60,0x90,0x90,0xA0,0xA0,0x90,0x88,0x88,0xB0,0x00,0x00, /* 223 */ +0x00,0x00,0x40,0x20,0x00,0x70,0x08,0x78,0x88,0x98,0x68,0x00,0x00, /* 224 */ +0x00,0x00,0x10,0x20,0x00,0x70,0x08,0x78,0x88,0x98,0x68,0x00,0x00, /* 225 */ +0x00,0x00,0x30,0x48,0x00,0x70,0x08,0x78,0x88,0x98,0x68,0x00,0x00, /* 226 */ +0x00,0x00,0x28,0x50,0x00,0x70,0x08,0x78,0x88,0x98,0x68,0x00,0x00, /* 227 */ +0x00,0x00,0x50,0x50,0x00,0x70,0x08,0x78,0x88,0x98,0x68,0x00,0x00, /* 228 */ +0x00,0x30,0x48,0x30,0x00,0x70,0x08,0x78,0x88,0x98,0x68,0x00,0x00, /* 229 */ +0x00,0x00,0x00,0x00,0x00,0x70,0x28,0x70,0xA0,0xA8,0x50,0x00,0x00, /* 230 */ +0x00,0x00,0x00,0x00,0x00,0x70,0x88,0x80,0x80,0x88,0x70,0x20,0x40, /* 231 */ +0x00,0x00,0x40,0x20,0x00,0x70,0x88,0xF8,0x80,0x88,0x70,0x00,0x00, /* 232 */ +0x00,0x00,0x10,0x20,0x00,0x70,0x88,0xF8,0x80,0x88,0x70,0x00,0x00, /* 233 */ +0x00,0x00,0x30,0x48,0x00,0x70,0x88,0xF8,0x80,0x88,0x70,0x00,0x00, /* 234 */ +0x00,0x00,0x50,0x50,0x00,0x70,0x88,0xF8,0x80,0x88,0x70,0x00,0x00, /* 235 */ +0x00,0x00,0x40,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 236 */ +0x00,0x00,0x10,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 237 */ +0x00,0x00,0x30,0x48,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 238 */ +0x00,0x00,0x50,0x50,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, /* 239 */ +0x00,0x50,0x20,0x60,0x10,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 240 */ +0x00,0x00,0x28,0x50,0x00,0xB0,0xC8,0x88,0x88,0x88,0x88,0x00,0x00, /* 241 */ +0x00,0x00,0x40,0x20,0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 242 */ +0x00,0x00,0x10,0x20,0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 243 */ +0x00,0x00,0x30,0x48,0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 244 */ +0x00,0x00,0x28,0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 245 */ +0x00,0x00,0x50,0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00, /* 246 */ +0x00,0x00,0x00,0x20,0x20,0x00,0xF8,0x00,0x20,0x20,0x00,0x00,0x00, /* 247 */ +0x00,0x00,0x00,0x00,0x08,0x70,0x98,0xA8,0xA8,0xC8,0x70,0x80,0x00, /* 248 */ +0x00,0x00,0x40,0x20,0x00,0x88,0x88,0x88,0x88,0x98,0x68,0x00,0x00, /* 249 */ +0x00,0x00,0x10,0x20,0x00,0x88,0x88,0x88,0x88,0x98,0x68,0x00,0x00, /* 250 */ +0x00,0x00,0x30,0x48,0x00,0x88,0x88,0x88,0x88,0x98,0x68,0x00,0x00, /* 251 */ +0x00,0x00,0x50,0x50,0x00,0x88,0x88,0x88,0x88,0x98,0x68,0x00,0x00, /* 252 */ +0x00,0x00,0x10,0x20,0x00,0x88,0x88,0x88,0x98,0x68,0x08,0x88,0x70, /* 253 */ +0x00,0x00,0x00,0x80,0x80,0xB0,0xC8,0x88,0x88,0xC8,0xB0,0x80,0x80, /* 254 */ +0x00,0x00,0x50,0x50,0x00,0x88,0x88,0x88,0x98,0x68,0x08,0x88,0x70, /* 255 */ +}; +static int default6x13FontMetaData[256*5]={ +0,6,13,0,-2,13,6,13,0,-2,26,6,13,0,-2,39,6,13,0,-2,52,6,13,0,-2,65,6,13,0,-2,78,6,13,0,-2,91,6,13,0,-2,104,6,13,0,-2,117,6,13,0,-2,130,6,13,0,-2,143,6,13,0,-2,156,6,13,0,-2,169,6,13,0,-2,182,6,13,0,-2,195,6,13,0,-2,208,6,13,0,-2,221,6,13,0,-2,234,6,13,0,-2,247,6,13,0,-2,260,6,13,0,-2,273,6,13,0,-2,286,6,13,0,-2,299,6,13,0,-2,312,6,13,0,-2,325,6,13,0,-2,338,6,13,0,-2,351,6,13,0,-2,364,6,13,0,-2,377,6,13,0,-2,390,6,13,0,-2,403,6,13,0,-2,416,6,13,0,-2,429,6,13,0,-2,442,6,13,0,-2,455,6,13,0,-2,468,6,13,0,-2,481,6,13,0,-2,494,6,13,0,-2,507,6,13,0,-2,520,6,13,0,-2,533,6,13,0,-2,546,6,13,0,-2,559,6,13,0,-2,572,6,13,0,-2,585,6,13,0,-2,598,6,13,0,-2,611,6,13,0,-2,624,6,13,0,-2,637,6,13,0,-2,650,6,13,0,-2,663,6,13,0,-2,676,6,13,0,-2,689,6,13,0,-2,702,6,13,0,-2,715,6,13,0,-2,728,6,13,0,-2,741,6,13,0,-2,754,6,13,0,-2,767,6,13,0,-2,780,6,13,0,-2,793,6,13,0,-2,806,6,13,0,-2,819,6,13,0,-2,832,6,13,0,-2,845,6,13,0,-2,858,6,13,0,-2,871,6,13,0,-2,884,6,13,0,-2,897,6,13,0,-2,910,6,13,0,-2,923,6,13,0,-2,936,6,13,0,-2,949,6,13,0,-2,962,6,13,0,-2,975,6,13,0,-2,988,6,13,0,-2,1001,6,13,0,-2,1014,6,13,0,-2,1027,6,13,0,-2,1040,6,13,0,-2,1053,6,13,0,-2,1066,6,13,0,-2,1079,6,13,0,-2,1092,6,13,0,-2,1105,6,13,0,-2,1118,6,13,0,-2,1131,6,13,0,-2,1144,6,13,0,-2,1157,6,13,0,-2,1170,6,13,0,-2,1183,6,13,0,-2,1196,6,13,0,-2,1209,6,13,0,-2,1222,6,13,0,-2,1235,6,13,0,-2,1248,6,13,0,-2,1261,6,13,0,-2,1274,6,13,0,-2,1287,6,13,0,-2,1300,6,13,0,-2,1313,6,13,0,-2,1326,6,13,0,-2,1339,6,13,0,-2,1352,6,13,0,-2,1365,6,13,0,-2,1378,6,13,0,-2,1391,6,13,0,-2,1404,6,13,0,-2,1417,6,13,0,-2,1430,6,13,0,-2,1443,6,13,0,-2,1456,6,13,0,-2,1469,6,13,0,-2,1482,6,13,0,-2,1495,6,13,0,-2,1508,6,13,0,-2,1521,6,13,0,-2,1534,6,13,0,-2,1547,6,13,0,-2,1560,6,13,0,-2,1573,6,13,0,-2,1586,6,13,0,-2,1599,6,13,0,-2,1612,6,13,0,-2,1625,6,13,0,-2,1638,6,13,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1651,6,13,0,-2,1664,6,13,0,-2,1677,6,13,0,-2,1690,6,13,0,-2,1703,6,13,0,-2,1716,6,13,0,-2,1729,6,13,0,-2,1742,6,13,0,-2,1755,6,13,0,-2,1768,6,13,0,-2,1781,6,13,0,-2,1794,6,13,0,-2,1807,6,13,0,-2,1820,6,13,0,-2,1833,6,13,0,-2,1846,6,13,0,-2,1859,6,13,0,-2,1872,6,13,0,-2,1885,6,13,0,-2,1898,6,13,0,-2,1911,6,13,0,-2,1924,6,13,0,-2,1937,6,13,0,-2,1950,6,13,0,-2,1963,6,13,0,-2,1976,6,13,0,-2,1989,6,13,0,-2,2002,6,13,0,-2,2015,6,13,0,-2,2028,6,13,0,-2,2041,6,13,0,-2,2054,6,13,0,-2,2067,6,13,0,-2,2080,6,13,0,-2,2093,6,13,0,-2,2106,6,13,0,-2,2119,6,13,0,-2,2132,6,13,0,-2,2145,6,13,0,-2,2158,6,13,0,-2,2171,6,13,0,-2,2184,6,13,0,-2,2197,6,13,0,-2,2210,6,13,0,-2,2223,6,13,0,-2,2236,6,13,0,-2,2249,6,13,0,-2,2262,6,13,0,-2,2275,6,13,0,-2,2288,6,13,0,-2,2301,6,13,0,-2,2314,6,13,0,-2,2327,6,13,0,-2,2340,6,13,0,-2,2353,6,13,0,-2,2366,6,13,0,-2,2379,6,13,0,-2,2392,6,13,0,-2,2405,6,13,0,-2,2418,6,13,0,-2,2431,6,13,0,-2,2444,6,13,0,-2,2457,6,13,0,-2,2470,6,13,0,-2,2483,6,13,0,-2,2496,6,13,0,-2,2509,6,13,0,-2,2522,6,13,0,-2,2535,6,13,0,-2,2548,6,13,0,-2,2561,6,13,0,-2,2574,6,13,0,-2,2587,6,13,0,-2,2600,6,13,0,-2,2613,6,13,0,-2,2626,6,13,0,-2,2639,6,13,0,-2,2652,6,13,0,-2,2665,6,13,0,-2,2678,6,13,0,-2,2691,6,13,0,-2,2704,6,13,0,-2,2717,6,13,0,-2,2730,6,13,0,-2,2743,6,13,0,-2,2756,6,13,0,-2,2769,6,13,0,-2,2782,6,13,0,-2,2795,6,13,0,-2,2808,6,13,0,-2,2821,6,13,0,-2,2834,6,13,0,-2,2847,6,13,0,-2,2860,6,13,0,-2,2873,6,13,0,-2,2886,6,13,0,-2,}; +static rfbFontData default6x13Font={default6x13FontData, default6x13FontMetaData}; +/////// + static int in_login = 0, in_passwd = 0, tries = 0; static int char_row = 0, char_col = 0; static int char_x = 0, char_y = 0, char_w = 8, char_h = 16; @@ -146,6 +377,35 @@ int white_pixel(void) { } } +int black_pixel(void) { + static unsigned long black_pix = 0, white_pix = 1, set = 0; + + RAWFB_RET(0x000000) + + if (depth <= 8 && ! set) { + X_LOCK; + black_pix = BlackPixel(dpy, scr); + white_pix = WhitePixel(dpy, scr); + X_UNLOCK; + set = 1; + } + if (depth <= 8) { + return (int) black_pix; + } else if (depth < 24) { + return 0x0000; + } else { + return 0x000000; + } +} + +static void unixpw_mark(void) { + if (scaling) { + mark_rect_as_modified(0, 0, scaled_x, scaled_y, 1); + } else { + mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); + } +} + static int text_x(void) { return char_x + char_col * char_w; } @@ -157,6 +417,8 @@ static int text_y(void) { static rfbScreenInfo fscreen; static rfbScreenInfoPtr pscreen; +static int f1_help = 0; + void unixpw_screen(int init) { if (unixpw_cmd) { ; /* OK */ @@ -180,7 +442,7 @@ void unixpw_screen(int init) { mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); x = nfix(dpy_x / 2 - strlen(log) * char_w, dpy_x); - y = dpy_y / 4; + y = (int) (dpy_y / 3.5); if (scaling) { x = (int) (x * scale_fac_x); @@ -198,6 +460,21 @@ void unixpw_screen(int init) { pscreen = screen; } + if (pscreen && pscreen->width >= 640) { + rfbDrawString(pscreen, &default6x13Font, 8, 2+1*13, "F1-Help:", white_pixel()); + } + f1_help = 0; + + if (unixpw_system_greeter) { + unixpw_system_greeter_active = 0; + if (use_dpy && strstr(use_dpy, "xdmcp")) { + char moo[] = "Press 'Escape' for System Greeter"; + set_env("X11VNC_XDM_ONLY", "0"); + unixpw_system_greeter_active = 1; + rfbDrawString(pscreen, &default8x16Font, x-90, y-30, moo, white_pixel()); + } + } + rfbDrawString(pscreen, &default8x16Font, x, y, log, white_pixel()); char_x = x; @@ -208,11 +485,7 @@ void unixpw_screen(int init) { set_warrow_cursor(); } - if (scaling) { - mark_rect_as_modified(0, 0, scaled_x, scaled_y, 1); - } else { - mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); - } + unixpw_mark(); } @@ -531,7 +804,7 @@ int crypt_verify(char *user, char *pass) { #endif /* UNIXPW_CRYPT */ } -int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n, int nodisp) { +int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n) { int i, len, rc; char *str; FILE *out; @@ -1218,11 +1491,7 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "*** char_col = strlen(log); - if (scaling) { - mark_rect_as_modified(0, 0, scaled_x, scaled_y, 1); - } else { - mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); - } + unixpw_mark(); unixpw_last_try_time = time(NULL); unixpw_keystroke(0, 0, 2); @@ -1246,6 +1515,11 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) { static int echo = 1; char keystr[100]; char *str; + static int skip_it = 0; + + if (skip_it) { + return; + } if (first) { set_db(); @@ -1328,6 +1602,68 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) { } else if (! down) { return; } + if (keysym == XK_F1 && pscreen && pscreen->width >= 640) { + char h1[] = "F1-Help: For 'login:' type in the username and press Enter, then for 'Password:' type in the password."; + char h2[] = " Specify options after a ':' like this: username:opt,opt=val,... Where an opt may be any of:"; + char h3[] = " scale=... (n/m); scale_cursor=... (sc=); solid (so); id=; repeat; clear_mods (cm); clear_keys (ck);"; + char h4[] = " clear_all (ca); speeds=... (sp=); readtimeout=... (rd=) rotate=... (ro=); noncache (nc) (nc=n);"; + char h5[] = " geom=WxHxD (ge=); nodisplay=... (nd=); viewonly (vo); gnome kde twm fvwm mwm dtwm wmaker xfce"; + char h6[] = " enlightenment Xsession failsafe. Examples: fred:3/4,so,cm wilma:geom=1024x768x16,kde"; + int ch = 13, p; + if (f1_help) { + p = black_pixel(); + f1_help = 0; + } else { + p = white_pixel(); + f1_help = 1; + unixpw_last_try_time = time(NULL) + 45; + } + rfbDrawString(pscreen, &default6x13Font, 8, 2+1*ch, h1, p); + rfbDrawString(pscreen, &default6x13Font, 8, 2+2*ch, h2, p); + rfbDrawString(pscreen, &default6x13Font, 8, 2+3*ch, h3, p); + rfbDrawString(pscreen, &default6x13Font, 8, 2+4*ch, h4, p); + rfbDrawString(pscreen, &default6x13Font, 8, 2+5*ch, h5, p); + rfbDrawString(pscreen, &default6x13Font, 8, 2+6*ch, h6, p); + if (!f1_help) { + rfbDrawString(pscreen, &default6x13Font, 8, 2+1*ch, "F1-Help:", white_pixel()); + } + unixpw_mark(); + return; + } + if (unixpw_system_greeter_active && keysym == XK_Escape) { + char *u = get_user_name(); + if (keep_unixpw) { + char *colon = strchr(user, ':'); + keep_unixpw_user = strdup(u); + keep_unixpw_pass = strdup(""); + if (colon) { + keep_unixpw_opts = strdup(colon+1); + } else { + keep_unixpw_opts = strdup(""); + } + } + unixpw_system_greeter_active = 2; + set_env("X11VNC_XDM_ONLY", "1"); + rfbLog("unixpw_system_greeter: VNC client pressed 'Escape'. Allowing\n"); + rfbLog("unixpw_system_greeter: a *FREE* (no password) connection to\n"); + rfbLog("unixpw_system_greeter: the system XDM/GDM/KDM login greeter.\n"); + if (1) { + char msg[] = " Please wait... "; + rfbDrawString(pscreen, &default8x16Font, + text_x(), text_y(), msg, white_pixel()); + unixpw_mark(); + skip_it = 1; + rfbPE(-1); + rfbPE(-1); + rfbPE(-1); + skip_it = 0; + usleep(10*1000); + } + unixpw_accept(u); + free(u); + return; + } + if (in_login && keysym == XK_Escape && u_cnt == 0) { echo = 0; rfbLog("unixpw_keystroke: echo off.\n"); @@ -1389,13 +1725,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) { white_pixel()); char_col = strlen(pw); - if (scaling) { - mark_rect_as_modified(0, 0, scaled_x, - scaled_y, 1); - } else { - mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); - } - + unixpw_mark(); return; } @@ -1428,7 +1758,6 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) { char_col++; usleep(10*1000); } - return; } @@ -1493,6 +1822,19 @@ if (db && db <= 2) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x '%s'\n", u_cnt, x, return; } + if (1) { + char msg[] = " Please wait... "; + rfbDrawString(pscreen, &default8x16Font, + text_x(), text_y(), msg, white_pixel()); + unixpw_mark(); + skip_it = 1; + rfbPE(-1); + rfbPE(-1); + rfbPE(-1); + skip_it = 0; + usleep(10*1000); + } + in_login = 0; in_passwd = 0; @@ -1630,7 +1972,9 @@ static void apply_opts (char *user) { void unixpw_accept(char *user) { apply_opts(user); - ssl_helper_pid(0, -2); /* waitall */ + if (!use_stunnel) { + ssl_helper_pid(0, -2); /* waitall */ + } if (accept_cmd && strstr(accept_cmd, "popup") == accept_cmd) { if (use_dpy && strstr(use_dpy, "WAIT:") == use_dpy && @@ -1711,14 +2055,11 @@ void unixpw_deny(void) { y = char_y + char_row * char_h; rfbDrawString(pscreen, &default8x16Font, x, y, pd, white_pixel()); - if (scaling) { - mark_rect_as_modified(0, 0, scaled_x, scaled_y, 1); - } else { - mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); - } + unixpw_mark(); for (i=0; i<5; i++) { rfbPE(-1); + rfbPE(-1); usleep(500 * 1000); } } @@ -1750,14 +2091,11 @@ void unixpw_msg(char *msg, int delay) { y = char_y + char_row * char_h; rfbDrawString(pscreen, &default8x16Font, x, y, msg, white_pixel()); - if (scaling) { - mark_rect_as_modified(0, 0, scaled_x, scaled_y, 1); - } else { - mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); - } + unixpw_mark(); for (i=0; i<5; i++) { rfbPE(-1); + rfbPE(-1); usleep(500 * 1000); if (i >= delay) { break; diff --git a/x11vnc/unixpw.h b/x11vnc/unixpw.h index 6da79e0..8675624 100644 --- a/x11vnc/unixpw.h +++ b/x11vnc/unixpw.h @@ -42,7 +42,7 @@ extern void unixpw_accept(char *user); extern void unixpw_deny(void); extern void unixpw_msg(char *msg, int delay); extern int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int nodisp); -extern int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n, int nodisp); +extern int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n); extern int crypt_verify(char *user, char *pass); extern int cmd_verify(char *user, char *pass); extern int unixpw_verify(char *user, char *pass); diff --git a/x11vnc/user.c b/x11vnc/user.c index d1772d2..363d02e 100644 --- a/x11vnc/user.c +++ b/x11vnc/user.c @@ -1291,13 +1291,13 @@ void user_supplied_opts(char *opts) { if (scale_str) free(scale_str); scale_str = strdup(p); } else if (ok) { - if (strstr(p, "display=") == p) { + if (0 && strstr(p, "display=") == p) { if (use_dpy) free(use_dpy); use_dpy = strdup(p + strlen("display=")); - } else if (strstr(p, "auth=") == p) { + } else if (0 && strstr(p, "auth=") == p) { if (auth_file) free(auth_file); auth_file = strdup(p + strlen("auth=")); - } else if (!strcmp(p, "shared")) { + } else if (0 && !strcmp(p, "shared")) { shared = 1; } else if (strstr(p, "scale=") == p) { if (scale_str) free(scale_str); @@ -1443,8 +1443,16 @@ static void setup_fake_fb(XImage* fb_image, int w, int h, int b) { off_y = 0; } +void do_announce_http(void); +void do_mention_java_urls(void); + static void setup_service(void) { + if (remote_direct) { + return; + } if (!inetd) { + do_mention_java_urls(); + do_announce_http(); if (!use_openssl) { announce(screen->port, use_openssl, NULL); fprintf(stdout, "PORT=%d\n", screen->port); @@ -1564,9 +1572,12 @@ static void loop_for_connect(int did_client_connect) { goto screen_check; } } - if (use_openssl && !inetd) { - check_openssl(); - check_https(); + if ((use_openssl || use_stunnel) && !inetd) { + int enc_none = (enc_str && !strcmp(enc_str, "none")); + if (!use_stunnel || enc_none) { + check_openssl(); + check_https(); + } /* * This is to handle an initial verify cert from viewer, * they disconnect right after fetching the cert. @@ -1655,6 +1666,15 @@ static void do_unixpw_loop(void) { unixpw_in_rfbPE = 0; } if (unixpw_in_progress) { + static double lping = 0.0; + if (lping < dnow() + 5) { + mark_rect_as_modified(0, 0, 1, 1, 1); + lping = dnow(); + } + if (time(NULL) > unixpw_last_try_time + 45) { + rfbLog("unixpw_deny: timed out waiting for reply.\n"); + unixpw_deny(); + } usleep(20 * 1000); continue; } @@ -2000,7 +2020,7 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t p++; } if (ok && strlen(q) < 32) { - sprintf(fdgeom, q); + sprintf(fdgeom, "%s", q); if (!quiet) { rfbLog("set create display geom: %s\n", fdgeom); } @@ -2203,6 +2223,12 @@ static void check_nodisplay(char **nd) { } } } + if (unixpw_system_greeter_active == 2) { + if (!keep_unixpw_user) { + clean_up_exit(1); + } + *nd = strdup("all"); + } } static char *get_usslpeer() { @@ -2242,6 +2268,10 @@ static char *get_usslpeer() { } static void do_try_switch(char *usslpeer, char *users_list_save) { + if (unixpw_system_greeter_active == 2) { + rfbLog("unixpw_system_greeter: not trying switch to user '%s'\n", usslpeer ? usslpeer : ""); + return; + } if (usslpeer) { char *u = (char *) malloc(strlen(usslpeer+2)); sprintf(u, "+%s", usslpeer); @@ -2365,11 +2395,14 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr memset(line, 0, 18000); - if (keep_unixpw_user && keep_unixpw_pass) { + if (unixpw_system_greeter_active == 2) { + rfbLog("unixpw_system_greeter: forcing find display failure.\n"); + res = 0; + } else if (keep_unixpw_user && keep_unixpw_pass) { n = 18000; if (unixpw_cmd != NULL) { res = unixpw_cmd_run(keep_unixpw_user, - keep_unixpw_pass, cmd, line, &n, nodisp); + keep_unixpw_pass, cmd, line, &n); } else { res = su_verify(keep_unixpw_user, keep_unixpw_pass, cmd, line, &n, nodisp); @@ -2378,7 +2411,7 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr if (db) {fprintf(stderr, "line: "); write(2, line, n); write(2, "\n", 1); fprintf(stderr, "res=%d n=%d\n", res, n);} if (! res) { - rfbLog("wait_for_client: find display cmd failed\n"); + rfbLog("wait_for_client: find display cmd failed.\n"); } if (! res && create_cmd) { @@ -2398,8 +2431,8 @@ if (db) {fprintf(stderr, "line: "); write(2, line, n); write(2, "\n", 1); fprint n = 18000; close_exec_fds(); res = unixpw_cmd_run(keep_unixpw_user, - keep_unixpw_pass, create_cmd, line, &n, nodisp); - } else if (getuid() != 0) { + keep_unixpw_pass, create_cmd, line, &n); + } else if (getuid() != 0 && unixpw_system_greeter_active != 2) { /* if not root, run as the other user... */ n = 18000; close_exec_fds(); @@ -2410,6 +2443,10 @@ if (db) fprintf(stderr, "c-res=%d n=%d line: '%s'\n", res, n, line); } else { FILE *p; close_exec_fds(); + if (unixpw_system_greeter_active == 2) { + rfbLog("unixpw_system_greeter: not trying su_verify() to run\n"); + rfbLog("unixpw_system_greeter: create display command.\n"); + } rfbLog("wait_for_client: running: %s\n", create_cmd); p = popen(create_cmd, "r"); if (! p) { @@ -2432,7 +2469,7 @@ if (db) fprintf(stderr, "line1: '%s'\n", line1); } } } - if (res && saw_xdmcp) { + if (res && saw_xdmcp && unixpw_system_greeter_active != 2) { xdmcp_insert = strdup(keep_unixpw_user); } } @@ -2533,7 +2570,7 @@ if (db) fprintf(stderr, "\n"); rc = pclose(p); if (rc != 0) { - rfbLog("wait_for_client: find display cmd failed\n"); + rfbLog("wait_for_client: find display cmd failed.\n"); } if (create_cmd && rc != 0) { @@ -2844,6 +2881,18 @@ int wait_for_client(int *argc, char** argv, int http) { initialize_screen(argc, argv, fb_image); + if (! inetd && ! use_openssl) { + if (! screen->port || screen->listenSock < 0) { + if (got_rfbport && got_rfbport_val == 0) { + ; + } else { + rfbLogEnable(1); + rfbLog("Error: could not obtain listening port.\n"); + clean_up_exit(1); + } + } + } + initialize_signals(); if (ssh_str != NULL) { diff --git a/x11vnc/util.c b/x11vnc/util.c index 0a586f6..a00679a 100644 --- a/x11vnc/util.c +++ b/x11vnc/util.c @@ -75,7 +75,7 @@ double dnowx(void); double rnow(void); double rfac(void); -void rfbPE(long usec); +int rfbPE(long usec); void rfbCFD(long usec); double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1, @@ -173,6 +173,26 @@ void strzero(char *str) { } } +int is_decimal(char *str) { + char *p = str; + if (p != NULL) { + int first = 1; + while (*p != '\0') { + if (first && *p == '-') { + ; + } else if (isdigit((int) *p)) { + ; + } else { + return 0; + } + first = 0; + p++; + } + return 1; + } + return 0; +} + int scan_hexdec(char *str, unsigned long *num) { if (sscanf(str, "0x%lx", num) != 1) { if (sscanf(str, "%lu", num) != 1) { @@ -450,26 +470,34 @@ double rfac(void) { void check_allinput_rate(void) { static double last_all_input_check = 0.0; - static int set = 0; + static int set = 0, verb = -1; if (use_threads) { return; } + if (verb < 0) { + verb = 0; + if (getenv("RATE_VERB")) verb = 1; + } if (! set) { set = 1; last_all_input_check = dnow(); } else { - int dt = 4; + int dt = 5; if (x11vnc_current > last_all_input_check + dt) { int n, nq = 0; while ((n = rfbCheckFds(screen, 0))) { nq += n; } - fprintf(stderr, "nqueued: %d\n", nq); - if (0 && nq > 25 * dt) { + if (verb) fprintf(stderr, "nqueued: %d\n", nq); + if (getenv("CHECK_RATE") && nq > 18 * dt) { double rate = nq / dt; - rfbLog("Client is sending %.1f extra requests per second for the\n", rate); - rfbLog("past %d seconds! Switching to -allpinput mode. (queued: %d)\n", dt, nq); - all_input = 1; + if (verb) rfbLog("check_allinput_rate:\n"); + if (verb) rfbLog("Client is sending %.1f extra requests per second for the\n", rate); + if (verb) rfbLog("past %d seconds! (queued: %d)\n", dt, nq); + if (strstr(getenv("CHECK_RATE"), "allinput") && !all_input) { + rfbLog("Switching to -allpinput mode.\n"); + all_input = 1; + } } set = 0; } @@ -478,8 +506,8 @@ void check_allinput_rate(void) { static void do_allinput(long usec) { static double last = 0.0; - static int meas = 0; - int n, f = 1, cnt = 0; + static int meas = 0, verb = -1; + int n, f = 1, cnt = 0, m = 0; long usec0; double now; if (!screen || !screen->clientHead) { @@ -495,21 +523,26 @@ static void do_allinput(long usec) { if (last == 0.0) { last = dnow(); } + if (verb < 0) { + verb = 0; + if (getenv("RATE_VERB")) verb = 1; + } while ((n = rfbCheckFds(screen, usec)) > 0) { if (f) { - fprintf(stderr, " *"); + if (verb) fprintf(stderr, " *"); f = 0; } if (cnt++ > 30) { break; } meas += n; + m += n; } - fprintf(stderr, "-%d", cnt); + if (verb) fprintf(stderr, "+%d/%d", cnt, m); now = dnow(); if (now > last + 2.0) { double rate = meas / (now - last); - fprintf(stderr, "\n%.2f ", rate); + if (verb) fprintf(stderr, "\n allinput rate: %.2f ", rate); meas = 0; last = dnow(); } @@ -520,15 +553,16 @@ static void do_allinput(long usec) { * checks that we are not in threaded mode. */ #define USEC_MAX 999999 /* libvncsever assumes < 1 second */ -void rfbPE(long usec) { +int rfbPE(long usec) { int uip0 = unixpw_in_progress; static int check_rate = -1; + int res = 0; if (! screen) { - return; + return res; } if (unixpw && unixpw_in_progress && !unixpw_in_rfbPE) { rfbLog("unixpw_in_rfbPE: skipping rfbPE\n"); - return; + return res; } if (debug_tiles > 2) { @@ -541,7 +575,11 @@ void rfbPE(long usec) { usec = USEC_MAX; } if (! use_threads) { - rfbProcessEvents(screen, usec); + rfbBool r; + r = rfbProcessEvents(screen, usec); + if (r) { + res = 1; + } } if (unixpw && unixpw_in_progress && !uip0) { @@ -566,6 +604,7 @@ void rfbPE(long usec) { if (all_input) { do_allinput(usec); } + return res; } void rfbCFD(long usec) { diff --git a/x11vnc/util.h b/x11vnc/util.h index 2136fe1..41014ce 100644 --- a/x11vnc/util.h +++ b/x11vnc/util.h @@ -63,7 +63,7 @@ extern double dnowx(void); extern double rnow(void); extern double rfac(void); -extern void rfbPE(long usec); +extern int rfbPE(long usec); extern void rfbCFD(long usec); extern double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2); diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index 6c93474..09c0275 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -1,8 +1,8 @@ .\" This file was automatically generated from x11vnc -help output. -.TH X11VNC "1" "August 2009" "x11vnc " "User Commands" +.TH X11VNC "1" "October 2009" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.9.9, lastmod: 2009-08-10 + version: 0.9.9, lastmod: 2009-10-07 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -884,7 +884,7 @@ 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 +send one before a 45 second timeout. Existing clients are view-only during this period. .IP If the first character received is "Escape" then the @@ -1192,6 +1192,10 @@ XDM/GDM/KDM prompt. Subsequent re-connections will only require the \fB-unixpw\fR password. See the discussion under \fB-display\fR WAIT:... for more details about XDM, etc configuration. +.IP +Remember to enable XDMCP in the xdm-config, gdm.conf, +or kdmrc configuration file. See \fB-display\fR WAIT: for +more info. .PP \fB-sshxdmsvc\fR .IP @@ -1206,6 +1210,50 @@ the XDM GDM KDM prompt. Subsequent re-connections will only only require the SSH login. See the discussion under \fB-display\fR WAIT:... for more details about XDM, etc configuration. +.IP +Remember to enable XDMCP in the xdm-config, gdm.conf, +or kdmrc configuration file. See \fB-display\fR WAIT: for +more info. +.PP +\fB-unixpw_system_greeter\fR +.IP +Present a "Press 'Escape' for System Greeter" option +to the connecting VNC client in combined \fB-unixpw\fR +and xdmcp FINDCREATEDISPLAY modes (e.g. \fB-xdmsvc).\fR +.IP +Normally in a \fB-unixpw\fR mode the VNC client must +supply a valid username and password to gain access. +However, if \fB-unixpw_system_greeter\fR is supplied AND +the FINDCREATEDISPLAY command matches 'xdmcp', then +the user has the option to press Escape and then get a +XDM/GDM/KDM login/greeter panel instead. They will then +supply a username and password directly to the greeter. +.IP +Otherwise, in xdmcp FINDCREATEDISPLAY mode the user +must supply his username and password TWICE. First to +the initial unixpw login dialog, and second to the +subsequent XDM/GDM/KDM greeter. Note that if the user +re-connects and supplies his username and password in +the unixpw dialog the xdmcp greeter is skipped and +he is connected directly to his existing X session. +So the \fB-unixpw_system_greeter\fR option avoids the extra +password at X session creation time. +.IP +Example: x11vnc \fB-xdmsvc\fR \fB-unixpw_system_greeter\fR +See \fB-unixpw\fR and \fB-display\fR WAIT:... for more info. +.IP +The special options after a colon at the end of the +username (e.g. user:solid) described under \fB-display\fR +WAIT: are also applied in this mode if they are typed +in before the user hits Escape. The username is ignored +but the colon options are not. +.IP +If the user pressed Escape the FINDCREATEDISPLAY command +will be run with the env. var. X11VNC_XDM_ONLY=1. +.IP +Remember to enable XDMCP in the xdm-config, gdm.conf, +or kdmrc configuration file. See \fB-display\fR WAIT: for +more info. .PP \fB-redirect\fR \fIport\fR .IP @@ -1285,12 +1333,13 @@ helper program supports RFB_UNIXPW_CMD_RUN (see the Also in the case of \fB-unixpw,\fR the user logging in can place a colon at the end of her username and supply a few options: scale=, scale_cursor= (or sc=), solid -(or so), id=, clear_mods (or cm), clear_keys (or ck), -repeat, speeds= (or sp=), readtimeout= (or rd=), -rotate= (or ro=), or noncache (or nc), all 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, +(or so), id=, clear_mods (or cm), clear_keys (or +ck), clear_all (or ca), repeat, speeds= (or sp=), +readtimeout= (or rd=), viewonly (or vo), nodisplay= +(or nd=), rotate= (or ro=), or noncache (or nc), +all 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,sc=1,repeat Password: ... @@ -1302,6 +1351,9 @@ type and enter your password incorrectly, to retrieve your long "login:" line press the Up arrow once (before typing anything else). .IP +In the login panel, press F1 to get a list of the +available options that you can add after the username. +.IP Another option is "geom=WxH" or "geom=WxHxD" (or ge=). This only has an effect in FINDCREATEDISPLAY mode when a virtual X server such as Xvfb is going @@ -1381,7 +1433,9 @@ comma separated list of displays (e.g. ":0,:1") to ignore in the finding process. The ":" is optional. Ranges n-m e.g. 0-20 can also be supplied. This string can also be set by the connecting user via "nd=" -using "+" instead of "," +using "+" instead of "," If "nd=all" or you set +X11VNC_SKIP_DISPLAY=all then all display finding fails +as if you set X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (below.) .IP Automatic Creation of User X Sessions: .IP @@ -1441,6 +1495,8 @@ See the \fB-svc/-service\fR option alias above. If for some reason you do not want x11vnc to ever try to find an existing display set the env. var X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (also \fB-env\fR ...) +This is the same as setting X11VNC_SKIP_DISPLAY=all or +supplying "nd=all" after "username:" .IP Use WAIT:cmd=FINDCREATEDISPLAY-print to print out the script that is used for this. @@ -1474,12 +1530,15 @@ to pass to the X server. You can also set FD_PROG to be the full path to the session/windowmanager program. .IP More FD tricks: FD_CUPS=port or FD_CUPS=host:port -will set the cups printing environment. Similarly -for FD_ESD=port or FD_ESD=host:port for esddsp sound -redirection. FD_XDUMMY_NOROOT means the Xdummy server -does not need to be started as root (e.g. it will sudo -automatically). Set FD_EXTRA to a command to be run -a few seconds after the X server starts up. +will set the cups printing environment. Similarly for +FD_ESD=port or FD_ESD=host:port for esddsp sound +redirection. FD_XDUMMY_NOROOT means the Xdummy +server does not need to be started as root (e.g. it +will sudo automatically). Set FD_EXTRA to a command +to be run a few seconds after the X server starts up. +Set FD_TAG to be a unique name for the session, it is +set as an X property, that makes FINDDISPLAY only find +sessions with that tag value. .IP If you want the FINDCREATEDISPLAY session to contact an XDMCP login manager (xdm/gdm/kdm) on the same machine, @@ -1561,8 +1620,9 @@ username+passwd method is enabled for Unix logins. Otherwise in \fB-unixpw\fR mode the normal login panel is provided. .IP -You *MUST* supply the \fB-ssl\fR option for VeNCrypt to be -active. This option only fine-tunes its operation. +You *MUST* supply the \fB-ssl\fR option for VeNCrypt to +be active. The \fB-vencrypt\fR option only fine-tunes its +operation. .PP \fB-anontls\fR \fImode\fR .IP @@ -1599,8 +1659,9 @@ description of "plain:" under \fB-vencrypt.\fR .IP Long example: \fB-anontls\fR newdh:plain:support .IP -You *MUST* supply the \fB-ssl\fR option for ANONTLS to be -active. This option only fine-tunes its operation. +You *MUST* supply the \fB-ssl\fR option for ANONTLS to +be active. The \fB-anontls\fR option only fine-tunes its +operation. .PP \fB-sslonly\fR .IP @@ -1631,16 +1692,17 @@ to unset any *earlier* \fB-ssl\fR option (or \fB-svc...)\fR .IP Use the openssl library (www.openssl.org) to provide a built-in encrypted SSL/TLS 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. +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. See the \fB-stunnel\fR option below for +an alternative. .IP The VNC Viewer-side needs to support SSL/TLS as well. See this URL and also the discussion below for ideas on how to enable SSL support for the viewer: http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tun -nel-viewers x11vnc provides an SSL enabled Java +nel-viewers . x11vnc provides an SSL enabled Java viewer applet in the classes/ssl directory (-http or \fB-httpdir\fR options.) The SSVNC viewer package supports SSL tunnels too. @@ -1738,6 +1800,11 @@ a SSL PEM you created or the default "SAVE" method. See \fB-ssldir\fR below to use a directory besides the default ~/.vnc/certs .IP +If your x11vnc binary was not compiled with OpenSSL +library support, use of the \fB-ssl\fR option will induce an +immediate failure and exit. For such binaries, consider +using the \fB-stunnel\fR option for SSL encrypted connections. +.IP Misc Info: In temporary cert creation mode "TMP", set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc print out the entire certificate, including the PRIVATE KEY @@ -1847,7 +1914,7 @@ 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 +\fB-sslEncKey,\fR \fB-sslCertInfo,\fR and \fB-sslCRL\fR are provided for completeness, but for casual usage they are overkill. .IP They provide VNC Certificate Authority (CA) key creation @@ -1901,8 +1968,9 @@ the ss_vncviewer example script in the FAQ and SSVNC.) \fB-sslCRL\fR \fIpath\fR .IP Set the Certificate Revocation Lists (CRL) to \fIpath\fR. +This setting applies for both \fB-ssl\fR and \fB-stunnel\fR modes. .IP -If path is a file, the file contains one more more CRLs +If path is a file, the file contains one or more CRLs in PEM format. If path is a directory, it contains hash named files of CRLs in the usual OpenSSL manner. See the OpenSSL and @@ -1916,6 +1984,10 @@ certificate chain used to verify the VNC client. The \fB-sslCRL\fR setting will be ignored when \fB-sslverify\fR is not specified. .IP +Note that if a CRL's expiration date has passed, all +SSL connections will fail regardless of if they are +related to the subject of the CRL or not. +.IP Only rarely will one's x11vnc \fB-ssl\fR infrastructure be so large that this option would be useful (since normally maintaining the contents of the \fB-sslverify\fR file or @@ -2034,11 +2106,13 @@ 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-qualified 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. +certificate when it is created. +.IP +Tip: if you know the fully-qualified 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 that 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 @@ -2062,14 +2136,14 @@ e.g. ~/.vnc/certs/clients/.pem contains both the cert and private key. The .crt contains the certificate only. .IP -NOTE: It is very important to know one should always +NOTE: It is very important to know one should 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 +be typed in EVERY time x11vnc or the client app is started up. .IP Examples: @@ -2180,16 +2254,30 @@ 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.) +works well and avoids the requirement of linking with +the OpenSSL libraries. This mode 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. +See the \fB-ssl\fR option for more info on certificate files. +.IP +Whether or not your stunnel has its own certificate +depends on your stunnel configuration; stunnel often +generates one at install time. See your stunnel +documentation for details. In any event, if you want to +use this certificate you must supply the full path to it +as [pem]. Note: the file may only be readable by root. +.IP +[pem] may also be the special strings "TMP", "SAVE", +and "SAVE..." as described in the \fB-ssl\fR option. +If [pem] is not supplied, "SAVE" is assumed. +.IP +Note that the VeNCrypt, ANONTLS, and "ANON" modes +are not supported in \fB-stunnel\fR mode. .IP stunnel is started up as a child process of x11vnc and any SSL connections stunnel receives are decrypted and @@ -2197,22 +2285,37 @@ 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. +The \fB-localhost\fR option is enforced by default to avoid +people routing around the SSL channel. Use \fB-env\fR +STUNNEL_DISABLE_LOCALHOST=1 to disable this security +requirement. +.IP +Set \fB-env\fR STUNNEL_DEBUG=1 for more debugging printout. .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. +Your VNC viewer will also need to be able to connect +via SSL. Unfortunately not too many do this. See the +information about SSL viewers under the \fB-ssl\fR option. .IP -Also, in the x11vnc distribution, a patched TightVNC -Java applet is provided in classes/ssl that does SSL -connections (only). +Also, in the x11vnc distribution, patched TightVNC +and UltraVNC Java applet jar files are provided in +the classes/ssl directory that do SSL connections. +Enable serving them with the \fB-http,\fR \fB-http_ssl,\fR \fB-https,\fR +or \fB-httpdir\fR (see the option descriptions for more info.) .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: +Note that for the Java viewer applet usage the +"?PORT=xxxx" in the various URLs printed at startup +will need to be supplied to the web browser to connect +properly. +.IP +Currently the automatic "single port" HTTPS mode of +\fB-ssl\fR is not fully supported in \fB-stunnel\fR mode. However, +it can be emulated via: +.IP +% x11vnc \fB-stunnel\fR \fB-http_ssl\fR \fB-http_oneport\fR ... +.IP +In general, 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 @@ -2224,7 +2327,8 @@ and SSVNC for more examples. \fB-stunnel3\fR \fI[pem]\fR .IP Use version 3.x stunnel command line syntax instead of -version 4.x +version 4.x. The \fB-http/-httpdir\fR Java applet serving +is currently not available in this mode. .PP \fB-enc\fR \fIcipher:keyfile\fR .IP @@ -2245,7 +2349,7 @@ that you do not have control over. Note that this mode will NOT work with the UltraVNC DSM plugins because they alter the RFB protocol in addition to tunnelling with the symmetric cipher (an unfortunate -choice of implementation). +choice of implementation...) .IP cipher can be one of: arc4, aesv2, aes-cfb, blowfish, aes256, or 3des. See the OpenSSL documentation for @@ -2321,9 +2425,9 @@ salt,ivec sizes (in GUI or, e.g. arc4@8,16). .PP \fB-https\fR \fI[port]\fR .IP -Use a special, separate HTTPS port (-ssl mode only) -for HTTPS Java viewer applet downloading. I.e. not 5900 -and not 5800 (the defaults.) +Use a special, separate HTTPS port (-ssl and +\fB-stunnel\fR modes only) for HTTPS Java viewer applet +downloading. I.e. not 5900 and not 5800 (the defaults.) .IP BACKGROUND: In \fB-ssl\fR mode, it turns out you can use the single VNC port (e.g. 5900) for both VNC and HTTPS @@ -2343,6 +2447,8 @@ 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 +END OF BACKGROUND. +.IP USAGE: 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. @@ -2377,10 +2483,12 @@ other ports must be explicitly indicated, for example: https://mygateway.com:8000/?PORT=8000. To avoid having to include the PORT= in the browser URL, simply supply "\fB-httpsredir\fR" to x11vnc. +.IP +This options does not work in \fB-stunnel\fR mode. .PP \fB-http_oneport\fR .IP -For un-encrypted connections mode (i.e. no \fB-ssl,\fR +For UN-encrypted connections mode (i.e. no \fB-ssl,\fR \fB-stunnel,\fR or \fB-enc\fR options), allow the Java VNC Viewer applet to be downloaded thru the VNC port via HTTP. .IP @@ -4041,7 +4149,7 @@ times for more output. .PP \fB-defer\fR \fItime\fR .IP -Time in ms to wait for updates before sending to client +Time in ms to delay sending updates to connected clients (deferUpdateTime) Default: 20 .PP \fB-wait\fR \fItime\fR @@ -4049,6 +4157,17 @@ Time in ms to wait for updates before sending to client Time in ms to pause between screen polls. Used to cut down on load. Default: 20 .PP +\fB-extra_fbur\fR \fIn\fR +.IP +Perform extra FrameBufferUpdateRequests checks to +try to be in better sync with the client's requests. +What this does is perform extra polls of the client +socket at critical times (before '-defer' and '-wait' +calls.) The default is n=1. Set to a larger number to +insert more checks or set to n=0 to disable. A downside +of these extra calls is that more mouse input may be +processed than desired. +.PP \fB-wait_ui\fR \fIfactor\fR .IP Factor by which to cut the \fB-wait\fR time if there @@ -4104,14 +4223,14 @@ Default: take naps .IP Time in seconds after NO activity (e.g. screen blank) to really throttle down the screen polls (i.e. sleep -for about 1.5 secs). Use 0 to disable. Default: 20 +for about 1.5 secs). Use 0 to disable. Default: 60 .PP \fB-readtimeout\fR \fIn\fR .IP Set libvncserver rfbMaxClientWait to n seconds. On slow links that take a long time to paint the first screen libvncserver may hit the timeout and drop the -connection. Default: 60 seconds. +connection. Default: 20 seconds. .PP \fB-ping\fR \fIn\fR .IP @@ -4987,6 +5106,28 @@ If you do not intend to start x11vnc from the gui gui process can run on a different machine from the x11vnc server as long as X permissions, etc. permit communication between the two. +.IP +FONTS: On some systems the tk fonts can be too small, +jagged, or otherwise unreadable. There are 4 env vars +you can set to be the tk font you prefer: +.IP +X11VNC_FONT_BOLD main font for menus and buttons. +X11VNC_FONT_FIXED font for fixed width text. +.IP +X11VNC_FONT_BOLD_SMALL tray icon font. +X11VNC_FONT_REG_SMALL tray icon menu font. +.IP +The last two only apply for the tray icon mode. +.IP +Here are some examples: +.IP +\fB-env\fR X11VNC_FONT_BOLD='Helvetica \fB-16\fR bold' +\fB-env\fR X11VNC_FONT_FIXED='Courier \fB-14'\fR +\fB-env\fR X11VNC_FONT_REG_SMALL='Helvetica \fB-12'\fR +.IP +You can put the lines like the above (without the +quotes) in your ~/.x11vncrc file to avoid having to +specify them on the x11vnc command line. .PP \fB-remote\fR \fIcommand\fR .IP @@ -5013,6 +5154,18 @@ For example: 'x11vnc \fB-remote\fR stop' (which is the same as \'x11vnc \fB-R\fR shared' will enable shared connections, and \'x11vnc \fB-R\fR scale:3/4' will rescale the desktop. .IP +To run a bunch of commands in a sequence use something +like: x11vnc \fB-R\fR 'script:firstcmd;secondcmd;...' +.IP +Use x11vnc \fB-R\fR script:file=/path/to/file to read commands +from a file (can be multi-line and use the comment '#' +character in the normal way. The ';' separator must +still be used to separate each command.) +.IP +To not try to contact another x11vnc process and instead +just run the command (or query) directly, prefix the +command with the string "DIRECT:" +.IP .IP The following \fB-remote/-R\fR commands are supported: .IP @@ -5020,7 +5173,10 @@ stop terminate the server, same as "quit" "exit" or "shutdown". .IP ping see if the x11vnc server responds. -Return is: ans=ping: +return is: ans=ping: +.IP +ping:mystring as above, but use your own unique string. +return is: ans=ping:mystring: .IP blacken try to push a black fb update to all clients (due to timings a client @@ -5174,6 +5330,8 @@ grabalways enable \fB-grabalways\fR mode. .IP nograbalways disable \fB-grabalways\fR mode. .IP +grablocal:n set \fB-grablocal\fR to n. +.IP client_input:str set the K, M, B \fB-input\fR on a per-client basis. select which client as for disconnect, e.g. client_input:host:MB @@ -5322,6 +5480,12 @@ setclipboard disable \fB-nosetclipboard\fR mode. .IP seldir:str set \fB-seldir\fR to "str" .IP +resend_cutbuffer resend the most recent CUTBUFFER0 copy +.IP +resend_clipboard resend the most recent CLIPBOARD copy +.IP +resend_primary resend the most recent PRIMARY copy +.IP cursor:mode enable \fB-cursor\fR "mode". .IP show_cursor enable showing a cursor. @@ -5465,10 +5629,42 @@ debug_keyboard enable \fB-debug_keyboard,\fR same as "dk" .IP nodebug_keyboard disable \fB-debug_keyboard,\fR same as "nodk" .IP +keycode:n inject keystroke 'keycode' (xmodmap \fB-pk)\fR +.IP +keycode:n,down inject 'keycode' (down=0,1) +.IP +keysym:str inject keystroke 'keysym' (number/name) +.IP +keysym:str,down inject 'keysym' (down=0,1) +.IP +ptr:x,y,mask inject pointer event x, y, button-mask +.IP +sleep:t sleep floating point time t. +.IP +get_xprop:p get X property named 'p'. +.IP +set_xprop:p:val set X property named 'p' to 'val'. +p -> id=NNN:p for hex/dec window id. +.IP +wininfo:id get info about X window id. use 'root' +for root window, use +id for children. +.IP +grab_state get state of pointer and keyboard grab. +.IP +pointer_pos print XQueryPointer x,y cursor position. +.IP +mouse_x print x11vnc's idea of cursor position. +.IP +mouse_y print x11vnc's idea of cursor position. +.IP +noop do nothing. +.IP defer:n set \fB-defer\fR to n ms,same as deferupdate:n .IP wait:n set \fB-wait\fR to n ms. .IP +extra_fbur:n set \fB-extra_fbur\fR to n. +.IP wait_ui:f set \fB-wait_ui\fR factor to f. .IP setdefer:n set \fB-setdefer\fR to \fB-2,-1,0,1,\fR or 2. @@ -5545,6 +5741,8 @@ rawfb:str set \fB-rawfb\fR mode to "str". .IP uinput_accel:f set uinput_accel to f. .IP +uinput_thresh:n set uinput_thresh to n. +.IP uinput_reset:n set uinput_reset to n ms. .IP uinput_always:n set uinput_always to 1/0. @@ -5578,7 +5776,11 @@ maciconanim:n set \fB-maciconanim\fR to n. .IP macmenu enable \fB-macmenu\fR mode. .IP -macnomenu disable \fB-macnmenu\fR mode. +macnomenu disable \fB-macmenu\fR mode. +.IP +macuskbd enable \fB-macuskbd\fR mode. +.IP +macnouskbd disable \fB-macuskbd\fR mode. .IP httpport:n set \fB-httpport\fR to n. .IP @@ -5644,33 +5846,116 @@ noremote disable the \fB-remote\fR command processing, it cannot be turned back on. .IP .IP +bcx_xattach:str This remote control command is for +use with the BARCO xattach program or the x2x program. +Both of these programs are for 'pointer and keyboard' +sharing between separate X displays. In general the +two displays are usually nearby, e.g. on the same desk, +and this allows the user to share a single pointer and +keyboard between them. The user moves the mouse to +an edge and then the mouse pointer appears to 'jump' +to the other display screen. Thus it emulates what a +single X server would do for two screens (e.g. :0.0 and +:0.1) The illusion of a single Xserver with multiple +screens is achieved by forwarding events to the 2nd +one via the XTEST extension. +.IP +What the x11vnc bcx_xattach command does is to perform +some pointer movements to try to INDUCE xattach/x2x +to 'jump' to the other display. In what follows the +\'master' display refers to the one that when it has +\'focus' it is basically doing nothing besides watching +for the mouse to go over an edge. The 'slave' +display refers to the one to which the mouse and +keyboard is redirected to once an edge in the master +has been crossed. Note that the x11vnc executing the +bcx_xattach command MUST be the one connected to the +*master* display. +.IP +Also note that when input is being redirected (via +XTEST) from the master display to the slave display, +the master display's pointer and keyboard are *grabbed* +by xattach/x2x. x11vnc can use this info to verify that +the master/slave mode change has taken place correctly. +If you specify the "ifneeded" option (see below) +and the initial grab state is that of the desired +final state, then no pointer movements are injected +and "DONE,GRAB_OK" is returned. +.IP +"str" must contain one of "up", "down", "left", +or "right" to indicate the direction of the 'jump'. +"str" must also contain one of "master_to_slave" +or "slave_to_master" to indicate the type of mode +change induced by the jump. Use "M2S" and "S2M" +as shorter aliases. +.IP +"str" may be a "+" separated list of additional +tuning options. The "shift=n" option indicates an +offset shift position away from (0,0) (default 20). +"final=x+y" specifies the final position of the cursor +at the end of the normal move sequence; default 30+30. +"extra_move=x+y" means to do one more pointer move +after "final" to x+y. "dt=n" sets the sleep time +in milliseconds between pointer moves (default: 40ms) +"retry=n" specifies the maximum number of retries if +the grab state change fails. "ifneeded" means to not +apply the pointer movements if the initial grab state is +that of the desired final state. "nograbcheck" means +to not check if the grab state changed as expected and +only apply the pointer movements (default is to check +the grab states.) +.IP +If you do not specify "up", etc., to bcx_xattach +nothing will be attempted and the command returns +the string FAIL,NO_DIRECTION_SPECIFIED. If you do +not specify "master_to_slave" or "M2S", etc., to +bcx_xattach nothing will be attempted and the command +returns the string FAIL,NO_MODE_CHANGE_SPECIFIED. +.IP +Otherwise, the returned string will contain "DONE". +It will be "DONE,GRAB_OK" if the grab state changed +as expected (or if "ifneeded" was supplied and +the initial grab state was already the desired +one.) If the initial grab state was incorrect, +but the final grab state was correct then it is +"DONE,GRAB_FAIL_INIT". If the initial grab state +was correct, but the final grab state was incorrect +then it is "DONE,GRAB_FAIL_FINAL". If both are +incorrect it will be "DONE,GRAB_FAIL". Under grab +failure the string will be followed by ":p1,k1-p2,k2" +where p1,k1 indicates the initial pointer and keyboard +grab states and p2,k2 the final ones. If GRAB_FAIL or +GRAB_FAIL_FINAL occurs, the action will be retried up +to 3 times; trying to reset the state and sleeping a +bit between each try. Set retry=n to adjust the number +of retries, zero to disable retries. +.IP +Examples: +\fB-R\fR bcx_xattach:down+M2S +\fB-R\fR bcx_xattach:up+S2M +\fB-R\fR bcx_xattach:up+S2M+nograbcheck+dt=30 +\fB-R\fR bcx_xattach:down+M2S+extra_move=100+100 +.IP +or use \fB-Q\fR instead of \fB-R\fR to retrieve the result text. +.IP +End of the bcx_xattach:str description. +.IP The .IR vncconnect (1) command from standard VNC -.IP distributions may also be used if string is prefixed -.IP with "cmd=" E.g. 'vncconnect cmd=stop'. Under some -.IP circumstances .IR xprop (1) can used if it supports \fB-set\fR -.IP (see the FAQ). .IP -.IP If "\fB-connect\fR \fI/path/to/file\fR" has been supplied to the -.IP running x11vnc server then that file can be used as a -.IP communication channel (this is the only way to remote -.IP control one of many x11vnc's polling the same X display) -.IP Simply run: 'x11vnc \fB-connect\fR /path/to/file \fB-remote\fR ...' -.IP or you can directly write to the file via something -.IP like: "echo cmd=stop > /path/to/file", etc. .PP \fB-query\fR \fIvariable\fR @@ -5689,7 +5974,8 @@ these cases the value returned is "N/A". To direct a query straight to the X11VNC_REMOTE property or connect file use "qry=..." instead of "cmd=..." .IP -ans= stop quit exit shutdown ping blacken zero +ans= stop quit exit shutdown ping resend_cutbuffer +resend_clipboard resend_primary blacken zero refresh reset close disconnect id sid waitmapped nowaitmapped clip flashcmap noflashcmap shiftcmap truecolor notruecolor overlay nooverlay overlay_cursor @@ -5700,7 +5986,7 @@ viewonly noviewonly shared noshared forever noforever once timeout tightfilexfer notightfilexfer ultrafilexfer noultrafilexfer rfbversion deny lock nodeny unlock avahi mdns zeroconf noavahi nomdns nozeroconf connect -proxy allowonce allow localhost nolocalhost listen +proxy allowonce allow localhost nolocalhost listen lookup nolookup accept afteraccept gone shm noshm flipbyteorder noflipbyteorder onetile noonetile solid_color solid nosolid blackout xinerama noxinerama @@ -5710,10 +5996,10 @@ nocapslock skip_lockkeys noskip_lockkeys skip_keycodes sloppy_keys nosloppy_keys skip_dups noskip_dups add_keysyms noadd_keysyms clear_mods noclear_mods clear_keys noclear_keys clear_all clear_locks keystate -remap repeat norepeat fb nofb bell nobell sel nosel -primary noprimary setprimary nosetprimary clipboard -noclipboard setclipboard nosetclipboard seldir -cursorshape nocursorshape cursorpos nocursorpos +remap repeat norepeat fb nofb bell nobell sendbell +sel nosel primary noprimary setprimary nosetprimary +clipboard noclipboard setclipboard nosetclipboard +seldir cursorshape nocursorshape cursorpos nocursorpos cursor_drag nocursor_drag cursor show_cursor noshow_cursor nocursor arrow xfixes noxfixes xdamage noxdamage xd_area xd_mem alphacut alphafrac alpharemove @@ -5729,16 +6015,18 @@ debug_ncache nodebug_ncache wireframe_mode wireframe wf nowireframe nowf wireframelocal wfl nowireframelocal nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area scr_skip scr_inc scr_keys scr_term scr_keyrepeat -scr_parms scrollcopyrect scr noscrollcopyrect noscr -fixscreen noxrecord xrecord reset_record pointer_mode pm -input_skip allinput noallinput input grabkbd nograbkbd -grabptr nograbptr grabalways nograbalways grablocal -client_input ssltimeout speeds wmdt debug_pointer dp -nodebug_pointer nodp debug_keyboard dk nodebug_keyboard -nodk keycode deferupdate defer setdefer wait_ui -wait_bog nowait_bog slow_fb xrefresh wait readtimeout -nap nonap sb screen_blank fbpm nofbpm dpms nodpms -clientdpms noclientdpms forcedpms noforcedpms +scr_parms scrollcopyrect scr noscrollcopyrect +noscr fixscreen noxrecord xrecord reset_record +pointer_mode pm input_skip allinput noallinput input +grabkbd nograbkbd grabptr nograbptr grabalways +nograbalways grablocal client_input ssltimeout +speeds wmdt debug_pointer dp nodebug_pointer nodp +debug_keyboard dk nodebug_keyboard nodk keycode +keysym ptr sleep get_xprop set_xprop wininfo +bcx_xattach deferupdate defer setdefer extra_fbur +wait_ui wait_bog nowait_bog slow_fb xrefresh wait +readtimeout nap nonap sb screen_blank fbpm nofbpm dpms +nodpms clientdpms noclientdpms forcedpms noforcedpms noserverdpms serverdpms noultraext ultraext chatwindow nochatwindow chaton chatoff fs gaps grow fuzz snapfb nosnapfb rawfb uinput_accel uinput_thresh uinput_reset @@ -5756,21 +6044,23 @@ nomacnowait macwheel macnoswap macswap nomacnoswap macnoresize macresize nomacnoresize maciconanim macmenu macnomenu nomacmenu macuskbd nomacuskbd noremote .IP -aro= noop display vncdisplay desktopname guess_desktop -http_url auth xauth users rootshift clipshift scale_str -scaled_x scaled_y scale_numer scale_denom scale_fac_x +aro= noop display vncdisplay autoport loop loopbg +desktopname guess_desktop http_url auth xauth +users rootshift clipshift scale_str scaled_x +scaled_y scale_numer scale_denom scale_fac_x scale_fac_y scaling_blend scaling_nomult4 scaling_pad scaling_interpolate inetd privremote unsafe safer nocmds passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem sslverify stunnel stunnel_pem https httpsredir -usepw using_shm logfile o flag rc norc h help V version -lastmod bg sigpipe threads readrate netrate netlatency -pipeinput clients client_count pid ext_xtest ext_xtrap -ext_xrecord ext_xkb ext_xshm ext_xinerama ext_overlay -ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons -button_mask mouse_x mouse_y bpp depth indexed_color -dpy_x dpy_y wdpy_x wdpy_y off_x off_y cdpy_x cdpy_y -coff_x coff_y rfbauth passwd viewpasswd +usepw using_shm logfile o flag rmflag rc norc h help +V version lastmod bg sigpipe threads readrate netrate +netlatency pipeinput clients client_count pid ext_xtest +ext_xtrap ext_xrecord ext_xkb ext_xshm ext_xinerama +ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin +num_buttons button_mask mouse_x mouse_y grab_state +pointer_pos bpp depth indexed_color dpy_x dpy_y wdpy_x +wdpy_y off_x off_y cdpy_x cdpy_y coff_x coff_y rfbauth +passwd viewpasswd .PP \fB-QD\fR \fIvariable\fR .IP @@ -5794,10 +6084,47 @@ first (synchronously: no need for \fB-sync),\fR and then the \fB-query\fR request is processed in the normal way. This allows for a reliable way to see if the \fB-remote\fR command was processed by querying for any new settings. -Note however that there is timeout of a few seconds so -if the x11vnc takes longer than that to process the -requests the requester will think that a failure has -taken place. +Note however that there is timeout of a few seconds +(see the next paragraph) so if the x11vnc takes longer +than that to process the requests the requester will +think that a failure has taken place. +.IP +The default is to wait 3.5 seconds. Or if cmd=stop +only 1.0 seconds. If cmd matches 'script:' then it +will wait up to 10.0 seconds. Set X11VNC_SYNC_TIMEOUT +to the number of seconds you want it to wait. +.PP +\fB-query_retries\fR \fIstr\fR +.IP +If a query fails to get a response from an x11vnc +server, retry up to n times. \fIstr\fR is specified as +n[:t][/match] Optionally the delay between tries may +be specified by "t" a floating point time (default +0.5 seconds.) Note: the response is not checked for +validity or whether it corresponds to the query sent. +The query "ping:mystring" may be used to help uniquely +identify the query. Optionally, a matching string after +a "/" will be used to check the result text. Up to +n retries will take place until the matching string is +found in the output text. If the match string is never +found the program's exit code is 1; if the match is +found it exits with 0. Note that there may be stdout +printed for each retry (i.e. multiple lines printed +out to stdout.) +Example: \fB-query_retries\fR 4:1.5/grab_state +.PP +\fB-remote_prefix\fR \fIstr\fR +.IP +Enable a remote-control communication channel for +connected VNC clients. str is a non-empty string. If a +VNC client sends rfbCutText having the prefix \fIstr\fR +then the part after it is processed as though it were +sent via 'x11vnc \fB-remote\fR ...'. If it begins with +neither 'cmd=' nor 'qry=' then 'qry=' is assumed. +Any corresponding output text for that remote control +command is sent back to all client as rfbCutText. +The returned output is also prefixed with \fIstr\fR. +Example: \fB-remote_prefix\fR DO_THIS: .PP \fB-noremote,\fR \fB-yesremote\fR .IP diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 2ef6217..d4dcce7 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -8,7 +8,8 @@ * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; version 2 of the License, or (at + * your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -456,7 +457,7 @@ if (tstk[j] != 0) fprintf(stderr, "B redir[%d][%d] = %d %s\n", i, j, tstk[j], t int p0, p, found = -1, jzero = -1; int conn = -1; - get_prop(num, 32, atom[i]); + get_prop(num, 32, atom[i], None); p0 = atoi(num); for (j = TSSTK-1; j >= 0; j--) { @@ -654,7 +655,7 @@ void do_tsd(void) { prop[0] = '\0'; a = XInternAtom(dpy, "TS_REDIR_LIST", False); if (a != None) { - get_prop(prop, 512, a); + get_prop(prop, 512, a, None); } if (db) fprintf(stderr, "TS_REDIR_LIST Atom: %d = '%s'\n", (int) a, prop); @@ -784,7 +785,7 @@ static void check_redir_services(void) { a = XInternAtom(dpy, "TS_REDIR_PID", False); if (a != None) { prop[0] = '\0'; - get_prop(prop, 512, a); + get_prop(prop, 512, a, None); if (prop[0] != '\0') { pid = (pid_t) atoi(prop); } @@ -806,7 +807,7 @@ static void check_redir_services(void) { prop[0] = '\0'; a = XInternAtom(dpy, "TS_REDIR", False); if (a != None) { - get_prop(prop, 512, a); + get_prop(prop, 512, a, None); } if (db) fprintf(stderr, "TS_REDIR Atom: %d = '%s'\n", (int) a, prop); if (prop[0] == '\0') { @@ -1851,6 +1852,9 @@ char msg2[] = if (quiet) { return; } + if (remote_direct) { + return; + } if (nofb) { return; } @@ -1859,7 +1863,7 @@ char msg2[] = #endif if (ncache == 0) { - fprintf(stderr, msg2); + fprintf(stderr, "%s", msg2); ncache0 = ncache = 0; } else { fprintf(stderr, msg, ncache); @@ -1904,6 +1908,7 @@ static void do_sleepin(char *sleep) { } extern int dragum(void); +extern int is_decimal(char *); int main(int argc, char* argv[]) { @@ -1913,6 +1918,9 @@ int main(int argc, char* argv[]) { int remote_sync = 0; char *remote_cmd = NULL; char *query_cmd = NULL; + int query_retries = 0; + double query_delay = 0.5; + char *query_match = NULL; char *gui_str = NULL; int got_gui_pw = 0; int pw_loc = -1, got_passwd = 0, got_rfbauth = 0, nopw = NOPW; @@ -2440,6 +2448,10 @@ int main(int argc, char* argv[]) { got_localhost = 1; continue; } + if (!strcmp(arg, "-unixpw_system_greeter")) { + unixpw_system_greeter = 1; + continue; + } if (!strcmp(arg, "-unixpw_cmd") || !strcmp(arg, "-unixpw_cmd_unsafe")) { CHECK_ARGC @@ -2693,7 +2705,11 @@ int main(int argc, char* argv[]) { stunnel_pem = strdup(s); } i++; + } else { + stunnel_pem = strdup("SAVE"); } + } else { + stunnel_pem = strdup("SAVE"); } continue; } @@ -2709,7 +2725,11 @@ int main(int argc, char* argv[]) { stunnel_pem = strdup(s); } i++; + } else { + stunnel_pem = strdup("SAVE"); } + } else { + stunnel_pem = strdup("SAVE"); } continue; } @@ -3397,6 +3417,11 @@ int main(int argc, char* argv[]) { got_waitms = 1; continue; } + if (!strcmp(arg, "-extra_fbur")) { + CHECK_ARGC + extra_fbur = atoi(argv[++i]); + continue; + } if (!strcmp(arg, "-wait_ui")) { CHECK_ARGC wait_ui = atof(argv[++i]); @@ -3700,17 +3725,39 @@ int main(int argc, char* argv[]) { remote_cmd = str; } } - quiet = 1; + if (!getenv("QUERY_VERBOSE")) { + quiet = 1; + } xkbcompat = 0; continue; } if (!strcmp(arg, "-query") || !strcmp(arg, "-Q")) { CHECK_ARGC query_cmd = strdup(argv[++i]); - quiet = 1; + if (!getenv("QUERY_VERBOSE")) { + quiet = 1; + } xkbcompat = 0; continue; } + if (!strcmp(arg, "-query_retries")) { + char *s; + CHECK_ARGC + s = strdup(argv[++i]); + /* n[:t][/match] */ + if (strchr(s, '/')) { + char *q = strchr(s, '/'); + query_match = strdup(q+1); + *q = '\0'; + } + if (strchr(s, ':')) { + char *q = strchr(s, ':'); + query_delay = atof(q+1); + } + query_retries = atoi(s); + free(s); + continue; + } if (!strcmp(arg, "-QD")) { CHECK_ARGC query_cmd = strdup(argv[++i]); @@ -3725,6 +3772,11 @@ int main(int argc, char* argv[]) { remote_sync = 0; continue; } + if (!strcmp(arg, "-remote_prefix")) { + CHECK_ARGC + remote_prefix = strdup(argv[++i]); + continue; + } if (!strcmp(arg, "-noremote")) { accept_remote_cmds = 0; continue; @@ -3784,10 +3836,23 @@ int main(int argc, char* argv[]) { } if (!strcmp(arg, "-rfbport") && i < argc-1) { got_rfbport = 1; + if (!strcasecmp(argv[i+1], "prompt")) { + ; + } else if (!is_decimal(argv[i+1])) { + rfbLog("Invalid -rfbport value: '%s'\n", argv[i+1]); + rfbLog("setting it to '-1' to induce failure.\n"); + argv[i+1] = strdup("-1"); + } got_rfbport_str = strdup(argv[i+1]); got_rfbport_pos = argc_vnc+1; got_rfbport_val = atoi(argv[i+1]); } + if (!strcmp(arg, "-httpport") && i < argc-1) { + if (!is_decimal(argv[i+1])) { + rfbLog("Invalid -httpport value: '%s'\n", argv[i+1]); + clean_up_exit(1); + } + } if (!strcmp(arg, "-alwaysshared ")) { got_alwaysshared = 1; } @@ -3815,6 +3880,11 @@ int main(int argc, char* argv[]) { set_env("LIBXCB_ALLOW_SLOPPY_LOCK", "1"); } + if (getenv("PATH") == NULL || !strcmp(getenv("PATH"), "")) { + /* set a minimal PATH, usually only null in inetd. */ + set_env("PATH", "/bin:/usr/bin"); + } + /* set OS struct UT */ uname(&UT); @@ -4052,8 +4122,25 @@ int main(int argc, char* argv[]) { * similar for query_default. */ if (client_connect_file || query_default) { - int rc = do_remote_query(remote_cmd, query_cmd, - remote_sync, query_default); + int i, rc = 1; + for (i=0; i <= query_retries; i++) { + rc = do_remote_query(remote_cmd, query_cmd, + remote_sync, query_default); + if (rc == 0) { + if (query_match) { + if (query_result && strstr(query_result, query_match)) { + break; + } + rc = 1; + } else { + break; + } + } + if (i < query_retries) { + fprintf(stderr, "sleep: %.3f\n", query_delay); + usleep( (int) (query_delay * 1000 * 1000) ); + } + } fflush(stderr); fflush(stdout); exit(rc); @@ -4426,6 +4513,8 @@ int main(int argc, char* argv[]) { } } + http_try_it = try_http; + if (flip_byte_order && using_shm && ! quiet) { rfbLog("warning: -flipbyte order only works with -noshm\n"); } @@ -4492,11 +4581,13 @@ int main(int argc, char* argv[]) { } if (debug_pointer || debug_keyboard) { - if (bg || quiet) { - rfbLog("disabling -bg/-q under -debug_pointer" - "/-debug_keyboard\n"); - bg = 0; - quiet = 0; + if (!logfile) { + if (bg || quiet) { + rfbLog("disabling -bg/-q under -debug_pointer" + "/-debug_keyboard\n"); + bg = 0; + quiet = 0; + } } } @@ -4521,7 +4612,7 @@ int main(int argc, char* argv[]) { if (verbose) { print_settings(try_http, bg, gui_str); } - rfbLog("x11vnc version: %s\n", lastmod); + rfbLog("x11vnc version: %s pid: %d\n", lastmod, getpid()); } else { rfbLogEnable(0); } @@ -4728,14 +4819,38 @@ if (0) fprintf(stderr, "XA: %s\n", getenv("XAUTHORITY")); window = save; } - if (! quiet && ! raw_fb_str) { - rfbLog("\n"); - rfbLog("------------------ USEFUL INFORMATION ------------------\n"); - } - - if (remote_cmd || query_cmd) { - int rc = do_remote_query(remote_cmd, query_cmd, remote_sync, - query_default); + if ( (remote_cmd && strstr(remote_cmd, "DIRECT:") == remote_cmd) + || (query_cmd && strstr(query_cmd, "DIRECT:") == query_cmd )) { + /* handled below after most everything is setup. */ + if (getenv("QUERY_VERBOSE")) { + quiet = 0; + } else { + quiet = 1; + remote_direct = 1; + } + if (!auto_port) { + auto_port = 5970; + } + } else if (remote_cmd || query_cmd) { + int i, rc = 1; + for (i=0; i <= query_retries; i++) { + rc = do_remote_query(remote_cmd, query_cmd, remote_sync, + query_default); + if (rc == 0) { + if (query_match) { + if (query_result && strstr(query_result, query_match)) { + break; + } + rc = 1; + } else { + break; + } + } + if (i < query_retries) { + fprintf(stderr, "sleep: %.3f\n", query_delay); + usleep( (int) (query_delay * 1000 * 1000) ); + } + } XFlush_wr(dpy); fflush(stderr); fflush(stdout); @@ -4744,6 +4859,11 @@ if (0) fprintf(stderr, "XA: %s\n", getenv("XAUTHORITY")); exit(rc); } + if (! quiet && ! raw_fb_str) { + rfbLog("\n"); + rfbLog("------------------ USEFUL INFORMATION ------------------\n"); + } + if (priv_remote) { if (! remote_control_access_ok()) { rfbLog("** Disabling remote commands in -privremote mode.\n"); @@ -5086,7 +5206,9 @@ if (0) fprintf(stderr, "XA: %s\n", getenv("XAUTHORITY")); } #endif - check_pm(); + if (!getenv("X11VNC_NO_CHECK_PM")) { + check_pm(); + } if (! quiet && ! raw_fb_str) { rfbLog("--------------------------------------------------------\n"); @@ -5322,6 +5444,13 @@ if (0) fprintf(stderr, "XA: %s\n", getenv("XAUTHORITY")); ncache_beta_tester_message(); } + if (remote_cmd || query_cmd) { + /* This is DIRECT: case */ + do_remote_query(remote_cmd, query_cmd, remote_sync, query_default); + if (getenv("SLEEP")) sleep(atoi(getenv("SLEEP"))); + clean_up_exit(0); + } + #if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID if (bg) { int p, n; diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index cc973f0..470d23a 100644 --- a/x11vnc/x11vnc_defs.c +++ b/x11vnc/x11vnc_defs.c @@ -47,7 +47,7 @@ int xtrap_base_event_type = 0; int xdamage_base_event_type = 0; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.9.9 lastmod: 2009-08-10"; +char lastmod[] = "0.9.9 lastmod: 2009-10-07"; /* X display info */ diff --git a/x11vnc/xdamage.c b/x11vnc/xdamage.c index 9db86ae..946aff2 100644 --- a/x11vnc/xdamage.c +++ b/x11vnc/xdamage.c @@ -56,6 +56,8 @@ int xdamage_max_area = 20000; /* pixels */ double xdamage_memory = 1.0; /* in units of NSCAN */ int xdamage_tile_count = 0, xdamage_direct_count = 0; double xdamage_scheduled_mark = 0.0; +double xdamage_crazy_time = 0.0; +double xdamage_crazy_delay = 300.0; sraRegionPtr xdamage_scheduled_mark_region = NULL; sraRegionPtr *xdamage_regions = NULL; int xdamage_ticker = 0; @@ -400,6 +402,7 @@ int collect_xdamage(int scancnt, int call) { #define DUPSZ 32 int dup_x[DUPSZ], dup_y[DUPSZ], dup_w[DUPSZ], dup_h[DUPSZ]; double tm, dt; + int mark_all = 0, retries = 0, too_many = 1000, tot_ev = 0; RAWFB_RET(0) @@ -443,6 +446,9 @@ int collect_xdamage(int scancnt, int call) { X_LOCK; if (0) XFlush_wr(dpy); if (0) XEventsQueued(dpy, QueuedAfterFlush); + + come_back_for_more: + while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) { /* * TODO max cut off time in this loop? @@ -450,6 +456,26 @@ if (0) XEventsQueued(dpy, QueuedAfterFlush); * screen. */ ecount++; + tot_ev++; + + if (mark_all) { + continue; + } + if (ecount == too_many) { + int nqa = XEventsQueued(dpy, QueuedAlready); + if (nqa >= too_many) { + static double last_msg = 0.0; + tmpregion = sraRgnCreateRect(0, 0, dpy_x, dpy_y); + sraRgnOr(reg, tmpregion); + sraRgnDestroy(tmpregion); + if (dnow() > last_msg + xdamage_crazy_delay) { + rfbLog("collect_xdamage: too many xdamage events %d+%d\n", ecount, nqa); + last_msg = dnow(); + } + mark_all = 1; + } + } + if (ev.type != xdamage_base_event_type + XDamageNotify) { break; } @@ -537,12 +563,37 @@ if (0) XEventsQueued(dpy, QueuedAfterFlush); rect_count++; ccount++; } + + if (mark_all) { + if (ecount + XEventsQueued(dpy, QueuedAlready) >= 3 * too_many && retries < 3) { + retries++; + XFlush_wr(dpy); + usleep(20 * 1000); + XFlush_wr(dpy); + ecount = 0; + goto come_back_for_more; + } + } + /* clear the whole damage region for next time. XXX check */ if (call == 1) { XDamageSubtract(dpy, xdamage, None, None); } X_UNLOCK; + if (tot_ev > 20 * too_many) { + rfbLog("collect_xdamage: xdamage has gone crazy (screensaver or game?) ev: %d ret: %d\n", tot_ev, retries); + rfbLog("collect_xdamage: disabling xdamage for %d seconds.\n", (int) xdamage_crazy_delay); + destroy_xdamage_if_needed(); + X_LOCK; + XSync(dpy, False); + while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) { + ; + } + X_UNLOCK; + xdamage_crazy_time = dnow(); + } + if (0 && xdamage_direct_count) { fb_push(); } @@ -726,7 +777,7 @@ void create_xdamage_if_needed(int force) { xdamage = XDamageCreate(dpy, window, XDamageReportRawRectangles); XDamageSubtract(dpy, xdamage, None, None); X_UNLOCK; - rfbLog("created xdamage object: 0x%lx\n", xdamage); + rfbLog("created xdamage object: 0x%lx\n", xdamage); } #endif } @@ -762,6 +813,9 @@ void check_xdamage_state(void) { * Create or destroy the Damage object as needed, we don't want * one if no clients are connected. */ + if (xdamage_crazy_time > 0.0 && dnow() < xdamage_crazy_time + xdamage_crazy_delay) { + return; + } if (client_count && use_xdamage) { create_xdamage_if_needed(0); if (xdamage_scheduled_mark > 0.0 && dnow() > diff --git a/x11vnc/xdamage.h b/x11vnc/xdamage.h index 25e8fde..22046a6 100644 --- a/x11vnc/xdamage.h +++ b/x11vnc/xdamage.h @@ -44,6 +44,8 @@ extern int xdamage_max_area; extern double xdamage_memory; extern int xdamage_tile_count, xdamage_direct_count; extern double xdamage_scheduled_mark; +extern double xdamage_crazy_time; +extern double xdamage_crazy_delay; extern sraRegionPtr xdamage_scheduled_mark_region; extern sraRegionPtr *xdamage_regions; extern int xdamage_ticker; diff --git a/x11vnc/xevents.c b/x11vnc/xevents.c index 1a94d4e..c1389ad 100644 --- a/x11vnc/xevents.c +++ b/x11vnc/xevents.c @@ -76,7 +76,7 @@ void set_server_input(rfbClientPtr cl, int s); void set_text_chat(rfbClientPtr cl, int l, char *t); int get_keyboard_led_state_hook(rfbScreenInfoPtr s); int get_file_transfer_permitted(rfbClientPtr cl); -void get_prop(char *str, int len, Atom prop); +void get_prop(char *str, int len, Atom prop, Window w); static void initialize_xevents(int reset); static void print_xevent_bases(void); @@ -212,7 +212,7 @@ static void print_xevent_bases(void) { fprintf(stderr, " SelClear=%d, Expose=%d\n", SelectionClear, Expose); } -void get_prop(char *str, int len, Atom prop) { +void get_prop(char *str, int len, Atom prop, Window w) { int i; #if !NO_X11 Atom type; @@ -235,9 +235,12 @@ void get_prop(char *str, int len, Atom prop) { #else slen = 0; - + if (w == None) { + w = DefaultRootWindow(dpy); + } + do { - if (XGetWindowProperty(dpy, DefaultRootWindow(dpy), + if (XGetWindowProperty(dpy, w, prop, nitems/4, len/16, False, AnyPropertyType, &type, &format, &nitems, &bytes_after, &data) == Success) { @@ -584,7 +587,7 @@ static void grab_buster_watch(int parent, char *dstr) { break; } - get_prop(propval, 128, ticker_atom); + get_prop(propval, 128, ticker_atom, None); if (db) fprintf(stderr, "got_prop: %s\n", propval); if (!process_watch(propval, parent, db)) { @@ -871,21 +874,49 @@ void check_autorepeat(void) { } } else { if (idle_reset) { - int i, state[256]; + int i, state[256], didmsg = 0, pressed = 0; + int mwt = 600, mmax = 20; + static int msgcnt = 0; + static double lastmsg = 0.0; + for (i=0; i<256; i++) { state[i] = 0; } if (use_threads) {X_LOCK;} get_keystate(state); if (use_threads) {X_UNLOCK;} + for (i=0; i<256; i++) { if (state[i] != 0) { /* better wait until all keys are up */ - rfbLog("active keyboard: waiting until" - " all keys are up. key_down=%d\n", i); - return; + pressed++; + if (msgcnt < mmax || dnow() > lastmsg + mwt) { + char *str = "unset"; +#if !NO_X11 + if (use_threads) {X_LOCK;} + str = XKeysymToString(XKeycodeToKeysym(dpy, i, 0)); + if (use_threads) {X_UNLOCK;} +#endif + str = str ? str : "nosymbol"; + didmsg++; + rfbLog("active keyboard: waiting until " + "all keys are up. key_down=%d %s. " + "If the key is inaccessible via keyboard, " + "consider 'x11vnc -R clear_all'\n", i, str); + } } } + if (didmsg > 0) { + msgcnt++; + if (msgcnt == mmax) { + rfbLog("active keyboard: last such " + "message for %d secs.\n", mwt); + } + lastmsg = dnow(); + } + if (pressed > 0) { + return; + } } if (idle_reset) { static time_t last_msg = 0; @@ -1055,38 +1086,83 @@ void check_xevents(int reset) { last_call = now; } - /* check for CUT_BUFFER0 and VNC_CONNECT changes: */ + /* check for CUT_BUFFER0, VNC_CONNECT, X11VNC_REMOTE changes: */ if (XCheckTypedEvent(dpy, PropertyNotify, &xev)) { - if (xev.type == PropertyNotify) { - if (xev.xproperty.atom == XA_CUT_BUFFER0) { - /* - * Go retrieve CUT_BUFFER0 and send it. - * - * set_cutbuffer is a flag to try to avoid - * processing our own cutbuffer changes. - */ - if (have_clients && watch_selection - && ! set_cutbuffer) { - cutbuffer_send(); - sent_some_sel = 1; + int got_cutbuffer = 0; + int got_vnc_connect = 0; + int got_x11vnc_remote = 0; + static int prop_dbg = -1; + + /* to avoid piling up between calls, read all PropertyNotify now */ + do { + if (xev.type == PropertyNotify) { + if (xev.xproperty.atom == XA_CUT_BUFFER0) { + got_cutbuffer++; + } else if (vnc_connect && vnc_connect_prop != None + && xev.xproperty.atom == vnc_connect_prop) { + got_vnc_connect++; + } else if (vnc_connect && x11vnc_remote_prop != None + && xev.xproperty.atom == x11vnc_remote_prop) { + got_x11vnc_remote++; } - set_cutbuffer = 0; - } else if (vnc_connect && vnc_connect_prop != None - && xev.xproperty.atom == vnc_connect_prop) { - /* - * Go retrieve VNC_CONNECT string. - */ - read_vnc_connect_prop(0); - } else if (vnc_connect && x11vnc_remote_prop != None - && xev.xproperty.atom == x11vnc_remote_prop) { - /* - * Go retrieve X11VNC_REMOTE string. - */ - read_x11vnc_remote_prop(0); + set_prop_atom(xev.xproperty.atom); + } + } while (XCheckTypedEvent(dpy, PropertyNotify, &xev)); + if (prop_dbg < 0) { + prop_dbg = 0; + if (getenv("PROP_DBG")) { + prop_dbg = 1; + } + } + if (prop_dbg && (got_cutbuffer > 1 || got_vnc_connect > 1 || got_x11vnc_remote > 1)) { + static double lastmsg = 0.0; + static int count = 0; + double now = dnow(); + + if (1 && now > lastmsg + 300.0) { + if (got_cutbuffer > 1) { + rfbLog("check_xevents: warning: %d cutbuffer events since last check.\n", got_cutbuffer); + } + if (got_vnc_connect > 1) { + rfbLog("check_xevents: warning: %d vnc_connect events since last check.\n", got_vnc_connect); + } + if (got_x11vnc_remote > 1) { + rfbLog("check_xevents: warning: %d x11vnc_remote events since last check.\n", got_x11vnc_remote); + } + count++; + if (count >= 3) { + lastmsg = now; + count = 0; + } } - set_prop_atom(xev.xproperty.atom); + } + + if (got_cutbuffer) { + /* + * Go retrieve CUT_BUFFER0 and send it. + * + * set_cutbuffer is a flag to try to avoid + * processing our own cutbuffer changes. + */ + if (have_clients && watch_selection && !set_cutbuffer) { + cutbuffer_send(); + sent_some_sel = 1; + } + set_cutbuffer = 0; + } + if (got_vnc_connect) { + /* + * Go retrieve VNC_CONNECT string. + */ + read_vnc_connect_prop(0); + } + if (got_x11vnc_remote) { + /* + * Go retrieve X11VNC_REMOTE string. + */ + read_x11vnc_remote_prop(0); } } @@ -1367,6 +1443,39 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) { return; } + if (remote_prefix != NULL && strstr(text, remote_prefix) == text) { + char *result, *rcmd = text + strlen(remote_prefix); + char *tmp = (char *) calloc(len + 8, 1); + + if (strstr(rcmd, "cmd=") != rcmd && strstr(rcmd, "qry=") != rcmd) { + strcat(tmp, "qry="); + } + strncat(tmp, rcmd, len - strlen(remote_prefix)); + + rfbLog("remote_prefix command: '%s'\n", tmp); + + result = process_remote_cmd(tmp, 1); + if (result == NULL ) { + result = strdup("null"); + } else if (!strcmp(result, "")) { + free(result); + result = strdup("none"); + } + rfbLog("remote_prefix result: '%s'\n", result); + + free(tmp); + tmp = (char *) calloc(strlen(remote_prefix) + strlen(result) + 1, 1); + + strcat(tmp, remote_prefix); + strcat(tmp, result); + free(result); + + rfbSendServerCutText(screen, tmp, strlen(tmp)); + free(tmp); + + return; + } + if (! check_sel_direction("recv", "xcut_receive", text, len)) { return; } diff --git a/x11vnc/xevents.h b/x11vnc/xevents.h index 7a316b0..ed57b1e 100644 --- a/x11vnc/xevents.h +++ b/x11vnc/xevents.h @@ -59,7 +59,7 @@ extern void set_server_input(rfbClientPtr cl, int s); extern void set_text_chat(rfbClientPtr cl, int l, char *t); extern int get_keyboard_led_state_hook(rfbScreenInfoPtr s); extern int get_file_transfer_permitted(rfbClientPtr cl); -extern void get_prop(char *str, int len, Atom prop); +extern void get_prop(char *str, int len, Atom prop, Window w); #endif /* _X11VNC_XEVENTS_H */ diff --git a/x11vnc/xwrappers.c b/x11vnc/xwrappers.c index aa04f35..47e52da 100644 --- a/x11vnc/xwrappers.c +++ b/x11vnc/xwrappers.c @@ -755,7 +755,6 @@ if (db) fprintf(stderr, "lseek 0 ps: %d sz: %d off: %d bpl: %d\n", pixelsize, s del = 0; while (len > 0) { n = read(raw_fb_fd, dst + del, len); -//if (db > 2) fprintf(stderr, "len: %d n: %d\n", len, n); if (n > 0) { del += n; @@ -767,7 +766,6 @@ if (db) fprintf(stderr, "lseek 0 ps: %d sz: %d off: %d bpl: %d\n", pixelsize, s } } if (bpl > sz) { -//if (db > 1) fprintf(stderr, "bpl>sz %d %d\n", bpl, sz); off = (off_t) (bpl - sz); lseek(raw_fb_fd, off, SEEK_CUR); } -- cgit v1.1