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
...@@ -38,34 +38,43 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile ...@@ -38,34 +38,43 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile
@$(ExportJavaClasses) @$(ExportJavaClasses)
diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto.java diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto.java
--- vnc_javasrc.orig/RfbProto.java 2004-03-04 08:34:25.000000000 -0500 --- vnc_javasrc.orig/RfbProto.java 2004-03-04 08:34:25.000000000 -0500
+++ vnc_javasrc/RfbProto.java 2006-04-03 11:22:30.000000000 -0400 +++ vnc_javasrc/RfbProto.java 2006-04-16 11:17:37.000000000 -0400
@@ -199,7 +199,21 @@ @@ -199,7 +199,21 @@
host = h; host = h;
port = p; port = p;
- if (viewer.socketFactory == null) { - if (viewer.socketFactory == null) {
+ if (! viewer.disableSSL) { + if (! viewer.disableSSL) {
+ System.out.println("new SSLSocketToMe"); + System.out.println("new SSLSocketToMe");
+ SSLSocketToMe ssl; + SSLSocketToMe ssl;
+ try { + try {
+ ssl = new SSLSocketToMe(host, port, v); + ssl = new SSLSocketToMe(host, port, v);
+ } catch (Exception e) { + } catch (Exception e) {
+ throw new IOException(e.getMessage()); + throw new IOException(e.getMessage());
+ } + }
+ +
+ try { + try {
+ sock = ssl.connectSock(); + sock = ssl.connectSock();
+ } catch (Exception es) { + } catch (Exception es) {
+ throw new IOException(es.getMessage()); + throw new IOException(es.getMessage());
+ } + }
+ } else if (viewer.socketFactory == null) { + } else if (viewer.socketFactory == null) {
sock = new Socket(host, port); sock = new Socket(host, port);
} else { } else {
try { try {
@@ -255,7 +269,7 @@
|| (b[10] < '0') || (b[10] > '9') || (b[11] != '\n'))
{
throw new Exception("Host " + host + " port " + port +
- " is not an RFB server");
+ " is not an RFB server: " + b);
}
serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java
--- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 --- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500
+++ vnc_javasrc/SSLSocketToMe.java 2006-04-04 13:17:39.000000000 -0400 +++ vnc_javasrc/SSLSocketToMe.java 2006-04-16 11:21:30.000000000 -0400
@@ -0,0 +1,1040 @@ @@ -0,0 +1,1204 @@
+/* +/*
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
+ * + *
...@@ -111,10 +120,14 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -111,10 +120,14 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ +
+ /* fallback for Proxy connection */ + /* fallback for Proxy connection */
+ boolean proxy_in_use = false; + boolean proxy_in_use = false;
+ boolean proxy_is_https = false;
+ boolean proxy_failure = false; + boolean proxy_failure = false;
+ public DataInputStream is = null; + public DataInputStream is = null;
+ public OutputStream os = null; + public OutputStream os = null;
+ +
+ String proxy_dialog_host = null;
+ int proxy_dialog_port = 0;
+
+ Socket proxySock; + Socket proxySock;
+ DataInputStream proxy_is; + DataInputStream proxy_is;
+ OutputStream proxy_os; + OutputStream proxy_os;
...@@ -149,7 +162,6 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -149,7 +162,6 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ +
+ /* create trust managers used if initial handshake fails: */ + /* create trust managers used if initial handshake fails: */
+ +
+
+ trustAllCerts = new TrustManager[] { + trustAllCerts = new TrustManager[] {
+ /* + /*
+ * this one accepts everything. + * this one accepts everything.
...@@ -349,15 +361,17 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -349,15 +361,17 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ return false; + return false;
+ } + }
+ +
+ public Socket connectSock() throws IOException { + public void check_for_proxy() {
+
+ boolean result = false;
+ String ustr = "https://" + host + ":" + port;
+ ustr += viewer.urlPrefix + "/check.https.proxy.connection";
+
+ trusturlCerts = null;
+ proxy_in_use = false;
+ +
+ /*
+ * first try a https connection to detect a proxy, and
+ * also grab the VNC server cert.
+ */
+ URL url = new URL("https://" + host + ":" + port +
+ "/check.https.proxy.connection");
+ try { + try {
+ URL url = new URL(ustr);
+ HttpsURLConnection https = (HttpsURLConnection) + HttpsURLConnection https = (HttpsURLConnection)
+ url.openConnection(); + url.openConnection();
+ +
...@@ -374,15 +388,59 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -374,15 +388,59 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ +
+ if (https.usingProxy()) { + if (https.usingProxy()) {
+ proxy_in_use = true; + proxy_in_use = true;
+ proxy_is_https = true;
+ dbg("HTTPS proxy in use. There may be connection problems."); + dbg("HTTPS proxy in use. There may be connection problems.");
+ } + }
+ Object output = https.getContent(); + Object output = https.getContent();
+ https.disconnect(); + https.disconnect();
+ result = true;
+
+ } catch(Exception e) {
+ dbg("HttpsURLConnection: " + e.getMessage());
+ }
+
+ if (proxy_in_use) {
+ return;
+ }
+
+ ustr = "http://" + host + ":" + port;
+ ustr += viewer.urlPrefix + "/index.vnc";
+
+ try {
+ URL url = new URL(ustr);
+ HttpURLConnection http = (HttpURLConnection)
+ url.openConnection();
+
+ http.setUseCaches(false);
+ http.setRequestMethod("GET");
+ http.setRequestProperty("Pragma", "No-Cache");
+ http.setRequestProperty("Proxy-Connection",
+ "Keep-Alive");
+ http.setDoInput(true);
+
+ http.connect();
+
+ if (http.usingProxy()) {
+ proxy_in_use = true;
+ proxy_is_https = false;
+ dbg("HTTP proxy in use. There may be connection problems.");
+ }
+ Object output = http.getContent();
+ http.disconnect();
+ +
+ } catch(Exception e) { + } catch(Exception e) {
+ trusturlCerts = null; + dbg("HttpURLConnection: " + e.getMessage());
+ } + }
+ }
+ +
+ public Socket connectSock() throws IOException {
+
+ /*
+ * first try a https connection to detect a proxy, and
+ * also grab the VNC server cert.
+ */
+ check_for_proxy();
+
+ if (use_url_cert_for_auth && trusturlCerts != null) { + if (use_url_cert_for_auth && trusturlCerts != null) {
+ factory = trusturl_ctx.getSocketFactory(); + factory = trusturl_ctx.getSocketFactory();
+ } else { + } else {
...@@ -391,11 +449,23 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -391,11 +449,23 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ +
+ socket = null; + socket = null;
+ try { + try {
+ if (proxy_in_use && viewer.forceProxy) {
+ throw new Exception("forcing proxy (forceProxy)");
+ } else if (viewer.CONNECT != null) {
+ throw new Exception("forcing CONNECT");
+ }
+
+ socket = (SSLSocket) factory.createSocket(host, port); + socket = (SSLSocket) factory.createSocket(host, port);
+
+ } catch (Exception esock) { + } catch (Exception esock) {
+ if (proxy_in_use) { + dbg("esock: " + esock.getMessage());
+ if (proxy_in_use || viewer.CONNECT != null) {
+ proxy_failure = true; + proxy_failure = true;
+ dbg("HTTPS proxy in use. Trying to go with it."); + if (proxy_in_use) {
+ dbg("HTTPS proxy in use. Trying to go with it.");
+ } else {
+ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it.");
+ }
+ try { + try {
+ socket = proxy_socket(factory); + socket = proxy_socket(factory);
+ } catch (Exception e) { + } catch (Exception e) {
...@@ -522,6 +592,31 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -522,6 +592,31 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ } + }
+ } + }
+ +
+ if (socket != null && viewer.GET != null) {
+ String str = "GET ";
+ str += viewer.urlPrefix;
+ str += "/request.https.vnc.connection";
+ str += " HTTP/1.0\r\n";
+ str += "Pragma: No-Cache\r\n";
+ str += "\r\n";
+ System.out.println("sending GET: " + str);
+ OutputStream os = socket.getOutputStream();
+ os.write(str.getBytes());
+ os.flush();
+ if (false) {
+ String rep = "";
+ DataInputStream is = new DataInputStream(
+ new BufferedInputStream(socket.getInputStream(), 16384));
+ while (true) {
+ rep += readline(is);
+ if (rep.indexOf("\r\n\r\n") >= 0) {
+ break;
+ }
+ }
+ System.out.println("rep: " + rep);
+ }
+ }
+
+ dbg("SSL returning socket to caller."); + dbg("SSL returning socket to caller.");
+ return (Socket) socket; + return (Socket) socket;
+ } + }
...@@ -532,10 +627,24 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -532,10 +627,24 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ } + }
+ } + }
+ +
+ private int gint(String s) {
+ int n = -1;
+ try {
+ Integer I = new Integer(s);
+ n = I.intValue();
+ } catch (Exception ex) {
+ return -1;
+ }
+ return n;
+ }
+
+ public SSLSocket proxy_socket(SSLSocketFactory factory) { + public SSLSocket proxy_socket(SSLSocketFactory factory) {
+ Properties props = null; + Properties props = null;
+ String proxyHost = null; + String proxyHost = null;
+ int proxyPort = 0; + int proxyPort = 0;
+ String proxyHost_nossl = null;
+ int proxyPort_nossl = 0;
+ String str;
+ +
+ /* see if we can guess the proxy info from Properties: */ + /* see if we can guess the proxy info from Properties: */
+ try { + try {
...@@ -548,16 +657,33 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -548,16 +657,33 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ props.list(System.out); + props.list(System.out);
+ dbg("\n---------------\n\n"); + dbg("\n---------------\n\n");
+ +
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { + for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) {
+ String s = (String) e.nextElement(); + String s = (String) e.nextElement();
+ String v = System.getProperty(s); + String v = System.getProperty(s);
+ String l1 = s.toLowerCase(); + String s2 = s.toLowerCase();
+ String l2 = v.toLowerCase(); + String v2 = v.toLowerCase();
+ +
+ if (l1.indexOf("proxy") < 0 && l2.indexOf("proxy") < 0) { + if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) {
+ continue; + continue;
+ } + }
+ if (l2.indexOf("https") < 0) { + if (v2.indexOf("https") < 0) {
+ continue;
+ }
+
+ if (s2.indexOf("proxy.https.host") >= 0) {
+ proxyHost = v2;
+ continue;
+ }
+ if (s2.indexOf("proxy.https.port") >= 0) {
+ proxyPort = gint(v2);
+ continue;
+ }
+ if (s2.indexOf("proxy.http.host") >= 0) {
+ proxyHost_nossl = v2;
+ continue;
+ }
+ if (s2.indexOf("proxy.http.port") >= 0) {
+ proxyPort_nossl = gint(v2);
+ continue; + continue;
+ } + }
+ +
...@@ -578,10 +704,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -578,10 +704,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ continue; + continue;
+ } + }
+ if (hp[0].length() > 1 && hp[1].length() > 1) { + if (hp[0].length() > 1 && hp[1].length() > 1) {
+ try { +
+ Integer I = new Integer(hp[1]); + proxyPort = gint(hp[1]);
+ proxyPort = I.intValue(); + if (proxyPort < 0) {
+ } catch (Exception ex) {
+ continue; + continue;
+ } + }
+ proxyHost = new String(hp[0]); + proxyHost = new String(hp[0]);
...@@ -591,65 +716,113 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -591,65 +716,113 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ } + }
+ } + }
+ if (proxyHost != null) { + if (proxyHost != null) {
+ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); + if (proxyHost_nossl != null && proxyPort_nossl > 0) {
+ } else { + dbg("Using http proxy info instead of https.");
+ /* ask user to help us: */ + proxyHost = proxyHost_nossl;
+ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); + proxyPort = proxyPort_nossl;
+ pd.queryUser(); + }
+ proxyHost = pd.getHost();
+ proxyPort = pd.getPort();
+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort());
+ } + }
+ +
+ proxySock = psocket(proxyHost, proxyPort); + if (proxy_in_use) {
+ if (proxySock == null) { + if (proxy_dialog_host != null && proxy_dialog_port > 0) {
+ dbg("1 sadly, returning a null socket"); + proxyHost = proxy_dialog_host;
+ return null; + proxyPort = proxy_dialog_port;
+ } + }
+ String hp = host + ":" + port; + if (proxyHost != null) {
+ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort);
+ } else {
+ /* ask user to help us: */
+ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort);
+ pd.queryUser();
+ proxyHost = pd.getHost();
+ proxyPort = pd.getPort();
+ proxy_dialog_host = new String(proxyHost);
+ proxy_dialog_port = proxyPort;
+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort());
+ }
+ +
+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" + dbg("proxy_in_use psocket:");
+ + "Host: " + hp + "\r\n\r\n"; + proxySock = psocket(proxyHost, proxyPort);
+ if (proxySock == null) {
+ dbg("1-a sadly, returning a null socket");
+ return null;
+ }
+ String hp = host + ":" + port;
+ +
+ /* not working for SSL yet: */ + String req1 = "CONNECT " + hp + " HTTP/1.1\r\n"
+ String req2 = "GET https://" + hp + + "Host: " + hp + "\r\n\r\n";
+ + "/request.https.proxy.connection HTTP/1.1\r\n"
+ + "Host: " + hp + "\r\n\r\n";
+ +
+ dbg("requesting: " + req1); + dbg("requesting1: " + req1);
+ +
+ try { + try {
+ proxy_os.write(req1.getBytes()); + proxy_os.write(req1.getBytes());
+ String reply = readline(proxy_is); + String reply = readline(proxy_is);
+ +
+ dbg("proxy replied: " + reply); + dbg("proxy replied1: " + reply.trim());
+ +
+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { + if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
+ proxySock.close(); + proxySock.close();
+ proxySock = psocket(proxyHost, proxyPort); + proxySock = psocket(proxyHost, proxyPort);
+ if (proxySock == null) { + if (proxySock == null) {
+ dbg("2 sadly, returning a null socket"); + dbg("2-a sadly, returning a null socket");
+ return null; + return null;
+ }
+ } + }
+ dbg("requesting: " + req2); + } catch(Exception e) {
+ dbg("sock prob1: " + e.getMessage());
+ }
+
+ while (true) {
+ String line = readline(proxy_is);
+ dbg("proxy line1: " + line.trim());
+ if (line.equals("\r\n") || line.equals("\n")) {
+ break;
+ }
+ }
+ } else if (viewer.CONNECT != null) {
+ dbg("viewer.CONNECT psocket:");
+ proxySock = psocket(host, port);
+ if (proxySock == null) {
+ dbg("1-b sadly, returning a null socket");
+ return null;
+ }
+ }
+
+ if (viewer.CONNECT != null) {
+ String hp = viewer.CONNECT;
+ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n"
+ + "Host: " + hp + "\r\n\r\n";
+
+ dbg("requesting2: " + req2);
+
+ try {
+ proxy_os.write(req2.getBytes()); + proxy_os.write(req2.getBytes());
+ String reply = readline(proxy_is);
+ +
+ reply = readline(proxy_is); + dbg("proxy replied2: " + reply.trim());
+ +
+ dbg("proxy replied: " + reply); + if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
+ proxySock.close();
+ proxySock = psocket(proxyHost, proxyPort);
+ if (proxySock == null) {
+ dbg("2-b sadly, returning a null socket");
+ return null;
+ }
+ }
+ } catch(Exception e) {
+ dbg("sock prob2: " + e.getMessage());
+ } + }
+ } catch(Exception e) {
+ dbg("sock prob: " + e.getMessage());
+ }
+ +
+ while (true) { + while (true) {
+ String line = readline(proxy_is); + String line = readline(proxy_is);
+ dbg("proxy line: " + line); + dbg("proxy line2: " + line.trim());
+ if (line.equals("\r\n") || line.equals("\n")) { + if (line.equals("\r\n") || line.equals("\n")) {
+ break; + break;
+ }
+ } + }
+
+ } + }
+ +
+ Socket sslsock = null; + Socket sslsock = null;
+ try { + try {
+ sslsock = factory.createSocket(proxySock, host, port, true); + sslsock = factory.createSocket(proxySock, host, port, true);
...@@ -1108,16 +1281,21 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ...@@ -1108,16 +1281,21 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+} +}
diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncViewer.java diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncViewer.java
--- vnc_javasrc.orig/VncViewer.java 2004-03-04 08:34:25.000000000 -0500 --- vnc_javasrc.orig/VncViewer.java 2004-03-04 08:34:25.000000000 -0500
+++ vnc_javasrc/VncViewer.java 2006-03-27 22:20:19.000000000 -0500 +++ vnc_javasrc/VncViewer.java 2006-04-16 11:21:13.000000000 -0400
@@ -87,6 +87,7 @@ @@ -88,6 +88,12 @@
int deferScreenUpdates;
int deferCursorUpdates; int deferCursorUpdates;
int deferUpdateRequests; int deferUpdateRequests;
+ boolean disableSSL;
+ boolean disableSSL;
+ String GET;
+ String CONNECT;
+ String urlPrefix;
+ boolean forceProxy;
+
// Reference to this applet for inter-applet communication. // Reference to this applet for inter-applet communication.
public static java.applet.Applet refApplet; public static java.applet.Applet refApplet;
@@ -626,6 +627,12 @@
@@ -626,6 +632,39 @@
// SocketFactory. // SocketFactory.
socketFactory = readParameter("SocketFactory", false); socketFactory = readParameter("SocketFactory", false);
...@@ -1127,6 +1305,33 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView ...@@ -1127,6 +1305,33 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView
+ str = readParameter("DisableSSL", false); + str = readParameter("DisableSSL", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) + if (str != null && str.equalsIgnoreCase("Yes"))
+ disableSSL = true; + disableSSL = true;
+
+ // Extra GET, CONNECT string:
+ CONNECT = readParameter("CONNECT", false);
+ if (CONNECT != null) {
+ CONNECT = CONNECT.replaceAll(" ", ":");
+ }
+ GET = readParameter("GET", false);
+ urlPrefix = "";
+ if (GET != null) {
+ GET = GET.replaceAll("%2F", "/");
+ GET = GET.replaceAll("%2f", "/");
+ GET = GET.replaceAll("_2F_", "/");
+ if (! GET.equals("1")) {
+ if (GET.indexOf("/") != 0) {
+ urlPrefix += "/";
+ }
+ urlPrefix += GET;
+ }
+ }
+ urlPrefix = urlPrefix.replaceAll("%2f", "/");
+ System.out.println("urlPrefix: " + urlPrefix);
+
+ forceProxy = false;
+ str = readParameter("forceProxy", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ forceProxy = true;
+ }
} }
public String readParameter(String name, boolean required) { public String readParameter(String name, boolean required) {
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 source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -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