summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrunge <runge>2006-09-21 02:11:14 +0000
committerrunge <runge>2006-09-21 02:11:14 +0000
commitdea53c22101473a58bfb113529713383203c80df (patch)
tree7f1bac1c1efbd1dc644853c6758199d2d7a187c5
parent52ed38f64789b9500d3d2e8b616aa5d1a01d5c57 (diff)
downloadlibtdevnc-dea53c22.tar.gz
libtdevnc-dea53c22.zip
x11vnc: -unixpw_cmd, -passwfile cmd:/custom:, -sslnofail, -ultrafilexfer
-rw-r--r--x11vnc/ChangeLog4
-rw-r--r--x11vnc/README204
-rw-r--r--x11vnc/connections.c73
-rw-r--r--x11vnc/connections.h2
-rw-r--r--x11vnc/help.c78
-rw-r--r--x11vnc/options.c2
-rw-r--r--x11vnc/options.h2
-rw-r--r--x11vnc/sslhelper.c18
-rw-r--r--x11vnc/unixpw.c115
-rw-r--r--x11vnc/unixpw.h1
-rw-r--r--x11vnc/user.c95
-rw-r--r--x11vnc/user.h3
-rw-r--r--x11vnc/x11vnc.186
-rw-r--r--x11vnc/x11vnc.c51
-rw-r--r--x11vnc/x11vnc.h1
-rw-r--r--x11vnc/x11vnc_defs.c3
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;