x11vnc: -unixpw and -stunnel. Add clipboard to input control.

pull/1/head
runge 18 years ago
parent b7773ea6e6
commit 79310af7e7

@ -1,3 +1,7 @@
2006-02-24 Karl Runge <runge@karlrunge.com>
* x11vnc: -unixpw and -stunnel options. Add clipboard input
to per-client input controls.
2006-02-24 Rohit Kumar <rokumar@novell.com>
* main.c, rfbtightserver.c, rfb.h: added method to get
extension specific client data.

@ -345,7 +345,7 @@ AC_SUBST(WSOCKLIB)
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h sys/timeb.h syslog.h unistd.h pwd.h sys/wait.h utmpx.h])
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h sys/timeb.h syslog.h unistd.h pwd.h sys/wait.h utmpx.h termios.h sys/ioctl.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@ -377,7 +377,7 @@ AC_FUNC_VPRINTF
AC_FUNC_FORK
AC_CHECK_LIB(nsl,gethostbyname)
AC_CHECK_LIB(socket,socket)
AC_CHECK_FUNCS([ftime gethostbyname gethostname gettimeofday inet_ntoa memmove memset mmap mkfifo select socket strchr strcspn strdup strerror strstr setsid getpwuid getpwnam getuid geteuid setuid waitpid setutxent])
AC_CHECK_FUNCS([ftime gethostbyname gethostname gettimeofday inet_ntoa memmove memset mmap mkfifo select socket strchr strcspn strdup strerror strstr setsid getpwuid getpwnam getuid geteuid setuid seteuid setegid waitpid setutxent grantpt])
# check, if shmget is in cygipc.a
AC_CHECK_LIB(cygipc,shmget)

@ -1,3 +1,8 @@
2006-02-24 Karl Runge <runge@karlrunge.com>
* x11vnc: -unixpw for Unix password auth, -stunnel to setup
stunnel(1) for an SSL tunnel on the server end. Add clipboard
input to per-client input controls.
2006-02-20 Karl Runge <runge@karlrunge.com>
* x11vnc: add SIGINT SIGQUIT handling for run_user_command(),
set some signal handlers to SIG_DLF for forked children,

@ -13,7 +13,7 @@ endif
if HAVE_X
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 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 tkx11vnc.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 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
INCLUDES=@X_CFLAGS@
x11vnc_LDADD=$(LDADD) @X_LIBS@ $(LD_CYGIPC)
endif

File diff suppressed because it is too large Load Diff

@ -7,6 +7,7 @@ typedef struct allowed_input {
int keystroke;
int motion;
int button;
int clipboard;
} allowed_input_t;
#endif /* _X11VNC_ALLOWED_INPUT_T_H */

