Commit 0ef122b6 authored by runge's avatar runge

Apache SSL gateway. More web proxy cases for Java and ssl_vncviewer.

parent d14cf0a8
#!/bin/sh #!/bin/sh
# #
# ssl_vncviewer: wrapper for vncviewer to use stunnel SSL tunnel. # ssl_vncviewer: wrapper for vncviewer to use an stunnel SSL tunnel.
#
# Copyright (c) 2006 by Karl J. Runge <runge@karlrunge.com>
# #
# You must have stunnel(8) installed on the system and in your # You must have stunnel(8) installed on the system and in your
# PATH (n.b. stunnel is usually in an sbin subdir). # PATH (n.b. stunnel is usually in an sbin subdir).
...@@ -16,6 +18,7 @@ ...@@ -16,6 +18,7 @@
# [cert-args] can be: # [cert-args] can be:
# -verify /path/to/cacert.pem # -verify /path/to/cacert.pem
# -mycert /path/to/mycert.pem # -mycert /path/to/mycert.pem
# -proxy host:port
# #
# -verify specifies a CA cert PEM file (or a self-signed one) for # -verify specifies a CA cert PEM file (or a self-signed one) for
# authenticating the VNC server. # authenticating the VNC server.
...@@ -23,12 +26,19 @@ ...@@ -23,12 +26,19 @@
# -mycert specifies this client's cert+key PEM file for the VNC server to # -mycert specifies this client's cert+key PEM file for the VNC server to
# authenticate this client. # authenticate this client.
# #
# -proxy try host:port as a Web proxy to use the CONNECT method
# to reach the VNC server (e.g. your firewall requires a proxy).
# For the "double proxy" case use -proxy host1:port1,host2:port2
#
#
# set VNCVIEWERCMD to whatever vncviewer command you want to use:
#
VNCVIEWERCMD=${VNCVIEWERCMD:-vncviewer}
VNCVIEWERCMD="vncviewer"
PATH=$PATH:/usr/sbin:/usr/local/sbin:/dist/sbin; export PATH PATH=$PATH:/usr/sbin:/usr/local/sbin:/dist/sbin; export PATH
help() { help() {
head -26 $0 | tail +2 head -36 $0 | tail +2
} }
# grab our cmdline options: # grab our cmdline options:
...@@ -39,6 +49,8 @@ do ...@@ -39,6 +49,8 @@ do
;; ;;
"-mycert") shift; mycert="$1" "-mycert") shift; mycert="$1"
;; ;;
"-proxy") shift; proxy="$1"
;;
"-h"*) help; exit 0 "-h"*) help; exit 0
;; ;;
*) break *) break
...@@ -59,12 +71,19 @@ host=`echo "$orig" | awk -F: '{print $1}'` ...@@ -59,12 +71,19 @@ host=`echo "$orig" | awk -F: '{print $1}'`
disp=`echo "$orig" | awk -F: '{print $2}'` disp=`echo "$orig" | awk -F: '{print $2}'`
if [ $disp -lt 200 ]; then if [ $disp -lt 200 ]; then
port=`expr $disp + 5900` port=`expr $disp + 5900`
else
port=$disp
fi fi
# try to find an open listening port via netstat(1): # try to find an open listening port via netstat(1):
use="" use=""
inuse=""
if uname | grep Linux > /dev/null; then if uname | grep Linux > /dev/null; then
inuse=`netstat -ant | grep LISTEN | awk '{print $4}' | sed 's/^.*://'` inuse=`netstat -ant | grep LISTEN | awk '{print $4}' | sed 's/^.*://'`
elif uname | grep SunOS > /dev/null; then
inuse=`netstat -an -f inet -P tcp | grep LISTEN | awk '{print $1}' | sed 's/^.*\.//'`
fi
if [ "x$inuse" != "x" ]; then
try=5920 try=5920
while [ $try -lt 6000 ] while [ $try -lt 6000 ]
do do
...@@ -95,6 +114,145 @@ if [ "X$mycert" != "X" ]; then ...@@ -95,6 +114,145 @@ if [ "X$mycert" != "X" ]; then
cert="cert = $mycert" cert="cert = $mycert"
fi fi
pcode() {
tf=$1
SSL_VNC_PROXY=$proxy; export SSL_VNC_PROXY
SSL_VNC_DEST="$host:$port"; export SSL_VNC_DEST
cod='#!/usr/bin/perl
# A hack to glue stunnel to a Web proxy for client connections.
use IO::Socket::INET;
my ($first, $second) = split(/,/, $ENV{SSL_VNC_PROXY});
my ($proxy_host, $proxy_port) = split(/:/, $first);
my $connect = $ENV{SSL_VNC_DEST};
print STDERR "\nperl script for web proxing:\n";
print STDERR "proxy_host: $proxy_host\n";
print STDERR "proxy_port: $proxy_port\n";
print STDERR "proxy_connect: $connect\n";
my $sock = IO::Socket::INET->new(
PeerAddr => $proxy_host,
PeerPort => $proxy_port,
Proto => "tcp");
if (! $sock) {
unlink($0);
die "perl proxy: $!\n";
}
my $con = "";
if ($second ne "") {
$con = "CONNECT $second HTTP/1.1\r\n";
$con .= "Host: $second\r\n\r\n";
} else {
$con = "CONNECT $connect HTTP/1.1\r\n";
$con .= "Host: $connect\r\n\r\n";
}
print STDERR "proxy_request1:\n$con";
print $sock $con;
unlink($0);
my $rep = "";
while ($rep !~ /\r\n\r\n/) {
my $c = getc($sock);
print STDERR $c;
$rep .= $c;
}
if ($rep !~ m,HTTP/.* 200,) {
die "proxy error: $rep\n";
}
if ($second ne "") {
$con = "CONNECT $connect HTTP/1.1\r\n";
$con .= "Host: $connect\r\n\r\n";
print STDERR "proxy_request2:\n$con";
print $sock $con;
$rep = "";
while ($rep !~ /\r\n\r\n/) {
my $c = getc($sock);
print STDERR $c;
$rep .= $c;
}
if ($rep !~ m,HTTP/.* 200,) {
die "proxy error: $rep\n";
}
}
if (fork) {
print STDERR "parent\[$$] STDIN -> socket\n\n";
xfer(STDIN, $sock);
} else {
print STDERR "child \[$$] socket -> STDOUT\n\n";
xfer($sock, STDOUT);
}
exit;
sub xfer {
my($in, $out) = @_;
$RIN = $WIN = $EIN = "";
$ROUT = "";
vec($RIN, fileno($in), 1) = 1;
vec($WIN, fileno($in), 1) = 1;
$EIN = $RIN | $WIN;
while (1) {
my $nf = 0;
while (! $nf) {
$nf = select($ROUT=$RIN, undef, undef, undef);
}
my $len = sysread($in, $buf, 8192);
if (! defined($len)) {
next if $! =~ /^Interrupted/;
print STDERR "perl proxy\[$$]: $!\n";
last;
} elsif ($len == 0) {
print STDERR "perl proxy\[$$]: Input is EOF.\n";
last;
}
my $offset = 0;
my $quit = 0;
while ($len) {
my $written = syswrite($out, $buf, $len, $offset);
if (! defined $written) {
print STDERR "perl proxy\[$$]: Output is EOF. $!\n";
$quit = 1;
last;
}
$len -= $written;
$offset += $written;
}
last if $quit;
}
close($in);
close($out);
}
'
rm -f $tf
if [ -f $tf ]; then
echo "$tf still exists!"
exit 1
fi
echo "$cod" > $tf
chmod 700 $tf
}
ptmp=""
if [ "X$proxy" != "X" ]; then
ptmp="/tmp/ssl_vncviewer.$$.pl"
pcode $ptmp
connect="exec = $ptmp"
else
connect="connect = $host:$port"
fi
##debug = 7 ##debug = 7
tmp=/tmp/ssl_vncviewer.$$ tmp=/tmp/ssl_vncviewer.$$
cat > $tmp <<END cat > $tmp <<END
...@@ -106,12 +264,13 @@ $cert ...@@ -106,12 +264,13 @@ $cert
[vnc_stunnel] [vnc_stunnel]
accept = $use accept = $use
connect= $host:$port $connect
END END
echo "" echo ""
echo "Using this stunnel configuration:" echo "Using this stunnel configuration:"
cat $tmp echo ""
cat $tmp | uniq
echo "" echo ""
sleep 1 sleep 1
...@@ -140,3 +299,4 @@ else ...@@ -140,3 +299,4 @@ else
fi fi
kill $pid kill $pid
sleep 1
2006-04-16 Karl Runge <runge@karlrunge.com>
* x11vnc: More web proxy work for Java SSL applet and wrapper
script ssl_vncviewer. Apache SSL gateway support for
incoming x11vnc connections. Handle "double proxy" case.
2006-04-05 Karl Runge <runge@karlrunge.com> 2006-04-05 Karl Runge <runge@karlrunge.com>
* x11vnc: add FBPM support (-fbpm) for Suns. -rawfb ZERO for * x11vnc: add FBPM support (-fbpm) for Suns. -rawfb ZERO for
testing. Basic key+cert management utilities: -sslGenCA, testing. Basic key+cert management utilities: -sslGenCA,
......
This diff is collapsed.
...@@ -122,6 +122,11 @@ void clean_up_exit (int ret) { ...@@ -122,6 +122,11 @@ void clean_up_exit (int ret) {
/* remove the shm areas: */ /* remove the shm areas: */
clean_shm(0); clean_shm(0);
stop_stunnel();
if (use_openssl) {
ssl_helper_pid(0, 0); /* killall */
}
if (! dpy) exit(ret); /* raw_rb hack */ if (! dpy) exit(ret); /* raw_rb hack */
/* X keyboard cleanups */ /* X keyboard cleanups */
...@@ -139,11 +144,6 @@ void clean_up_exit (int ret) { ...@@ -139,11 +144,6 @@ void clean_up_exit (int ret) {
if (use_solid_bg) { if (use_solid_bg) {
solid_bg(1); solid_bg(1);
} }
stop_stunnel();
if (use_openssl) {
ssl_helper_pid(0, 0); /* killall */
}
X_LOCK; X_LOCK;
XTestDiscard_wr(dpy); XTestDiscard_wr(dpy);
#if LIBVNCSERVER_HAVE_LIBXDAMAGE #if LIBVNCSERVER_HAVE_LIBXDAMAGE
......
...@@ -632,10 +632,8 @@ void print_help(int mode) { ...@@ -632,10 +632,8 @@ void print_help(int mode) {
" filesystem to prevent network snooping (for example\n" " filesystem to prevent network snooping (for example\n"
" -ssldir /var/lib/x11vnc-certs).\n" " -ssldir /var/lib/x11vnc-certs).\n"
"\n" "\n"
" -ssldir effects the other -ssl* options. In the case\n" " -ssldir affects nearly all of the other -ssl* options,\n"
" of maintenance commands where the VNC server is not run\n" " e.g. -ssl SAVE, -sslGenCert, etc..\n"
" (e.g. -sslGenCA), the -ssldir option must precede the\n"
" command. E.g. x11vnc -ssldir ~/mydir -sslCertInfo LIST\n"
"\n" "\n"
"-sslverify [path] For either of the -ssl or -stunnel modes, use [path]\n" "-sslverify [path] For either of the -ssl or -stunnel modes, use [path]\n"
" to provide certificates to authenticate incoming VNC\n" " to provide certificates to authenticate incoming VNC\n"
......
...@@ -51,7 +51,7 @@ void check_stunnel(void) { ...@@ -51,7 +51,7 @@ void check_stunnel(void) {
int start_stunnel(int stunnel_port, int x11vnc_port) { int start_stunnel(int stunnel_port, int x11vnc_port) {
#ifdef SSLCMDS #ifdef SSLCMDS
char extra[] = ":/usr/sbin:/usr/local/sbin"; char extra[] = ":/usr/sbin:/usr/local/sbin:/dist/sbin";
char *path, *p, *exe; char *path, *p, *exe;
char *stunnel_path = NULL; char *stunnel_path = NULL;
struct stat verify_buf; struct stat verify_buf;
...@@ -119,6 +119,15 @@ int start_stunnel(int stunnel_port, int x11vnc_port) { ...@@ -119,6 +119,15 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
stunnel_port, x11vnc_port); stunnel_port, x11vnc_port);
} }
if (stunnel_pem && strstr(stunnel_pem, "SAVE") == stunnel_pem) {
stunnel_pem = get_saved_pem(stunnel_pem, 1);
if (! stunnel_pem) {
rfbLog("start_stunnel: could not create or open"
" saved PEM:\n", stunnel_pem);
clean_up_exit(1);
}
}
if (ssl_verify) { if (ssl_verify) {
if (stat(ssl_verify, &verify_buf) != 0) { if (stat(ssl_verify, &verify_buf) != 0) {
rfbLog("stunnel: %s does not exist.\n", ssl_verify); rfbLog("stunnel: %s does not exist.\n", ssl_verify);
...@@ -510,30 +519,30 @@ void sslEncKey(char *path, int mode) { ...@@ -510,30 +519,30 @@ void sslEncKey(char *path, int mode) {
sprintf(tca, "%s/CA/cacert.pem", cdir); sprintf(tca, "%s/CA/cacert.pem", cdir);
path = tca; path = tca;
} else if (info_only && (!strcasecmp(path, "LIST") || } else if (info_only && (!strcasecmp(path, "LIST") || !strcasecmp(path, "LS") ||
!strcasecmp(path, "ALL"))) { !strcasecmp(path, "ALL"))) {
if (! cdir || strchr(cdir, '\'')) { if (! cdir || strchr(cdir, '\'')) {
fprintf(stderr, "bad certdir char: %s\n", cdir ? cdir : "null"); fprintf(stderr, "bad certdir char: %s\n", cdir ? cdir : "null");
exit(1); exit(1);
} }
tca = (char *) malloc(2*strlen(cdir) + strlen(program_name) + 1000); tca = (char *) malloc(2*strlen(cdir) + strlen(program_name) + 1000);
sprintf(tca, "find '%s' -type f | egrep '\\.(crt|pem|key|req)$' " sprintf(tca, "find '%s' | egrep '/(CA|tmp|clients)$|\\.(crt|pem|key|req)$' "
"| grep -v CA/newcerts", cdir); "| grep -v CA/newcerts", cdir);
if (!strcasecmp(path, "ALL")) { if (!strcasecmp(path, "ALL")) {
/* ugh.. */ /* ugh.. */
strcat(tca, " | grep -v private/cakey.pem | xargs -n1 "); strcat(tca, " | egrep -v 'private/cakey.pem|(CA|tmp|clients)$' | xargs -n1 ");
strcat(tca, program_name); strcat(tca, program_name);
strcat(tca, " -ssldir '"); strcat(tca, " -ssldir '");
strcat(tca, cdir); strcat(tca, cdir);
strcat(tca, "' -sslCertInfo 2>&1 "); strcat(tca, "' -sslCertInfo 2>&1 ");
} else if (listlong) { } else if (listlong) {
strcat(tca, " | xargs ls -l "); strcat(tca, " | xargs ls -ld ");
} }
system(tca); system(tca);
return; return;
} else if (info_only && (!strcasecmp(path, "HASHON") || } else if (info_only && (!strcasecmp(path, "HASHON")
!strcasecmp(path, "HASHOFF"))) { || !strcasecmp(path, "HASHOFF"))) {
tmp_fd = mkstemp(tmp); tmp_fd = mkstemp(tmp);
if (tmp_fd < 0) { if (tmp_fd < 0) {
......
...@@ -122,7 +122,9 @@ char *get_saved_pem(char *save, int create) { ...@@ -122,7 +122,9 @@ char *get_saved_pem(char *save, int create) {
char *new = NULL; char *new = NULL;
if (create) { if (create) {
new = create_tmp_pem(path, prompt); new = create_tmp_pem(path, prompt);
sslEncKey(new, 0); if (! getenv("X11VNC_SSL_NO_PASSPHRASE") && ! inetd) {
sslEncKey(new, 0);
}
} }
return new; return new;
} else { } else {
...@@ -977,6 +979,11 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get, ...@@ -977,6 +979,11 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
int nfd, db = 0; int nfd, db = 0;
struct timeval tv; struct timeval tv;
fd_set rd; fd_set rd;
if (getenv("ACCEPT_OPENSSL_DEBUG")) {
db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
}
/* /*
* we'll do a select() on s_in for reading. this is not an * we'll do a select() on s_in for reading. this is not an
* absolute proof that SSL_read is ready (XXX use SSL utility). * absolute proof that SSL_read is ready (XXX use SSL utility).
...@@ -984,6 +991,7 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get, ...@@ -984,6 +991,7 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
tv.tv_sec = 2; tv.tv_sec = 2;
tv.tv_usec = 0; tv.tv_usec = 0;
if (mode == OPENSSL_INETD) { if (mode == OPENSSL_INETD) {
/* /*
* https via inetd is icky because x11vnc is restarted * https via inetd is icky because x11vnc is restarted
...@@ -1003,7 +1011,7 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get, ...@@ -1003,7 +1011,7 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
tv.tv_sec = 4; tv.tv_sec = 4;
} }
} }
if (1) fprintf(stderr, "tv_sec: %d - %s\n", (int) tv.tv_sec, last_get); if (db) fprintf(stderr, "tv_sec: %d - %s\n", (int) tv.tv_sec, last_get);
FD_ZERO(&rd); FD_ZERO(&rd);
FD_SET(s_in, &rd); FD_SET(s_in, &rd);
...@@ -1024,7 +1032,7 @@ if (1) fprintf(stderr, "tv_sec: %d - %s\n", (int) tv.tv_sec, last_get); ...@@ -1024,7 +1032,7 @@ if (1) fprintf(stderr, "tv_sec: %d - %s\n", (int) tv.tv_sec, last_get);
static int watch_for_http_traffic(char *buf_a, int *n_a) { static int watch_for_http_traffic(char *buf_a, int *n_a) {
int is_http, err, n, n2; int is_http, err, n, n2;
char *buf; char *buf;
int db = 1; int db = 0;
/* /*
* sniff the first couple bytes of the stream and try to see * sniff the first couple bytes of the stream and try to see
* if it is http or not. if we read them OK, we must read the * if it is http or not. if we read them OK, we must read the
...@@ -1032,6 +1040,9 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) { ...@@ -1032,6 +1040,9 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
* what has be read is returned in buf_a and n_a. * what has be read is returned in buf_a and n_a.
* *buf_a is BSIZE+1 long and zeroed. * *buf_a is BSIZE+1 long and zeroed.
*/ */
if (getenv("ACCEPT_OPENSSL_DEBUG")) {
db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
}
buf = (char *) calloc(sizeof(BSIZE+1), 1); buf = (char *) calloc(sizeof(BSIZE+1), 1);
*n_a = 0; *n_a = 0;
...@@ -1076,6 +1087,7 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) { ...@@ -1076,6 +1087,7 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
} }
static int csock_timeout_sock = -1; static int csock_timeout_sock = -1;
static void csock_timeout (int sig) { static void csock_timeout (int sig) {
rfbLog("sig: %d, csock_timeout.\n", sig); rfbLog("sig: %d, csock_timeout.\n", sig);
if (csock_timeout_sock >= 0) { if (csock_timeout_sock >= 0) {
...@@ -1114,6 +1126,10 @@ int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie, ...@@ -1114,6 +1126,10 @@ int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie,
rfbLog("SSL: accept_openssl: detected https proxied connection" rfbLog("SSL: accept_openssl: detected https proxied connection"
" request.\n"); " request.\n");
if (getenv("ACCEPT_OPENSSL_DEBUG")) {
db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
}
SSL_write(ssl, reply0, strlen(reply0)); SSL_write(ssl, reply0, strlen(reply0));
SSL_shutdown(ssl); SSL_shutdown(ssl);
SSL_shutdown(ssl); SSL_shutdown(ssl);
...@@ -1192,6 +1208,10 @@ void accept_openssl(int mode) { ...@@ -1192,6 +1208,10 @@ void accept_openssl(int mode) {
} }
first = 0; first = 0;
if (getenv("ACCEPT_OPENSSL_DEBUG")) {
db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
}
/* do INETD, VNC, or HTTPS cases (result is client socket or pipe) */ /* do INETD, VNC, or HTTPS cases (result is client socket or pipe) */
if (mode == OPENSSL_INETD) { if (mode == OPENSSL_INETD) {
ssl_initialized = 1; ssl_initialized = 1;
...@@ -1314,7 +1334,8 @@ void accept_openssl(int mode) { ...@@ -1314,7 +1334,8 @@ void accept_openssl(int mode) {
/* now connect back to parent socket: */ /* now connect back to parent socket: */
vncsock = rfbConnectToTcpAddr("127.0.0.1", cport); vncsock = rfbConnectToTcpAddr("127.0.0.1", cport);
if (vncsock < 0) { if (vncsock < 0) {
rfbLog("SSL: ssl_helper: could not connect back to: %d\n", cport); rfbLog("SSL: ssl_helper[%d]: could not connect"
" back to: %d\n", getpid(), cport);
close(vncsock); close(vncsock);
exit(1); exit(1);
} }
...@@ -1327,6 +1348,7 @@ void accept_openssl(int mode) { ...@@ -1327,6 +1348,7 @@ void accept_openssl(int mode) {
} else { } else {
s_in = s_out = sock; s_in = s_out = sock;
} }
if (! ssl_init(s_in, s_out)) { if (! ssl_init(s_in, s_out)) {
close(vncsock); close(vncsock);
exit(1); exit(1);
...@@ -1342,8 +1364,8 @@ void accept_openssl(int mode) { ...@@ -1342,8 +1364,8 @@ void accept_openssl(int mode) {
have_httpd = 1; have_httpd = 1;
} }
if (mode == OPENSSL_HTTPS && ! have_httpd) { if (mode == OPENSSL_HTTPS && ! have_httpd) {
rfbLog("SSL: accept_openssl: no httpd socket for " rfbLog("SSL: accept_openssl[%d]: no httpd socket for "
"-https mode\n"); "-https mode\n", getpid());
close(vncsock); close(vncsock);
exit(1); exit(1);
} }
...@@ -1371,7 +1393,6 @@ void accept_openssl(int mode) { ...@@ -1371,7 +1393,6 @@ void accept_openssl(int mode) {
* Check if there is stuff to read from remote end * Check if there is stuff to read from remote end
* if so it is likely a GET or HEAD. * if so it is likely a GET or HEAD.
*/ */
if (1) fprintf(stderr, "is_ssl_readable\n");
if (! is_ssl_readable(s_in, last_https, last_get, if (! is_ssl_readable(s_in, last_https, last_get,
mode)) { mode)) {
goto write_cookie; goto write_cookie;
...@@ -1384,7 +1405,7 @@ void accept_openssl(int mode) { ...@@ -1384,7 +1405,7 @@ void accept_openssl(int mode) {
* is ever sent. So often we timeout here. * is ever sent. So often we timeout here.
*/ */
if (1) fprintf(stderr, "watch_for_http_traffic\n"); if (db) fprintf(stderr, "watch_for_http_traffic\n");
is_http = watch_for_http_traffic(buf, &n); is_http = watch_for_http_traffic(buf, &n);
if (is_http < 0 || is_http == 0) { if (is_http < 0 || is_http == 0) {
...@@ -1392,27 +1413,47 @@ void accept_openssl(int mode) { ...@@ -1392,27 +1413,47 @@ void accept_openssl(int mode) {
* error or http not detected, fall back * error or http not detected, fall back
* to normal VNC socket. * to normal VNC socket.
*/ */
if (db) fprintf(stderr, "is_http err: %d n: %d\n", is_http, n);
write(vncsock, cookie, strlen(cookie)); write(vncsock, cookie, strlen(cookie));
if (n > 0) { if (n > 0) {
write(vncsock, buf, n); write(vncsock, buf, n);
} }
goto wrote_cookie; goto wrote_cookie;
} }
if (1) fprintf(stderr, "buf: '%s'\n", buf); if (db) fprintf(stderr, "is_http: %d n: %d\n", is_http, n);
if (db) fprintf(stderr, "buf: '%s'\n", buf);
if (strstr(buf, "/request.https.proxy.connection")) { if (strstr(buf, "/request.https.vnc.connection")) {
char reply[] = "HTTP/1.0 200 OK\r\n"
"Content-Type: octet-stream\r\n"
"Connection: Keep-Alive\r\n"
"Pragma: no-cache\r\n\r\n";
/* /*
* special case proxy coming thru https * special case proxy coming thru https
* instead of a direct SSL connection. * instead of a direct SSL connection.
*/ */
if (! proxy_hack(vncsock, listen, s_in, s_out, rfbLog("Handling VNC request via https GET. [%d]\n", getpid());
cookie, mode)) { if (strstr(buf, "/reverse.proxy")) {
strcpy(tbuf, uniq); char *buf;
strcat(tbuf, cookie); int n, ptr;
write(vncsock, tbuf, strlen(tbuf)); SSL_write(ssl, reply, strlen(reply));
close(vncsock);
buf = (char *) calloc((8192+1), 1);
n = 0;
ptr = 0;
while (ptr < 8192) {
n = SSL_read(ssl, buf + ptr, 1);
if (n > 0) {
ptr += n;
}
if (db) fprintf(stderr, "buf2: '%s'\n", buf);
if (strstr(buf, "\r\n\r\n")) {
break;
}
}
} }
exit(0); goto write_cookie;
} else if (strstr(buf, "/check.https.proxy.connection")) { } else if (strstr(buf, "/check.https.proxy.connection")) {
char reply[] = "HTTP/1.0 200 OK\r\n" char reply[] = "HTTP/1.0 200 OK\r\n"
...@@ -1491,7 +1532,8 @@ if (db) fprintf(stderr, "iface: %s\n", iface); ...@@ -1491,7 +1532,8 @@ if (db) fprintf(stderr, "iface: %s\n", iface);
rfbLog("Could not connect to httpd socket!\n"); rfbLog("Could not connect to httpd socket!\n");
exit(1); exit(1);
} }
if (db) fprintf(stderr, "ssl_helper: httpsock: %d %d\n", httpsock, n); if (db) fprintf(stderr, "ssl_helper[%d]: httpsock: %d %d\n",
getpid(), httpsock, n);
/* /*
* send what we read to httpd, and then connect * send what we read to httpd, and then connect
...@@ -1651,11 +1693,14 @@ static void ssl_timeout (int sig) { ...@@ -1651,11 +1693,14 @@ static void ssl_timeout (int sig) {
static int ssl_init(int s_in, int s_out) { static int ssl_init(int s_in, int s_out) {
unsigned char *sid = (unsigned char *) "x11vnc SID"; unsigned char *sid = (unsigned char *) "x11vnc SID";
char *name; char *name;
int db = 1, rc, err; int db = 0, rc, err;
int ssock = s_in; int ssock = s_in;
double start = dnow(); double start = dnow();
int timeout = 20; int timeout = 20;
if (getenv("SSL_DEBUG")) {
db = atoi(getenv("SSL_DEBUG"));
}
if (db) fprintf(stderr, "ssl_init: %d/%d\n", s_in, s_out); if (db) fprintf(stderr, "ssl_init: %d/%d\n", s_in, s_out);
ssl = SSL_new(ctx); ssl = SSL_new(ctx);
...@@ -1749,7 +1794,7 @@ if (db > 1) fprintf(stderr, "d\n"); ...@@ -1749,7 +1794,7 @@ if (db > 1) fprintf(stderr, "d\n");
usleep(10 * 1000); usleep(10 * 1000);
} }
rfbLog("SSL: ssl_helper: SSL_accept() succeeded for: %s\n", name); rfbLog("SSL: ssl_helper[%d]: SSL_accept() succeeded for: %s\n", getpid(), name);
free(name); free(name);
return 1; return 1;
...@@ -1816,14 +1861,39 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { ...@@ -1816,14 +1861,39 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) {
int cptr, sptr, c_rd, c_wr, s_rd, s_wr; int cptr, sptr, c_rd, c_wr, s_rd, s_wr;
fd_set rd, wr; fd_set rd, wr;
struct timeval tv; struct timeval tv;
int ssock; int ssock, cnt = 0;
/*
* we want to switch to a longer timeout for long term VNC
* connections (in case the network is not working for short
* periods), but we also want the timeout shorter at the beginning
* in case the client went away.
*/
time_t start;
int tv_https_early = 60;
int tv_https_later = 20;
int tv_vnc_early = 25;
int tv_vnc_later = 300;
int tv_cutover = 120;
int tv_use;
if (dbxfer) { if (dbxfer) {
raw_xfer(csock, s_in, s_out); raw_xfer(csock, s_in, s_out);
return; return;
} }
if (getenv("SSL_DEBUG")) {
db = atoi(getenv("SSL_DEBUG"));
}
if (db) fprintf(stderr, "ssl_xfer begin\n");
if (db) fprintf(stderr, "ssl_xfer begin\n"); start = time(0);
if (is_https) {
tv_use = tv_https_early;
} else {
tv_use = tv_vnc_early;
}
/* /*
* csock: clear text socket with libvncserver. "C" * csock: clear text socket with libvncserver. "C"
...@@ -1890,6 +1960,7 @@ if (db) fprintf(stderr, "ssl_xfer begin\n"); ...@@ -1890,6 +1960,7 @@ if (db) fprintf(stderr, "ssl_xfer begin\n");
*/ */
break; break;
} }
cnt++;
/* set up the fd sets for the two sockets for read & write: */ /* set up the fd sets for the two sockets for read & write: */
...@@ -1927,11 +1998,15 @@ if (db) fprintf(stderr, "ssl_xfer begin\n"); ...@@ -1927,11 +1998,15 @@ if (db) fprintf(stderr, "ssl_xfer begin\n");
} }
} }
if (is_https) { if (tv_cutover && time(0) > start + tv_cutover) {
tv.tv_sec = 50; tv_cutover = 0;
} else { if (is_https) {
tv.tv_sec = 35; tv_use = tv_https_later;
} else {
tv_use = tv_vnc_later;
}
} }
tv.tv_sec = tv_use;
tv.tv_usec = 0; tv.tv_usec = 0;
/* do the select, repeat if interrupted */ /* do the select, repeat if interrupted */
...@@ -1939,7 +2014,7 @@ if (db) fprintf(stderr, "ssl_xfer begin\n"); ...@@ -1939,7 +2014,7 @@ if (db) fprintf(stderr, "ssl_xfer begin\n");
nfd = select(fdmax+1, &rd, &wr, NULL, &tv); nfd = select(fdmax+1, &rd, &wr, NULL, &tv);
} while (nfd < 0 && errno == EINTR); } while (nfd < 0 && errno == EINTR);
if (db) fprintf(stderr, "nfd: %d\n", nfd); if (db > 1) fprintf(stderr, "nfd: %d\n", nfd);
if (nfd < 0) { if (nfd < 0) {
rfbLog("SSL: ssl_xfer[%d]: select error: %d\n", getpid(), nfd); rfbLog("SSL: ssl_xfer[%d]: select error: %d\n", getpid(), nfd);
......
...@@ -267,15 +267,20 @@ char genCert[] = ...@@ -267,15 +267,20 @@ char genCert[] =
"\n" "\n"
"direrror() {\n" "direrror() {\n"
" echo \"\"\n" " echo \"\"\n"
" echo \"You need first to run:\"\n"
" echo \"\"\n"
" if echo \"$DIR\" | grep '/\\.vnc/certs' > /dev/null; then\n" " if echo \"$DIR\" | grep '/\\.vnc/certs' > /dev/null; then\n"
" echo \"You need first to run: x11vnc -sslGenCA\"\n" " echo \" x11vnc -sslGenCA\"\n"
" else\n" " else\n"
" echo \"You need first to run: x11vnc -sslGenCA $DIR\"\n" " echo \" x11vnc -sslGenCA $DIR\"\n"
" fi\n" " fi\n"
" echo \"\"\n"
" echo \"to create the CA cert file and other needed config files and directories.\"\n" " echo \"to create the CA cert file and other needed config files and directories.\"\n"
" echo \"\"\n" " echo \"\"\n"
" echo \"Then you can run: x11vnc -sslGenCert $type $name0\"\n"
" echo \"\"\n"
" if [ \"X$1\" != \"X\" ]; then\n" " if [ \"X$1\" != \"X\" ]; then\n"
" echo \"(missing: $1)\"\n" " echo \"(missing file/dir: $1)\"\n"
" echo \"\"\n" " echo \"\"\n"
" fi\n" " fi\n"
" exit 1\n" " exit 1\n"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
.TH X11VNC "1" "April 2006" "x11vnc " "User Commands" .TH X11VNC "1" "April 2006" "x11vnc " "User Commands"
.SH NAME .SH NAME
x11vnc - allow VNC connections to real X11 displays x11vnc - allow VNC connections to real X11 displays
version: 0.8.1, lastmod: 2006-04-05 version: 0.8.1, lastmod: 2006-04-16
.SH SYNOPSIS .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [OPTION]...
...@@ -755,10 +755,8 @@ might want your certificates and keys to be on a local ...@@ -755,10 +755,8 @@ might want your certificates and keys to be on a local
filesystem to prevent network snooping (for example filesystem to prevent network snooping (for example
\fB-ssldir\fR /var/lib/x11vnc-certs). \fB-ssldir\fR /var/lib/x11vnc-certs).
.IP .IP
\fB-ssldir\fR effects the other \fB-ssl*\fR options. In the case \fB-ssldir\fR affects nearly all of the other \fB-ssl*\fR options,
of maintenance commands where the VNC server is not run e.g. \fB-ssl\fR SAVE, \fB-sslGenCert,\fR etc..
(e.g. \fB-sslGenCA),\fR the \fB-ssldir\fR option must precede the
command. E.g. x11vnc \fB-ssldir\fR ~/mydir \fB-sslCertInfo\fR LIST
.PP .PP
\fB-sslverify\fR \fI[path]\fR \fB-sslverify\fR \fI[path]\fR
.IP .IP
......
...@@ -1439,6 +1439,21 @@ int main(int argc, char* argv[]) { ...@@ -1439,6 +1439,21 @@ int main(int argc, char* argv[]) {
exit(1); \ exit(1); \
} }
/*
* do a quick check for parameters that apply to "utility"
* commands, i.e. ones that do not run the server.
*/
for (i=1; i < argc; i++) {
arg = argv[i];
if (strstr(arg, "--") == arg) {
arg++;
}
if (!strcmp(arg, "-ssldir")) {
CHECK_ARGC
ssl_certs_dir = strdup(argv[++i]);
}
}
for (i=1; i < argc; i++) { for (i=1; i < argc; i++) {
/* quick-n-dirty --option handling. */ /* quick-n-dirty --option handling. */
arg = argv[i]; arg = argv[i];
......
...@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0; ...@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0; int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */ /* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.8.1 lastmod: 2006-04-05"; char lastmod[] = "0.8.1 lastmod: 2006-04-16";
/* X display info */ /* X display info */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment