summaryrefslogtreecommitdiffstats
path: root/x11vnc/misc/connect_switch
diff options
context:
space:
mode:
authorrunge <runge@karlrunge.com>2010-03-21 00:05:51 -0400
committerrunge <runge@karlrunge.com>2010-03-21 00:05:51 -0400
commit97540de56ca8a975ed31d86879d0e5c4cf169173 (patch)
tree6c8c0a28c3559a15c6a76bed92dc2a4c62630914 /x11vnc/misc/connect_switch
parentedb79ae2b1d39bc12d489bcded74ab966e019994 (diff)
downloadlibtdevnc-97540de56ca8a975ed31d86879d0e5c4cf169173.tar.gz
libtdevnc-97540de56ca8a975ed31d86879d0e5c4cf169173.zip
classes/ssl: Many improvements to Java SSL applet, onetimekey
serverCert param, debugging printout, user dialogs, catch socket exceptions, autodetect x11vnc for GET=1. x11vnc: misc/scripts: desktop.cgi, inet6to4, panner.pl. X11VNC_HTTPS_DOWNLOAD_WAIT_TIME, -unixpw %xxx documented, and can run user cmd in UNIXPW_CMD. FD_XDMCP_IF for create script, autodetect dm on udp6 only. Queries: pointer_x, pointer_y, pointer_same, pointer_root. Switch on -xkd if keysyms per key > 4 in all cases. daemon mode improvements for connect_switch, inet6to4, ultravnc_repeater.pl. Dynamic change of -clip do not create new fb if WxH is unchanged.
Diffstat (limited to 'x11vnc/misc/connect_switch')
-rwxr-xr-xx11vnc/misc/connect_switch276
1 files changed, 250 insertions, 26 deletions
diff --git a/x11vnc/misc/connect_switch b/x11vnc/misc/connect_switch
index ad6d138..212157f 100755
--- a/x11vnc/misc/connect_switch
+++ b/x11vnc/misc/connect_switch
@@ -1,6 +1,6 @@
#!/usr/bin/perl
#
-# Copyright (c) 2006-2009 by Karl J. Runge <runge@karlrunge.com>
+# Copyright (c) 2006-2010 by Karl J. Runge <runge@karlrunge.com>
#
# connect_switch is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -35,10 +35,14 @@
# because the CONNECT request appears to be forwarded encrypted to
# the remote host and so the SSL dies immediately.
#
+# It can also be used to redirect ANY protocol, e.g. SSH, not just VNC.
+# See CONNECT_SWITCH_APPLY_VNC_OFFSET=0 to disable VNC 5900 shift.
+#
# Note: There is no need to use this script for a non-ssl apache webserver
# port because mod_proxy works fine for doing the switching all inside
# apache (see ProxyRequests and AllowCONNECT parameters).
#
+#
# Apache configuration:
#
# The mod_ssl configuration is often in a file named ssl.conf. In the
@@ -68,6 +72,126 @@
# It is probably a good idea to set $listen_host below to the known
# IP address you want the service to listen on (to avoid localhost where
# apache is listening).
+#
+
+####################################################################
+# NOTE: For more info on configuration settings, read below for
+# all of the CONNECT_SWITCH_* env. var. parameters.
+####################################################################
+
+
+####################################################################
+# Allow env vars to also be specified on cmdline:
+#
+foreach my $arg (@ARGV) {
+ if ($arg =~ /^(CONNECT_SWITCH.*?)=(.*)$/) {
+ $ENV{$1} = $2;
+ }
+}
+
+# Set up logging:
+#
+if (exists $ENV{CONNECT_SWITCH_LOGFILE}) {
+ close STDOUT;
+ if (!open(STDOUT, ">>$ENV{CONNECT_SWITCH_LOGFILE}")) {
+ die "connect_switch: $ENV{CONNECT_SWITCH_LOGFILE} $!\n";
+ }
+ close STDERR;
+ open(STDERR, ">&STDOUT");
+}
+select(STDERR); $| = 1;
+select(STDOUT); $| = 1;
+
+# interrupt handler:
+#
+my $looppid = '';
+my $pidfile = '';
+my $listen_sock = ''; # declared here for get_out()
+#
+sub get_out {
+ print STDERR "$_[0]:\t$$ looppid=$looppid\n";
+ close $listen_sock if $listen_sock;
+ if ($looppid) {
+ kill 'TERM', $looppid;
+ fsleep(0.2);
+ }
+ unlink $pidfile if $pidfile;
+ exit 0;
+}
+$SIG{INT} = \&get_out;
+$SIG{TERM} = \&get_out;
+
+# pidfile:
+#
+sub open_pidfile {
+ if (exists $ENV{CONNECT_SWITCH_PIDFILE}) {
+ my $pf = $ENV{CONNECT_SWITCH_PIDFILE};
+ if (open(PID, ">$pf")) {
+ print PID "$$\n";
+ close PID;
+ $pidfile = $pf;
+ } else {
+ print STDERR "could not open pidfile: $pf - $! - continuing...\n";
+ }
+ delete $ENV{CONNECT_SWITCH_PIDFILE};
+ }
+}
+
+####################################################################
+# Set CONNECT_SWITCH_LOOP=1 to have this script create an outer loop
+# restarting itself if it ever exits. Set CONNECT_SWITCH_LOOP=BG to
+# do this in the background as a daemon.
+
+if (exists $ENV{CONNECT_SWITCH_LOOP}) {
+ my $csl = $ENV{CONNECT_SWITCH_LOOP};
+ if ($csl ne 'BG' && $csl ne '1') {
+ die "connect_switch: invalid CONNECT_SWITCH_LOOP.\n";
+ }
+ if ($csl eq 'BG') {
+ # go into bg as "daemon":
+ setpgrp(0, 0);
+ my $pid = fork();
+ if (! defined $pid) {
+ die "connect_switch: $!\n";
+ } elsif ($pid) {
+ wait;
+ exit 0;
+ }
+ if (fork) {
+ exit 0;
+ }
+ setpgrp(0, 0);
+ close STDIN;
+ if (! $ENV{CONNECT_SWITCH_LOGFILE}) {
+ close STDOUT;
+ close STDERR;
+ }
+ }
+ delete $ENV{CONNECT_SWITCH_LOOP};
+
+ if (exists $ENV{CONNECT_SWITCH_PIDFILE}) {
+ open_pidfile();
+ }
+
+ print STDERR "connect_switch: starting service at ", scalar(localtime), " master-pid=$$\n";
+ while (1) {
+ $looppid = fork;
+ if (! defined $looppid) {
+ sleep 10;
+ } elsif ($looppid) {
+ wait;
+ } else {
+ exec $0;
+ exit 1;
+ }
+ print STDERR "connect_switch: re-starting service at ", scalar(localtime), " master-pid=$$\n";
+ sleep 1;
+ }
+ exit 0;
+}
+if (exists $ENV{CONNECT_SWITCH_PIDFILE}) {
+ open_pidfile();
+}
############################################################################
@@ -83,15 +207,29 @@
# CONNECT_SWITCH_VERBOSE
# CONNECT_SWITCH_APPLY_VNC_OFFSET
# CONNECT_SWITCH_VNC_OFFSET
+# CONNECT_SWITCH_LISTEN_IPV6
+# CONNECT_SWITCH_BUFSIZE
+# CONNECT_SWITCH_LOGFILE
+# CONNECT_SWITCH_PIDFILE
+#
+# You can also set these on the cmdline:
+# connect_switch CONNECT_SWITCH_LISTEN=X CONNECT_SWITCH_ALLOW_FILE=Y ...
+#
+# By default we will use hostname and assume it resolves:
+#
my $hostname = `hostname`;
chomp $hostname;
my $listen_host = $hostname;
my $listen_port = 443;
+# Let user override listening situation, e.g. multihomed:
+#
if (exists $ENV{CONNECT_SWITCH_LISTEN}) {
+ #
# E.g. CONNECT_SWITCH_LISTEN=192.168.0.32:443
+ #
($listen_host, $listen_port) = split(/:/, $ENV{CONNECT_SWITCH_LISTEN});
}
@@ -99,10 +237,21 @@ my $httpd_host = 'localhost';
my $httpd_port = 443;
if (exists $ENV{CONNECT_SWITCH_HTTPD}) {
+ #
# E.g. CONNECT_SWITCH_HTTPD=127.0.0.1:443
+ #
($httpd_host, $httpd_port) = split(/:/, $ENV{CONNECT_SWITCH_HTTPD});
}
+my $bufsize = 8192;
+if (exists $ENV{CONNECT_SWITCH_BUFSIZE}) {
+ #
+ # E.g. CONNECT_SWITCH_BUFSIZE=32768
+ #
+ $bufsize = $ENV{CONNECT_SWITCH_BUFSIZE};
+}
+
+
############################################################################
# You can/should override the host/port settings here:
#
@@ -113,6 +262,9 @@ if (exists $ENV{CONNECT_SWITCH_HTTPD}) {
# You must set the allowed host:port CONNECT redirection list.
# Only these host:port pairs will be redirected to.
+# Port ranges are allowed too: host:5900-5930.
+# If there is one entry named ALL all connections are allow.
+# You must supply something, default is deny.
#
my @allowed = qw(
machine1:5915
@@ -141,6 +293,8 @@ if (exists $ENV{CONNECT_SWITCH_ALLOWED}) {
# fredsbox 15
# rupert 1
+# For examply, mine is:
+#
my $allow_file = '/dist/apache/2.0/conf/vnc.hosts';
$allow_file = '';
@@ -158,25 +312,34 @@ my $apply_vnc_offset = 1;
my $vnc_offset = 5900;
if (exists $ENV{CONNECT_SWITCH_APPLY_VNC_OFFSET}) {
+ #
# E.g. CONNECT_SWITCH_APPLY_VNC_OFFSET=0
+ #
$apply_vnc_offset = $ENV{CONNECT_SWITCH_APPLY_VNC_OFFSET};
}
if (exists $ENV{CONNECT_SWITCH_VNC_OFFSET}) {
+ #
# E.g. CONNECT_SWITCH_VNC_OFFSET=6000
+ #
$vnc_offset = $ENV{CONNECT_SWITCH_VNC_OFFSET};
}
-# Set to 1 for more debugging output:
+# Set to 1 or higher for more info output:
#
my $verbose = 0;
if (exists $ENV{CONNECT_SWITCH_VERBOSE}) {
+ #
# E.g. CONNECT_SWITCH_VERBOSE=1
+ #
$verbose = $ENV{CONNECT_SWITCH_VERBOSE};
}
-############################################################################
+
+
+#===========================================================================
# No need for any changes below here.
+#===========================================================================
use IO::Socket::INET;
use strict;
@@ -186,12 +349,29 @@ my $killpid = 1;
setpgrp(0, 0);
-my $listen_sock = IO::Socket::INET->new(
- Listen => 10,
- LocalAddr => $listen_host,
- LocalPort => $listen_port,
- Proto => "tcp"
-);
+if (exists $ENV{CONNECT_SWITCH_LISTEN_IPV6}) {
+ # note we leave out LocalAddr.
+ my $cmd = '
+ use IO::Socket::INET6;
+ $listen_sock = IO::Socket::INET6->new(
+ Listen => 10,
+ LocalPort => $listen_port,
+ ReuseAddr => 1,
+ Domain => AF_INET6,
+ Proto => "tcp"
+ );
+ ';
+ eval $cmd;
+ die "$@\n" if $@;
+} else {
+ $listen_sock = IO::Socket::INET->new(
+ Listen => 10,
+ LocalAddr => $listen_host,
+ LocalPort => $listen_port,
+ ReuseAddr => 1,
+ Proto => "tcp"
+ );
+}
if (! $listen_sock) {
die "connect_switch: $!\n";
@@ -210,7 +390,7 @@ while (1) {
fsleep(0.5);
next;
}
- print STDERR "conn: $conn -- ", $client->peerhost(), "\n" if $verbose;
+ print STDERR "conn: $conn -- ", $client->peerhost(), " at ", scalar(localtime), "\n" if $verbose;
my $pid = fork();
if (! defined $pid) {
@@ -237,6 +417,10 @@ sub handle_conn {
my @allow = @allowed;
+ # read allow file. Note we read it for every connection
+ # to allow the admin to modify it w/o restarting us.
+ # better way would be to read in parent and check mtime.
+ #
if ($allow_file && -f $allow_file) {
if (open(ALLOW, "<$allow_file")) {
while (<ALLOW>) {
@@ -259,6 +443,8 @@ sub handle_conn {
}
}
+ # Read the first 7 bytes of connection, see if it is 'CONNECT'
+ #
my $str = '';
my $N = 0;
my $isconn = 1;
@@ -267,7 +453,7 @@ sub handle_conn {
sysread($client, $b, 1);
$str .= $b;
$N++;
- print STDERR "read: '$str'\n" if $verbose;
+ print STDERR "read: '$str'\n" if $verbose > 1;
my $cstr = substr('CONNECT', 0, $i+1);
if ($str ne $cstr) {
$isconn = 0;
@@ -276,28 +462,60 @@ sub handle_conn {
}
my $sock = '';
+
if ($isconn) {
+ # it is CONNECT, read rest of HTTP header:
+ #
while ($str !~ /\r\n\r\n/) {
my $b;
sysread($client, $b, 1);
$str .= $b;
}
- print STDERR "read: $str\n" if $verbose;
+ print STDERR "read: $str\n" if $verbose > 1;
+ # get http version and host:port
+ #
my $ok = 0;
my $hostport = '';
my $http_vers = '1.0';
if ($str =~ /^CONNECT\s+(\S+)\s+HTTP\/(\S+)/) {
$hostport = $1;
$http_vers = $2;
- foreach my $hp (@allow) {
- if ($hp eq $hostport) {
- $ok = 1;
- last;
+
+ my ($h, $p) = split(/:/, $hostport);
+ if ($p =~ /^\d+$/) {
+ # check allowed host list:
+ foreach my $hp (@allow) {
+ if ($hp eq 'ALL') {
+ $ok = 1;
+ }
+ if ($hp eq $hostport) {
+ $ok = 1;
+ }
+ if ($hp =~ /^(.*):(\d+)-(\d+)$/) {
+ my $ahost = $1;
+ my $pmin = $2;
+ my $pmax = $3;
+ if ($h eq $ahost) {
+ if ($p >= $pmin && $p <= $pmax) {
+ $ok = 1;
+ }
+ }
+ }
+ last if $ok;
}
}
}
+
+ my $msg_1 = "HTTP/$http_vers 200 Connection Established\r\n"
+ . "Proxy-agent: connect_switch v0.2\r\n\r\n";
+ my $msg_2 = "HTTP/$http_vers 502 Bad Gateway\r\n"
+ . "Connection: close\r\n\r\n";
+
if (! $ok) {
+ # disallowed. drop with message.
+ #
+ syswrite($client, $msg_2, length($msg_2));
close $client;
exit 0;
}
@@ -312,18 +530,20 @@ sub handle_conn {
Proto => "tcp"
);
my $msg;
+
+ # send the connect proxy reply:
+ #
if ($sock) {
- $msg = "HTTP/$http_vers 200 Connection Established\r\n"
- . "Proxy-agent: connect_switch v0.2\r\n\r\n";
+ $msg = $msg_1;
} else {
- $msg = "HTTP/$http_vers 502 Bad Gateway\r\n"
- . "Connection: close\r\n\r\n";
+ $msg = $msg_2;
}
syswrite($client, $msg, length($msg));
$str = '';
} else {
- print STDERR "connecting to: $httpd_host:$httpd_port\n"
- if $verbose;
+ # otherwise, redirect to apache for normal https:
+ #
+ print STDERR "connecting to: $httpd_host:$httpd_port\n" if $verbose;
$sock = IO::Socket::INET->new(
PeerAddr => $httpd_host,
PeerPort => $httpd_port,
@@ -336,6 +556,8 @@ sub handle_conn {
die "connect_switch: $!\n";
}
+ # get ready for xfer phase:
+ #
$current_fh1 = $client;
$current_fh2 = $sock;
@@ -349,6 +571,8 @@ sub handle_conn {
kill 'TERM', $child;
}
} else {
+ # write those first bytes if not CONNECT:
+ #
if ($str ne '' && $N > 0) {
syswrite($sock, $str, $N);
}
@@ -358,9 +582,9 @@ sub handle_conn {
kill 'TERM', $parent;
}
}
- if ($verbose) {
+ if ($verbose > 1) {
my $dt = time() - $start;
- print STDERR "dt\[$$]: $dt\n";
+ print STDERR "duration\[$$]: $dt seconds. ", scalar(localtime), "\n";
}
exit 0;
}
@@ -380,7 +604,7 @@ sub xfer {
while (! $nf) {
$nf = select($ROUT=$RIN, undef, undef, undef);
}
- my $len = sysread($in, $buf, 8192);
+ my $len = sysread($in, $buf, $bufsize);
if (! defined($len)) {
next if $! =~ /^Interrupted/;
print STDERR "connect_switch\[$lab/$conn/$$]: $!\n";
@@ -392,7 +616,7 @@ sub xfer {
}
if (0) {
- # verbose debugging of data:
+ # very verbose debugging of data:
syswrite(STDERR , "\n$lab: ", 6);
syswrite(STDERR , $buf, $len);
}