@ -8,6 +8,8 @@
#include "scan.h"
#include "gui.h"
#include "solid.h"
#include "unixpw.h"
#include "sslcmds.h"
/*
* Exiting and error handling routines
@ -130,6 +132,8 @@ void clean_up_exit (int ret) {
if (use_solid_bg) {
solid_bg(1);
}
stop_stunnel();
X_LOCK;
XTestDiscard_wr(dpy);
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
@ -380,6 +384,7 @@ static void interrupted (int sig) {
if (use_solid_bg) {
solid_bg(1);
}
stop_stunnel();
if (crash_debug) {
crash_shell();

@ -9,6 +9,7 @@
#include "solid.h"
#include "rates.h"
#include "screen.h"
#include "unixpw.h"
/*
* routines for handling incoming, outgoing, etc connections
@ -262,7 +263,7 @@ void set_client_input(char *str) {
}
*p = '\0';
p++;
val = short_kmb(p);
val = short_kmbc(p);
cl_list = client_match(str);
@ -504,6 +505,14 @@ static void client_gone(rfbClientPtr client) {
rfbLog("client_count: %d\n", client_count);
if (unixpw_in_progress && unixpw_client) {
if (client == unixpw_client) {
unixpw_in_progress = 0;
unixpw_client = NULL;
copy_screen();
}
}
if (no_autorepeat && client_count == 0) {
autorepeat(1, 0);
}
@ -1518,6 +1527,8 @@ static void send_client_connect(void) {
*/
void check_connect_inputs(void) {
if (unixpw_in_progress) return;
/* flush any already set: */
send_client_connect();
@ -1543,6 +1554,8 @@ void check_gui_inputs(void) {
char buf[VNC_CONNECT_MAX+1];
ssize_t nbytes;
if (unixpw_in_progress) return;
for (i=0; i<ICON_MODE_SOCKS; i++) {
if (icon_mode_socks[i] >= 0) {
socks[n++] = i;
@ -1624,6 +1637,11 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
clients_served++;
if (unixpw && unixpw_in_progress) {
rfbLog("denying additional client: %s during -unixpw login.\n",
client->host);
return(RFB_CLIENT_REFUSE);
}
if (connect_once) {
if (screen->dontDisconnect && screen->neverShared) {
if (! shared && accepted_client) {
@ -1696,6 +1714,14 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
accepted_client = 1;
last_client = time(0);
if (unixpw) {
unixpw_in_progress = 1;
unixpw_client = client;
unixpw_last_try_time = time(0);
unixpw_screen(1);
unixpw_keystroke(0, 0, 1);
}
return(RFB_CLIENT_ACCEPT);
}
@ -1832,6 +1858,15 @@ void check_new_clients(void) {
rfbClientPtr cl;
int i, send_info = 0;
int run_after_accept = 0;
if (unixpw_in_progress) {
int present = 0;
if (time(0) > unixpw_last_try_time + 20) {
rfbLog("unixpw_deny: timed out waiting for reply.\n");
unixpw_deny();
return;
}
}
if (client_count == last_count) {
return;

@ -5,6 +5,7 @@
#include "cleanup.h"
#include "screen.h"
#include "scan.h"
#include "unixpw.h"
int xfixes_present = 0;
int use_xfixes = 1;
@ -1569,6 +1570,7 @@ void disable_cursor_shape_updates(rfbScreenInfoPtr s) {
if (! s || ! s->clientHead) {
return;
}
if (unixpw_in_progress) return;
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
@ -1760,6 +1762,8 @@ int check_x11_pointer(void) {
if (raw_fb && ! dpy) return 0; /* raw_fb hack */
if (unixpw_in_progress) return 0;
X_LOCK;
ret = XQueryPointer(dpy, rootwin, &root_w, &child_w, &root_x, &root_y,
&win_x, &win_y, &mask);

@ -348,16 +348,17 @@ void print_help(int mode) {
"\n"
"-input string Fine tuning of allowed user input. If \"string\" does\n"
" not contain a comma \",\" the tuning applies only to\n"
" normal clients. Otherwise the part before \",\" is\n"
" for normal clients and the part after for view-only\n"
" clients. \"K\" is for Keystroke input, \"M\" for\n"
" Mouse-motion input, and \"B\" for Button-click input.\n"
" Their presence in the string enables that type of input.\n"
" E.g. \"-input M\" means normal users can only move\n"
" the mouse and \"-input KMB,M\" lets normal users do\n"
" anything and enables view-only users to move the mouse.\n"
" This option is ignored when a global -viewonly is in\n"
" effect (all input is discarded in that case).\n"
" normal clients. Otherwise the part before \",\" is for\n"
" normal clients and the part after for view-only clients.\n"
" \"K\" is for Keystroke input, \"M\" for Mouse-motion\n"
" input, \"B\" for Button-click input, and \"C\" is for\n"
" Clipboard input. Their presence in the string enables\n"
" that type of input. E.g. \"-input M\" means normal\n"
" users can only move the mouse and \"-input KMBC,M\"\n"
" lets normal users do anything and enables view-only\n"
" users to move the mouse. This option is ignored when\n"
" a global -viewonly is in effect (all input is discarded\n"
" in that case).\n"
"\n"
"-viewpasswd string Supply a 2nd password for view-only logins. The -passwd\n"
" (full-access) password must also be supplied.\n"
@ -399,7 +400,81 @@ void print_help(int mode) {
" used to have viewonly passwords. (tip: make the 3rd\n"
" and last line be \"__BEGIN_VIEWONLY__\" to have 2\n"
" full-access passwords)\n"
"\n"
"-unixpw [list] Experimental option: use Unix username and password\n"
" authentication. x11vnc uses the su(1) program to\n"
" verify the user's password. [list] is an optional\n"
" comma separated list of allowed Unix usernames.\n"
"\n"
" A familiar \"login:\" and \"Password:\" dialog is\n"
" presented to the user on a black screen inside the\n"
" vncviewer. The connection is dropped if the user fails\n"
" to supply the correct password in 3 tries or does not\n"
" send one before a 20 second timeout. Existing clients\n"
" are view-only during this period.\n"
"\n"
" *IMPORTANT*: to prevent the Unix password being sent in\n"
" *clear text* over the network, two x11vnc options are\n"
" enforced: 1) -localhost and 2) -stunnel. The former\n"
" requires the viewer connection to appear to come from\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"
" To override these restrictions you can set environment\n"
" variables before starting x11vnc:\n"
"\n"
" Set UNIXPW_DISABLE_STUNNEL=1 to disable using -stunnel.\n"
" Evidently you will be using a different method to\n"
" encrypt the data between the vncviewer and x11vnc:\n"
" e.g. ssh(1) or a VPN. Note that use of ssh(1) with\n"
" -localhost is roughly the same as requiring a Unix\n"
" user login (since Unix password or the user's public\n"
" key authentication is used by ssh)\n"
"\n"
" Set UNIXPW_DISABLE_LOCALHOST=1 to disable the -localhost\n"
" requirement. One should never do this (i.e. allow the\n"
" Unix passwords to be sniffed on the network).\n"
"\n"
" NOTE: in -inetd mode the two settings are not enforced\n"
" since x11vnc does not make network connections in\n"
" that case. Be sure to use encryption from the viewer\n"
" to inetd. One can also have your own stunnel spawn\n"
" x11vnc in -inetd mode.\n"
"\n"
"-stunnel [pem] Use the stunnel(1) (www.stunnel.org) to provide an\n"
" encrypted SSL tunnel between viewers and x11vnc.\n"
" This requires stunnel be installed on the system and\n"
" available via PATH (n.b. stunnel is often installed in\n"
" sbin directories). Version 4.x of stunnel is assumed.\n"
"\n"
" [pem] is optional, use \"-stunnel /path/to/stunnel.pem\"\n"
" to specify a PEM certificate file to pass to stunnel.\n"
"\n"
" stunnel is started up as a child process and any SSL\n"
" connections it receives are decrypted and sent to x11vnc\n"
" over a local socket. The strings \"The SSL VNC desktop\n"
" is ...\" and SSLPORT=... are printed out at startup.\n"
"\n"
" The -localhost option is enforced by default. Set\n"
" STUNNEL_DISABLE_LOCALHOST=1 to disable the requirement.\n"
"\n"
" Your VNC viewer will need to be able to connect via SSL.\n"
" Unfortunately not too many do this. UltraVNC seems to\n"
" have a SSL plugin. It is not too difficult to set up\n"
" an stunnel or other SSL tunnel on the viewer side.\n"
"\n"
" A simple example on Unix using stunnel 3.x is:\n"
"\n"
" %% stunnel -c -d localhost:5901 -r remote:5900\n"
" %% vncviewer localhost:1\n"
"\n"
" For Windows, stunnel has been ported to it and there\n"
" are probably other such tools available.\n"
"\n"
"-stunnel3 [pem] Use version 3.x stunnel command line syntax instead of\n"
" version 4.x\n"
"\n"
"-nopw Disable the big warning message when you use x11vnc\n"
" without some sort of password.\n"
"-storepasswd pass file Store password \"pass\" as the VNC password in the\n"
@ -2063,7 +2138,7 @@ void print_help(int mode) {
/* have both our help and rfbUsage to stdout for more(1), etc. */
dup2(1, 2);
/* register extention(s) to get their help output */
/* register extension(s) to get their help output */
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
rfbRegisterTightVNCFileTransferExtension();
#endif

@ -16,6 +16,7 @@ int get_local_port(int sock);
char *get_remote_host(int sock);
char *get_local_host(int sock);
char *ident_username(rfbClientPtr client);
int find_free_port(int start, int end);
static int get_port(int sock, int remote);
@ -295,4 +296,21 @@ char *ident_username(rfbClientPtr client) {
return str;
}
int find_free_port(int start, int end) {
int port;
if (start <= 0) {
start = 1024;
}
if (end <= 0) {
end = 65530;
}
for (port = start; port <= end; port++) {
int sock = rfbListenOnTCPPort(port, htonl(INADDR_ANY));
if (sock >= 0) {
close(sock);
return port;
}
}
return 0;
}

@ -13,5 +13,6 @@ extern int get_local_port(int sock);
extern char *get_remote_host(int sock);
extern char *get_local_host(int sock);
extern char *ident_username(rfbClientPtr client);
extern int find_free_port(int start, int end);
#endif /* _X11VNC_INET_H */

@ -10,6 +10,7 @@
#include "rates.h"
#include "cleanup.h"
#include "allowed_input_t.h"
#include "unixpw.h"
void get_keystate(int *keystate);
void clear_modifiers(int init);
@ -24,7 +25,7 @@ void delete_added_keycodes(int bequiet);
void initialize_remap(char *infile);
int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new);
void switch_to_xkb_if_better(void);
char *short_kmb(char *str);
char *short_kmbc(char *str);
void initialize_allowed_input(void);
void initialize_modtweak(void);
void initialize_keyboard_and_pointer(void);
@ -313,6 +314,9 @@ void check_add_keysyms(void) {
static time_t last_check = 0;
int clear_freq = 300, quiet = 1, count;
time_t now = time(0);
if (unixpw_in_progress) return;
if (now > last_check + clear_freq) {
count = count_added_keycodes();
/*
@ -2019,8 +2023,8 @@ if (sym >> 8 == 0) { \
}
#endif
char *short_kmb(char *str) {
int i, saw_k = 0, saw_m = 0, saw_b = 0, n = 10;
char *short_kmbc(char *str) {
int i, saw_k = 0, saw_m = 0, saw_b = 0, saw_c = 0, n = 10;
char *p, tmp[10];
for (i=0; i<n; i++) {
@ -2039,6 +2043,9 @@ char *short_kmb(char *str) {
} else if ((*p == 'B' || *p == 'b') && !saw_b) {
tmp[i++] = 'B';
saw_b = 1;
} else if ((*p == 'C' || *p == 'c') && !saw_c) {
tmp[i++] = 'C';
saw_c = 1;
}
p++;
}
@ -2058,7 +2065,7 @@ void initialize_allowed_input(void) {
}
if (! allowed_input_str) {
allowed_input_normal = strdup("KMB");
allowed_input_normal = strdup("KMBC");
allowed_input_view_only = strdup("");
} else {
char *p, *str = strdup(allowed_input_str);
@ -2075,11 +2082,11 @@ void initialize_allowed_input(void) {
}
/* shorten them */
str = short_kmb(allowed_input_normal);
str = short_kmbc(allowed_input_normal);
free(allowed_input_normal);
allowed_input_normal = str;
str = short_kmb(allowed_input_view_only);
str = short_kmbc(allowed_input_view_only);
free(allowed_input_view_only);
allowed_input_view_only = str;
@ -2351,6 +2358,7 @@ void get_allowed_input(rfbClientPtr client, allowed_input_t *input) {
input->keystroke = 0;
input->motion = 0;
input->button = 0;
input->clipboard = 0;
if (! client) {
return;
@ -2370,7 +2378,7 @@ void get_allowed_input(rfbClientPtr client, allowed_input_t *input) {
if (allowed_input_normal) {
str = allowed_input_normal;
} else {
str = "KMB";
str = "KMBC";
}
}
@ -2381,6 +2389,8 @@ void get_allowed_input(rfbClientPtr client, allowed_input_t *input) {
input->motion = 1;
} else if (*str == 'B') {
input->button = 1;
} else if (*str == 'C') {
input->clipboard = 1;
}
str++;
}
@ -2543,6 +2553,14 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
(int) keysym, str ? str : "null", tnow - x11vnc_start);
X_UNLOCK;
}
if (unixpw && unixpw_in_progress) {
if (client != unixpw_client) {
return;
}
unixpw_keystroke(down, keysym, 0);
return;
}
if (skip_duplicate_key_events) {
if (keysym == last_keysym && down == last_down) {

@ -17,7 +17,7 @@ extern void delete_added_keycodes(int bequiet);
extern void initialize_remap(char *infile);
extern int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new);
extern void switch_to_xkb_if_better(void);
extern char *short_kmb(char *str);
extern char *short_kmbc(char *str);
extern void initialize_allowed_input(void);
extern void initialize_modtweak(void);
extern void initialize_keyboard_and_pointer(void);

@ -15,6 +15,11 @@ char *logfile = NULL; /* -o, -logfile */
int logfile_append = 0;
char *flagfile = NULL; /* -flag */
char *passwdfile = NULL; /* -passwdfile */
int unixpw = 0; /* -unixpw */
char *unixpw_list = NULL;
int use_stunnel = 0; /* -stunnel */
int stunnel_port = 0;
char *stunnel_pem = NULL;
char *blackout_str = NULL; /* -blackout */
int blackout_ptr = 0;
char *clip_str = NULL; /* -clip */

@ -15,6 +15,11 @@ extern char *logfile;
extern int logfile_append;
extern char *flagfile;
extern char *passwdfile;
extern int unixpw;
extern char *unixpw_list;
extern int use_stunnel;
extern int stunnel_port;
extern char *stunnel_pem;
extern char *blackout_str;
extern int blackout_ptr;
extern char *clip_str;

@ -10,6 +10,7 @@
#include "userinput.h"
#include "connections.h"
#include "cleanup.h"
#include "unixpw.h"
int pointer_queued_sent = 0;
@ -603,6 +604,9 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
last_x = x;
last_y = y;
}
if (mask >= 0 && unixpw && unixpw_in_progress) {
return;
}
if (scaling) {
/* map from rfb size to X11 size: */

@ -1141,18 +1141,6 @@ char *process_remote_cmd(char *cmd, int stringonly) {
first_conn_timeout = to;
rfbLog("remote_cmd: set -timeout to %d\n", -to);
#if 0
} else if (!strcmp(p, "filexfer")) {
/* does this work after rfbInitServer? */
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, filexfer);
goto qry;
}
rfbLog("remote_cmd: enabling -filexfer.\n");
filexfer = 1;
rfbRegisterTightVNCFileTransferExtension();
#endif
} else if (!strcmp(p, "deny") || !strcmp(p, "lock")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, deny_all);
@ -1194,6 +1182,11 @@ char *process_remote_cmd(char *cmd, int stringonly) {
NONUL(allow_list));
goto qry;
}
if (unixpw) {
rfbLog("remote_cmd: cannot change allow in -unixpw\n");
goto done;
}
p += strlen("allow:");
if (allow_list && strchr(allow_list, '/')) {
rfbLog("remote_cmd: cannot use allow:host\n");
@ -1278,6 +1271,10 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "ans=%s:%d", p, !state);
goto qry;
}
if (unixpw) {
rfbLog("remote_cmd: cannot change localhost in -unixpw\n");
goto done;
}
if (allow_list) {
before = strdup(allow_list);
} else {
@ -1318,6 +1315,10 @@ char *process_remote_cmd(char *cmd, int stringonly) {
NONUL(listen_str));
goto qry;
}
if (unixpw) {
rfbLog("remote_cmd: cannot change listen in -unixpw\n");
goto done;
}
if (listen_str) {
before = strdup(listen_str);
} else {
@ -3666,6 +3667,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%d", p, no_external_cmds);
} else if (!strcmp(p, "passwdfile")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(passwdfile));
} else if (!strcmp(p, "unixpw")) {
snprintf(buf, bufn, "aro=%s:%d", p, unixpw);
} else if (!strcmp(p, "using_shm")) {
snprintf(buf, bufn, "aro=%s:%d", p, !using_shm);
} else if (!strcmp(p, "logfile") || !strcmp(p, "o")) {

@ -10,6 +10,7 @@
#include "screen.h"
#include "pointer.h"
#include "cleanup.h"
#include "unixpw.h"
/*
* routines for scanning and reading the X11 display for changes, and
@ -1951,6 +1952,7 @@ int copy_screen(void) {
if (! fs_factor) {
return 0;
}
if (unixpw_in_progress) return 0;
block_size = (dpy_x * (dpy_y/fs_factor) * pixelsize);
@ -2398,6 +2400,8 @@ int scan_for_updates(int count_only) {
double frac3 = 0.02; /* do scan_display() again after copy_tiles() */
static double last_poll = 0.0;
if (unixpw_in_progress) return 0;
if (slow_fb > 0.0) {
double now = dnow();
if (now < last_poll + slow_fb) {

@ -16,6 +16,8 @@
#include "cursor.h"
#include "connections.h"
#include "remote.h"
#include "unixpw.h"
#include "sslcmds.h"
void set_colormap(int reset);
void set_nofb_params(int restore);
@ -40,6 +42,7 @@ static void initialize_snap_fb(void);
static XImage *initialize_raw_fb(void);
static void initialize_clipshift(void);
static int wait_until_mapped(Window win);
static void announce(int lport, int ssl, char *iface);
static void setup_scaling(int *width_in, int *height_in);
@ -622,6 +625,8 @@ void check_padded_fb(void) {
if (! fake_fb) {
return;
}
if (unixpw_in_progress) return;
if (time(0) > pad_geometry_time+1 && all_clients_initialized()) {
remove_fake_fb();
}
@ -1560,6 +1565,9 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
/* n.b. samplesPerPixel (set = 1 here) seems to be unused. */
if (create_screen) {
if (use_stunnel) {
setup_stunnel(0, argc, argv);
}
screen = rfbGetScreen(argc, argv, width, height,
bits_per_color, 1, fb_bpp/8);
if (screen && http_dir) {
@ -1669,6 +1677,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
&& dpy && CellsOfScreen(ScreenOfDisplay(dpy, scr))) {
/* indexed color */
if (!quiet) {
rfbLog("\n");
rfbLog("X display %s is 8bpp indexed color\n",
DisplayString(dpy));
if (! flash_cmap && ! overlay) {
@ -1693,14 +1702,17 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
*/
if (! quiet) {
if (raw_fb) {
rfbLog("\n");
rfbLog("Raw fb at addr %p is %dbpp depth=%d "
"true color\n", raw_fb_addr,
fb_bpp, fb_depth);
} else if (have_masks == 2) {
rfbLog("\n");
rfbLog("X display %s is %dbpp depth=%d indexed "
"color (-8to24 mode)\n", DisplayString(dpy),
fb->bits_per_pixel, fb->depth);
} else {
rfbLog("\n");
rfbLog("X display %s is %dbpp depth=%d true "
"color\n", DisplayString(dpy),
fb_bpp, fb_depth);
@ -1938,67 +1950,89 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
install_passwds();
}
void set_vnc_desktop_name(void) {
int sz = 256;
sprintf(vnc_desktop_name, "unknown");
if (inetd) {
sprintf(vnc_desktop_name, "inetd-no-further-clients");
static void announce(int lport, int ssl, char *iface) {
char *host = this_host();
char *tvdt;
if (! ssl) {
tvdt = "The VNC desktop";
} else {
tvdt = "The SSL VNC desktop";
}
if (screen->port) {
char *host = this_host();
int lport = screen->port;
char *iface = listen_str;
if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) {
host = iface;
}
if (host != NULL) {
/* note that vncviewer special cases 5900-5999 */
if (inetd) {
; /* should not occur (port) */
} else if (quiet) {
if (lport >= 5900) {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport - 5900);
fprintf(stderr, "The VNC desktop is "
"%s\n", vnc_desktop_name);
} else {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport);
fprintf(stderr, "The VNC desktop is "
"%s\n", vnc_desktop_name);
}
} else if (lport >= 5900) {
if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) {
host = iface;
}
if (host != NULL) {
/* note that vncviewer special cases 5900-5999 */
int sz = 256;
if (inetd) {
; /* should not occur (port) */
} else if (quiet) {
if (lport >= 5900) {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport - 5900);
rfbLog("\n");
rfbLog("The VNC desktop is %s\n",
fprintf(stderr, "%s is %s\n", tvdt,
vnc_desktop_name);
if (lport >= 6000) {
rfbLog("possible aliases: %s:%d, "
"%s::%d\n", host, lport,
host, lport);
}
} else {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport);
rfbLog("\n");
rfbLog("The VNC desktop is %s\n",
fprintf(stderr, "%s is %s\n", tvdt,
vnc_desktop_name);
rfbLog("possible alias: %s::%d\n",
}
} else if (lport >= 5900) {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport - 5900);
fprintf(stderr, "%s is %s\n", tvdt, vnc_desktop_name);
if (lport >= 6000) {
rfbLog("possible aliases: %s:%d, "
"%s::%d\n", host, lport,
host, lport);
}
} else {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport);
fprintf(stderr, "%s is %s\n", tvdt, vnc_desktop_name);
rfbLog("possible alias: %s::%d\n",
host, lport);
}
}
}
void set_vnc_desktop_name(void) {
sprintf(vnc_desktop_name, "unknown");
if (inetd) {
sprintf(vnc_desktop_name, "inetd-no-further-clients");
}
if (screen->port) {
if (! quiet) {
rfbLog("\n");
}
announce(screen->port, 0, listen_str);
if (stunnel_port) {
announce(stunnel_port, 1, NULL);
}
fflush(stderr);
if (inetd) {
; /* should not occur (port != 0) */
} else {
fprintf(stdout, "PORT=%d\n", screen->port);
if (stunnel_port) {
fprintf(stdout, "SSLPORT=%d\n", stunnel_port);
}
fflush(stdout);
if (flagfile) {
FILE *flag = fopen(flagfile, "w");
if (flag) {
fprintf(flag, "PORT=%d\n",screen->port);
if (stunnel_port) {
fprintf(flag, "SSL_PORT=%d\n",
stunnel_port);
}
fflush(flag);
fclose(flag);
} else {

@ -3,6 +3,7 @@
#include "x11vnc.h"
#include "cleanup.h"
#include "connections.h"
#include "unixpw.h"
/*
* Selection/Cutbuffer/Clipboard handlers.
@ -184,6 +185,9 @@ void cutbuffer_send(void) {
rfbLog("cutbuffer_send: no send: uninitialized clients\n");
return; /* some clients initializing, cannot send */
}
if (unixpw_in_progress) {
return;
}
/* now send it to any connected VNC clients (rfbServerCutText) */
if (!screen) {
@ -284,6 +288,10 @@ void selection_send(XEvent *ev) {
return; /* some clients initializing, cannot send */
}
if (unixpw_in_progress) {
return;
}
/* now send it to any connected VNC clients (rfbServerCutText) */
if (!screen) {
return;

@ -0,0 +1,236 @@
/* -- sslcmds.c -- */
#include "x11vnc.h"
#include "inet.h"
#include "cleanup.h"
#if LIBVNCSERVER_HAVE_FORK
#if LIBVNCSERVER_HAVE_SYS_WAIT_H
#if LIBVNCSERVER_HAVE_WAITPID
#define SSLCMDS
#endif
#endif
#endif
int start_stunnel(int stunnel_port, int x11vnc_port);
void stop_stunnel(void);
void setup_stunnel(int rport, int *argc, char **argv);
static pid_t stunnel_pid = 0;
int start_stunnel(int stunnel_port, int x11vnc_port) {
#ifdef SSLCMDS
char extra[] = ":/usr/sbin:/usr/local/sbin";
char *path, *p, *exe;
char *stunnel_path = NULL;
int status;
if (stunnel_pid) {
stop_stunnel();
}
stunnel_pid = 0;
path = getenv("PATH");
if (! path) {
path = strdup(extra);
} else {
path = (char *) malloc(strlen(path)+strlen(extra)+1);
if (! path) {
return 0;
}
strcpy(path, getenv("PATH"));
strcat(path, extra);
}
exe = (char *) malloc(strlen(path) + strlen("stunnel") + 1);
p = strtok(path, ":");
exe[0] = '\0';
while (p) {
struct stat sbuf;
sprintf(exe, "%s/%s", p, "stunnel");
if (! stunnel_path && stat(exe, &sbuf) == 0) {
if (! S_ISDIR(sbuf.st_mode)) {
stunnel_path = exe;
break;
}
}
p = strtok(NULL, ":");
}
if (path) {
free(path);
}
if (! stunnel_path) {
return 0;
}
if (stunnel_path[0] == '\0') {
free(stunnel_path);
return 0;
}
if (! quiet) {
rfbLog("\n");
rfbLog("starting ssl tunnel: %s %d -> %d\n", stunnel_path,
stunnel_port, x11vnc_port);
}
if (0) {
fprintf(stderr, "foreground = yes\n");
fprintf(stderr, "pid =\n");
fprintf(stderr, ";debug = 7\n");
fprintf(stderr, "[x11vnc_stunnel]\n");
fprintf(stderr, "accept = %d\n", stunnel_port);
fprintf(stderr, "connect = %d\n", x11vnc_port);
}
stunnel_pid = fork();
if (stunnel_pid < 0) {
stunnel_pid = 0;
free(stunnel_path);
return 0;
}
if (stunnel_pid == 0) {
FILE *in;
char fd[20];
int i;
for (i=3; i<256; i++) {
close(i);
}
if (use_stunnel == 3) {
char sp[20], xp[20];
sprintf(sp, "%d", stunnel_port);
sprintf(xp, "%d", x11vnc_port);
if (stunnel_pem) {
execlp(stunnel_path, stunnel_path, "-f", "-d",
sp, "-r", xp, "-P", "none", "-p",
stunnel_pem, (char *) NULL);
} else {
execlp(stunnel_path, stunnel_path, "-f", "-d",
sp, "-r", xp, "-P", "none", (char *) NULL);
}
exit(1);
}
in = tmpfile();
if (! in) {
exit(1);
}
fprintf(in, "foreground = yes\n");
fprintf(in, "pid =\n");
if (stunnel_pem) {
fprintf(in, "cert = %s\n", stunnel_pem);
}
fprintf(in, ";debug = 7\n");
fprintf(in, "[x11vnc_stunnel]\n");
fprintf(in, "accept = %d\n", stunnel_port);
fprintf(in, "connect = %d\n", x11vnc_port);
fflush(in);
rewind(in);
sprintf(fd, "%d", fileno(in));
execlp(stunnel_path, stunnel_path, "-fd", fd, (char *) NULL);
exit(1);
}
free(stunnel_path);
usleep(500 * 1000);
waitpid(stunnel_pid, &status, WNOHANG);
if (kill(stunnel_pid, 0) != 0) {
waitpid(stunnel_pid, &status, WNOHANG);
stunnel_pid = 0;
return 0;
}
if (! quiet) {
rfbLog("stunnel pid is: %d\n", (int) stunnel_pid);
}
return 1;
#else
return 0;
#endif
}
void stop_stunnel(void) {
int status;
if (! stunnel_pid) {
return;
}
#ifdef SSLCMDS
kill(stunnel_pid, SIGTERM);
usleep (150 * 1000);
kill(stunnel_pid, SIGKILL);
usleep (50 * 1000);
waitpid(stunnel_pid, &status, WNOHANG);
#endif
stunnel_pid = 0;
}
void setup_stunnel(int rport, int *argc, char **argv) {
int i, xport = 0;
if (! rport) {
for (i=0; i< *argc; i++) {
if (!strcmp(argv[i], "-rfbport")) {
if (i < *argc - 1) {
rport = atoi(argv[i+1]);
break;
}
}
}
}
if (! rport) {
/* we do our own autoprobing then... */
rport = find_free_port(5900, 5999);
if (! rport) {
goto stunnel_fail;
}
}
xport = find_free_port(5950, 5999);
if (! xport) {
goto stunnel_fail;
}
if (start_stunnel(rport, xport)) {
int tweaked = 0;
char tmp[10];
sprintf(tmp, "%d", xport);
if (argv) {
for (i=0; i< *argc; i++) {
if (!strcmp(argv[i], "-rfbport")) {
if (i < *argc - 1) {
argv[i+i] = strdup(tmp);
tweaked = 1;
break;
}
}
}
if (! tweaked) {
i = *argc;
argv[i] = strdup("-rfbport");
argv[i+1] = strdup(tmp);
*argc += 2;
got_rfbport = 1;
}
}
stunnel_port = rport;
return;
}
stunnel_fail:
rfbLog("failed to start stunnel.\n");
clean_up_exit(1);
}

@ -0,0 +1,11 @@
#ifndef _X11VNC_SSLCMDS_H
#define _X11VNC_SSLCMDS_H
/* -- sslcmds.h -- */
extern int start_stunnel(int stunnel_port, int x11vnc_port);
extern void stop_stunnel(void);
extern void setup_stunnel(int rport, int *argc, char **argv);
#endif /* _X11VNC_SSLCMDS_H */

@ -502,9 +502,9 @@ You can choose to disconnect the client by clicking on the
confirmation dialog to doublecheck.
Alternatively, you can fine tune the VNC client's input permissions
by selecting any of the Keystrokes, Mouse Motion, or Button Clicks
checkboxes and pressing \"OK\". This is like the \"-input\" option
but on a per-client basis.
by selecting any of the Keystrokes, Mouse-Motion, Button-Clicks, or
Clipboard-Input checkboxes and pressing \"OK\". This is like the
\"-input\" option but on a per-client basis.
To not change any aspects of the VNC client press \"Cancel\".
"
@ -1849,8 +1849,8 @@ proc push_new_value {item name new {query 1}} {
}
}
proc set_kmb_str {} {
global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb
proc set_kmbc_str {} {
global vl_bk vl_bm vl_bb vl_bc vr_bk vr_bm vr_bb vr_bc
set str ""
if {$vl_bk} {
@ -1862,7 +1862,10 @@ proc set_kmb_str {} {
if {$vl_bb} {
append str "B"
}
if {$vr_bk || $vr_bm || $vr_bb} {
if {$vl_bc} {
append str "C"
}
if {$vr_bk || $vr_bm || $vr_bb || $vr_bc} {
append str ","
}
if {$vr_bk} {
@ -1874,16 +1877,19 @@ proc set_kmb_str {} {
if {$vr_bb} {
append str "B"
}
if {$vr_bc} {
append str "C"
}
entry_insert $str
}
proc insert_input_window {} {
global text_area cleanup_window
global ffont menu_var
global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb
global vl_bk vl_bm vl_bb vl_bc vr_bk vr_bm vr_bb vr_bc
append_text "\nUse these checkboxes to set the input permissions, "
append_text "or type in the \"KMB...\"\n"
append_text "or type in the \"KMBC...\"\n"
append_text "-input string manually. Then press \"OK\" or \"Cancel\".\n"
append_text "(note: an empty setting means use the default behavior, "
append_text "see viewonly)\n\n"
@ -1896,18 +1902,22 @@ proc insert_input_window {} {
frame $fr
label $fl.l -font $ffont -text "Normal clients: "
checkbutton $fl.bk -pady 1 -font $ffont -anchor w -variable vl_bk \
-pady 1 -command set_kmb_str -text "Keystrokes"
-pady 1 -command set_kmbc_str -text "Keystrokes"
checkbutton $fl.bm -font $ffont -anchor w -variable vl_bm \
-pady 1 -command set_kmb_str -text "Mouse Motion"
-pady 1 -command set_kmbc_str -text "Mouse-Motion"
checkbutton $fl.bb -font $ffont -anchor w -variable vl_bb \
-pady 1 -command set_kmb_str -text "Button Clicks"
-pady 1 -command set_kmbc_str -text "Button-Clicks"
checkbutton $fl.bc -font $ffont -anchor w -variable vl_bc \
-pady 1 -command set_kmbc_str -text "Clipboard-Input"
label $fr.l -pady 1 -font $ffont -text "View-Only clients:"
checkbutton $fr.bk -font $ffont -anchor w -variable vr_bk \
-pady 1 -command set_kmb_str -text "Keystrokes"
-pady 1 -command set_kmbc_str -text "Keystrokes"
checkbutton $fr.bm -font $ffont -anchor w -variable vr_bm \
-pady 1 -command set_kmb_str -text "Mouse Motion"
-pady 1 -command set_kmbc_str -text "Mouse-Motion"
checkbutton $fr.bb -font $ffont -anchor w -variable vr_bb \
-pady 1 -command set_kmb_str -text "Button Clicks"
-pady 1 -command set_kmbc_str -text "Button-Clicks"
checkbutton $fr.bc -font $ffont -anchor w -variable vr_bc \
-pady 1 -command set_kmbc_str -text "Clipboard-Input"
if {[info exists menu_var(input)]} {
set input_str $menu_var(input)
@ -1924,9 +1934,11 @@ proc insert_input_window {} {
set vl_bk 0
set vl_bm 0
set vl_bb 0
set vl_bc 0
set vr_bk 0
set vr_bm 0
set vr_bb 0
set vr_bc 0
if {[regexp -nocase {K} $normal]} {
set vl_bk 1
@ -1937,6 +1949,9 @@ proc insert_input_window {} {
if {[regexp -nocase {B} $normal]} {
set vl_bb 1
}
if {[regexp -nocase {C} $normal]} {
set vl_bc 1
}
if {[regexp -nocase {K} $viewonly]} {
set vr_bk 1
}
@ -1946,9 +1961,12 @@ proc insert_input_window {} {
if {[regexp -nocase {B} $viewonly]} {
set vr_bb 1
}
if {[regexp -nocase {C} $viewonly]} {
set vr_bc 1
}
pack $fl.l $fl.bk $fl.bm $fl.bb -side top -fill x
pack $fr.l $fr.bk $fr.bm $fr.bb -side top -fill x
pack $fl.l $fl.bk $fl.bm $fl.bb $fl.bc -side top -fill x
pack $fr.l $fr.bk $fr.bm $fr.bb $fr.bc -side top -fill x
pack $fl $fr -side left
update
update idletasks
@ -1961,19 +1979,21 @@ proc insert_input_window {} {
}
proc set_ca_str {w} {
global ca_bk ca_bm ca_bb ca_bk ca_di
global ca_bk ca_bm ca_bb ca_bc ca_di
if {$ca_di} {
entry_insert "disconnect"
$w.bk configure -state disabled
$w.bm configure -state disabled
$w.bb configure -state disabled
$w.bc configure -state disabled
return
}
$w.bk configure -state normal
$w.bm configure -state normal
$w.bb configure -state normal
$w.bc configure -state normal
set str ""
if {$ca_bk} {
@ -1985,13 +2005,16 @@ proc set_ca_str {w} {
if {$ca_bb} {
append str "B"
}
if {$ca_bc} {
append str "C"
}
entry_insert $str
}
proc insert_client_action_window {input} {
global text_area cleanup_window
global ffont menu_var
global ca_bk ca_bm ca_bb ca_bk ca_di
global ca_bk ca_bm ca_bb ca_bc ca_di
append_text "\nUse these checkboxes to set the input permissions "
append_text "for this client\n-OR- whether to disconnect it instead. "
@ -2004,14 +2027,17 @@ proc insert_client_action_window {input} {
checkbutton $w.bk -font $ffont -anchor w -variable ca_bk \
-pady 1 -command "set_ca_str $w" -text "Keystrokes"
checkbutton $w.bm -font $ffont -anchor w -variable ca_bm \
-pady 1 -command "set_ca_str $w" -text "Mouse Motion"
-pady 1 -command "set_ca_str $w" -text "Mouse-Motion"
checkbutton $w.bb -font $ffont -anchor w -variable ca_bb \
-pady 1 -command "set_ca_str $w" -text "Button Clicks"
-pady 1 -command "set_ca_str $w" -text "Button-Clicks"
checkbutton $w.bc -font $ffont -anchor w -variable ca_bc \
-pady 1 -command "set_ca_str $w" -text "Clipboard"
set ca_di 0
set ca_bk 0
set ca_bm 0
set ca_bb 0
set ca_bc 0
if {[regexp -nocase {K} $input]} {
set ca_bk 1
@ -2022,8 +2048,11 @@ proc insert_client_action_window {input} {
if {[regexp -nocase {B} $input]} {
set ca_bb 1
}
if {[regexp -nocase {C} $input]} {
set ca_bc 1
}
pack $w.di $w.bk $w.bm $w.bb -side left
pack $w.di $w.bk $w.bm $w.bb $w.bc -side left
update
update idletasks
$text_area window create end -window $w
@ -3188,16 +3217,17 @@ proc client_dialog {client} {
set input $m6
set logvo $m7
append_text "Host: $host, Port: $port, User: $user, IP: $ip, Id: $cid\n"
append_text " - originally logged in as: "
append_text " - originally logged in as: "
if {$logvo == "1" } {
append_text "View-Only Client\n"
} else {
append_text "Normal Client\n"
}
append_text " - currently allowed input: "
append_text " - currently allowed input: "
set sk 0
set sm 0
set sb 0
set sc 0
if {[regexp -nocase {K} $input]} {
append_text "Keystrokes"
set sk 1
@ -3216,7 +3246,14 @@ proc client_dialog {client} {
append_text "Button-Clicks"
set sb 1
}
if {! $sk && ! $sm && ! $sb} {
if {[regexp -nocase {C} $input]} {
if {$sk || $sm || $sb} {
append_text ", "
}
append_text "Clipboard"
set sm 1
}
if {! $sk && ! $sm && ! $sb && ! $sm} {
append_text "None"
}
append_text "\n"
@ -3243,7 +3280,7 @@ proc client_dialog {client} {
} elseif {[regexp -nocase {(disconnect|close)} $val]} {
disconnect_dialog $client
} else {
regsub -all -nocase {[^KMB]} $val "" val
regsub -all -nocase {[^KMBC]} $val "" val
set item_bool(client_input) 0
push_new_value "client_input" "client_input" "$cid:$val" 0
}

@ -513,9 +513,9 @@ char gui_code[] = "";
"confirmation dialog to doublecheck.\n"
"\n"
"Alternatively, you can fine tune the VNC client's input permissions\n"
"by selecting any of the Keystrokes, Mouse Motion, or Button Clicks\n"
"checkboxes and pressing \\\"OK\\\". This is like the \\\"-input\\\" option\n"
"but on a per-client basis.\n"
"by selecting any of the Keystrokes, Mouse-Motion, Button-Clicks, or\n"
"Clipboard-Input checkboxes and pressing \\\"OK\\\". This is like the\n"
"\\\"-input\\\" option but on a per-client basis.\n"
"\n"
"To not change any aspects of the VNC client press \\\"Cancel\\\".\n"
"\"\n"
@ -1860,8 +1860,8 @@ char gui_code[] = "";
" }\n"
"}\n"
"\n"
"proc set_kmb_str {} {\n"
" global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb \n"
"proc set_kmbc_str {} {\n"
" global vl_bk vl_bm vl_bb vl_bc vr_bk vr_bm vr_bb vr_bc\n"
"\n"
" set str \"\"\n"
" if {$vl_bk} {\n"
@ -1873,7 +1873,10 @@ char gui_code[] = "";
" if {$vl_bb} {\n"
" append str \"B\"\n"
" }\n"
" if {$vr_bk || $vr_bm || $vr_bb} {\n"
" if {$vl_bc} {\n"
" append str \"C\"\n"
" }\n"
" if {$vr_bk || $vr_bm || $vr_bb || $vr_bc} {\n"
" append str \",\"\n"
" }\n"
" if {$vr_bk} {\n"
@ -1885,16 +1888,19 @@ char gui_code[] = "";
" if {$vr_bb} {\n"
" append str \"B\"\n"
" }\n"
" if {$vr_bc} {\n"
" append str \"C\"\n"
" }\n"
" entry_insert $str\n"
"}\n"
"\n"
"proc insert_input_window {} {\n"
" global text_area cleanup_window\n"
" global ffont menu_var\n"
" global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb \n"
" global vl_bk vl_bm vl_bb vl_bc vr_bk vr_bm vr_bb vr_bc\n"
"\n"
" append_text \"\\nUse these checkboxes to set the input permissions, \"\n"
" append_text \"or type in the \\\"KMB...\\\"\\n\"\n"
" append_text \"or type in the \\\"KMBC...\\\"\\n\"\n"
" append_text \"-input string manually. Then press \\\"OK\\\" or \\\"Cancel\\\".\\n\"\n"
" append_text \"(note: an empty setting means use the default behavior, \"\n"
" append_text \"see viewonly)\\n\\n\"\n"
@ -1907,18 +1913,22 @@ char gui_code[] = "";
" frame $fr\n"
" label $fl.l -font $ffont -text \"Normal clients: \"\n"
" checkbutton $fl.bk -pady 1 -font $ffont -anchor w -variable vl_bk \\\n"
" -pady 1 -command set_kmb_str -text \"Keystrokes\" \n"
" -pady 1 -command set_kmbc_str -text \"Keystrokes\" \n"
" checkbutton $fl.bm -font $ffont -anchor w -variable vl_bm \\\n"
" -pady 1 -command set_kmb_str -text \"Mouse Motion\" \n"
" -pady 1 -command set_kmbc_str -text \"Mouse-Motion\" \n"
" checkbutton $fl.bb -font $ffont -anchor w -variable vl_bb \\\n"
" -pady 1 -command set_kmb_str -text \"Button Clicks\"\n"
" -pady 1 -command set_kmbc_str -text \"Button-Clicks\"\n"
" checkbutton $fl.bc -font $ffont -anchor w -variable vl_bc \\\n"
" -pady 1 -command set_kmbc_str -text \"Clipboard-Input\"\n"
" label $fr.l -pady 1 -font $ffont -text \"View-Only clients:\"\n"
" checkbutton $fr.bk -font $ffont -anchor w -variable vr_bk \\\n"
" -pady 1 -command set_kmb_str -text \"Keystrokes\" \n"
" -pady 1 -command set_kmbc_str -text \"Keystrokes\" \n"
" checkbutton $fr.bm -font $ffont -anchor w -variable vr_bm \\\n"
" -pady 1 -command set_kmb_str -text \"Mouse Motion\" \n"
" -pady 1 -command set_kmbc_str -text \"Mouse-Motion\" \n"
" checkbutton $fr.bb -font $ffont -anchor w -variable vr_bb \\\n"
" -pady 1 -command set_kmb_str -text \"Button Clicks\"\n"
" -pady 1 -command set_kmbc_str -text \"Button-Clicks\"\n"
" checkbutton $fr.bc -font $ffont -anchor w -variable vr_bc \\\n"
" -pady 1 -command set_kmbc_str -text \"Clipboard-Input\"\n"
"\n"
" if {[info exists menu_var(input)]} {\n"
" set input_str $menu_var(input)\n"
@ -1935,9 +1945,11 @@ char gui_code[] = "";
" set vl_bk 0\n"
" set vl_bm 0\n"
" set vl_bb 0\n"
" set vl_bc 0\n"
" set vr_bk 0\n"
" set vr_bm 0\n"
" set vr_bb 0\n"
" set vr_bc 0\n"
"\n"
" if {[regexp -nocase {K} $normal]} {\n"
" set vl_bk 1\n"
@ -1948,6 +1960,9 @@ char gui_code[] = "";
" if {[regexp -nocase {B} $normal]} {\n"
" set vl_bb 1\n"
" }\n"
" if {[regexp -nocase {C} $normal]} {\n"
" set vl_bc 1\n"
" }\n"
" if {[regexp -nocase {K} $viewonly]} {\n"
" set vr_bk 1\n"
" }\n"
@ -1957,9 +1972,12 @@ char gui_code[] = "";
" if {[regexp -nocase {B} $viewonly]} {\n"
" set vr_bb 1\n"
" }\n"
" if {[regexp -nocase {C} $viewonly]} {\n"
" set vr_bc 1\n"
" }\n"
"\n"
" pack $fl.l $fl.bk $fl.bm $fl.bb -side top -fill x\n"
" pack $fr.l $fr.bk $fr.bm $fr.bb -side top -fill x\n"
" pack $fl.l $fl.bk $fl.bm $fl.bb $fl.bc -side top -fill x\n"
" pack $fr.l $fr.bk $fr.bm $fr.bb $fr.bc -side top -fill x\n"
" pack $fl $fr -side left\n"
" update\n"
" update idletasks\n"
@ -1972,19 +1990,21 @@ char gui_code[] = "";
"}\n"
"\n"
"proc set_ca_str {w} {\n"
" global ca_bk ca_bm ca_bb ca_bk ca_di\n"
" global ca_bk ca_bm ca_bb ca_bc ca_di\n"
"\n"
" if {$ca_di} {\n"
" entry_insert \"disconnect\"\n"
" $w.bk configure -state disabled\n"
" $w.bm configure -state disabled\n"
" $w.bb configure -state disabled\n"
" $w.bc configure -state disabled\n"
" return\n"
" }\n"
"\n"
" $w.bk configure -state normal\n"
" $w.bm configure -state normal\n"
" $w.bb configure -state normal\n"
" $w.bc configure -state normal\n"
"\n"
" set str \"\"\n"
" if {$ca_bk} {\n"
@ -1996,13 +2016,16 @@ char gui_code[] = "";
" if {$ca_bb} {\n"
" append str \"B\"\n"
" }\n"
" if {$ca_bc} {\n"
" append str \"C\"\n"
" }\n"
" entry_insert $str\n"
"}\n"
"\n"
"proc insert_client_action_window {input} {\n"
" global text_area cleanup_window\n"
" global ffont menu_var\n"
" global ca_bk ca_bm ca_bb ca_bk ca_di\n"
" global ca_bk ca_bm ca_bb ca_bc ca_di\n"
"\n"
" append_text \"\\nUse these checkboxes to set the input permissions \"\n"
" append_text \"for this client\\n-OR- whether to disconnect it instead. \"\n"
@ -2015,14 +2038,17 @@ char gui_code[] = "";
" checkbutton $w.bk -font $ffont -anchor w -variable ca_bk \\\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Keystrokes\" \n"
" checkbutton $w.bm -font $ffont -anchor w -variable ca_bm \\\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Mouse Motion\" \n"
" -pady 1 -command \"set_ca_str $w\" -text \"Mouse-Motion\" \n"
" checkbutton $w.bb -font $ffont -anchor w -variable ca_bb \\\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Button Clicks\"\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Button-Clicks\"\n"
" checkbutton $w.bc -font $ffont -anchor w -variable ca_bc \\\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Clipboard\"\n"
"\n"
" set ca_di 0\n"
" set ca_bk 0\n"
" set ca_bm 0\n"
" set ca_bb 0\n"
" set ca_bc 0\n"
"\n"
" if {[regexp -nocase {K} $input]} {\n"
" set ca_bk 1\n"
@ -2033,8 +2059,11 @@ char gui_code[] = "";
" if {[regexp -nocase {B} $input]} {\n"
" set ca_bb 1\n"
" }\n"
" if {[regexp -nocase {C} $input]} {\n"
" set ca_bc 1\n"
" }\n"
"\n"
" pack $w.di $w.bk $w.bm $w.bb -side left\n"
" pack $w.di $w.bk $w.bm $w.bb $w.bc -side left\n"
" update\n"
" update idletasks\n"
" $text_area window create end -window $w\n"
@ -3199,16 +3228,17 @@ char gui_code[] = "";
" set input $m6\n"
" set logvo $m7\n"
" append_text \"Host: $host, Port: $port, User: $user, IP: $ip, Id: $cid\\n\"\n"
" append_text \" - originally logged in as: \"\n"
" append_text \" - originally logged in as: \"\n"
" if {$logvo == \"1\" } {\n"
" append_text \"View-Only Client\\n\"\n"
" } else {\n"
" append_text \"Normal Client\\n\"\n"
" }\n"
" append_text \" - currently allowed input: \"\n"
" append_text \" - currently allowed input: \"\n"
" set sk 0\n"
" set sm 0\n"
" set sb 0\n"
" set sc 0\n"
" if {[regexp -nocase {K} $input]} {\n"
" append_text \"Keystrokes\"\n"
" set sk 1\n"
@ -3227,7 +3257,14 @@ char gui_code[] = "";
" append_text \"Button-Clicks\"\n"
" set sb 1\n"
" }\n"
" if {! $sk && ! $sm && ! $sb} {\n"
" if {[regexp -nocase {C} $input]} {\n"
" if {$sk || $sm || $sb} {\n"
" append_text \", \"\n"
" }\n"
" append_text \"Clipboard\"\n"
" set sm 1\n"
" }\n"
" if {! $sk && ! $sm && ! $sb && ! $sm} {\n"
" append_text \"None\"\n"
" }\n"
" append_text \"\\n\"\n"
@ -3254,7 +3291,7 @@ char gui_code[] = "";
" } elseif {[regexp -nocase {(disconnect|close)} $val]} {\n"
" disconnect_dialog $client\n"
" } else {\n"
" regsub -all -nocase {[^KMB]} $val \"\" val\n"
" regsub -all -nocase {[^KMBC]} $val \"\" val\n"
" set item_bool(client_input) 0\n"
" push_new_value \"client_input\" \"client_input\" \"$cid:$val\" 0\n"
" }\n"

@ -0,0 +1,442 @@
/* -- unixpw.c -- */
#ifdef __linux__
/* some conflict with _XOPEN_SOURCE */
extern int grantpt(int);
extern int unlockpt(int);
extern char *ptsname(int);
#endif
#include "x11vnc.h"
#include "scan.h"
#include "cleanup.h"
#include "xinerama.h"
#include <rfb/default8x16.h>
/* much to do for it to work on *BSD ... */
#if LIBVNCSERVER_HAVE_FORK
#if LIBVNCSERVER_HAVE_SETSID
#if LIBVNCSERVER_HAVE_SYS_WAIT_H
#if LIBVNCSERVER_HAVE_PWD_H
#if LIBVNCSERVER_HAVE_SETUID
#if LIBVNCSERVER_HAVE_WAITPID
#if LIBVNCSERVER_HAVE_TERMIOS_H
#if LIBVNCSERVER_HAVE_SYS_IOCTL_H
#if LIBVNCSERVER_HAVE_GRANTPT
#define UNIXPW
#include <sys/ioctl.h>
#include <termios.h>
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
void unixpw_screen(int init);
void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init);
void unixpw_accept(void);
void unixpw_deny(void);
static int white(void);
static int text_x(void);
static int text_y(void);
static int su_verify(char *user, char *pass);
static void unixpw_verify(char *user, char *pass);
int unixpw_in_progress = 0;
time_t unixpw_last_try_time = 0;
rfbClientPtr unixpw_client = NULL;
static int in_login = 0, in_passwd = 0, tries = 0;
static int char_row = 0, char_col = 0;
static int char_x = 0, char_y = 0, char_w = 8, char_h = 16;
static int white(void) {
static unsigned long black_pix = 0, white_pix = 1, set = 0;
if (depth <= 8 && ! set) {
X_LOCK;
black_pix = BlackPixel(dpy, scr);
white_pix = WhitePixel(dpy, scr);
X_UNLOCK;
set = 1;
}
if (depth <= 8) {
return (int) white_pix;
} else if (depth < 24) {
return 0xffff;
} else {
return 0xffffff;
}
}
static int text_x(void) {
return char_x + char_col * char_w;
}
static int text_y(void) {
return char_y + char_row * char_h;
}
void unixpw_screen(int init) {
#ifndef UNIXPW
rfbLog("-unixpw is not supported on this OS/machine\n");
clean_up_exit(1);
#endif
if (init) {
int x, y;
char log[] = "login: ";
zero_fb(0, 0, dpy_x, dpy_y);
x = nfix(dpy_x / 2 - strlen(log) * char_w, dpy_x);
y = dpy_y / 4;
rfbDrawString(screen, &default8x16Font, x, y, log, white());
char_x = x;
char_y = y;
char_col = strlen(log);
char_row = 0;
}
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
}
static int su_verify(char *user, char *pass) {
#ifdef UNIXPW
int status, fd, sfd;
char *slave;
pid_t pid, pidw;
struct stat sbuf;
if (unixpw_list) {
char *p, *str = strdup(unixpw_list);
int ok = 0;
p = strtok(str, ",");
while (p) {
if (!strcmp(user, p)) {
ok = 1;
break;
}
p = strtok(NULL, ",");
}
free(str);
if (! ok) {
return 0;
}
}
if (stat("/bin/su", &sbuf) != 0) {
rfbLogPerror("existence /bin/su");
return 0;
}
if (stat("/bin/true", &sbuf) != 0) {
rfbLogPerror("existence /bin/true");
return 0;
}
fd = open("/dev/ptmx", O_RDWR|O_NOCTTY);
if (fd < 0) {
rfbLogPerror("open /dev/ptmx");
return 0;
}
if (grantpt(fd) != 0) {
rfbLogPerror("grantpt");
close(fd);
return 0;
}
if (unlockpt(fd) != 0) {
rfbLogPerror("unlockpt");
close(fd);
return 0;
}
slave = ptsname(fd);
if (! slave) {
rfbLogPerror("ptsname");
close(fd);
return 0;
}
pid = fork();
if (pid < 0) {
rfbLogPerror("fork");
close(fd);
return 0;
}
if (pid == 0) {
int ttyfd;
struct passwd *pw;
close(fd);
pw = getpwnam("nobody");
if (pw) {
setuid(pw->pw_uid);
#if LIBVNCSERVER_HAVE_SETEUID
seteuid(pw->pw_uid);
#endif
setgid(pw->pw_gid);
#if LIBVNCSERVER_HAVE_SETEGID
setegid(pw->pw_gid);
#endif
}
if (getuid() == 0 || geteuid() == 0) {
fprintf(stderr, "could not switch to user nobody.\n");
exit(1);
}
if (setsid() == -1) {
perror("setsid");
exit(1);
}
#ifdef TIOCNOTTY
ttyfd = open("/dev/tty", O_RDWR);
if (ttyfd >= 0) {
(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
close(ttyfd);
}
#endif
close(0);
close(1);
close(2);
sfd = open(slave, O_RDWR);
if (sfd < 0) {
fprintf(stderr, "failed: %s\n", slave);
perror("open");
exit(1);
}
#ifdef TIOCSCTTY
if (ioctl(sfd, TIOCSCTTY, (char *) 0) != 0) {
perror("ioctl");
exit(1);
}
#endif
execlp("/bin/su", "/bin/su", user, "-c", "/bin/true",
(char *) NULL);
exit(1);
}
usleep( 500 * 1000 );
write(fd, pass, strlen(pass));
pidw = waitpid(pid, &status, 0);
close(fd);
if (pid != pidw) {
return 0;
}
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
return 1;
} else {
return 0;
}
#else
return 0;
#endif
}
static int db = 0;
static void unixpw_verify(char *user, char *pass) {
int x, y;
char li[] = "Login incorrect";
char log[] = "login: ";
if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "********");
if (su_verify(user, pass)) {
unixpw_accept();
return;
}
if (tries < 2) {
char_row++;
char_col = 0;
x = text_x();
y = text_y();
rfbDrawString(screen, &default8x16Font, x, y, li, white());
char_row += 2;
x = text_x();
y = text_y();
rfbDrawString(screen, &default8x16Font, x, y, log, white());
char_col = strlen(log);
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
unixpw_last_try_time = time(0);
unixpw_keystroke(0, 0, 2);
tries++;
} else {
unixpw_deny();
}
}
void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
int x, y, i, nmax = 100;
static char user[100], pass[100];
static int u_cnt = 0, p_cnt = 0, first = 1;
char str[100];
if (first) {
if (getenv("DEBUG_UNIXPW")) {
db = atoi(getenv("DEBUG_UNIXPW"));
}
first = 0;
}
if (init) {
in_login = 1;
in_passwd = 0;
if (init == 1) {
tries = 0;
}
u_cnt = 0;
p_cnt = 0;
for (i=0; i<nmax; i++) {
user[i] = '\0';
pass[i] = '\0';
}
return;
}
if (down) {
return;
}
if (in_login) {
if (keysym == XK_BackSpace || keysym == XK_Delete) {
if (u_cnt > 0) {
user[u_cnt-1] = '\0';
x = text_x();
y = text_y();
zero_fb(x - char_w, y - char_h, x, y);
mark_rect_as_modified(x - char_w, y - char_h,
x, y, 0);
char_col--;
u_cnt--;
}
return;
}
if (keysym == XK_Return || keysym == XK_Linefeed) {
char pw[] = "Password: ";
in_login = 0;
in_passwd = 1;
char_row++;
char_col = 0;
x = text_x();
y = text_y();
rfbDrawString(screen, &default8x16Font, x, y, pw,
white());
char_col = strlen(pw);
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
return;
}
if (keysym <= ' ' || keysym >= 0x7f) {
return;
}
if (u_cnt >= nmax - 1) {
rfbLog("unixpw_deny: username too long\n");
unixpw_deny();
return;
}
X_LOCK;
sprintf(str, "%s", XKeysymToString(keysym));
X_UNLOCK;
user[u_cnt++] = str[0];
x = text_x();
y = text_y();
if (db) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x %s\n", u_cnt, x, y, keysym, str);
str[1] = '\0';
rfbDrawString(screen, &default8x16Font, x, y, str, white());
mark_rect_as_modified(x, y-char_h, x+char_w, y, 0);
char_col++;
} else if (in_passwd) {
if (keysym == XK_BackSpace || keysym == XK_Delete) {
if (p_cnt > 0) {
pass[p_cnt-1] = '\0';
p_cnt--;
}
return;
}
if (keysym == XK_Return || keysym == XK_Linefeed) {
in_login = 0;
in_passwd = 0;
pass[p_cnt++] = '\n';
unixpw_verify(user, pass);
return;
}
if (keysym <= ' ' || keysym >= 0x7f) {
return;
}
if (p_cnt >= nmax - 2) {
rfbLog("unixpw_deny: password too long\n");
unixpw_deny();
return;
}
pass[p_cnt++] = (char) keysym;
}
}
void unixpw_accept(void) {
unixpw_in_progress = 0;
unixpw_client = NULL;
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
}
void unixpw_deny(void) {
int x, y, i;
char pd[] = "Permission denied.";
char_row += 2;
char_col = 0;
x = char_x + char_col * char_w;
y = char_y + char_row * char_h;
rfbDrawString(screen, &default8x16Font, x, y, pd, white());
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
for (i=0; i<5; i++) {
rfbPE(-1);
usleep(500 * 1000);
}
rfbCloseClient(unixpw_client);
rfbClientConnectionGone(unixpw_client);
rfbPE(-1);
unixpw_in_progress = 0;
unixpw_client = NULL;
copy_screen();
}

@ -0,0 +1,15 @@
#ifndef _X11VNC_UNIXPW_H
#define _X11VNC_UNIXPW_H
/* -- unixpw.h -- */
extern void unixpw_screen(int init);
extern void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init);
extern void unixpw_accept(void);
extern void unixpw_deny(void);
extern int unixpw_in_progress;
extern time_t unixpw_last_try_time;
extern rfbClientPtr unixpw_client;
#endif /* _X11VNC_UNIXPW_H */

@ -5,6 +5,7 @@
#include "cleanup.h"
#include "scan.h"
#include "screen.h"
#include "unixpw.h"
void check_switched_user(void);
void lurk_loop(char *str);
@ -44,6 +45,8 @@ void check_switched_user(void) {
int delay = 15;
time_t now = time(0);
if (unixpw_in_progress) return;
if (started_as_root == 1 && users_list) {
try_to_switch_users();
if (started_as_root == 2) {
@ -923,6 +926,8 @@ void check_new_passwds(void) {
if (strstr(passwdfile, "read:") != passwdfile) {
return;
}
if (unixpw_in_progress) return;
now = time(0);
if (now > last_check + 1) {
if (read_passwds(passwdfile)) {

@ -15,6 +15,7 @@
#include "solid.h"
#include "xrandr.h"
#include "8to24.h"
#include "unixpw.h"
/*
* user input handling heuristics
@ -2710,6 +2711,8 @@ int check_xrecord(void) {
if (! use_xrecord) {
return 0;
}
if (unixpw_in_progress) return 0;
if (skip_cr_when_scaling("scroll")) {
return 0;
}
@ -3136,6 +3139,7 @@ void check_fixscreen(void) {
if (!client_count) {
return;
}
if (unixpw_in_progress) return;
if (screen_fixup_X > 0.0) {
static double last = 0.0;
@ -3287,6 +3291,7 @@ int check_wireframe(void) {
int try_it = 0;
DB_SET
if (unixpw_in_progress) return 0;
if (nofb) {
return 0;
}

@ -2,7 +2,7 @@
.TH X11VNC "1" "February 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.1, lastmod: 2006-02-20
version: 0.8.1, lastmod: 2006-02-24
.SH SYNOPSIS
.B x11vnc
[OPTION]...
@ -433,16 +433,17 @@ lookups time out, etc.
.IP
Fine tuning of allowed user input. If \fIstring\fR does
not contain a comma "," the tuning applies only to
normal clients. Otherwise the part before "," is
for normal clients and the part after for view-only
clients. "K" is for Keystroke input, "M" for
Mouse-motion input, and "B" for Button-click input.
Their presence in the string enables that type of input.
E.g. "\fB-input\fR \fIM\fR" means normal users can only move
the mouse and "\fB-input\fR \fIKMB,M\fR" lets normal users do
anything and enables view-only users to move the mouse.
This option is ignored when a global \fB-viewonly\fR is in
effect (all input is discarded in that case).
normal clients. Otherwise the part before "," is for
normal clients and the part after for view-only clients.
"K" is for Keystroke input, "M" for Mouse-motion
input, "B" for Button-click input, and "C" is for
Clipboard input. Their presence in the string enables
that type of input. E.g. "\fB-input\fR \fIM\fR" means normal
users can only move the mouse and "\fB-input\fR \fIKMBC,M\fR"
lets normal users do anything and enables view-only
users to move the mouse. This option is ignored when
a global \fB-viewonly\fR is in effect (all input is discarded
in that case).
.PP
\fB-viewpasswd\fR \fIstring\fR
.IP
@ -491,6 +492,94 @@ used to have viewonly passwords. (tip: make the 3rd
and last line be "__BEGIN_VIEWONLY__" to have 2
full-access passwords)
.PP
\fB-unixpw\fR \fI[list]\fR
.IP
Experimental option: use Unix username and password
authentication. x11vnc uses the
.IR su (1)
program to
verify the user's password. [list] is an optional
comma separated list of allowed Unix usernames.
.IP
A familiar "login:" and "Password:" dialog is
presented to the user on a black screen inside the
vncviewer. The connection is dropped if the user fails
to supply the correct password in 3 tries or does not
send one before a 20 second timeout. Existing clients
are view-only during this period.
.IP
*IMPORTANT*: to prevent the Unix password being sent in
*clear text* over the network, two x11vnc options are
enforced: 1) \fB-localhost\fR and 2) \fB-stunnel.\fR The former
requires the viewer connection to appear to come from
the same machine x11vnc is running on (e.g. from a ssh
\fB-L\fR port redirection). The latter requires the \fB-stunnel\fR
SSL mode be used (see the description below).
.IP
To override these restrictions you can set environment
variables before starting x11vnc:
.IP
Set UNIXPW_DISABLE_STUNNEL=1 to disable using \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
.IR ssh (1)
with
\fB-localhost\fR is roughly the same as requiring a Unix
user login (since Unix password or the user's public
key authentication is used by ssh)
.IP
Set UNIXPW_DISABLE_LOCALHOST=1 to disable the \fB-localhost\fR
requirement. One should never do this (i.e. allow the
Unix passwords to be sniffed on the network).
.IP
NOTE: in \fB-inetd\fR mode the two settings are not enforced
since x11vnc does not make network connections in
that case. Be sure to use encryption from the viewer
to inetd. One can also have your own stunnel spawn
x11vnc in \fB-inetd\fR mode.
.PP
\fB-stunnel\fR \fI[pem]\fR
.IP
Use the
.IR stunnel (1)
(www.stunnel.org) to provide an
encrypted SSL tunnel between viewers and x11vnc.
This requires stunnel be installed on the system and
available via PATH (n.b. stunnel is often installed in
sbin directories). Version 4.x of stunnel is assumed.
.IP
[pem] is optional, use "\fB-stunnel\fR \fI/path/to/stunnel.pem\fR"
to specify a PEM certificate file to pass to stunnel.
.IP
stunnel is started up as a child process and any SSL
connections it receives are decrypted and sent to x11vnc
over a local socket. The strings "The SSL VNC desktop
is ..." and SSLPORT=... are printed out at startup.
.IP
The \fB-localhost\fR option is enforced by default. Set
STUNNEL_DISABLE_LOCALHOST=1 to disable the requirement.
.IP
Your VNC viewer will need to be able to connect via SSL.
Unfortunately not too many do this. UltraVNC seems to
have a SSL plugin. It is not too difficult to set up
an stunnel or other SSL tunnel on the viewer side.
.IP
A simple example on Unix using stunnel 3.x is:
.IP
% stunnel \fB-c\fR \fB-d\fR localhost:5901 \fB-r\fR remote:5900
% vncviewer localhost:1
.IP
For Windows, stunnel has been ported to it and there
are probably other such tools available.
.PP
\fB-stunnel3\fR \fI[pem]\fR
.IP
Use version 3.x stunnel command line syntax instead of
version 4.x
.PP
\fB-nopw\fR
.IP
Disable the big warning message when you use x11vnc

@ -137,6 +137,7 @@
#include "screen.h"
#include "connections.h"
#include "rates.h"
#include "unixpw.h"
/*
* main routine for the x11vnc program
@ -159,6 +160,8 @@ static void check_loop_mode(int argc, char* argv[]);
static void check_cursor_changes(void) {
static double last_push = 0.0;
if (unixpw_in_progress) return;
cursor_changes += check_x11_pointer();
if (cursor_changes) {
@ -220,6 +223,9 @@ static void record_last_fb_update(void) {
/* check every second or so */
return;
}
if (unixpw_in_progress) return;
last_call = now;
if (! screen) {
@ -933,6 +939,8 @@ static void print_settings(int try_http, int bg, char *gui_str) {
? allowed_input_str : "null");
fprintf(stderr, " passfile: %s\n", passwdfile ? passwdfile
: "null");
fprintf(stderr, " unixpw: %d\n", unixpw);
fprintf(stderr, " stunnel: %d\n", use_stunnel);
fprintf(stderr, " accept: %s\n", accept_cmd ? accept_cmd
: "null");
fprintf(stderr, " accept: %s\n", afteraccept_cmd ? afteraccept_cmd
@ -1157,6 +1165,7 @@ int main(int argc, char* argv[]) {
char *gui_str = NULL;
int pw_loc = -1, got_passwd = 0, got_rfbauth = 0, nopw = NOPW;
int got_viewpasswd = 0, got_localhost = 0, got_passwdfile = 0;
int got_stunnel = 0;
int vpw_loc = -1;
int dt = 0, bg = 0;
int got_rfbwait = 0;
@ -1350,6 +1359,35 @@ int main(int argc, char* argv[]) {
CHECK_ARGC
passwdfile = strdup(argv[++i]);
got_passwdfile = 1;
} else if (!strcmp(arg, "-unixpw")) {
unixpw = 1;
if (i < argc-1) {
char *s = argv[i+1];
if (s[0] != '-') {
unixpw_list = strdup(s);
i++;
}
}
} else if (!strcmp(arg, "-stunnel")) {
use_stunnel = 1;
got_stunnel = 1;
if (i < argc-1) {
char *s = argv[i+1];
if (s[0] != '-') {
stunnel_pem = strdup(s);
i++;
}
}
} else if (!strcmp(arg, "-stunnel3")) {
use_stunnel = 3;
got_stunnel = 1;
if (i < argc-1) {
char *s = argv[i+1];
if (s[0] != '-') {
stunnel_pem = strdup(s);
i++;
}
}
} else if (!strcmp(arg, "-nopw")) {
nopw = 1;
} else if (!strcmp(arg, "-storepasswd")) {
@ -1825,8 +1863,8 @@ int main(int argc, char* argv[]) {
if (!strcmp(arg, "-deferupdate")) {
got_deferupdate = 1;
}
if (!strcmp(arg, "-rfbport")) {
got_rfbport = 1;
if (!strcmp(arg, "-rfbport") && i < argc-1) {
got_rfbport = atoi(argv[i+1]);
}
if (!strcmp(arg, "-alwaysshared ")) {
got_alwaysshared = 1;
@ -1999,9 +2037,9 @@ int main(int argc, char* argv[]) {
}
if (!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list)
&& !query_cmd && !remote_cmd) {
char message[] =
"-rfbauth, -passwdfile, or -passwd password required.";
&& !query_cmd && !remote_cmd && !unixpw) {
char message[] = "-rfbauth, -passwdfile, -passwd password, "
"or -unixpw required.";
if (! nopw) {
nopassword_warning_msg(got_localhost);
}
@ -2032,6 +2070,33 @@ int main(int argc, char* argv[]) {
launch_gui = 0;
}
if (! inetd) {
if (unixpw) {
if (! got_localhost && ! getenv("UNIXPW_DISABLE_LOCALHOST")) {
if (! quiet) {
rfbLog("Setting -localhost in -unixpw mode.\n");
}
allow_list = strdup("127.0.0.1");
got_localhost = 1;
}
if (! got_stunnel && ! getenv("UNIXPW_DISABLE_STUNNEL")) {
if (! quiet) {
rfbLog("Setting -stunnel in -unixpw mode.\n");
}
use_stunnel = 1;
}
} else if (use_stunnel) {
if (! got_localhost && ! getenv("STUNNEL_DISABLE_LOCALHOST")) {
if (! quiet) {
rfbLog("Setting -localhost in -stunnel mode.\n");
}
allow_list = strdup("127.0.0.1");
got_localhost = 1;
}
}
}
/* fixup settings that do not make sense */
if (use_threads && nofb && cursor_pos_updates) {
@ -2082,6 +2147,7 @@ int main(int argc, char* argv[]) {
shared = 0;
connect_once = 1;
bg = 0;
use_stunnel = 0;
/* others? */
}
@ -2591,11 +2657,6 @@ int main(int argc, char* argv[]) {
}
#endif
if (filexfer) {
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
rfbRegisterTightVNCFileTransferExtension();
#endif
}
if (! quiet) {
rfbLog("--------------------------------------------------------\n");
@ -2604,6 +2665,13 @@ int main(int argc, char* argv[]) {
raw_fb_pass_go_and_collect_200_dollars:
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
if (filexfer) {
rfbRegisterTightVNCFileTransferExtension();
} else {
rfbUnregisterTightVNCFileTransferExtension();
}
#endif
if (! dt) {
static char str[] = "-desktop";
argv_vnc[argc_vnc++] = str;
@ -2655,7 +2723,8 @@ int main(int argc, char* argv[]) {
}
if (! quiet) {
rfbLog("screen setup finished.\n");
if (!got_passwd && !got_rfbauth && !got_passwdfile && !nopw) {
if (!got_passwd && !got_rfbauth && !got_passwdfile && !unixpw
&& !nopw) {
rfbLog("\n");
rfbLog("WARNING: You are running x11vnc WITHOUT"
" a password. See\n");

@ -435,6 +435,7 @@ typedef struct _ClientData {
double latency;
int cmp_bytes_sent;
int raw_bytes_sent;
} ClientData;
#include "params.h"

@ -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.1 lastmod: 2006-02-20";
char lastmod[] = "0.8.1 lastmod: 2006-02-24";
/* X display info */

@ -3,6 +3,7 @@
#include "x11vnc.h"
#include "xwrappers.h"
#include "userinput.h"
#include "unixpw.h"
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
Damage xdamage = 0;
@ -177,6 +178,7 @@ void clear_xdamage_mark_region(sraRegionPtr markregion, int flush) {
if (! xdamage_base_event_type) {
return;
}
if (unixpw_in_progress) return;
X_LOCK;
if (flush) {

@ -11,6 +11,7 @@
#include "cursor.h"
#include "gui.h"
#include "connections.h"
#include "unixpw.h"
/* XXX CHECK BEFORE RELEASE */
int grab_buster = 0;
@ -553,6 +554,8 @@ void check_keycode_state(void) {
if (raw_fb && ! dpy) return; /* raw_fb hack */
if (unixpw_in_progress) return;
/*
* periodically update our model of the keycode_state[]
* by correlating with the Xserver. wait for a pause in
@ -578,6 +581,9 @@ void check_autorepeat(void) {
if (now <= last_check + 1) {
return;
}
if (unixpw_in_progress) return;
last_check = now;
autorepeat_is_on = get_autorepeat_state();
@ -651,6 +657,8 @@ void check_xevents(void) {
if (raw_fb && ! dpy) return; /* raw_fb hack */
if (unixpw_in_progress) return;
if (now > last_init_check+1) {
last_init_check = now;
initialize_xevents();
@ -935,6 +943,8 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
if (raw_fb && ! dpy) return; /* raw_fb hack */
if (unixpw_in_progress) return;
if (!watch_selection) {
return;
}
@ -945,8 +955,7 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
return;
}
get_allowed_input(cl, &input);
if (!input.keystroke && !input.motion && !input.button) {
/* maybe someday KMBC for cut text... */
if (!input.clipboard) {
return;
}

@ -7,6 +7,7 @@
#include "userinput.h"
#include "winattr_t.h"
#include "scrollevent_t.h"
#include "unixpw.h"
#define SCR_EV_MAX 128
scroll_event_t scr_ev[SCR_EV_MAX];
@ -1303,6 +1304,7 @@ static void check_xrecord_grabserver(void) {
if (!gdpy_ctrl || !gdpy_data) {
return;
}
if (unixpw_in_progress) return;
dtime0(&d);
XFlush(gdpy_ctrl);
@ -1437,6 +1439,8 @@ void check_xrecord_reset(int force) {
return;
}
if (unixpw_in_progress) return;
#if LIBVNCSERVER_HAVE_RECORD
if (! rc_scroll) {
return;

Loading…
Cancel
Save