x11vnc: add -ssl mode using libssl. Include Xdummy in misc.

pull/1/head
runge 18 years ago
parent 5e72609631
commit e2e9347946

@ -175,7 +175,7 @@ if test "$X_CFLAGS" != "-DX_DISPLAY_MISSING"; then
esac esac
fi fi
# only x11vnc uses crypt() # currently only x11vnc uses crypt() or libssl:
AH_TEMPLATE(HAVE_LIBCRYPT, [libcrypt library present]) AH_TEMPLATE(HAVE_LIBCRYPT, [libcrypt library present])
AC_ARG_WITH(crypt, AC_ARG_WITH(crypt,
[ --without-crypt disable support for libcrypt],,) [ --without-crypt disable support for libcrypt],,)
@ -188,6 +188,25 @@ if test "$X_CFLAGS" != "-DX_DISPLAY_MISSING"; then
$X_LIBS $X_PRELIBS -lcrypt $X_EXTRA_LIBS) $X_LIBS $X_PRELIBS -lcrypt $X_EXTRA_LIBS)
fi fi
fi fi
AH_TEMPLATE(HAVE_LIBSSL, [openssl libssl library present])
AC_ARG_WITH(ssl,
[ --without-ssl disable support for openssl libssl],,)
if test "x$with_ssl" != "xno"; then
AC_CHECK_LIB(ssl, SSL_library_init,
X_PRELIBS="$X_PRELIBS -lssl"
[AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], ,
$X_LIBS $X_PRELIBS -lssl $X_EXTRA_LIBS)
fi
AH_TEMPLATE(HAVE_LIBCRYPTO, [openssl libcrypto library present])
AC_ARG_WITH(crypto,
[ --without-crypto disable support for openssl libcrypto],,)
# some OS's need both -lssl and -lcrypto
if test "x$HAVE_LIBSSL" = "xtrue"; then
AC_CHECK_LIB(crypto, RAND_load_file,
X_PRELIBS="$X_PRELIBS -lcrypto"
[AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], ,
$X_LIBS $X_PRELIBS -lcrypto $X_EXTRA_LIBS)
fi
X_LIBS="$X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS" X_LIBS="$X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS"

@ -1,3 +1,7 @@
2006-03-11 Karl Runge <runge@karlrunge.com>
* x11vnc: add -ssl mode using libssl. Include Xdummy in misc.
a few more macros for smallerfoot, etc.
2006-03-08 Karl Runge <runge@karlrunge.com> 2006-03-08 Karl Runge <runge@karlrunge.com>
* x11vnc: manage CLIPBOARD in addition to PRIMARY. -debug_sel * x11vnc: manage CLIPBOARD in addition to PRIMARY. -debug_sel
Make reverse connections require passwords. -usepw option. Make reverse connections require passwords. -usepw option.

@ -13,7 +13,7 @@ endif
if HAVE_X if HAVE_X
bin_PROGRAMS=x11vnc bin_PROGRAMS=x11vnc
x11vnc_SOURCES = 8to24.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c options.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c unixpw.c user.c userinput.c util.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h blackout_t.h cleanup.h connections.h cursor.h enums.h gui.h help.h inet.h keyboard.h options.h params.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h tkx11vnc.h unixpw.h user.h userinput.h util.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h x11vnc_SOURCES = 8to24.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c options.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c unixpw.c user.c userinput.c util.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h blackout_t.h cleanup.h connections.h cursor.h enums.h gui.h help.h inet.h keyboard.h options.h params.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h tkx11vnc.h unixpw.h user.h userinput.h util.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h
INCLUDES=@X_CFLAGS@ INCLUDES=@X_CFLAGS@
x11vnc_LDADD=$(LDADD) @X_LIBS@ $(LD_CYGIPC) x11vnc_LDADD=$(LDADD) @X_LIBS@ $(LD_CYGIPC)
endif endif

File diff suppressed because it is too large Load Diff

@ -10,6 +10,7 @@
#include "solid.h" #include "solid.h"
#include "unixpw.h" #include "unixpw.h"
#include "sslcmds.h" #include "sslcmds.h"
#include "sslhelper.h"
/* /*
* Exiting and error handling routines * Exiting and error handling routines
@ -133,6 +134,9 @@ void clean_up_exit (int ret) {
solid_bg(1); solid_bg(1);
} }
stop_stunnel(); stop_stunnel();
if (use_openssl) {
ssh_helper_pid(0, 0); /* killall */
}
X_LOCK; X_LOCK;
XTestDiscard_wr(dpy); XTestDiscard_wr(dpy);

@ -11,6 +11,8 @@
#include "screen.h" #include "screen.h"
#include "unixpw.h" #include "unixpw.h"
#include "scan.h" #include "scan.h"
#include "sslcmds.h"
#include "sslhelper.h"
/* /*
* routines for handling incoming, outgoing, etc connections * routines for handling incoming, outgoing, etc connections
@ -542,6 +544,7 @@ static int accepted_client = 0;
* callback for when a client disconnects * callback for when a client disconnects
*/ */
static void client_gone(rfbClientPtr client) { static void client_gone(rfbClientPtr client) {
ClientData *cd = NULL;
client_count--; client_count--;
if (client_count < 0) client_count = 0; if (client_count < 0) client_count = 0;
@ -559,17 +562,27 @@ static void client_gone(rfbClientPtr client) {
} }
} }
if (no_autorepeat && client_count == 0) { if (no_autorepeat && client_count == 0) {
autorepeat(1, 0); autorepeat(1, 0);
} }
if (use_solid_bg && client_count == 0) { if (use_solid_bg && client_count == 0) {
solid_bg(1); solid_bg(1);
} }
if (gone_cmd && *gone_cmd != '\0') { if (client->clientData) {
ClientData *cd = NULL; cd = (ClientData *) client->clientData;
if (client->clientData) { if (cd->ssh_helper_pid > 0) {
cd = (ClientData *) client->clientData; int status;
rfbLog("sending SIGTERM to ssh_helper_pid: %d\n",
cd->ssh_helper_pid);
kill(cd->ssh_helper_pid, SIGTERM);
#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID
waitpid(cd->ssh_helper_pid, &status, WNOHANG);
#endif
ssh_helper_pid(cd->ssh_helper_pid, -1); /* delete */
} }
}
if (gone_cmd && *gone_cmd != '\0') {
if (strstr(gone_cmd, "popup") == gone_cmd) { if (strstr(gone_cmd, "popup") == gone_cmd) {
int x = -64000, y = -64000, timeout = 120; int x = -64000, y = -64000, timeout = 120;
char *userhost = ident_username(client); char *userhost = ident_username(client);
@ -1452,6 +1465,10 @@ static int do_reverse_connect(char *str) {
rfbLog("reverse_connect: screen not setup yet.\n"); rfbLog("reverse_connect: screen not setup yet.\n");
return 0; return 0;
} }
if (use_openssl && !getenv("X11VNC_SSL_ALLOW_REVERSE")) {
rfbLog("reverse connections disabled in -ssl mode.\n");
return 0;
}
/* copy in to host */ /* copy in to host */
host = (char *) malloc(len+1); host = (char *) malloc(len+1);
@ -1476,7 +1493,7 @@ static int do_reverse_connect(char *str) {
return 0; return 0;
} }
} }
if (! getenv("UNIXPW_DISABLE_STUNNEL") && ! have_ssh_env()) { if (! getenv("UNIXPW_DISABLE_SSL") && ! have_ssh_env()) {
rfbLog("reverse_connect: in -inetd stunnel/ssh\n"); rfbLog("reverse_connect: in -inetd stunnel/ssh\n");
rfbLog("required under -unixpw\n"); rfbLog("required under -unixpw\n");
return 0; return 0;
@ -1824,6 +1841,13 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
clients_served++; clients_served++;
if (0) fprintf(stderr, "new_client: %s %d\n", client->host, clients_served); if (0) fprintf(stderr, "new_client: %s %d\n", client->host, clients_served);
if (use_openssl || use_stunnel) {
if (! ssl_initialized) {
rfbLog("denying additional client: %s ssl not setup"
" yet.\n", client->host);
return(RFB_CLIENT_REFUSE);
}
}
if (unixpw && unixpw_in_progress) { if (unixpw && unixpw_in_progress) {
rfbLog("denying additional client: %s during -unixpw login.\n", rfbLog("denying additional client: %s during -unixpw login.\n",
client->host); client->host);
@ -1857,6 +1881,13 @@ if (0) fprintf(stderr, "new_client: %s %d\n", client->host, clients_served);
cd->input[0] = '-'; cd->input[0] = '-';
cd->login_viewonly = -1; cd->login_viewonly = -1;
cd->login_time = time(0); cd->login_time = time(0);
cd->ssh_helper_pid = 0;
if (use_openssl && openssl_last_helper_pid) {
if (0) fprintf(stderr, "SET ssh_helper_pid: %d\n", openssl_last_helper_pid);
cd->ssh_helper_pid = openssl_last_helper_pid;
openssl_last_helper_pid = 0;
}
if (! accept_client(client)) { if (! accept_client(client)) {
rfbLog("denying client: %s local user rejected connection.\n", rfbLog("denying client: %s local user rejected connection.\n",

@ -188,6 +188,7 @@ static int got_sigusr1 = 0;
static void sigusr1 (int sig) { static void sigusr1 (int sig) {
got_sigusr1 = 1; got_sigusr1 = 1;
if (0) sig = 0;
} }
static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc, static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc,

@ -14,7 +14,7 @@ void nopassword_warning_msg(int gotloc);
void print_help(int mode) { void print_help(int mode) {
#if !SMALL_FOOTPRINT #if !SKIP_HELP
char help[] = char help[] =
"\n" "\n"
"x11vnc: allow VNC connections to real X11 displays. %s\n" "x11vnc: allow VNC connections to real X11 displays. %s\n"
@ -423,9 +423,9 @@ void print_help(int mode) {
" send one before a 25 second timeout. Existing clients\n" " send one before a 25 second timeout. Existing clients\n"
" are view-only during this period.\n" " are view-only during this period.\n"
"\n" "\n"
" Since the detailed behavior of su(1) can vary from\n" " Since the detailed behavior of su(1) can vary from OS\n"
" OS to OS and for local configurations, please test\n" " to OS and for local configurations, please test the mode\n"
" the mode carefully on your systems before using it.\n" " carefully on your systems before using it in production.\n"
" E.g. try different combinations of valid/invalid\n" " E.g. try different combinations of valid/invalid\n"
" usernames and valid/invalid passwords to see if it\n" " usernames and valid/invalid passwords to see if it\n"
" behaves correctly. x11vnc will be conservative and\n" " behaves correctly. x11vnc will be conservative and\n"
@ -443,53 +443,64 @@ void print_help(int mode) {
" e.g. password aging modules. These logins will fail\n" " e.g. password aging modules. These logins will fail\n"
" as well even when the correct password is supplied.\n" " as well even when the correct password is supplied.\n"
"\n" "\n"
" *IMPORTANT*: to prevent the Unix password being sent in\n" " **IMPORTANT**: to prevent the Unix password being sent\n"
" *clear text* over the network, two x11vnc options are\n" " in *clear text* over the network, one of two schemes\n"
" enforced: 1) -localhost and 2) -stunnel. The former\n" " will be enforced: 1) the -ssl builtin SSL mode, or 2)\n"
" requires the viewer connection to appear to come from\n" " require both -localhost and -stunnel be enabled.\n"
" the same machine x11vnc is running on (e.g. from a ssh\n"
" -L port redirection). The latter requires the -stunnel\n"
" SSL mode be used (see the description below).\n"
"\n" "\n"
" To override these restrictions you can set environment\n" " Method 1) ensures the traffic is encrypted between\n"
" variables before starting x11vnc:\n" " viewer and server. A PEM file will be required, see the\n"
" discussion under -ssl below (under some circumstances\n"
" a temporary one can be automatically generated).\n"
"\n" "\n"
" Set UNIXPW_DISABLE_STUNNEL=1 to disable using -stunnel.\n" " Method 2) requires the viewer connection to appear\n"
" Evidently you will be using a different method to\n" " to come from the same machine x11vnc is running on\n"
" encrypt the data between the vncviewer and x11vnc:\n" " (e.g. from a ssh -L port redirection). And that the\n"
" e.g. ssh(1) or a VPN. Note that use of -localhost\n" " -stunnel SSL mode be used for encryption over the\n"
" with ssh(1) is roughly the same as requiring a Unix\n" " network.(see the description of -stunnel below).\n"
" user login (since a Unix password or the user's public\n"
" key authentication is used by ssh on the machine where\n"
" x11vnc runs and only local connections are accepted)\n"
"\n" "\n"
" As a convenience, if you ssh(1) in and start x11vnc it\n" " As a convenience, if you ssh(1) in and start x11vnc it\n"
" will check if the environment variable SSH_CONNECTION\n" " will check if the environment variable SSH_CONNECTION\n"
" is set and appears reasonable. If it does, then the\n" " is set and appears reasonable. If it does, then the\n"
" stunnel requirement is dropped since it is assumed\n" " -ssl or -stunnel requirement will be dropped since it is\n"
" you are using ssh for the encrypted tunnelling.\n" " assumed you are using ssh for the encrypted tunnelling.\n"
" Use -stunnel to force stunnel usage for this case.\n" " -localhost is still enforced. Use -ssl or -stunnel to\n"
" force SSL usage for this case.\n"
"\n"
" To override these restrictions you can set environment\n"
" variables before starting x11vnc:\n"
"\n"
" Set UNIXPW_DISABLE_SSL=1 to disable requiring either\n"
" -ssl or -stunnel. Evidently you will be using a\n"
" different method to encrypt the data between the\n"
" vncviewer and x11vnc: e.g. ssh(1) or a VPN. Note that\n"
" use of -localhost with ssh(1) is roughly the same as\n"
" requiring a Unix user login (since a Unix password or\n"
" the user's public key authentication is used by sshd on\n"
" the machine where x11vnc runs and only local connections\n"
" are accepted)\n"
"\n" "\n"
" Set UNIXPW_DISABLE_LOCALHOST=1 to disable the -localhost\n" " Set UNIXPW_DISABLE_LOCALHOST=1 to disable the -localhost\n"
" requirement. One should never do this (i.e. allow the\n" " requirement in Method 2). One should never do this\n"
" Unix passwords to be sniffed on the network).\n" " (i.e. allow the Unix passwords to be sniffed on the\n"
" network).\n"
"\n" "\n"
" Regarding reverse connections (e.g. -R connect:host),\n" " Regarding reverse connections (e.g. -R connect:host),\n"
" the -localhost constraint is in effect and the reverse\n" " if the -localhost constraint is in effect then reverse\n"
" connections can only be used to connect to the same\n" " connections can only be used to connect to the same\n"
" machine x11vnc is running on (default port 5500).\n" " machine x11vnc is running on (default port 5500).\n"
" Please use a ssh or stunnel port redirection to the\n" " Please use a ssh or stunnel port redirection to the\n"
" viewer machine to tunnel the reverse connection over\n" " viewer machine to tunnel the reverse connection over\n"
" an encrypted channel. Note that Unix username and\n" " an encrypted channel. Note that in -ssl mode reverse\n"
" password *will* be prompted for (unlike VNC passwords\n" " connection are disabled.\n"
" that are skipped for reverse connections).\n"
"\n" "\n"
" NOTE: in -inetd mode the two settings are attempted\n" " XXX -inetd + -ssl\n"
" to be enforced for reverse connections. Be sure to\n" " In -inetd mode the two settings are attempted to be\n"
" enforced for reverse connections. Be sure to also\n"
" use encryption from the viewer to inetd since x11vnc\n" " use encryption from the viewer to inetd since x11vnc\n"
" cannot guess easily if it is encrpyted. Note: you can\n" " cannot guess easily if it is encrpyted. Tip: you can\n"
" also have your own stunnel spawn x11vnc in -inetd mode\n" " also have your own stunnel spawn x11vnc in -inetd mode\n"
" (i.e. bypassing inetd). See the FAQ.\n" " (i.e. bypassing inetd). See the FAQ for details.\n"
"\n" "\n"
" The user names in the comma separated [list] can have\n" " The user names in the comma separated [list] can have\n"
" per-user options after a \":\", e.g. \"fred:opts\"\n" " per-user options after a \":\", e.g. \"fred:opts\"\n"
@ -521,17 +532,84 @@ void print_help(int mode) {
" other environment. All of the -unixpw options and\n" " other environment. All of the -unixpw options and\n"
" contraints apply.\n" " contraints apply.\n"
"\n" "\n"
"-stunnel [pem] Use the stunnel(1) (www.stunnel.org) to provide\n" "-ssl [pem] Use the openssl library (www.openssl.org) to provide a\n"
" built-in encrypted SSL tunnel between VNC viewers and\n"
" x11vnc. This requires libssl support to be compiled\n"
" into x11vnc at build time. If x11vnc is not built\n"
" with libssl support it will exit immediately when -ssl\n"
" is prescribed.\n"
"\n"
" [pem] is optional, use \"-ssl /path/to/mycert.pem\" to\n"
" specify a PEM certificate file to use to identify and\n"
" provide a key for this server.\n"
"\n"
" Connecting VNC viewer SSL tunnels can authenticate\n"
" this server if they have the public key part of the\n"
" certificate (or a common certificate authority, CA,\n"
" verifies this server's cert). This is used to prevent\n"
" man-in-the-middle attacks. Otherwise, if the VNC viewer\n"
" accepts this server's key without verification, at\n"
" least the traffic is protected from passive sniffing\n"
" on the network.\n"
"\n"
" If [pem] is not supplied and the openssl(1) utility\n"
" command exists in PATH, then a temporary, self-signed\n"
" certificate will be generated for this session (this\n"
" may take 5-20 seconds on slow machines). If openssl(1)\n"
" cannot be used to generate a temporary certificate\n"
" x11vnc exits immediately.\n"
"\n"
" If successful in using openssl(1) to generate a\n"
" certificate, the public part of it will be displayed\n"
" to stdout (e.g. one could copy it to the client-side\n"
" to provide authentication of the server to VNC viewers.)\n"
"\n"
" Set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc\n"
" print out the entire certificate, including the PRIVATE\n"
" KEY part, to stderr. One could reuse this cert if saved\n"
" in a [pem] file. Similarly, set X11VNC_KEEP_TMP_PEM=1\n"
" to not delete the temporary PEM file: the file name\n"
" will be printed to stderr (so one could move it to a\n"
" safe place for reuse).\n"
"\n"
" Reverse connections are disabled in -ssl\n"
" mode because the data cannot be encrypted.\n"
" Set X11VNC_SSL_ALLOW_REVERSE=1 to override this.\n"
"\n"
" Your VNC viewer will also need to be able to connect\n"
" via SSL. See the discussion below under -stunnel and\n"
" the FAQ for how this might be achieved. E.g. on Unix it\n"
" is easy to write a shell script that starts up stunnel\n"
" and then vncviewer.\n"
"\n"
"-sslverify [path] For either of the -ssl or -stunnel modes, use [path]\n"
" to provide certificates to authenticate incoming VNC\n"
" client connections. This can be used as a method to\n"
" replace standard password authentication.\n"
"\n"
" If [path] is a directory it contains the client (or CA)\n"
" certificates in separate files. If [path] is a file, it\n"
" contains multiple certificates. These correspond to the\n"
" \"CApath = dir\" and \"CAfile = file\" stunnel options.\n"
" See the stunnel(8) manpage for details.\n"
"\n"
" To create certificates for all sorts of authentications\n"
" (clients, servers, via CA, etc) see the openssl(1)\n"
" command. Of particular usefulness is the x509\n"
" subcommand of openssl(1).\n"
"\n"
"-stunnel [pem] Use the stunnel(8) (www.stunnel.org) to provide\n"
" an encrypted SSL tunnel between viewers and x11vnc.\n" " an encrypted SSL tunnel between viewers and x11vnc.\n"
" This requires stunnel to be installed on the system and\n" " This requires stunnel to be installed on the system and\n"
" available via PATH (n.b. stunnel is often installed in\n" " available via PATH (n.b. stunnel is often installed in\n"
" sbin directories). Version 4.x of stunnel is assumed;\n" " sbin directories). Version 4.x of stunnel is assumed\n"
" see -stunnel3 below.\n" " (but see -stunnel3 below.)\n"
"\n" "\n"
" [pem] is optional, use \"-stunnel /path/to/stunnel.pem\"\n" " [pem] is optional, use \"-stunnel /path/to/stunnel.pem\"\n"
" to specify a PEM certificate file to pass to stunnel.\n" " to specify a PEM certificate file to pass to stunnel.\n"
" Whether one is needed or not depends on your stunnel\n" " Whether one is needed or not depends on your stunnel\n"
" configuration.\n" " configuration. stunnel often generates one at install\n"
" time.\n"
"\n" "\n"
" stunnel is started up as a child process of x11vnc and\n" " stunnel is started up as a child process of x11vnc and\n"
" any SSL connections stunnel receives are decrypted and\n" " any SSL connections stunnel receives are decrypted and\n"
@ -543,14 +621,15 @@ void print_help(int mode) {
" avoid people routing around the SSL channel. Set\n" " avoid people routing around the SSL channel. Set\n"
" STUNNEL_DISABLE_LOCALHOST=1 to disable the requirement.\n" " STUNNEL_DISABLE_LOCALHOST=1 to disable the requirement.\n"
"\n" "\n"
" Your VNC viewer will need to be able to connect via SSL.\n" " Your VNC viewer will also need to be able to connect\n"
" Unfortunately not too many do this. UltraVNC seems to\n" " via SSL. Unfortunately not too many do this. UltraVNC\n"
" have a SSL plugin. It is not too difficult to set up\n" " seems to have an encryption plugin. It is not too\n"
" an stunnel or other SSL tunnel on the viewer side.\n" " difficult to set up an stunnel or other SSL tunnel on\n"
" the viewer side.\n"
"\n" "\n"
" A simple example on Unix using stunnel 3.x is:\n" " A simple example on Unix using stunnel 3.x is:\n"
"\n" "\n"
" %% stunnel -c -d localhost:5901 -r remote:5900\n" " %% stunnel -c -d localhost:5901 -r remotehost:5900\n"
" %% vncviewer localhost:1\n" " %% vncviewer localhost:1\n"
"\n" "\n"
" For Windows, stunnel has been ported to it and there\n" " For Windows, stunnel has been ported to it and there\n"
@ -2175,22 +2254,24 @@ void print_help(int mode) {
" debug_xdamage debug_wireframe nodebug_wireframe\n" " debug_xdamage debug_wireframe nodebug_wireframe\n"
" debug_wireframe debug_scroll nodebug_scroll debug_scroll\n" " debug_wireframe debug_scroll nodebug_scroll debug_scroll\n"
" debug_tiles dbt nodebug_tiles nodbt debug_tiles\n" " debug_tiles dbt nodebug_tiles nodbt debug_tiles\n"
" debug_grabs nodebug_grabs dbg nodbg noremote\n" " debug_grabs nodebug_grabs debug_sel nodebug_sel dbg\n"
" nodbg noremote\n"
"\n" "\n"
" aro= noop display vncdisplay desktopname guess_desktop\n" " aro= noop display vncdisplay desktopname guess_desktop\n"
" http_url auth xauth users rootshift clipshift\n" " http_url auth xauth users rootshift clipshift\n"
" scale_str scaled_x scaled_y scale_numer scale_denom\n" " scale_str scaled_x scaled_y scale_numer scale_denom\n"
" scale_fac scaling_blend scaling_nomult4 scaling_pad\n" " scale_fac scaling_blend scaling_nomult4 scaling_pad\n"
" scaling_interpolate inetd privremote unsafe safer\n" " scaling_interpolate inetd privremote unsafe safer\n"
" nocmds passwdfile unixpw unixpw_nis unixpw_list stunnel\n" " nocmds passwdfile unixpw unixpw_nis unixpw_list ssl\n"
" stunnel_pem using_shm logfile o flag rc norc h help\n" " ssl_pem sslverify stunnel stunnel_pem usepw using_shm\n"
" V version lastmod bg sigpipe threads readrate netrate\n" " logfile o flag rc norc h help V version lastmod bg\n"
" netlatency pipeinput clients client_count pid ext_xtest\n" " sigpipe threads readrate netrate netlatency pipeinput\n"
" ext_xtrap ext_xrecord ext_xkb ext_xshm ext_xinerama\n" " clients client_count pid ext_xtest ext_xtrap ext_xrecord\n"
" ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin\n" " ext_xkb ext_xshm ext_xinerama ext_overlay ext_xfixes\n"
" num_buttons button_mask mouse_x mouse_y bpp depth\n" " ext_xdamage ext_xrandr rootwin num_buttons button_mask\n"
" indexed_color dpy_x dpy_y wdpy_x wdpy_y off_x off_y\n" " mouse_x mouse_y bpp depth indexed_color dpy_x dpy_y\n"
" cdpy_x cdpy_y coff_x coff_y rfbauth passwd viewpasswd\n" " wdpy_x wdpy_y off_x off_y cdpy_x cdpy_y coff_x coff_y\n"
" rfbauth passwd viewpasswd\n"
"\n" "\n"
"-QD variable Just like -query variable, but returns the default\n" "-QD variable Just like -query variable, but returns the default\n"
" value for that parameter (no running x11vnc server\n" " value for that parameter (no running x11vnc server\n"

File diff suppressed because it is too large Load Diff

@ -21,6 +21,11 @@ char *unixpw_list = NULL;
int use_stunnel = 0; /* -stunnel */ int use_stunnel = 0; /* -stunnel */
int stunnel_port = 0; int stunnel_port = 0;
char *stunnel_pem = NULL; char *stunnel_pem = NULL;
int use_openssl = 0;
char *openssl_pem = NULL;
char *ssl_verify = NULL;
int ssl_initialized = 0;
int usepw = USEPW;
char *blackout_str = NULL; /* -blackout */ char *blackout_str = NULL; /* -blackout */
int blackout_ptr = 0; int blackout_ptr = 0;
char *clip_str = NULL; /* -clip */ char *clip_str = NULL; /* -clip */

@ -21,6 +21,11 @@ extern char *unixpw_list;
extern int use_stunnel; extern int use_stunnel;
extern int stunnel_port; extern int stunnel_port;
extern char *stunnel_pem; extern char *stunnel_pem;
extern int use_openssl;
extern char *openssl_pem;
extern char *ssl_verify;
extern int ssl_initialized;
extern int usepw;
extern char *blackout_str; extern char *blackout_str;
extern int blackout_ptr; extern int blackout_ptr;
extern char *clip_str; extern char *clip_str;

@ -3775,10 +3775,18 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%d", p, unixpw_nis); snprintf(buf, bufn, "aro=%s:%d", p, unixpw_nis);
} else if (!strcmp(p, "unixpw_list")) { } else if (!strcmp(p, "unixpw_list")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(unixpw_list)); snprintf(buf, bufn, "aro=%s:%s", p, NONUL(unixpw_list));
} else if (!strcmp(p, "ssl")) {
snprintf(buf, bufn, "aro=%s:%d", p, use_openssl);
} else if (!strcmp(p, "ssl_pem")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(openssl_pem));
} else if (!strcmp(p, "sslverify")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(ssl_verify));
} else if (!strcmp(p, "stunnel")) { } else if (!strcmp(p, "stunnel")) {
snprintf(buf, bufn, "aro=%s:%d", p, use_stunnel); snprintf(buf, bufn, "aro=%s:%d", p, use_stunnel);
} else if (!strcmp(p, "stunnel_pem")) { } else if (!strcmp(p, "stunnel_pem")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(stunnel_pem)); snprintf(buf, bufn, "aro=%s:%s", p, NONUL(stunnel_pem));
} else if (!strcmp(p, "usepw")) {
snprintf(buf, bufn, "aro=%s:%d", p, usepw);
} else if (!strcmp(p, "using_shm")) { } else if (!strcmp(p, "using_shm")) {
snprintf(buf, bufn, "aro=%s:%d", p, !using_shm); snprintf(buf, bufn, "aro=%s:%d", p, !using_shm);
} else if (!strcmp(p, "logfile") || !strcmp(p, "o")) { } else if (!strcmp(p, "logfile") || !strcmp(p, "o")) {

@ -2146,8 +2146,9 @@ static void ping_clients(int tile_cnt) {
} }
if (tile_cnt) { if (tile_cnt) {
last_send = now; last_send = now;
} else if (now - last_send > 1) { } else if (now - last_send > 2) {
/* Send small heartbeat to client */ /* Send small heartbeat to client */
if (0) fprintf(stderr, "ping_clients 2\n");
mark_rect_as_modified(0, 0, 1, 1, 1); mark_rect_as_modified(0, 0, 1, 1, 1);
last_send = now; last_send = now;
} }
@ -2638,6 +2639,8 @@ int scan_for_updates(int count_only) {
/* Work around threaded rfbProcessClientMessage() calls timeouts */ /* Work around threaded rfbProcessClientMessage() calls timeouts */
if (use_threads) { if (use_threads) {
ping_clients(tile_diffs); ping_clients(tile_diffs);
} else if (use_openssl && !tile_diffs) {
ping_clients(0);
} }

@ -18,11 +18,13 @@
#include "remote.h" #include "remote.h"
#include "unixpw.h" #include "unixpw.h"
#include "sslcmds.h" #include "sslcmds.h"
#include "sslhelper.h"
void set_colormap(int reset); void set_colormap(int reset);
void set_nofb_params(int restore); void set_nofb_params(int restore);
void set_raw_fb_params(int restore); void set_raw_fb_params(int restore);
void do_new_fb(int reset_mem); void do_new_fb(int reset_mem);
void free_old_fb(char *old_main, char *old_rfb, char *old_8to24);
void check_padded_fb(void); void check_padded_fb(void);
void install_padded_fb(char *geom); void install_padded_fb(char *geom);
XImage *initialize_xdisplay_fb(void); XImage *initialize_xdisplay_fb(void);
@ -552,6 +554,18 @@ static void nofb_hook(rfbClientPtr cl) {
screen->displayHook = NULL; screen->displayHook = NULL;
} }
void free_old_fb(char *old_main, char *old_rfb, char *old_8to24) {
if (old_main) {
free(old_main);
}
if (old_rfb && old_rfb != old_main) {
free(old_rfb);
}
if (old_8to24 && old_8to24 != old_main && old_8to24 != old_rfb) {
free(old_8to24);
}
}
void do_new_fb(int reset_mem) { void do_new_fb(int reset_mem) {
XImage *fb; XImage *fb;
char *old_main = main_fb; char *old_main = main_fb;
@ -580,15 +594,8 @@ void do_new_fb(int reset_mem) {
initialize_polling_images(); initialize_polling_images();
} }
if (old_main) { free_old_fb(old_main, old_rfb, old_8to24);
free(old_main);
}
if (old_rfb && old_rfb != old_main) {
free(old_rfb);
}
if (old_8to24 && old_8to24 != old_main && old_8to24 != old_rfb) {
free(old_8to24);
}
fb0 = fb; fb0 = fb;
} }
@ -1572,7 +1579,9 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
/* n.b. samplesPerPixel (set = 1 here) seems to be unused. */ /* n.b. samplesPerPixel (set = 1 here) seems to be unused. */
if (create_screen) { if (create_screen) {
if (use_stunnel) { if (use_openssl) {
openssl_init();
} else if (use_stunnel) {
setup_stunnel(0, argc, argv); setup_stunnel(0, argc, argv);
} }
screen = rfbGetScreen(argc, argv, width, height, screen = rfbGetScreen(argc, argv, width, height,
@ -1954,6 +1963,10 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
rfbInitServer(screen); rfbInitServer(screen);
if (use_openssl) {
openssl_port();
}
install_passwds(); install_passwds();
} }

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

@ -302,7 +302,7 @@ void selection_send(XEvent *ev) {
PROP_MAX); PROP_MAX);
break; break;
} }
if (debug_sel) fprintf(stderr, "selection_send: data: '%s' dlen: %d nitems: %d ba: %d\n", data, dlen, nitems, bytes_after); if (debug_sel) fprintf(stderr, "selection_send: data: '%s' dlen: %d nitems: %lu ba: %lu\n", data, dlen, nitems, bytes_after);
memcpy(selection_str+slen, data, dlen); memcpy(selection_str+slen, data, dlen);
slen += dlen; slen += dlen;
selection_str[slen] = '\0'; selection_str[slen] = '\0';

@ -46,6 +46,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
char extra[] = ":/usr/sbin:/usr/local/sbin"; char extra[] = ":/usr/sbin:/usr/local/sbin";
char *path, *p, *exe; char *path, *p, *exe;
char *stunnel_path = NULL; char *stunnel_path = NULL;
struct stat verify_buf;
int status; int status;
if (stunnel_pid) { if (stunnel_pid) {
@ -110,13 +111,11 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
stunnel_port, x11vnc_port); stunnel_port, x11vnc_port);
} }
if (0) { if (ssl_verify) {
fprintf(stderr, "foreground = yes\n"); if (stat(ssl_verify, &verify_buf) != 0) {
fprintf(stderr, "pid =\n"); rfbLog("stunnel: %s does not exist.\n", ssl_verify);
fprintf(stderr, ";debug = 7\n"); return 0;
fprintf(stderr, "[x11vnc_stunnel]\n"); }
fprintf(stderr, "accept = %d\n", stunnel_port);
fprintf(stderr, "connect = %d\n", x11vnc_port);
} }
stunnel_pid = fork(); stunnel_pid = fork();
@ -137,18 +136,37 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
} }
if (use_stunnel == 3) { if (use_stunnel == 3) {
char sp[20], xp[20]; char sp[20], xp[20], *a = NULL;
char *st = stunnel_path;
char *pm = stunnel_pem;
char *sv = ssl_verify;
sprintf(sp, "%d", stunnel_port); sprintf(sp, "%d", stunnel_port);
sprintf(xp, "%d", x11vnc_port); sprintf(xp, "%d", x11vnc_port);
if (ssl_verify) {
if(S_ISDIR(verify_buf.st_mode)) {
a = "-a";
} else {
a = "-A";
}
}
if (stunnel_pem) { if (stunnel_pem && ssl_verify) {
execlp(stunnel_path, stunnel_path, "-f", "-d", execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
sp, "-r", xp, "-P", "none", "-p", "none", "-p", pm, a, sv, "-v", "2",
stunnel_pem, (char *) NULL); (char *) NULL);
} else if (stunnel_pem && !ssl_verify) {
execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
"none", "-p", pm,
(char *) NULL);
} else if (!stunnel_pem && ssl_verify) {
execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
"none", a, sv, "-v", "2",
(char *) NULL);
} else { } else {
execlp(stunnel_path, stunnel_path, "-f", "-d", execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
sp, "-r", xp, "-P", "none", (char *) NULL); "none", (char *) NULL);
} }
exit(1); exit(1);
} }
@ -162,7 +180,15 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
if (stunnel_pem) { if (stunnel_pem) {
fprintf(in, "cert = %s\n", stunnel_pem); fprintf(in, "cert = %s\n", stunnel_pem);
} }
fprintf(in, ";debug = 7\n"); if (ssl_verify) {
if(S_ISDIR(verify_buf.st_mode)) {
fprintf(in, "CApath = %s\n", ssl_verify);
} else {
fprintf(in, "CAfile = %s\n", ssl_verify);
}
fprintf(in, "verify = 2\n");
}
fprintf(in, ";debug = 7\n\n");
fprintf(in, "[x11vnc_stunnel]\n"); fprintf(in, "[x11vnc_stunnel]\n");
fprintf(in, "accept = %d\n", stunnel_port); fprintf(in, "accept = %d\n", stunnel_port);
fprintf(in, "connect = %d\n", x11vnc_port); fprintf(in, "connect = %d\n", x11vnc_port);
@ -256,6 +282,7 @@ void setup_stunnel(int rport, int *argc, char **argv) {
} }
} }
stunnel_port = rport; stunnel_port = rport;
ssl_initialized = 1;
return; return;
} }

