diff options
author | runge <runge> | 2006-09-21 02:11:14 +0000 |
---|---|---|
committer | runge <runge> | 2006-09-21 02:11:14 +0000 |
commit | dea53c22101473a58bfb113529713383203c80df (patch) | |
tree | 7f1bac1c1efbd1dc644853c6758199d2d7a187c5 /x11vnc | |
parent | 52ed38f64789b9500d3d2e8b616aa5d1a01d5c57 (diff) | |
download | libtdevnc-dea53c22101473a58bfb113529713383203c80df.tar.gz libtdevnc-dea53c22101473a58bfb113529713383203c80df.zip |
x11vnc: -unixpw_cmd, -passwfile cmd:/custom:, -sslnofail, -ultrafilexfer
Diffstat (limited to 'x11vnc')
-rw-r--r-- | x11vnc/ChangeLog | 4 | ||||
-rw-r--r-- | x11vnc/README | 204 | ||||
-rw-r--r-- | x11vnc/connections.c | 73 | ||||
-rw-r--r-- | x11vnc/connections.h | 2 | ||||
-rw-r--r-- | x11vnc/help.c | 78 | ||||
-rw-r--r-- | x11vnc/options.c | 2 | ||||
-rw-r--r-- | x11vnc/options.h | 2 | ||||
-rw-r--r-- | x11vnc/sslhelper.c | 18 | ||||
-rw-r--r-- | x11vnc/unixpw.c | 115 | ||||
-rw-r--r-- | x11vnc/unixpw.h | 1 | ||||
-rw-r--r-- | x11vnc/user.c | 95 | ||||
-rw-r--r-- | x11vnc/user.h | 3 | ||||
-rw-r--r-- | x11vnc/x11vnc.1 | 86 | ||||
-rw-r--r-- | x11vnc/x11vnc.c | 51 | ||||
-rw-r--r-- | x11vnc/x11vnc.h | 1 | ||||
-rw-r--r-- | x11vnc/x11vnc_defs.c | 3 |
16 files changed, 587 insertions, 151 deletions
diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 8bcd818..6250651 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,7 @@ +2006-09-20 Karl Runge <runge@karlrunge.com> + * x11vnc: -unixpw_cmd, -passwfile cmd:/custom:, -sslnofail, + -ultrafilexfer + 2006-09-17 Karl Runge <runge@karlrunge.com> * x11vnc: move some info printout to -v, -verbose mode. Add -connect_or_exit option. Have -rfbport 0 lead to no TCP diff --git a/x11vnc/README b/x11vnc/README index 9c66244..b5fce8e 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Sun Sep 17 19:51:07 EDT 2006 +x11vnc README file Date: Wed Sep 20 20:05:35 EDT 2006 The following information is taken from these URLs: @@ -5627,10 +5627,9 @@ EndSection -permitfiletransfer" options (UltraVNC incorrectly uses the RFB protocol version to determine if its features are available, so x11vnc has to pretend to - be version 3.6). - - If you find any bugs or performance issues with the file transfer, - please report them to the [621]LibVNCServer team. + be version 3.6). As of Sep/2006 "-ultrafilexfer" is an alias for these + two options. Note that running as RFB version 3.6 may confuse other + VNC Viewers. Q-101: Can I (temporarily) mount my local (viewer-side) Windows/Samba @@ -5639,7 +5638,7 @@ EndSection You will have to use an external network redirection for this. Filesystem mounting is not part of the VNC protocol. - We show a simple [622]Samba example here. + We show a simple [621]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: @@ -5676,7 +5675,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 [623]Enhanced TightVNC Viewer package we provide (as of Sep + into the [622]Enhanced TightVNC Viewer package we provide (as of Sep 2006 it is there for testing). @@ -5686,7 +5685,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 [624]CUPS example here. Non-CUPS port + We show a simple Unix to Unix [623]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). @@ -5758,7 +5757,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 [625]Enhanced TightVNC Viewer package we provide (as of Sep + into the [624]Enhanced TightVNC Viewer package we provide (as of Sep 2006 it is there for testing). @@ -5769,8 +5768,8 @@ d,ip=127.0.0.1,port=1139 Audio is not part of the VNC protocol. We show a simple Unix to Unix esd example here (artsd should be - possible too, and perhaps even one or both of these have been ported - to Windows so you can redirect the sound there). + possible too, we have also verified the esd Windows port works for the + method described below). First you will need a tunnel to redirect the audio from the remote machine to the one you sitting at. We use an ssh tunnel: @@ -5791,7 +5790,8 @@ way.east 'x11vnc -localhost -display :0' sitting-here> esd -promiscuous -port 16001 -tcp -bind 127.0.0.1 See the esd(1) man page for the meaning of the options (the above are - not very secure). + not very secure). (This method also works with the EsounD windows port + esd.exe) To test this sound tunnel, we use the esdplay program to play a simple .wav file: @@ -5858,8 +5858,8 @@ 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 [626]Enhanced TightVNC Viewer package we - provide (as of Sep 2006 it is there for testing). + redir setup into the [625]Enhanced TightVNC Viewer package we + provide (as of Sep/2006 it is there for testing). Q-104: Why don't I hear the "Beeps" in my X session (e.g. when typing @@ -5870,9 +5870,9 @@ 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 [627]-nobell option. If + If you don't want to hear the beeps use the [626]-nobell option. If you want to hear the audio from the remote applications, consider - trying a [628]redirector such as esd. + trying a [627]redirector such as esd. @@ -6509,14 +6509,13 @@ References 618. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-seldir 619. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-input 620. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nofilexfer - 621. http://sourceforge.net/projects/libvncserver - 622. http://www.samba.org/ - 623. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html - 624. http://www.cups.org/ + 621. http://www.samba.org/ + 622. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html + 623. http://www.cups.org/ + 624. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html 625. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html - 626. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html - 627. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nobell - 628. http://www.karlrunge.com/x11vnc/index.html#faq-sound + 626. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nobell + 627. http://www.karlrunge.com/x11vnc/index.html#faq-sound ======================================================================= http://www.karlrunge.com/x11vnc/chainingssh.html: @@ -7692,12 +7691,13 @@ http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html: Enhanced TightVNC Viewer The Enhanced TightVNC Viewer package is a project to add some patches - to the long neglected Unix TightVNC Viewer. It also adds a GUI for - Windows and Unix that automatically starts up a STUNNEL SSL tunnel for - SSL connections to [1]x11vnc (or any other VNC Server also running an - SSL tunnel, such as STUNNEL, at their end), and then launches the - TightVNC Viewer. The front-end program can also be used to set up SSH - tunnelled connections instead. + to the long neglected Unix TightVNC Viewer. + + It also adds a front-end GUI for Windows and Unix that automatically + starts up a STUNNEL SSL tunnel for SSL connections to [1]x11vnc (or + any other VNC Server also running an SSL tunnel, such as STUNNEL, at + their end), and then launches the TightVNC Viewer. The front-end + program can also be used to set up SSH tunnelled connections instead. Patches were created for the TightVNC 1.3dev7 vnc_unixsrc tree (and various wrappers written) to add these features: @@ -7716,7 +7716,7 @@ Enhanced TightVNC Viewer to a simple fixed port sequence and one-time-pad implementation, a hook is also provided to run any port knocking client before connecting. - * You can also use your own, e.g. UltraVNC or RealVNC, VNC Viewer + * You can also use your own VNC Viewer, e.g. UltraVNC or RealVNC, with the front-end if you like. * Sets up any additional SSH port redirections that you want. @@ -7764,15 +7764,15 @@ Enhanced TightVNC Viewer (and there should be kinks to work out). This package can be downloaded here: - [8]enhanced_tightvnc_viewer-1.0.3.zip All Unix and Windows + [8]enhanced_tightvnc_viewer-1.0.4.zip All Unix and Windows binaries and source. (~6MB) - [9]enhanced_tightvnc_viewer-1.0.3.tar.gz All Unix and Windows + [9]enhanced_tightvnc_viewer-1.0.4.tar.gz All Unix and Windows binaries and source. (~6MB) - [10]enhanced_tightvnc_viewer_all-1.0.3.zip All Unix and Windows + [10]enhanced_tightvnc_viewer_all-1.0.4.zip All Unix and Windows binaries and source and full archives in zip dir. (~9MB) - [11]enhanced_tightvnc_viewer_windows_only-1.0.3.zip Only the Windows bin + [11]enhanced_tightvnc_viewer_windows_only-1.0.4.zip Only the Windows bin aries. (~4MB) - [12]enhanced_tightvnc_viewer_no_windows-1.0.3.tar.gz No Windows binaries. + [12]enhanced_tightvnc_viewer_no_windows-1.0.4.tar.gz No Windows binaries. (~2MB) Sorry for the inconvenience of lumping all the Unix binaries and @@ -7805,7 +7805,7 @@ aries. (~4MB) [17]http://www.chiark.greenend.org.uk/~sgtatham/putty/ It is my belief (but I cannot be absolutely sure) that the bundle - enhanced_tightvnc_viewer_no_windows-1.0.3.tar.gz contains no + enhanced_tightvnc_viewer_no_windows-1.0.4.tar.gz contains no cryptographic software (again, if your situation warrants, you will need to check). This "no_windows" tarball only contains software (from the above URL's and elsewhere) that will use cryptographic software @@ -7879,17 +7879,24 @@ The enhanced TightVNC viewer features are: - xgrabserver support for fullscreen mode, for old window managers (-grab option, Unix only). + - Create or Import SSL Certificates and Private Keys. + - Automatic Service tunnelling via SSH for CUPS and SMB Printing, ESD/ARTSD Audio, and SMB (Windows/Samba) filesystem mounting. - Port Knocking for "closed port" SSH/SSL connections. In addition - to a simple fixed port sequence implementation and one-time-pad, + to a simple fixed port sequence and one-time-pad implementation, a hook is also provided to run any port knocking client before a connecting. + - You can also use your own VNC Viewer, e.g. UltraVNC or RealVNC, + with the front-end if you like. + + - Sets up any additional SSH port redirections that you want. + Your package should have included binaries for many OS's: Linux, Solaris, -FreeBSD, etc. See the subdirectories of +FreeBSD, etc. Unpack your archive and see the subdirectories of ./bin @@ -7915,7 +7922,8 @@ README is in) and like this: The programs: ------------ -The wrapper scripts: +Unpack your archive, and you will see "bin", "Windows", "src" directories +and other files. The wrapper scripts: ./bin/ssl_tightvncviewer ./bin/tightvncviewer @@ -7948,7 +7956,7 @@ assuming $HOME/bin is in your $PATH: "install" this package on Unix. -On Windows run: +On Windows unpack your archive and run: Windows/ssl_tightvncviewer.exe @@ -7956,6 +7964,9 @@ On Windows run: Examples: -------- +The following assume you are in the toplevel directory of the +archive you unpacked. + Use enhanced TightVNC unix viewer to connect to x11vnc via SSL: ./bin/ssl_tightvncviewer far-away.east:0 @@ -8028,12 +8039,16 @@ See also: Windows: ------- + Unpack the zip archive somewhere. + A wrapper to create a STUNNEL tunnel and then launch the Windows TightVNC viewer is provided in: Windows/ssl_tightvncviewer.exe - Just launch it and fill in the remote VNC display. + Just launch it (Start ... Run) and fill in the remote VNC + display then click "Connect". You can make a shortcut if + you prefer. Click the Help buttons for more info. There is also a Windows/README.txt file. @@ -8051,11 +8066,11 @@ References 5. http://www.karlrunge.com/x11vnc/index.html#faq-smb-shares 6. http://www.karlrunge.com/x11vnc/index.html#faq-cups 7. http://www.karlrunge.com/x11vnc/index.html#faq-sound - 8. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer-1.0.3.zip - 9. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer-1.0.3.tar.gz - 10. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer_all-1.0.3.zip - 11. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer_windows_only-1.0.3.zip - 12. http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer_no_windows-1.0.3.tar.gz + 8. http://www.karlrunge.com/x11vnc/etv/enhanced_tightvnc_viewer-1.0.4.zip + 9. http://www.karlrunge.com/x11vnc/etv/enhanced_tightvnc_viewer-1.0.4.tar.gz + 10. http://www.karlrunge.com/x11vnc/etv/enhanced_tightvnc_viewer_all-1.0.4.zip + 11. http://www.karlrunge.com/x11vnc/etv/enhanced_tightvnc_viewer_windows_only-1.0.4.zip + 12. http://www.karlrunge.com/x11vnc/etv/enhanced_tightvnc_viewer_no_windows-1.0.4.tar.gz 13. http://www.tightvnc.com/ 14. http://www.realvnc.com/ 15. http://www.stunnel.org/ @@ -8073,7 +8088,7 @@ x11vnc: a VNC server for real X displays Here are all of x11vnc command line options: % x11vnc -opts (see below for -help long descriptions) -x11vnc: allow VNC connections to real X11 displays. 0.8.3 lastmod: 2006-09-17 +x11vnc: allow VNC connections to real X11 displays. 0.8.3 lastmod: 2006-09-20 x11vnc options: -display disp -auth file -id windowid @@ -8083,13 +8098,14 @@ x11vnc options: -24to32 -scale fraction -scale_cursor frac -viewonly -shared -once -forever -loop -timeout n - -inetd -nofilexfer -http - -http_ssl -connect string -connect_or_exit str - -vncconnect -novncconnect -allow host1[,host2..] - -localhost -nolookup -input string - -grabkbd -grabptr -viewpasswd string - -passwdfile filename -unixpw [list] -unixpw_nis [list] - -display WAIT:... -ssl [pem] -ssltimeout n + -inetd -nofilexfer -ultrafilexfer + -http -http_ssl -connect string + -connect_or_exit str -vncconnect -novncconnect + -allow host1[,host2..] -localhost -nolookup + -input string -grabkbd -grabptr + -viewpasswd string -passwdfile filename -unixpw [list] + -unixpw_nis [list] -unixpw_cmd str -display WAIT:... + -ssl [pem] -ssltimeout n -sslnofail -ssldir [dir] -sslverify [path] -sslGenCA [dir] -sslGenCert type name -sslEncKey [pem] -sslCertInfo [pem] -sslDelCert [pem] -stunnel [pem] -stunnel3 [pem] @@ -8173,7 +8189,7 @@ libvncserver-tight-extension options: % x11vnc -help -x11vnc: allow VNC connections to real X11 displays. 0.8.3 lastmod: 2006-09-17 +x11vnc: allow VNC connections to real X11 displays. 0.8.3 lastmod: 2006-09-20 (type "x11vnc -opts" to just list the options.) @@ -8470,10 +8486,11 @@ Options: change the global or per-client viewonly state the filetransfer permissions will NOT change. - Note, to *enable* UltraVNC filetransfer (currently +-ultrafilexfer Note, to *enable* UltraVNC filetransfer (currently disabled by default, this may change...) and to get it to work you probably need to supply these libvncserver options: "-rfbversion 3.6 -permitfiletransfer" + "-ultrafilexfer" is an alias for this combination. -http Instead of using -httpdir (see below) to specify where the Java vncviewer applet is, have x11vnc try @@ -8587,20 +8604,59 @@ Options: -passwdfile filename Specify the libvncserver password via the first line of the file "filename" (instead of via -passwd on the command line where others might see it via ps(1)). - See below for how to supply multiple passwords. + + See the descriptions below for how to supply multiple + passwords, view-only passwords, to specify external + programs for the authentication, and other features. If the filename is prefixed with "rm:" it will be removed after being read. Perhaps this is useful in - limiting the readability of the file. In general, - the password file should not be readable by untrusted - users (BTW: neither should the VNC -rfbauth file: - it is NOT encrypted, only obscured). + limiting the readability of the file. In general, the + password file should not be readable by untrusted users + (BTW: neither should the VNC -rfbauth file: it is NOT + encrypted, only obscured with a fixed key). If the filename is prefixed with "read:" it will - periodically be checked for changes and reread. - - Note that only the first 8 characters of a password - are used. + periodically be checked for changes and reread. It it + guaranteed to be reread just when a new client connects + so that the latest passwords will be used. + + If "filename" is prefixed with "cmd:" then the + string after the ":" is run as an external command: + the output of the command will be interpreted as if it + were read from a password file (see below). If the + command does not exit with 0, then x11vnc terminates + immediately. To specify more than 1000 passwords this + way set X11VNC_MAX_PASSWDS before starting x11vnc. + The environment variables are set as in -accept. + + Note that due to the VNC protocol only the first 8 + characters of a password are used (DES key). + + If "filename" is prefixed with "custom:" then a + custom password checker is supplied as an external + command following the ":". The command will be run + when a client authenticates. If the command exits with + 0 the client is accepted, otherwise it is rejected. + The environment variables are set as in -accept. + + The standard input to the custom command will be a + decimal digit "len" followed by a newline. "len" + specifies the challenge size and is usually 16 (the + VNC spec). Then follows len bytes which is the random + challenge string that was sent to the client. This is + then followed by len more bytes holding the client's + response (i.e. the challenge string encrypted via DES + with the user password in the standard situation). + + The "custom:" scheme can be useful to implement + dynamic passwords or to implement methods where longer + passwords and/or different encryption algorithms + are used. The latter will require customizing the VNC + client as well. One could create an MD5SUM based scheme + for example. + + File format for -passwdfile: If multiple non-blank lines exist in the file they are all taken as valid passwords. Blank lines are ignored. @@ -8763,6 +8819,17 @@ Options: to use -users unixpw= to switch the process user after the user logs in. +-unixpw_cmd str As -unixpw above, however do not use su(1) but rather + run the externally supplied command "str". The first + line of its stdin will the username and the second line + the received password. If the command exits with status + 0 (success) the VNC client will be accepted. It will be + rejected for any other return status. Dynamic passwords + and non-unix passwords can be implemented this way by + providing your own custom helper program. Note that + under unixpw mode the remote viewer is given 3 tries + to enter the correct password. + -display_WAIT :... A special usage mode for the normal -display option. Useful with -unixpw, but can be used independently of it. If the display string begins with WAIT: then @@ -8940,6 +9007,11 @@ Options: Set to zero to poll forever. Set to a negative value to use the builtin setting. +-sslnofail Exit at the first SSL connection failure. Useful when + scripting SSL connections (e.g. x11vnc is started via + ssh) and you do not want x11vnc waiting around for more + connections, tying up ports, etc. + -ssldir [dir] Use [dir] as an alternate ssl certificate and key management toplevel directory. The default is ~/.vnc/certs @@ -11473,7 +11545,7 @@ n stunnel, ssl, unixpw, WAIT, id, accept, afteraccept, gone, pipeinput, v4l-info, rawfb-setup, dt, gui, - storepasswd, crash. + storepasswd, passwdfile, custom_passwd, crash. See each option's help to learn the associated external command. Note that the -nocmds option takes precedence diff --git a/x11vnc/connections.c b/x11vnc/connections.c index 291cd7b..5ef0f9f 100644 --- a/x11vnc/connections.c +++ b/x11vnc/connections.c @@ -10,6 +10,7 @@ #include "rates.h" #include "screen.h" #include "unixpw.h" +#include "user.h" #include "scan.h" #include "sslcmds.h" #include "sslhelper.h" @@ -49,10 +50,10 @@ void send_client_info(char *str); void adjust_grabs(int grab, int quiet); void check_new_clients(void); int accept_client(rfbClientPtr client); - +int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, + int len, FILE *output); static rfbClientPtr *client_match(char *str); -static int run_user_command(char *cmd, rfbClientPtr client, char *mode); static void free_client_data(rfbClientPtr client); static int check_access(char *addr); static void ugly_geom(char *p, int *x, int *y); @@ -365,12 +366,16 @@ int cmd_ok(char *cmd) { * utility to run a user supplied command setting some RFB_ env vars. * used by, e.g., accept_client() and client_gone() */ -static int run_user_command(char *cmd, rfbClientPtr client, char *mode) { +int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, + int len, FILE *output) { char *old_display = NULL; char *addr = client->host; char str[100]; int rc, ok; - ClientData *cd = (ClientData *) client->clientData; + ClientData *cd = NULL; + if (client != NULL) { + cd = (ClientData *) client->clientData; + } if (addr == NULL || addr[0] == '\0') { addr = "unknown-host"; @@ -492,6 +497,15 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) { if (!strcmp(mode, "gone") && cmd_ok("gone")) { ok = 1; } + if (!strcmp(mode, "cmd_verify") && cmd_ok("unixpw")) { + ok = 1; + } + if (!strcmp(mode, "read_passwds") && cmd_ok("passwdfile")) { + ok = 1; + } + if (!strcmp(mode, "custom_passwd") && cmd_ok("custom_passwd")) { + ok = 1; + } if (no_external_cmds || !ok) { rfbLogEnable(1); rfbLog("cannot run external commands in -nocmds mode:\n"); @@ -502,6 +516,32 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) { rfbLog("running command:\n"); rfbLog(" %s\n", cmd); + if (output != NULL) { + FILE *ph = popen(cmd, "r"); + char line[1024]; + if (ph == NULL) { + rfbLog("popen(%s) failed", cmd); + rfbLogPerror("popen"); + clean_up_exit(1); + } + while (fgets(line, 1024, ph) != NULL) { + if (0) fprintf(stderr, "line: %s", line); + fprintf(output, "%s", line); + } + rc = pclose(ph); + goto got_rc; + } else if (input != NULL) { + FILE *ph = popen(cmd, "w"); + if (ph == NULL) { + rfbLog("popen(%s) failed", cmd); + rfbLogPerror("popen"); + clean_up_exit(1); + } + write(fileno(ph), input, len); + rc = pclose(ph); + goto got_rc; + } + #if LIBVNCSERVER_HAVE_FORK { pid_t pid, pidw; @@ -549,6 +589,7 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) { /* this will still have port 5900 open */ rc = system(cmd); #endif + got_rc: if (rc >= 256) { rc = rc/256; @@ -671,7 +712,7 @@ void client_gone(rfbClientPtr client) { free(userhost); } else { rfbLog("client_gone: using cmd: %s\n", client->host); - run_user_command(gone_cmd, client, "gone"); + run_user_command(gone_cmd, client, "gone", NULL,0,NULL); } } @@ -1412,7 +1453,7 @@ int accept_client(rfbClientPtr client) { int rc; rfbLog("accept_client: using cmd for: %s\n", addr); - rc = run_user_command(cmd, client, "accept"); + rc = run_user_command(cmd, client, "accept", NULL, 0, NULL); if (action) { int result; @@ -1952,6 +1993,8 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { last_event = last_input = time(NULL); + latest_client = client; + if (inetd) { /* * Set this so we exit as soon as connection closes, @@ -2025,6 +2068,22 @@ if (0) fprintf(stderr, "SET ssl_helper_pid: %d\n", openssl_last_helper_pid); return(RFB_CLIENT_REFUSE); } + if (passwdfile) { + if (strstr(passwdfile, "read:") == passwdfile || + strstr(passwdfile, "cmd:") == passwdfile) { + if (read_passwds(passwdfile)) { + install_passwds(); + } else { + rfbLog("problem reading: %s\n", passwdfile); + clean_up_exit(1); + } + } else if (strstr(passwdfile, "custom:") == passwdfile) { + if (screen) { + screen->passwordCheck = custom_passwd_check; + } + } + } + cd->uid = clients_served; @@ -2340,7 +2399,7 @@ void check_new_clients(void) { } if (run_after_accept) { run_user_command(afteraccept_cmd, cl, - "afteraccept"); + "afteraccept", NULL, 0, NULL); } } } diff --git a/x11vnc/connections.h b/x11vnc/connections.h index d0fbdd2..f4fbc4a 100644 --- a/x11vnc/connections.h +++ b/x11vnc/connections.h @@ -32,5 +32,7 @@ extern void send_client_info(char *str); extern void adjust_grabs(int grab, int quiet); extern void check_new_clients(void); extern int accept_client(rfbClientPtr client); +extern int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, + int len, FILE *output); #endif /* _X11VNC_CONNECTIONS_H */ diff --git a/x11vnc/help.c b/x11vnc/help.c index 0959cb8..c66c10d 100644 --- a/x11vnc/help.c +++ b/x11vnc/help.c @@ -315,10 +315,11 @@ void print_help(int mode) { " change the global or per-client viewonly state the\n" " filetransfer permissions will NOT change.\n" "\n" -" Note, to *enable* UltraVNC filetransfer (currently\n" +"-ultrafilexfer Note, to *enable* UltraVNC filetransfer (currently\n" " disabled by default, this may change...) and to get it\n" " to work you probably need to supply these libvncserver\n" " options: \"-rfbversion 3.6 -permitfiletransfer\"\n" +" \"-ultrafilexfer\" is an alias for this combination.\n" "\n" "-http Instead of using -httpdir (see below) to specify\n" " where the Java vncviewer applet is, have x11vnc try\n" @@ -434,20 +435,59 @@ void print_help(int mode) { "-passwdfile filename Specify the libvncserver password via the first line\n" " of the file \"filename\" (instead of via -passwd on\n" " the command line where others might see it via ps(1)).\n" -" See below for how to supply multiple passwords.\n" +"\n" +" See the descriptions below for how to supply multiple\n" +" passwords, view-only passwords, to specify external\n" +" programs for the authentication, and other features.\n" "\n" " If the filename is prefixed with \"rm:\" it will be\n" " removed after being read. Perhaps this is useful in\n" -" limiting the readability of the file. In general,\n" -" the password file should not be readable by untrusted\n" -" users (BTW: neither should the VNC -rfbauth file:\n" -" it is NOT encrypted, only obscured).\n" +" limiting the readability of the file. In general, the\n" +" password file should not be readable by untrusted users\n" +" (BTW: neither should the VNC -rfbauth file: it is NOT\n" +" encrypted, only obscured with a fixed key).\n" "\n" " If the filename is prefixed with \"read:\" it will\n" -" periodically be checked for changes and reread.\n" -"\n" -" Note that only the first 8 characters of a password\n" -" are used.\n" +" periodically be checked for changes and reread. It it\n" +" guaranteed to be reread just when a new client connects\n" +" so that the latest passwords will be used.\n" +"\n" +" If \"filename\" is prefixed with \"cmd:\" then the\n" +" string after the \":\" is run as an external command:\n" +" the output of the command will be interpreted as if it\n" +" were read from a password file (see below). If the\n" +" command does not exit with 0, then x11vnc terminates\n" +" immediately. To specify more than 1000 passwords this\n" +" way set X11VNC_MAX_PASSWDS before starting x11vnc.\n" +" The environment variables are set as in -accept.\n" +"\n" +" Note that due to the VNC protocol only the first 8\n" +" characters of a password are used (DES key).\n" +"\n" +" If \"filename\" is prefixed with \"custom:\" then a\n" +" custom password checker is supplied as an external\n" +" command following the \":\". The command will be run\n" +" when a client authenticates. If the command exits with\n" +" 0 the client is accepted, otherwise it is rejected.\n" +" The environment variables are set as in -accept.\n" +"\n" +" The standard input to the custom command will be a\n" +" decimal digit \"len\" followed by a newline. \"len\"\n" +" specifies the challenge size and is usually 16 (the\n" +" VNC spec). Then follows len bytes which is the random\n" +" challenge string that was sent to the client. This is\n" +" then followed by len more bytes holding the client's\n" +" response (i.e. the challenge string encrypted via DES\n" +" with the user password in the standard situation).\n" +"\n" +" The \"custom:\" scheme can be useful to implement\n" +" dynamic passwords or to implement methods where longer\n" +" passwords and/or different encryption algorithms\n" +" are used. The latter will require customizing the VNC\n" +" client as well. One could create an MD5SUM based scheme\n" +" for example.\n" +"\n" +" File format for -passwdfile:\n" "\n" " If multiple non-blank lines exist in the file they are\n" " all taken as valid passwords. Blank lines are ignored.\n" @@ -611,6 +651,17 @@ void print_help(int mode) { " to use -users unixpw= to switch the process user after\n" " the user logs in.\n" "\n" +"-unixpw_cmd str As -unixpw above, however do not use su(1) but rather\n" +" run the externally supplied command \"str\". The first\n" +" line of its stdin will the username and the second line\n" +" the received password. If the command exits with status\n" +" 0 (success) the VNC client will be accepted. It will be\n" +" rejected for any other return status. Dynamic passwords\n" +" and non-unix passwords can be implemented this way by\n" +" providing your own custom helper program. Note that\n" +" under unixpw mode the remote viewer is given 3 tries\n" +" to enter the correct password.\n" +"\n" #endif "-display WAIT:... A special usage mode for the normal -display option.\n" " Useful with -unixpw, but can be used independently\n" @@ -792,6 +843,11 @@ void print_help(int mode) { " Set to zero to poll forever. Set to a negative value\n" " to use the builtin setting.\n" "\n" +"-sslnofail Exit at the first SSL connection failure. Useful when\n" +" scripting SSL connections (e.g. x11vnc is started via\n" +" ssh) and you do not want x11vnc waiting around for more\n" +" connections, tying up ports, etc.\n" +"\n" "-ssldir [dir] Use [dir] as an alternate ssl certificate and key\n" " management toplevel directory. The default is\n" " ~/.vnc/certs\n" @@ -3340,7 +3396,7 @@ void print_help(int mode) { "\n" " stunnel, ssl, unixpw, WAIT, id, accept, afteraccept,\n" " gone, pipeinput, v4l-info, rawfb-setup, dt, gui,\n" -" storepasswd, crash.\n" +" storepasswd, passwdfile, custom_passwd, crash.\n" "\n" " See each option's help to learn the associated external\n" " command. Note that the -nocmds option takes precedence\n" diff --git a/x11vnc/options.c b/x11vnc/options.c index 93d215b..42968ef 100644 --- a/x11vnc/options.c +++ b/x11vnc/options.c @@ -19,11 +19,13 @@ char *passwdfile = NULL; /* -passwdfile */ int unixpw = 0; /* -unixpw */ int unixpw_nis = 0; /* -unixpw_nis */ char *unixpw_list = NULL; +char *unixpw_cmd = NULL; int use_stunnel = 0; /* -stunnel */ int stunnel_port = 0; char *stunnel_pem = NULL; int use_openssl = 0; int http_ssl = 0; +int ssl_no_fail = 0; char *openssl_pem = NULL; char *ssl_certs_dir = NULL; int https_port_num = -1; diff --git a/x11vnc/options.h b/x11vnc/options.h index fb0b8da..835f86e 100644 --- a/x11vnc/options.h +++ b/x11vnc/options.h @@ -19,11 +19,13 @@ extern char *passwdfile; extern int unixpw; extern int unixpw_nis; extern char *unixpw_list; +extern char *unixpw_cmd; extern int use_stunnel; extern int stunnel_port; extern char *stunnel_pem; extern int use_openssl; extern int http_ssl; +extern int ssl_no_fail; extern char *openssl_pem; extern char *ssl_certs_dir; extern int https_port_num; diff --git a/x11vnc/sslhelper.c b/x11vnc/sslhelper.c index abd0a77..83a9f38 100644 --- a/x11vnc/sslhelper.c +++ b/x11vnc/sslhelper.c @@ -1326,6 +1326,9 @@ void accept_openssl(int mode) { 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; @@ -1335,6 +1338,9 @@ void accept_openssl(int mode) { 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; @@ -1357,7 +1363,7 @@ void accept_openssl(int mode) { if (! cport) { rfbLog("SSL: accept_openssl: could not find open port.\n"); close(sock); - if (mode == OPENSSL_INETD) { + if (mode == OPENSSL_INETD || ssl_no_fail) { clean_up_exit(1); } return; @@ -1370,7 +1376,7 @@ void accept_openssl(int mode) { rfbLog("SSL: accept_openssl: could not listen on port %d.\n", cport); close(sock); - if (mode == OPENSSL_INETD) { + if (mode == OPENSSL_INETD || ssl_no_fail) { clean_up_exit(1); } return; @@ -1416,7 +1422,7 @@ void accept_openssl(int mode) { rfbLogPerror("fork"); close(sock); close(csock); - if (mode == OPENSSL_INETD) { + if (mode == OPENSSL_INETD || ssl_no_fail) { clean_up_exit(1); } return; @@ -1721,7 +1727,7 @@ if (db) fprintf(stderr, "iface: %s\n", iface); kill(pid, SIGTERM); waitpid(pid, &status, WNOHANG); - if (mode == OPENSSL_INETD) { + if (mode == OPENSSL_INETD || ssl_no_fail) { clean_up_exit(1); } return; @@ -1787,7 +1793,7 @@ if (db) fprintf(stderr, "iface: %s\n", iface); } kill(pid, SIGTERM); waitpid(pid, &status, WNOHANG); - if (mode == OPENSSL_INETD) { + if (mode == OPENSSL_INETD || ssl_no_fail) { clean_up_exit(1); } return; @@ -1820,7 +1826,7 @@ if (db) fprintf(stderr, "iface: %s\n", iface); kill(pid, SIGTERM); waitpid(pid, &status, WNOHANG); - if (mode == OPENSSL_INETD) { + if (mode == OPENSSL_INETD || ssl_no_fail) { clean_up_exit(1); } return; diff --git a/x11vnc/unixpw.c b/x11vnc/unixpw.c index 9804fe9..c40d5d6 100644 --- a/x11vnc/unixpw.c +++ b/x11vnc/unixpw.c @@ -63,6 +63,7 @@ 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 crypt_verify(char *user, char *pass); +int cmd_verify(char *user, char *pass); static int white(void); static int text_x(void); @@ -408,6 +409,51 @@ int crypt_verify(char *user, char *pass) { #endif /* UNIXPW_CRYPT */ } +int cmd_verify(char *user, char *pass) { + int i, len, rc; + char *str; + + if (! user || ! pass) { + return 0; + } + if (! unixpw_cmd || *unixpw_cmd == '\0') { + return 0; + } + if (unixpw_client) { + ClientData *cd = (ClientData *) unixpw_client->clientData; + if (cd) { + cd->username = strdup(user); + } + } + + len = strlen(user) + 1 + strlen(pass) + 1 + 1; + str = (char *) malloc(len); + if (! str) { + return 0; + } + str[0] = '\0'; + strcat(str, user); + strcat(str, "\n"); + strcat(str, pass); + if (!strchr(pass, '\n')) { + strcat(str, "\n"); + } + + rc = run_user_command(unixpw_cmd, unixpw_client, "cmd_verify", + str, strlen(str), NULL); + + for (i=0; i < len; i++) { + str[i] = '\0'; + } + free(str); + + if (rc == 0) { + return 1; + } else { + return 0; + } +} + int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size) { #ifndef UNIXPW_SU return 0; @@ -849,6 +895,7 @@ static void unixpw_verify(char *user, char *pass) { char log[] = "login: "; char *colon = NULL; ClientData *cd = NULL; + int ok; if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "********"); rfbLog("unixpw_verify: %s\n", user); @@ -871,45 +918,55 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "*** } } - if (unixpw_nis) { + ok = 0; + if (unixpw_cmd) { + if (cmd_verify(user, pass)) { + rfbLog("unixpw_verify: cmd_verify login for '%s'" + " succeeded.\n", user); + ok = 1; + } else { + rfbLog("unixpw_verify: crypt_verify login for '%s'" + " failed.\n", user); + usleep(3000*1000); + ok = 0; + } + } else if (unixpw_nis) { if (crypt_verify(user, pass)) { rfbLog("unixpw_verify: crypt_verify login for '%s'" " succeeded.\n", user); - unixpw_accept(user); - if (keep_unixpw) { - keep_unixpw_user = strdup(user); - keep_unixpw_pass = strdup(pass); - if (colon) { - keep_unixpw_opts = strdup(colon+1); - } else { - keep_unixpw_opts = strdup(""); - } - } - if (colon) *colon = ':'; - return; + ok = 1; + } else { + rfbLog("unixpw_verify: crypt_verify login for '%s'" + " failed.\n", user); + usleep(3000*1000); + ok = 0; } - rfbLog("unixpw_verify: crypt_verify login for '%s' failed.\n", - user); - usleep(3000*1000); } else { if (su_verify(user, pass, NULL, NULL, NULL)) { rfbLog("unixpw_verify: su_verify login for '%s'" " succeeded.\n", user); - unixpw_accept(user); - if (keep_unixpw) { - keep_unixpw_user = strdup(user); - keep_unixpw_pass = strdup(pass); - if (colon) { - keep_unixpw_opts = strdup(colon+1); - } else { - keep_unixpw_opts = strdup(""); - } + ok = 1; + } else { + rfbLog("unixpw_verify: su_verify login for '%s'" + " failed.\n", user); + /* use su(1)'s sleep */ + ok = 0; + } + } + + if (ok) { + unixpw_accept(user); + if (keep_unixpw) { + keep_unixpw_user = strdup(user); + keep_unixpw_pass = strdup(pass); + if (colon) { + keep_unixpw_opts = strdup(colon+1); + } else { + keep_unixpw_opts = strdup(""); } - if (colon) *colon = ':'; - return; } - rfbLog("unixpw_verify: su_verify login for '%s' failed.\n", - user); + if (colon) *colon = ':'; + return; } if (colon) *colon = ':'; diff --git a/x11vnc/unixpw.h b/x11vnc/unixpw.h index 2283145..b7054a0 100644 --- a/x11vnc/unixpw.h +++ b/x11vnc/unixpw.h @@ -10,6 +10,7 @@ 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); extern int crypt_verify(char *user, char *pass); +extern int cmd_verify(char *user, char *pass); extern int unixpw_in_progress; extern int unixpw_denied; diff --git a/x11vnc/user.c b/x11vnc/user.c index d41faa7..6a6d3b8 100644 --- a/x11vnc/user.c +++ b/x11vnc/user.c @@ -19,9 +19,9 @@ void lurk_loop(char *str); int switch_user(char *user, int fb_mode); int read_passwds(char *passfile); void install_passwds(void); -void check_new_passwds(void); +void check_new_passwds(int force); int wait_for_client(int *argc, char** argv, int http); - +rfbBool custom_passwd_check(rfbClientPtr cl, const char *response, int len); static void switch_user_task_dummy(void); static void switch_user_task_solid_bg(void); @@ -722,16 +722,21 @@ int read_passwds(char *passfile) { char line[1024]; char *filename; char **old_passwd_list = passwd_list; - int remove = 0; - int read_mode = 0; - int begin_vo = -1; + int linecount = 0, i, remove = 0, read_mode = 0, begin_vo = -1; struct stat sbuf; - int linecount = 0, i, max; - FILE *in; + static int max = -1; + FILE *in = NULL; static time_t last_read = 0; static int read_cnt = 0; int db_passwd = 0; + if (max < 0) { + max = 1000; + if (getenv("X11VNC_MAX_PASSWDS")) { + max = atoi(getenv("X11VNC_MAX_PASSWDS")); + } + } + filename = passfile; if (strstr(filename, "rm:") == filename) { filename += strlen("rm:"); @@ -741,18 +746,37 @@ int read_passwds(char *passfile) { read_mode = 1; if (stat(filename, &sbuf) == 0) { if (sbuf.st_mtime <= last_read) { - return 0; + return 1; } last_read = sbuf.st_mtime; } + } else if (strstr(filename, "cmd:") == filename) { + int rc; + + filename += strlen("cmd:"); + read_mode = 1; + in = tmpfile(); + if (in == NULL) { + rfbLog("run_user_command tmpfile() failed: %s\n", + filename); + clean_up_exit(1); + } + rc = run_user_command(filename, latest_client, "read_passwds", + NULL, 0, in); + if (rc != 0) { + rfbLog("run_user_command command failed: %s\n", + filename); + clean_up_exit(1); + } + rewind(in); + } else if (strstr(filename, "custom:") == filename) { + return 1; } - if (stat(filename, &sbuf) == 0) { + if (in == NULL && stat(filename, &sbuf) == 0) { /* (poor...) upper bound to number of lines */ max = (int) sbuf.st_size; last_read = sbuf.st_mtime; - } else { - max = 64; } /* create 1 more than max to have it be the ending NULL */ @@ -761,7 +785,9 @@ int read_passwds(char *passfile) { passwd_list[i] = NULL; } - in = fopen(filename, "r"); + if (in == NULL) { + in = fopen(filename, "r"); + } if (in == NULL) { rfbLog("cannot open passwdfile: %s\n", passfile); rfbLogPerror("fopen"); @@ -827,6 +853,7 @@ int read_passwds(char *passfile) { } if (linecount >= max) { + rfbLog("read_passwds: hit max passwd: %d\n", max); break; } } @@ -927,7 +954,7 @@ void install_passwds(void) { } } -void check_new_passwds(void) { +void check_new_passwds(int force) { static time_t last_check = 0; time_t now; @@ -939,6 +966,10 @@ void check_new_passwds(void) { } if (unixpw_in_progress) return; + if (force) { + last_check = 0; + } + now = time(NULL); if (now > last_check + 1) { if (read_passwds(passwdfile)) { @@ -948,6 +979,44 @@ void check_new_passwds(void) { } } +rfbBool custom_passwd_check(rfbClientPtr cl, const char *response, int len) { + char *input, *q, *cmd; + char num[16]; + int j, i, n, rc; + + rfbLog("custom_passwd_check: len=%d\n", len); + + if (!passwdfile || strstr(passwdfile, "custom:") != passwdfile) { + return FALSE; + } + cmd = passwdfile + strlen("custom:"); + + sprintf(num, "%d\n", len); + + input = (char *) malloc(2 * len + 16 + 1); + + input[0] = '\0'; + strcat(input, num); + n = strlen(num); + + j = n; + for (i=0; i < len; i++) { + input[j] = cl->authChallenge[i]; + j++; + } + for (i=0; i < len; i++) { + input[j] = response[i]; + j++; + } + rc = run_user_command(cmd, cl, "custom_passwd", input, n+2*len, NULL); + free(input); + if (rc == 0) { + return TRUE; + } else { + return FALSE; + } +} + static void handle_one_http_request(void) { rfbLog("handle_one_http_request: begin.\n"); diff --git a/x11vnc/user.h b/x11vnc/user.h index 9dcfe41..543e1e5 100644 --- a/x11vnc/user.h +++ b/x11vnc/user.h @@ -8,7 +8,8 @@ extern void lurk_loop(char *str); extern int switch_user(char *, int); extern int read_passwds(char *passfile); extern void install_passwds(void); -extern void check_new_passwds(void); +extern void check_new_passwds(int force); extern int wait_for_client(int *argc, char** argv, int http); +extern rfbBool custom_passwd_check(rfbClientPtr cl, const char *response, int len); #endif /* _X11VNC_USER_H */ diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index e190b4d..0910f1e 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -2,7 +2,7 @@ .TH X11VNC "1" "September 2006" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.8.3, lastmod: 2006-09-17 + version: 0.8.3, lastmod: 2006-09-20 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -373,11 +373,14 @@ Also clients that log in viewonly cannot transfer files. However, if the remote control mechanism is used to change the global or per-client viewonly state the filetransfer permissions will NOT change. +.PP +\fB-ultrafilexfer\fR .IP Note, to *enable* UltraVNC filetransfer (currently disabled by default, this may change...) and to get it to work you probably need to supply these libvncserver options: "\fB-rfbversion\fR \fI3.6 \fB-permitfiletransfer\fR"\fR +"\fB-ultrafilexfer\fR" is an alias for this combination. .PP \fB-http\fR .IP @@ -533,20 +536,59 @@ of the file \fIfilename\fR (instead of via \fB-passwd\fR on the command line where others might see it via .IR ps (1) ). -See below for how to supply multiple passwords. +.IP +See the descriptions below for how to supply multiple +passwords, view-only passwords, to specify external +programs for the authentication, and other features. .IP If the filename is prefixed with "rm:" it will be removed after being read. Perhaps this is useful in -limiting the readability of the file. In general, -the password file should not be readable by untrusted -users (BTW: neither should the VNC \fB-rfbauth\fR file: -it is NOT encrypted, only obscured). +limiting the readability of the file. In general, the +password file should not be readable by untrusted users +(BTW: neither should the VNC \fB-rfbauth\fR file: it is NOT +encrypted, only obscured with a fixed key). .IP If the filename is prefixed with "read:" it will -periodically be checked for changes and reread. -.IP -Note that only the first 8 characters of a password -are used. +periodically be checked for changes and reread. It it +guaranteed to be reread just when a new client connects +so that the latest passwords will be used. +.IP +If \fIfilename\fR is prefixed with "cmd:" then the +string after the ":" is run as an external command: +the output of the command will be interpreted as if it +were read from a password file (see below). If the +command does not exit with 0, then x11vnc terminates +immediately. To specify more than 1000 passwords this +way set X11VNC_MAX_PASSWDS before starting x11vnc. +The environment variables are set as in \fB-accept.\fR +.IP +Note that due to the VNC protocol only the first 8 +characters of a password are used (DES key). +.IP +If \fIfilename\fR is prefixed with "custom:" then a +custom password checker is supplied as an external +command following the ":". The command will be run +when a client authenticates. If the command exits with +0 the client is accepted, otherwise it is rejected. +The environment variables are set as in \fB-accept.\fR +.IP +The standard input to the custom command will be a +decimal digit "len" followed by a newline. "len" +specifies the challenge size and is usually 16 (the +VNC spec). Then follows len bytes which is the random +challenge string that was sent to the client. This is +then followed by len more bytes holding the client's +response (i.e. the challenge string encrypted via DES +with the user password in the standard situation). +.IP +The "custom:" scheme can be useful to implement +dynamic passwords or to implement methods where longer +passwords and/or different encryption algorithms +are used. The latter will require customizing the VNC +client as well. One could create an MD5SUM based scheme +for example. +.IP +File format for \fB-passwdfile:\fR .IP If multiple non-blank lines exist in the file they are all taken as valid passwords. Blank lines are ignored. @@ -733,6 +775,21 @@ in /etc/shadow can then be authenticated. You may want to use \fB-users\fR unixpw= to switch the process user after the user logs in. .PP +\fB-unixpw_cmd\fR \fIstr\fR +.IP +As \fB-unixpw\fR above, however do not use +.IR su (1) +but rather +run the externally supplied command \fIstr\fR. The first +line of its stdin will the username and the second line +the received password. If the command exits with status +0 (success) the VNC client will be accepted. It will be +rejected for any other return status. Dynamic passwords +and non-unix passwords can be implemented this way by +providing your own custom helper program. Note that +under unixpw mode the remote viewer is given 3 tries +to enter the correct password. +.PP \fB-display\fR \fIWAIT:...\fR .IP A special usage mode for the normal \fB-display\fR option. @@ -926,6 +983,13 @@ timeout (25s for about the first minute, 43200s later). Set to zero to poll forever. Set to a negative value to use the builtin setting. .PP +\fB-sslnofail\fR +.IP +Exit at the first SSL connection failure. Useful when +scripting SSL connections (e.g. x11vnc is started via +ssh) and you do not want x11vnc waiting around for more +connections, tying up ports, etc. +.PP \fB-ssldir\fR \fI[dir]\fR .IP Use [dir] as an alternate ssl certificate and key @@ -4073,7 +4137,7 @@ associated options is: .IP stunnel, ssl, unixpw, WAIT, id, accept, afteraccept, gone, pipeinput, v4l-info, rawfb-setup, dt, gui, -storepasswd, crash. +storepasswd, passwdfile, custom_passwd, crash. .IP See each option's help to learn the associated external command. Note that the \fB-nocmds\fR option takes precedence diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index b5e8b98..1183e73 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -569,7 +569,7 @@ static void watch_loop(void) { check_xdamage_state(); check_xrecord_reset(0); check_add_keysyms(); - check_new_passwds(); + check_new_passwds(0); if (started_as_root) { check_switched_user(); } @@ -1049,7 +1049,15 @@ static void quick_pw(char *str) { } *q = '\0'; if (db) fprintf(stderr, "'%s' '%s'\n", p, q+1); - if (unixpw_nis) { + if (unixpw_cmd) { + if (cmd_verify(p, q+1)) { + fprintf(stdout, "Y %s\n", p); + exit(0); + } else { + fprintf(stdout, "N %s\n", p); + exit(1); + } + } else if (unixpw_nis) { if (crypt_verify(p, q+1)) { fprintf(stdout, "Y %s\n", p); exit(0); @@ -1707,6 +1715,16 @@ int main(int argc, char* argv[]) { passwdfile = strdup(argv[++i]); got_passwdfile = 1; #ifndef NO_SSL_OR_UNIXPW + } else if (!strcmp(arg, "-unixpw_cmd") + || !strcmp(arg, "-unixpw_cmd_unsafe")) { + CHECK_ARGC + unixpw_cmd = strdup(argv[++i]); + unixpw = 1; + if (strstr(arg, "_unsafe")) { + /* hidden option for testing. */ + set_env("UNIXPW_DISABLE_SSL", "1"); + set_env("UNIXPW_DISABLE_LOCALHOST", "1"); + } } else if (strstr(arg, "-unixpw") == arg) { unixpw = 1; if (strstr(arg, "-unixpw_nis")) { @@ -1741,6 +1759,8 @@ int main(int argc, char* argv[]) { } else if (!strcmp(arg, "-ssltimeout")) { CHECK_ARGC ssl_timeout_secs = atoi(argv[++i]); + } else if (!strcmp(arg, "-sslnofail")) { + ssl_no_fail = 1; } else if (!strcmp(arg, "-ssldir")) { CHECK_ARGC ssl_certs_dir = strdup(argv[++i]); @@ -2367,7 +2387,14 @@ int main(int argc, char* argv[]) { listen_str = strdup(argv[i+1]); } /* otherwise copy it for libvncserver use below. */ - if (argc_vnc < argc_vnc_max) { + if (!strcmp(arg, "-ultrafilexfer") || + !strcmp(arg, "-ultravncfilexfer")) { + if (argc_vnc + 2 < argc_vnc_max) { + argv_vnc[argc_vnc++] = strdup("-rfbversion"); + argv_vnc[argc_vnc++] = strdup("3.6"); + argv_vnc[argc_vnc++] = strdup("-permitfiletransfer"); + } + } else if (argc_vnc < argc_vnc_max) { argv_vnc[argc_vnc++] = strdup(arg); } else { rfbLog("too many arguments.\n"); @@ -2573,12 +2600,24 @@ int main(int argc, char* argv[]) { } } else if (passwdfile) { /* read passwd(s) from file */ - if (read_passwds(passwdfile)) { + if (strstr(passwdfile, "cmd:") == passwdfile || + strstr(passwdfile, "custom:") == passwdfile) { + char tstr[100], *q; + sprintf(tstr, "%f", dnow()); + if ((q = strrchr(tstr, '.')) == NULL) { + q = tstr; + } else { + q++; + } + /* never used under cmd:, used to force auth */ + argv_vnc[argc_vnc++] = strdup("-passwd"); + argv_vnc[argc_vnc++] = strdup(q); + } else if (read_passwds(passwdfile)) { argv_vnc[argc_vnc++] = strdup("-passwd"); argv_vnc[argc_vnc++] = strdup(passwd_list[0]); - got_passwd = 1; - pw_loc = 100; /* just for pw_loc check below */ } + got_passwd = 1; + pw_loc = 100; /* just for pw_loc check below */ } if (vpw_loc > 0) { int i; diff --git a/x11vnc/x11vnc.h b/x11vnc/x11vnc.h index 6d518d6..8b0c7f2 100644 --- a/x11vnc/x11vnc.h +++ b/x11vnc/x11vnc.h @@ -454,6 +454,7 @@ extern int hack_val; /* last client to move pointer */ extern rfbClientPtr last_pointer_client; +extern rfbClientPtr latest_client; extern int client_count; extern int clients_served; diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index b115171..cfe00fa 100644 --- a/x11vnc/x11vnc_defs.c +++ b/x11vnc/x11vnc_defs.c @@ -15,7 +15,7 @@ int xtrap_base_event_type = 0; int xdamage_base_event_type = 0; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.8.3 lastmod: 2006-09-17"; +char lastmod[] = "0.8.3 lastmod: 2006-09-20"; /* X display info */ @@ -127,6 +127,7 @@ int hack_val = 0; /* last client to move pointer */ rfbClientPtr last_pointer_client = NULL; +rfbClientPtr latest_client = NULL; int client_count = 0; int clients_served = 0; |