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

pull/1/head
runge 17 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