File diff suppressed because it is too large Load Diff

@ -0,0 +1,17 @@
#ifndef _X11VNC_SSLHELPER_H
#define _X11VNC_SSLHELPER_H
/* -- sslhelper.h -- */
extern int openssl_sock;
extern pid_t openssl_last_helper_pid;
extern int openssl_present(void);
extern void openssl_init(void);
extern void openssl_port(void);
extern void check_openssl(void);
extern void ssh_helper_pid(pid_t pid, int sock);
#endif /* _X11VNC_SSLHELPER_H */

@ -249,6 +249,8 @@ Debugging
=GA tail-logfile =GA tail-logfile
quiet quiet
-- --
=GA show-start-cmd
=DG debug_gui
=GAL Misc-Debug:: =GAL Misc-Debug::
debug_xevents debug_xevents
debug_xdamage debug_xdamage
@ -259,8 +261,6 @@ Debugging
debug_sel debug_sel
dbg dbg
=GAL LOFF =GAL LOFF
=GA show-start-cmd
=DG debug_gui
Permissions Permissions
=DRQA lock =DRQA lock
@ -289,19 +289,22 @@ Permissions
unixpw_nis_list: unixpw_nis_list:
=0 storepasswd =0 storepasswd
=GAL LOFF =GAL LOFF
=GAL Safe:: =GAL SSL::
ssl
=F ssl_pem:
stunnel
=F stunnel_pem:
=F sslverify:
=GAL LOFF
=GAL Misc-Perms::
safer safer
unsafe unsafe
=RA noremote =RA noremote
=GAL LOFF
=GAL Misc-Perms::
=0S alwaysshared =0S alwaysshared
=0S nevershared =0S nevershared
=0S dontdisconnect =0S dontdisconnect
=SQA deny_all =SQA deny_all
timeout: timeout:
stunnel
=F stunnel_pem:
=GAL LOFF =GAL LOFF
Tuning Tuning
@ -568,6 +571,10 @@ Set the -unixpw_nis usernames list value.
set helptext(stunnel_pem) " set helptext(stunnel_pem) "
Set the -stunnel pem filename value. Set the -stunnel pem filename value.
"
set helptext(ssl_pem) "
Set the -ssl pem filename value.
" "
set helptext(wireframe_mode) " set helptext(wireframe_mode) "
@ -786,6 +793,17 @@ work everywhere.
Regarding ViewOnly passwords (where a VNC client using that password Regarding ViewOnly passwords (where a VNC client using that password
can only watch the screen, not interact with it), this is not available can only watch the screen, not interact with it), this is not available
with -rfbauth, but only with -passwdfile, -passwd, and -viewpasswd. with -rfbauth, but only with -passwdfile, -passwd, and -viewpasswd.
"
set helptext(SSL:) "
In this sub-menu we provide the options related to SSL encrpytion
and authentication.
There is a built-in mode (-ssl) using the OpenSSL library, and a 2nd
using the external stunnel program (-stunnel, that needs to be installed
on the system). Either may require or benefit from having PEM certificate
files specified.
" "
set helptext(Misc-Perms:) " set helptext(Misc-Perms:) "
@ -5584,6 +5602,8 @@ proc get_nitem {item} {
set nitem "unixpw_nis" set nitem "unixpw_nis"
} elseif {$nitem == "stunnel_pem"} { } elseif {$nitem == "stunnel_pem"} {
set nitem "stunnel" set nitem "stunnel"
} elseif {$nitem == "ssl_pem"} {
set nitem "ssl"
} elseif {$nitem == "wireframe_mode"} { } elseif {$nitem == "wireframe_mode"} {
set nitem "wireframe" set nitem "wireframe"
} elseif {$nitem == "solid_color"} { } elseif {$nitem == "solid_color"} {

@ -260,6 +260,8 @@ char gui_code[] = "";
" =GA tail-logfile\n" " =GA tail-logfile\n"
" quiet\n" " quiet\n"
" --\n" " --\n"
" =GA show-start-cmd\n"
" =DG debug_gui\n"
" =GAL Misc-Debug::\n" " =GAL Misc-Debug::\n"
" debug_xevents\n" " debug_xevents\n"
" debug_xdamage\n" " debug_xdamage\n"
@ -270,8 +272,6 @@ char gui_code[] = "";
" debug_sel\n" " debug_sel\n"
" dbg\n" " dbg\n"
" =GAL LOFF\n" " =GAL LOFF\n"
" =GA show-start-cmd\n"
" =DG debug_gui\n"
"\n" "\n"
"Permissions\n" "Permissions\n"
" =DRQA lock\n" " =DRQA lock\n"
@ -300,19 +300,22 @@ char gui_code[] = "";
" unixpw_nis_list:\n" " unixpw_nis_list:\n"
" =0 storepasswd\n" " =0 storepasswd\n"
" =GAL LOFF\n" " =GAL LOFF\n"
" =GAL Safe::\n" " =GAL SSL::\n"
" ssl\n"
" =F ssl_pem:\n"
" stunnel\n"
" =F stunnel_pem:\n"
" =F sslverify:\n"
" =GAL LOFF\n"
" =GAL Misc-Perms::\n"
" safer\n" " safer\n"
" unsafe\n" " unsafe\n"
" =RA noremote\n" " =RA noremote\n"
" =GAL LOFF\n"
" =GAL Misc-Perms::\n"
" =0S alwaysshared\n" " =0S alwaysshared\n"
" =0S nevershared\n" " =0S nevershared\n"
" =0S dontdisconnect\n" " =0S dontdisconnect\n"
" =SQA deny_all\n" " =SQA deny_all\n"
" timeout:\n" " timeout:\n"
" stunnel\n"
" =F stunnel_pem:\n"
" =GAL LOFF\n" " =GAL LOFF\n"
"\n" "\n"
"Tuning\n" "Tuning\n"
@ -581,6 +584,10 @@ char gui_code[] = "";
"Set the -stunnel pem filename value.\n" "Set the -stunnel pem filename value.\n"
"\"\n" "\"\n"
"\n" "\n"
" set helptext(ssl_pem) \"\n"
"Set the -ssl pem filename value.\n"
"\"\n"
"\n"
" set helptext(wireframe_mode) \"\n" " set helptext(wireframe_mode) \"\n"
"Set the -wireframe mode string value.\n" "Set the -wireframe mode string value.\n"
"\"\n" "\"\n"
@ -799,6 +806,17 @@ char gui_code[] = "";
"with -rfbauth, but only with -passwdfile, -passwd, and -viewpasswd.\n" "with -rfbauth, but only with -passwdfile, -passwd, and -viewpasswd.\n"
"\"\n" "\"\n"
"\n" "\n"
" set helptext(SSL:) \"\n"
"In this sub-menu we provide the options related to SSL encrpytion\n"
"and authentication.\n"
"\n"
"There is a built-in mode (-ssl) using the OpenSSL library, and a 2nd\n"
"using the external stunnel program (-stunnel, that needs to be installed\n"
"on the system). Either may require or benefit from having PEM certificate\n"
"files specified.\n"
"\n"
"\"\n"
"\n"
" set helptext(Misc-Perms:) \"\n" " set helptext(Misc-Perms:) \"\n"
"In this sub-menu we provide some lesser used permission options.\n" "In this sub-menu we provide some lesser used permission options.\n"
"\n" "\n"
@ -5595,6 +5613,8 @@ char gui_code[] = "";
" set nitem \"unixpw_nis\"\n" " set nitem \"unixpw_nis\"\n"
" } elseif {$nitem == \"stunnel_pem\"} {\n" " } elseif {$nitem == \"stunnel_pem\"} {\n"
" set nitem \"stunnel\"\n" " set nitem \"stunnel\"\n"
" } elseif {$nitem == \"ssl_pem\"} {\n"
" set nitem \"ssl\"\n"
" } elseif {$nitem == \"wireframe_mode\"} {\n" " } elseif {$nitem == \"wireframe_mode\"} {\n"
" set nitem \"wireframe\"\n" " set nitem \"wireframe\"\n"
" } elseif {$nitem == \"solid_color\"} {\n" " } elseif {$nitem == \"solid_color\"} {\n"

@ -279,7 +279,7 @@ void try_to_be_nobody(void) {
} }
static int slave_fd = -1, alarm_fired = 0;; static int slave_fd = -1, alarm_fired = 0;
static void close_alarm (int sig) { static void close_alarm (int sig) {
if (slave_fd >= 0) { if (slave_fd >= 0) {

@ -2,7 +2,7 @@
.TH X11VNC "1" "March 2006" "x11vnc " "User Commands" .TH X11VNC "1" "March 2006" "x11vnc " "User Commands"
.SH NAME .SH NAME
x11vnc - allow VNC connections to real X11 displays x11vnc - allow VNC connections to real X11 displays
version: 0.8.1, lastmod: 2006-03-08 version: 0.8.1, lastmod: 2006-03-11
.SH SYNOPSIS .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [OPTION]...
@ -519,9 +519,9 @@ are view-only during this period.
.IP .IP
Since the detailed behavior of Since the detailed behavior of
.IR su (1) .IR su (1)
can vary from can vary from OS
OS to OS and for local configurations, please test to OS and for local configurations, please test the mode
the mode carefully on your systems before using it. carefully on your systems before using it in production.
E.g. try different combinations of valid/invalid E.g. try different combinations of valid/invalid
usernames and valid/invalid passwords to see if it usernames and valid/invalid passwords to see if it
behaves correctly. x11vnc will be conservative and behaves correctly. x11vnc will be conservative and
@ -541,59 +541,70 @@ problems are PAM modules that prompt for extra info,
e.g. password aging modules. These logins will fail e.g. password aging modules. These logins will fail
as well even when the correct password is supplied. as well even when the correct password is supplied.
.IP .IP
*IMPORTANT*: to prevent the Unix password being sent in **IMPORTANT**: to prevent the Unix password being sent
*clear text* over the network, two x11vnc options are in *clear text* over the network, one of two schemes
enforced: 1) \fB-localhost\fR and 2) \fB-stunnel.\fR The former will be enforced: 1) the \fB-ssl\fR builtin SSL mode, or 2)
requires the viewer connection to appear to come from require both \fB-localhost\fR and \fB-stunnel\fR be enabled.
the same machine x11vnc is running on (e.g. from a ssh
\fB-L\fR port redirection). The latter requires the \fB-stunnel\fR
SSL mode be used (see the description below).
.IP .IP
To override these restrictions you can set environment Method 1) ensures the traffic is encrypted between
variables before starting x11vnc: viewer and server. A PEM file will be required, see the
discussion under \fB-ssl\fR below (under some circumstances
a temporary one can be automatically generated).
.IP .IP
Set UNIXPW_DISABLE_STUNNEL=1 to disable using \fB-stunnel.\fR Method 2) requires the viewer connection to appear
Evidently you will be using a different method to to come from the same machine x11vnc is running on
encrypt the data between the vncviewer and x11vnc: (e.g. from a ssh \fB-L\fR port redirection). And that the
e.g. \fB-stunnel\fR SSL mode be used for encryption over the
.IR ssh (1) network.(see the description of \fB-stunnel\fR below).
or a VPN. Note that use of \fB-localhost\fR
with
.IR ssh (1)
is roughly the same as requiring a Unix
user login (since a Unix password or the user's public
key authentication is used by ssh on the machine where
x11vnc runs and only local connections are accepted)
.IP .IP
As a convenience, if you As a convenience, if you
.IR ssh (1) .IR ssh (1)
in and start x11vnc it in and start x11vnc it
will check if the environment variable SSH_CONNECTION will check if the environment variable SSH_CONNECTION
is set and appears reasonable. If it does, then the is set and appears reasonable. If it does, then the
stunnel requirement is dropped since it is assumed \fB-ssl\fR or \fB-stunnel\fR requirement will be dropped since it is
you are using ssh for the encrypted tunnelling. assumed you are using ssh for the encrypted tunnelling.
Use \fB-stunnel\fR to force stunnel usage for this case. \fB-localhost\fR is still enforced. Use \fB-ssl\fR or \fB-stunnel\fR to
force SSL usage for this case.
.IP
To override these restrictions you can set environment
variables before starting x11vnc:
.IP
Set UNIXPW_DISABLE_SSL=1 to disable requiring either
\fB-ssl\fR or \fB-stunnel.\fR Evidently you will be using a
different method to encrypt the data between the
vncviewer and x11vnc: e.g.
.IR ssh (1)
or a VPN. Note that
use of \fB-localhost\fR with
.IR ssh (1)
is roughly the same as
requiring a Unix user login (since a Unix password or
the user's public key authentication is used by sshd on
the machine where x11vnc runs and only local connections
are accepted)
.IP .IP
Set UNIXPW_DISABLE_LOCALHOST=1 to disable the \fB-localhost\fR Set UNIXPW_DISABLE_LOCALHOST=1 to disable the \fB-localhost\fR
requirement. One should never do this (i.e. allow the requirement in Method 2). One should never do this
Unix passwords to be sniffed on the network). (i.e. allow the Unix passwords to be sniffed on the
network).
.IP .IP
Regarding reverse connections (e.g. \fB-R\fR connect:host), Regarding reverse connections (e.g. \fB-R\fR connect:host),
the \fB-localhost\fR constraint is in effect and the reverse if the \fB-localhost\fR constraint is in effect then reverse
connections can only be used to connect to the same connections can only be used to connect to the same
machine x11vnc is running on (default port 5500). machine x11vnc is running on (default port 5500).
Please use a ssh or stunnel port redirection to the Please use a ssh or stunnel port redirection to the
viewer machine to tunnel the reverse connection over viewer machine to tunnel the reverse connection over
an encrypted channel. Note that Unix username and an encrypted channel. Note that in \fB-ssl\fR mode reverse
password *will* be prompted for (unlike VNC passwords connection are disabled.
that are skipped for reverse connections).
.IP .IP
NOTE: in \fB-inetd\fR mode the two settings are attempted XXX \fB-inetd\fR + \fB-ssl\fR
to be enforced for reverse connections. Be sure to In \fB-inetd\fR mode the two settings are attempted to be
enforced for reverse connections. Be sure to also
use encryption from the viewer to inetd since x11vnc use encryption from the viewer to inetd since x11vnc
cannot guess easily if it is encrpyted. Note: you can cannot guess easily if it is encrpyted. Tip: you can
also have your own stunnel spawn x11vnc in \fB-inetd\fR mode also have your own stunnel spawn x11vnc in \fB-inetd\fR mode
(i.e. bypassing inetd). See the FAQ. (i.e. bypassing inetd). See the FAQ for details.
.IP .IP
The user names in the comma separated [list] can have The user names in the comma separated [list] can have
per-user options after a ":", e.g. "fred:opts" per-user options after a ":", e.g. "fred:opts"
@ -635,21 +646,101 @@ is required), but it is unlikely it will work for any
other environment. All of the \fB-unixpw\fR options and other environment. All of the \fB-unixpw\fR options and
contraints apply. contraints apply.
.PP .PP
\fB-ssl\fR \fI[pem]\fR
.IP
Use the openssl library (www.openssl.org) to provide a
built-in encrypted SSL tunnel between VNC viewers and
x11vnc. This requires libssl support to be compiled
into x11vnc at build time. If x11vnc is not built
with libssl support it will exit immediately when \fB-ssl\fR
is prescribed.
.IP
[pem] is optional, use "\fB-ssl\fR \fI/path/to/mycert.pem\fR" to
specify a PEM certificate file to use to identify and
provide a key for this server.
.IP
Connecting VNC viewer SSL tunnels can authenticate
this server if they have the public key part of the
certificate (or a common certificate authority, CA,
verifies this server's cert). This is used to prevent
man-in-the-middle attacks. Otherwise, if the VNC viewer
accepts this server's key without verification, at
least the traffic is protected from passive sniffing
on the network.
.IP
If [pem] is not supplied and the
.IR openssl (1)
utility
command exists in PATH, then a temporary, self-signed
certificate will be generated for this session (this
may take 5-20 seconds on slow machines). If
.IR openssl (1)
cannot be used to generate a temporary certificate
x11vnc exits immediately.
.IP
If successful in using
.IR openssl (1)
to generate a
certificate, the public part of it will be displayed
to stdout (e.g. one could copy it to the client-side
to provide authentication of the server to VNC viewers.)
.IP
Set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc
print out the entire certificate, including the PRIVATE
KEY part, to stderr. One could reuse this cert if saved
in a [pem] file. Similarly, set X11VNC_KEEP_TMP_PEM=1
to not delete the temporary PEM file: the file name
will be printed to stderr (so one could move it to a
safe place for reuse).
.IP
Reverse connections are disabled in \fB-ssl\fR
mode because the data cannot be encrypted.
Set X11VNC_SSL_ALLOW_REVERSE=1 to override this.
.IP
Your VNC viewer will also need to be able to connect
via SSL. See the discussion below under \fB-stunnel\fR and
the FAQ for how this might be achieved. E.g. on Unix it
is easy to write a shell script that starts up stunnel
and then vncviewer.
.PP
\fB-sslverify\fR \fI[path]\fR
.IP
For either of the \fB-ssl\fR or \fB-stunnel\fR modes, use [path]
to provide certificates to authenticate incoming VNC
client connections. This can be used as a method to
replace standard password authentication.
.IP
If [path] is a directory it contains the client (or CA)
certificates in separate files. If [path] is a file, it
contains multiple certificates. These correspond to the
"CApath = dir" and "CAfile = file" stunnel options.
See the
.IR stunnel (8)
manpage for details.
.IP
To create certificates for all sorts of authentications
(clients, servers, via CA, etc) see the
.IR openssl (1)
command. Of particular usefulness is the x509
subcommand of
.IR openssl (1).
.PP
\fB-stunnel\fR \fI[pem]\fR \fB-stunnel\fR \fI[pem]\fR
.IP .IP
Use the Use the
.IR stunnel (1) .IR stunnel (8)
(www.stunnel.org) to provide (www.stunnel.org) to provide
an encrypted SSL tunnel between viewers and x11vnc. an encrypted SSL tunnel between viewers and x11vnc.
This requires stunnel to be installed on the system and This requires stunnel to be installed on the system and
available via PATH (n.b. stunnel is often installed in available via PATH (n.b. stunnel is often installed in
sbin directories). Version 4.x of stunnel is assumed; sbin directories). Version 4.x of stunnel is assumed
see \fB-stunnel3\fR below. (but see \fB-stunnel3\fR below.)
.IP .IP
[pem] is optional, use "\fB-stunnel\fR \fI/path/to/stunnel.pem\fR" [pem] is optional, use "\fB-stunnel\fR \fI/path/to/stunnel.pem\fR"
to specify a PEM certificate file to pass to stunnel. to specify a PEM certificate file to pass to stunnel.
Whether one is needed or not depends on your stunnel Whether one is needed or not depends on your stunnel
configuration. configuration. stunnel often generates one at install
time.
.IP .IP
stunnel is started up as a child process of x11vnc and stunnel is started up as a child process of x11vnc and
any SSL connections stunnel receives are decrypted and any SSL connections stunnel receives are decrypted and
@ -661,14 +752,15 @@ The \fB-localhost\fR option is enforced by default to
avoid people routing around the SSL channel. Set avoid people routing around the SSL channel. Set
STUNNEL_DISABLE_LOCALHOST=1 to disable the requirement. STUNNEL_DISABLE_LOCALHOST=1 to disable the requirement.
.IP .IP
Your VNC viewer will need to be able to connect via SSL. Your VNC viewer will also need to be able to connect
Unfortunately not too many do this. UltraVNC seems to via SSL. Unfortunately not too many do this. UltraVNC
have a SSL plugin. It is not too difficult to set up seems to have an encryption plugin. It is not too
an stunnel or other SSL tunnel on the viewer side. difficult to set up an stunnel or other SSL tunnel on
the viewer side.
.IP .IP
A simple example on Unix using stunnel 3.x is: A simple example on Unix using stunnel 3.x is:
.IP .IP
% stunnel \fB-c\fR \fB-d\fR localhost:5901 \fB-r\fR remote:5900 % stunnel \fB-c\fR \fB-d\fR localhost:5901 \fB-r\fR remotehost:5900
% vncviewer localhost:1 % vncviewer localhost:1
.IP .IP
For Windows, stunnel has been ported to it and there For Windows, stunnel has been ported to it and there
@ -2799,22 +2891,24 @@ debug_xevents debug_xdamage nodebug_xdamage
debug_xdamage debug_wireframe nodebug_wireframe debug_xdamage debug_wireframe nodebug_wireframe
debug_wireframe debug_scroll nodebug_scroll debug_scroll debug_wireframe debug_scroll nodebug_scroll debug_scroll
debug_tiles dbt nodebug_tiles nodbt debug_tiles debug_tiles dbt nodebug_tiles nodbt debug_tiles
debug_grabs nodebug_grabs dbg nodbg noremote debug_grabs nodebug_grabs debug_sel nodebug_sel dbg
nodbg noremote
.IP .IP
aro= noop display vncdisplay desktopname guess_desktop aro= noop display vncdisplay desktopname guess_desktop
http_url auth xauth users rootshift clipshift http_url auth xauth users rootshift clipshift
scale_str scaled_x scaled_y scale_numer scale_denom scale_str scaled_x scaled_y scale_numer scale_denom
scale_fac scaling_blend scaling_nomult4 scaling_pad scale_fac scaling_blend scaling_nomult4 scaling_pad
scaling_interpolate inetd privremote unsafe safer scaling_interpolate inetd privremote unsafe safer
nocmds passwdfile unixpw unixpw_nis unixpw_list stunnel nocmds passwdfile unixpw unixpw_nis unixpw_list ssl
stunnel_pem using_shm logfile o flag rc norc h help ssl_pem sslverify stunnel stunnel_pem usepw using_shm
V version lastmod bg sigpipe threads readrate netrate logfile o flag rc norc h help V version lastmod bg
netlatency pipeinput clients client_count pid ext_xtest sigpipe threads readrate netrate netlatency pipeinput
ext_xtrap ext_xrecord ext_xkb ext_xshm ext_xinerama clients client_count pid ext_xtest ext_xtrap ext_xrecord
ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin ext_xkb ext_xshm ext_xinerama ext_overlay ext_xfixes
num_buttons button_mask mouse_x mouse_y bpp depth ext_xdamage ext_xrandr rootwin num_buttons button_mask
indexed_color dpy_x dpy_y wdpy_x wdpy_y off_x off_y mouse_x mouse_y bpp depth indexed_color dpy_x dpy_y
cdpy_x cdpy_y coff_x coff_y rfbauth passwd viewpasswd wdpy_x wdpy_y off_x off_y cdpy_x cdpy_y coff_x coff_y
rfbauth passwd viewpasswd
.PP .PP
\fB-QD\fR \fIvariable\fR \fB-QD\fR \fIvariable\fR
.IP .IP

@ -140,6 +140,7 @@
#include "unixpw.h" #include "unixpw.h"
#include "inet.h" #include "inet.h"
#include "sslcmds.h" #include "sslcmds.h"
#include "sslhelper.h"
#include "selection.h" #include "selection.h"
/* /*
@ -471,6 +472,7 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
check_connect_inputs(); check_connect_inputs();
check_gui_inputs(); check_gui_inputs();
check_stunnel(); check_stunnel();
check_openssl();
record_last_fb_update(); record_last_fb_update();
check_padded_fb(); check_padded_fb();
check_fixscreen(); check_fixscreen();
@ -1353,7 +1355,8 @@ static void store_homedir_passwd(void) {
#define SHOW_NO_PASSWORD_WARNING \ #define SHOW_NO_PASSWORD_WARNING \
(!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) \ (!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) \
&& !query_cmd && !remote_cmd && !unixpw && !got_gui_pw) && !query_cmd && !remote_cmd && !unixpw && !got_gui_pw \
&& ! ssl_verify)
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
@ -1367,12 +1370,10 @@ int main(int argc, char* argv[]) {
int got_gui_pw = 0; int got_gui_pw = 0;
int pw_loc = -1, got_passwd = 0, got_rfbauth = 0, nopw = NOPW; int pw_loc = -1, got_passwd = 0, got_rfbauth = 0, nopw = NOPW;
int got_viewpasswd = 0, got_localhost = 0, got_passwdfile = 0; int got_viewpasswd = 0, got_localhost = 0, got_passwdfile = 0;
int got_stunnel = 0;
int vpw_loc = -1; int vpw_loc = -1;
int dt = 0, bg = 0; int dt = 0, bg = 0;
int got_rfbwait = 0; int got_rfbwait = 0;
int got_httpdir = 0, try_http = 0; int got_httpdir = 0, try_http = 0;
int usepw = 0;
/* used to pass args we do not know about to rfbGetScreen(): */ /* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc = 1; char *argv_vnc[128]; int argc_vnc = 1; char *argv_vnc[128];
@ -1583,12 +1584,23 @@ int main(int argc, char* argv[]) {
} }
if (strstr(arg, "_unsafe")) { if (strstr(arg, "_unsafe")) {
/* hidden option for testing. */ /* hidden option for testing. */
set_env("UNIXPW_DISABLE_STUNNEL", "1"); set_env("UNIXPW_DISABLE_SSL", "1");
set_env("UNIXPW_DISABLE_LOCALHOST", "1"); set_env("UNIXPW_DISABLE_LOCALHOST", "1");
} }
} else if (!strcmp(arg, "-ssl")) {
use_openssl = 1;
if (i < argc-1) {
char *s = argv[i+1];
if (s[0] != '-') {
openssl_pem = strdup(s);
i++;
}
}
} else if (!strcmp(arg, "-sslverify")) {
CHECK_ARGC
ssl_verify = strdup(argv[++i]);
} else if (!strcmp(arg, "-stunnel")) { } else if (!strcmp(arg, "-stunnel")) {
use_stunnel = 1; use_stunnel = 1;
got_stunnel = 1;
if (i < argc-1) { if (i < argc-1) {
char *s = argv[i+1]; char *s = argv[i+1];
if (s[0] != '-') { if (s[0] != '-') {
@ -1598,7 +1610,6 @@ int main(int argc, char* argv[]) {
} }
} else if (!strcmp(arg, "-stunnel3")) { } else if (!strcmp(arg, "-stunnel3")) {
use_stunnel = 3; use_stunnel = 3;
got_stunnel = 1;
if (i < argc-1) { if (i < argc-1) {
char *s = argv[i+1]; char *s = argv[i+1];
if (s[0] != '-') { if (s[0] != '-') {
@ -2301,6 +2312,16 @@ int main(int argc, char* argv[]) {
exit(1); exit(1);
} }
if (ssl_verify) {
struct stat sbuf;
if (stat(ssl_verify, &sbuf) != 0) {
rfbLog("x11vnc: -sslverify %s does not exist\n",
ssl_verify);
rfbLogPerror("stat");
exit(1);
}
}
/* /*
* If -passwd was used, clear it out of argv. This does not * If -passwd was used, clear it out of argv. This does not
* work on all UNIX, have to use execvp() in general... * work on all UNIX, have to use execvp() in general...
@ -2382,46 +2403,49 @@ int main(int argc, char* argv[]) {
launch_gui = 0; launch_gui = 0;
} }
if (! inetd) { if (! inetd && unixpw) {
if (unixpw) { if (! use_stunnel && ! use_openssl) {
if (! got_localhost && ! getenv("UNIXPW_DISABLE_LOCALHOST")) { if (have_ssh_env()) {
if (! quiet) {
rfbLog("Setting -localhost in -unixpw mode.\n");
}
allow_list = strdup("127.0.0.1");
got_localhost = 1;
}
if (! got_stunnel) {
if (! getenv("UNIXPW_DISABLE_STUNNEL") &&
! have_ssh_env()) {
if (! quiet) {
rfbLog("Setting -stunnel in -unixpw "
"mode.\n");
}
use_stunnel = 1;
} else if (! getenv("UNIXPW_DISABLE_STUNNEL")) {
char *s = getenv("SSH_CONNECTION"); char *s = getenv("SSH_CONNECTION");
if (! s) s = getenv("SSH_CLIENT"); if (! s) s = getenv("SSH_CLIENT");
if (! s) s = "SSH_CONNECTION"; if (! s) s = "SSH_CONNECTION";
fprintf(stderr, "\n"); fprintf(stderr, "\n");
rfbLog("Skipping -stunnel contraint in -unixpw mode,\n"); rfbLog("Skipping -ssl/-stunnel contraint in"
rfbLog("assuming your SSH encryption is: %s\n", s); " -unixpw\n");
rfbLog("mode, assuming your SSH encryption"
" is: %s\n", s);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
if (! nopw) { if (! nopw) {
usleep(2000*1000); usleep(2000*1000);
} }
} else if (getenv("UNIXPW_DISABLE_SSL")) {
rfbLog("Skipping -ssl/-stunnel requirement"
" due to\n");
rfbLog("UNIXPW_DISABLE_SSL setting.\n");
} else {
if (openssl_present()) {
rfbLog("set -ssl in -unixpw mode.\n");
use_openssl = 1;
} else {
rfbLog("set -stunnel in -unixpw mode.\n");
use_stunnel = 1;
}
} }
} }
} else if (use_stunnel) { }
if (use_stunnel && ! got_localhost) {
if (! got_localhost && ! getenv("STUNNEL_DISABLE_LOCALHOST")) { if (! getenv("STUNNEL_DISABLE_LOCALHOST") &&
! getenv("UNIXPW_DISABLE_LOCALHOST")) {
if (! quiet) { if (! quiet) {
rfbLog("Setting -localhost in -stunnel mode.\n"); rfbLog("Setting -localhost in -stunnel mode.\n");
} }
allow_list = strdup("127.0.0.1"); allow_list = strdup("127.0.0.1");
got_localhost = 1; got_localhost = 1;
} }
} }
if (ssl_verify && ! use_stunnel && ! use_openssl) {
rfbLog("-sslverify must be used with -ssl or -stunnel\n");
exit(1);
} }
/* fixup settings that do not make sense */ /* fixup settings that do not make sense */
@ -3041,7 +3065,7 @@ int main(int argc, char* argv[]) {
initialize_allowed_input(); initialize_allowed_input();
if (! inetd) { if (! inetd && ! use_openssl) {
if (! screen->port || screen->listenSock < 0) { if (! screen->port || screen->listenSock < 0) {
rfbLogEnable(1); rfbLogEnable(1);
rfbLog("Error: could not obtain listening port.\n"); rfbLog("Error: could not obtain listening port.\n");

@ -56,6 +56,7 @@
* -DHARDWIRE_PASSWD=... hardwired passwords, quoting necessary. * -DHARDWIRE_PASSWD=... hardwired passwords, quoting necessary.
* -DHARDWIRE_VIEWPASSWD=... * -DHARDWIRE_VIEWPASSWD=...
* -DNOPW=1 make -nopw the default (skip warning) * -DNOPW=1 make -nopw the default (skip warning)
* -DUSEPW=1 make -usepw the default
* -DPASSWD_REQUIRED=1 exit unless a password is supplied. * -DPASSWD_REQUIRED=1 exit unless a password is supplied.
* -DPASSWD_UNLESS_NOPW=1 exit unless a password is supplied and no -nopw. * -DPASSWD_UNLESS_NOPW=1 exit unless a password is supplied and no -nopw.
* *
@ -73,6 +74,9 @@
* -DSMALL_FOOTPRINT=1 for smaller binary size (no help, no gui, etc) * -DSMALL_FOOTPRINT=1 for smaller binary size (no help, no gui, etc)
* use 2 or 3 for even smaller footprint. * use 2 or 3 for even smaller footprint.
* -DNOGUI do not include the gui tkx11vnc. * -DNOGUI do not include the gui tkx11vnc.
* -DSKIP_HELP=1 smaller.
* -DSKIP_XKB=1 a little smaller.
* -DSKIP_8to24=1 a little smaller.
* -DPOLL_8TO24_DELAY=N * -DPOLL_8TO24_DELAY=N
* -DDEBUG_XEVENTS=1 enable printout for X events. * -DDEBUG_XEVENTS=1 enable printout for X events.
* *
@ -93,6 +97,10 @@
#define NOPW 0 #define NOPW 0
#endif #endif
#ifndef USEPW
#define USEPW 0
#endif
#ifndef PASSWD_REQUIRED #ifndef PASSWD_REQUIRED
#define PASSWD_REQUIRED 0 #define PASSWD_REQUIRED 0
#endif #endif
@ -116,13 +124,23 @@
#define SMALL_FOOTPRINT 0 #define SMALL_FOOTPRINT 0
#endif #endif
#ifndef SKIP_XKB
#define SKIP_XKB 0
#endif
#ifndef SKIP_8TO24
#define SKIP_8TO24 0
#endif
#ifndef SKIP_HELP
#define SKIP_HELP 0
#endif
#if SMALL_FOOTPRINT #if SMALL_FOOTPRINT
#undef NOGUI
#define NOGUI #define NOGUI
#undef SKIP_HELP
#define SKIP_HELP 0
#endif #endif
#define SKIP_XKB 0
#define SKIP_8TO24 0
#if (SMALL_FOOTPRINT > 1) #if (SMALL_FOOTPRINT > 1)
#undef SKIP_XKB #undef SKIP_XKB
#undef SKIP_8TO24 #undef SKIP_8TO24
@ -447,6 +465,8 @@ typedef struct _ClientData {
int login_viewonly; int login_viewonly;
time_t login_time; time_t login_time;
pid_t ssh_helper_pid;
int had_cursor_shape_updates; int had_cursor_shape_updates;
int had_cursor_pos_updates; int had_cursor_pos_updates;

@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0; int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */ /* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.8.1 lastmod: 2006-03-08"; char lastmod[] = "0.8.1 lastmod: 2006-03-11";
/* X display info */ /* X display info */

@ -818,7 +818,7 @@ void check_xevents(void) {
/* check for our PRIMARY request notification: */ /* check for our PRIMARY request notification: */
if (watch_primary || watch_clipboard) { if (watch_primary || watch_clipboard) {
int doprimary = 1, doclipboard = 2, which, own; int doprimary = 1, doclipboard = 2, which, own = 0;
double delay = 1.0; double delay = 1.0;
Atom atom; Atom atom;
char *req; char *req;

Loading…
Cancel
Save