summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrunge <runge@karlrunge.com>2010-05-01 13:16:37 -0400
committerrunge <runge@karlrunge.com>2010-05-01 13:16:37 -0400
commit59c0ae40935114b9bbe6a966446587469fc5deae (patch)
tree5e45a4014aa801de98ff65b0e9eb6209232a467d
parent8d79a63d3c8caca5d0db4827e072f7c773387afa (diff)
downloadlibtdevnc-59c0ae40935114b9bbe6a966446587469fc5deae.tar.gz
libtdevnc-59c0ae40935114b9bbe6a966446587469fc5deae.zip
x11vnc: X11VNC_DISABLE_SSL_CLIENT_MODE option to disable SSL
client role in reverse connections. Improvements to logging in ultravnc_repeater, ULTRAVNC_REPEATER_NO_RFB option. Increase SSL timeout and print message if 'repeater' mode is detected for reverse SSL connection. Fix RECORD scroll XCopyArea detection with recent gtk/gdk library; set X11VNC_SCROLL_MUST_EQUAL to disable. Limit logging of RECORD error messages.
-rw-r--r--x11vnc/ChangeLog9
-rw-r--r--x11vnc/README61
-rw-r--r--x11vnc/connections.c4
-rw-r--r--x11vnc/help.c22
-rwxr-xr-xx11vnc/misc/ultravnc_repeater.pl175
-rw-r--r--x11vnc/sslhelper.c36
-rw-r--r--x11vnc/x11vnc.124
-rw-r--r--x11vnc/x11vnc_defs.c2
-rw-r--r--x11vnc/xrecord.c145
9 files changed, 362 insertions, 116 deletions
diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog
index 75505a8..1a03b2c 100644
--- a/x11vnc/ChangeLog
+++ b/x11vnc/ChangeLog
@@ -1,3 +1,12 @@
+2010-05-01 Karl Runge <runge@karlrunge.com>
+ * x11vnc: X11VNC_DISABLE_SSL_CLIENT_MODE option to disable SSL
+ client role in reverse connections. Improvements to logging in
+ ultravnc_repeater, ULTRAVNC_REPEATER_NO_RFB option. Increase
+ SSL timeout and print message if 'repeater' mode is detected for
+ reverse SSL connection. Fix RECORD scroll XCopyArea detection
+ with recent gtk/gdk library; set X11VNC_SCROLL_MUST_EQUAL
+ to disable. Limit logging of RECORD error messages.
+
2010-04-25 Karl Runge <runge@karlrunge.com>
* x11vnc: incorporate new ultravnc_dsm_helper.c, add pointer_mask
remote control query. Cut openssl default -ping delay.
diff --git a/x11vnc/README b/x11vnc/README
index 7456442..2f5032b 100644
--- a/x11vnc/README
+++ b/x11vnc/README
@@ -2,7 +2,7 @@
Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
All rights reserved.
-x11vnc README file Date: Fri Apr 23 00:36:17 EDT 2010
+x11vnc README file Date: Fri Apr 30 00:43:58 EDT 2010
The following information is taken from these URLs:
@@ -34,7 +34,8 @@ x11vnc: a VNC server for real X displays
advertising; and TightVNC and UltraVNC file-transfer. It has also been
extended to work with non-X devices: natively on Mac OS X Aqua/Quartz,
webcams and TV tuner capture devices, and embedded Linux systems such
- as Qtopia Core. More features are described here.
+ as Qtopia Core. Full IPv6 support is provided. More features are
+ described here.
It also provides an encrypted Terminal Services mode (-create, -svc,
or -xdmsvc options) based on Unix usernames and Unix passwords where
@@ -56,14 +57,10 @@ x11vnc: a VNC server for real X displays
to many problems; and interesting applications, but nevertheless
please feel free to contact me if you have problems or questions (and
if I save you time or expense by giving you some of my time, please
- consider a PayPal Donation.)
-
- Do check the FAQ and this page first; I realize the pages are massive,
- but you can often use your browser's find-in-page search action using
- a keyword to find the answer to your problem or question.
-
- Please help test the performance speedup feature using viewer-side
- pixel caching "ncache".
+ consider a PayPal Donation.) Do check the FAQ and this page first; I
+ realize the pages are massive, but you can often use your browser's
+ find-in-page search action using a keyword to find the answer to your
+ problem or question.
SSVNC: An x11vnc side-project provides an Enhanced TightVNC Viewer
package (SSVNC) for Unix, Windows, and Mac OS X with automatic SSL
@@ -948,14 +945,16 @@ make
from being downloaded successfully in single-port HTTPS/VNC inetd
mode. The env. var. X11VNC_HTTPS_DOWNLOAD_WAIT_TIME can be used to
adjust for how many seconds a -inetd or -https httpd download is
- waited for (default 15 seconds.)
- * The TightVNC sercurity type (TightVNC features enabler) now works
+ waited for (default 15 seconds.) The applet will now autodetect
+ x11vnc and use GET=1 for faster connecting. Many other
+ improvements and fixes.
+ * The TightVNC security type (TightVNC features enabler) now works
for RFB version 3.8.
* The X property X11VNC_TRAP_XRANDR can be set on a desktop to force
x11vnc to use the -xrandr screen size change trapping code.
* New remote control query options: pointer_x, pointer_y,
- pointer_same, and pointer_root. A demo script using them
- misc/panner.pl is provided.
+ pointer_same, pointer_root, and pointer_mask. A demo script using
+ them misc/panner.pl is provided.
* The -sslScripts option prints out the SSL certificate management
scripts.
@@ -1567,7 +1566,9 @@ LAY
* Using -threads can expose some bugs/crashes in libvncserver.
Please feel free to contact me if you have any questions, problems, or
- comments about x11vnc, etc.
+ comments about x11vnc, etc. Please be polite, thorough, and not
+ demanding (sadly, the number of people contacting me that are rude and
+ demanding is increasing dramatically.)
Also, some people ask if they can make a donation, see this link for
that.
@@ -2234,8 +2235,8 @@ libssl.so libcrypto.so libcrypt.so
This is most likely due to you not having a working build environment
for the XTEST client library libXtst.so. The library is probably
- present on your system, but the package installing the development
- header file is missing.
+ present on your system, but the package installing the build header
+ file is missing.
If you were watching carefully while configure was running you would
have seen:
@@ -12078,7 +12079,7 @@ x11vnc: a VNC server for real X displays
Here are all of x11vnc command line options:
% x11vnc -opts (see below for -help long descriptions)
-x11vnc: allow VNC connections to real X11 displays. 0.9.10 lastmod: 2010-04-22
+x11vnc: allow VNC connections to real X11 displays. 0.9.10 lastmod: 2010-04-28
x11vnc options:
-display disp -auth file -N
@@ -12208,7 +12209,7 @@ libvncserver-tight-extension options:
% x11vnc -help
-x11vnc: allow VNC connections to real X11 displays. 0.9.10 lastmod: 2010-04-22
+x11vnc: allow VNC connections to real X11 displays. 0.9.10 lastmod: 2010-04-28
(type "x11vnc -opts" to just list the options.)
@@ -12786,6 +12787,28 @@ Options:
See also the -proxy option below for additional ways
to plumb reverse connections.
+ Reverse SSL: using -connect in -ssl mode makes x11vnc
+ act as an SSL client (initiates SSL connection) rather
+ than an SSL server. The idea is x11vnc might be
+ connecting to stunnel on the viewer side with the
+ viewer in listening mode. If you do not want this
+ behavior, use -env X11VNC_DISABLE_SSL_CLIENT_MODE=1.
+ With this the viewer side can act as the SSL client
+ as it normally does for forward connections.
+
+ Reverse SSL Repeater mode: This will work, but note
+ that if the VNC Client does any sort of a 'Fetch Cert'
+ action before connecting, then the Repeater will
+ likely drop the connection and both sides will need
+ to restart. Consider the use of -connect_or_exit
+ and -loop300,2 to have x11vnc reconnect once to the
+ repeater after the fetch. You will probably also want
+ to supply -sslonly to avoid x11vnc thinking the delay
+ in response means the connection is VeNCrypt. The env
+ var X11VNC_DISABLE_SSL_CLIENT_MODE=1 discussed above
+ may also be useful (i.e. the viewer can do a forward
+ connection as it normally does.)
+
IPv6: as of x11vnc 0.9.10 the -connect option should
connect to IPv6 hosts properly. If there are problems
you can disable IPv6 by setting -DX11VNC_IPV6=0
diff --git a/x11vnc/connections.c b/x11vnc/connections.c
index c664377..246acae 100644
--- a/x11vnc/connections.c
+++ b/x11vnc/connections.c
@@ -2644,7 +2644,9 @@ static int do_reverse_connect(char *str_in) {
}
/* XXX use header */
#define OPENSSL_REVERSE 6
- openssl_init(1);
+ if (!getenv("X11VNC_DISABLE_SSL_CLIENT_MODE")) {
+ openssl_init(1);
+ }
if (first_conn_timeout > 0) {
set_alarm = 1;
diff --git a/x11vnc/help.c b/x11vnc/help.c
index 1289a42..90dddfd 100644
--- a/x11vnc/help.c
+++ b/x11vnc/help.c
@@ -642,6 +642,28 @@ void print_help(int mode) {
" See also the -proxy option below for additional ways\n"
" to plumb reverse connections.\n"
"\n"
+" Reverse SSL: using -connect in -ssl mode makes x11vnc\n"
+" act as an SSL client (initiates SSL connection) rather\n"
+" than an SSL server. The idea is x11vnc might be\n"
+" connecting to stunnel on the viewer side with the\n"
+" viewer in listening mode. If you do not want this\n"
+" behavior, use -env X11VNC_DISABLE_SSL_CLIENT_MODE=1.\n"
+" With this the viewer side can act as the SSL client\n"
+" as it normally does for forward connections.\n"
+"\n"
+" Reverse SSL Repeater mode: This will work, but note\n"
+" that if the VNC Client does any sort of a 'Fetch Cert'\n"
+" action before connecting, then the Repeater will\n"
+" likely drop the connection and both sides will need\n"
+" to restart. Consider the use of -connect_or_exit\n"
+" and -loop300,2 to have x11vnc reconnect once to the\n"
+" repeater after the fetch. You will probably also want\n"
+" to supply -sslonly to avoid x11vnc thinking the delay\n"
+" in response means the connection is VeNCrypt. The env\n"
+" var X11VNC_DISABLE_SSL_CLIENT_MODE=1 discussed above\n"
+" may also be useful (i.e. the viewer can do a forward\n"
+" connection as it normally does.)\n"
+"\n"
" IPv6: as of x11vnc 0.9.10 the -connect option should\n"
" connect to IPv6 hosts properly. If there are problems\n"
" you can disable IPv6 by setting -DX11VNC_IPV6=0\n"
diff --git a/x11vnc/misc/ultravnc_repeater.pl b/x11vnc/misc/ultravnc_repeater.pl
index 5528bed..00ade34 100755
--- a/x11vnc/misc/ultravnc_repeater.pl
+++ b/x11vnc/misc/ultravnc_repeater.pl
@@ -50,6 +50,8 @@ ULTRAVNC_REPEATER_LOOP=1 or ULTRAVNC_REPEATER_LOOP=BG, the latter
forks into the background. Set ULTRAVNC_REPEATER_PIDFILE to a file
to store the master pid in.
+Set ULTRAVNC_REPEATER_NO_RFB=1 to disable sending "RFB 000.000" to
+the client. Then this program acts as general TCP rendezvous tool.
Examples:
@@ -83,7 +85,7 @@ my $looppid = '';
my $pidfile = '';
#
sub get_out {
- print STDERR "$_[0]:\t$$ looppid=$looppid\n";
+ lprint("$_[0]:\t$$ looppid=$looppid");
if ($looppid) {
kill 'TERM', $looppid;
fsleep(0.2);
@@ -93,6 +95,10 @@ sub get_out {
exit 0;
}
+sub lprint {
+ print STDERR scalar(localtime), ": ", @_, "\n";
+}
+
# These are overridden in actual server thread:
#
$SIG{INT} = \&get_out;
@@ -108,7 +114,7 @@ sub open_pidfile {
close PID;
$pidfile = $pf;
} else {
- print STDERR "could not open pidfile: $pf - $! - continuing...\n";
+ lprint("could not open pidfile: $pf - $! - continuing...");
}
delete $ENV{ULTRAVNC_REPEATER_PIDFILE};
}
@@ -150,7 +156,7 @@ if (exists $ENV{ULTRAVNC_REPEATER_LOOP}) {
open_pidfile();
}
- print STDERR "ultravnc_repeater.pl: starting service at ", scalar(localtime), " master-pid=$$\n";
+ lprint("ultravnc_repeater.pl: starting service. master-pid=$$");
while (1) {
$looppid = fork;
if (! defined $looppid) {
@@ -161,7 +167,7 @@ if (exists $ENV{ULTRAVNC_REPEATER_LOOP}) {
exec $0, @ARGV;
exit 1;
}
- print STDERR "ultravnc_repeater.pl: re-starting service at ", scalar(localtime), " master-pid=$$\n";
+ lprint("ultravnc_repeater.pl: re-starting service. master-pid=$$");
sleep 1;
}
exit 0;
@@ -184,7 +190,7 @@ eval "use IO::Socket::INET6;";
$have_inet6 = 1 if $@ eq "";
print "perl module IO::Socket::INET6 not available: no IPv6 support.\n" if ! $have_inet6;
-my $prog = 'ultravnc_repeater.pl';
+my $prog = 'ultravnc_repeater';
my %ID;
my $refuse = 0;
@@ -196,7 +202,7 @@ if (@ARGV && $ARGV[0] =~ /-h/) {
}
if (@ARGV && $ARGV[0] eq '-r') {
$refuse = 1;
- print "enabling refuse mode (-r).\n";
+ lprint("enabling refuse mode (-r).");
shift;
}
@@ -285,15 +291,16 @@ my $SOCK1 = '';
my $SOCK2 = '';
my $CURR = '';
-print "watching for IPv4 connections on $client_port/client\n" if $client_listen;
-print "watching for IPv4 connections on $server_port/server\n" if $server_listen;
-print "watching for IPv6 connections on $client_port/client\n" if $client_listen6;
-print "watching for IPv6 connections on $server_port/server\n" if $server_listen6;
+lprint("$prog: starting up. pid: $$");
+lprint("watching for IPv4 connections on $client_port/client.") if $client_listen;
+lprint("watching for IPv4 connections on $server_port/server.") if $server_listen;
+lprint("watching for IPv6 connections on $client_port/client.") if $client_listen6;
+lprint("watching for IPv6 connections on $server_port/server.") if $server_listen6;
my $alarm_sock = '';
my $got_alarm = 0;
sub alarm_handler {
- print "$prog: got sig alarm.\n";
+ lprint("$prog: got sig alarm.");
if ($alarm_sock ne '') {
close $alarm_sock;
}
@@ -303,24 +310,28 @@ sub alarm_handler {
while (my @ready = $select->can_read()) {
foreach my $fh (@ready) {
- if ($fh == $client_listen || $fh == $client_listen6) {
- print "new vnc client connecting at ", scalar(localtime), "\n";
- } elsif ($fh == $server_listen || $fh == $server_listen6) {
- print "new vnc server connecting at ", scalar(localtime), "\n";
+ if (($client_listen && $fh == $client_listen) || ($client_listen6 && $fh == $client_listen6)) {
+ lprint("new vnc client connecting.");
+ } elsif (($server_listen && $fh == $server_listen) || ($server_listen6 && $fh == $server_listen6)) {
+ lprint("new vnc server connecting.");
}
my $sock = $fh->accept();
if (! $sock) {
- print "$prog: accept $!\n";
+ lprint("$prog: accept $!");
next;
}
- if ($fh == $client_listen || $fh == $client_listen6) {
- my $str = "RFB 000.000\n";
- my $len = length $str;
- my $n = syswrite($sock, $str, $len, 0);
- if ($n != $len) {
- print "$prog: bad $str write: $n != $len $!\n";
- close $sock;
+ if (($client_listen && $fh == $client_listen) || ($client_listen6 && $fh == $client_listen6)) {
+ if (exists $ENV{ULTRAVNC_REPEATER_NO_RFB} && $ENV{ULTRAVNC_REPEATER_NO_RFB}) {
+ lprint("ULTRAVNC_REPEATER_NO_RFB: not sending RFB 000.000");
+ } else {
+ my $str = "RFB 000.000\n";
+ my $len = length $str;
+ my $n = syswrite($sock, $str, $len, 0);
+ if ($n != $len) {
+ lprint("$prog: bad $str write: $n != $len $!");
+ close $sock;
+ }
}
}
@@ -336,15 +347,15 @@ while (my @ready = $select->can_read()) {
alarm(0);
if ($got_alarm) {
- print "$prog: read timed out: $!\n";
+ lprint("$prog: read timed out: $!");
} elsif (! defined $n) {
- print "$prog: read error: $!\n";
+ lprint("$prog: read error: $!");
} elsif ($repeater_bufsize > 0 && $n != $size) {
- print "$prog: short read $n != $size $!\n";
+ lprint("$prog: short read $n != $size $!");
close $sock;
- } elsif ($fh == $client_listen || $fh == $client_listen6) {
+ } elsif (($client_listen && $fh == $client_listen) || ($client_listen6 && $fh == $client_listen6)) {
do_new_client($sock, $buf);
- } elsif ($fh == $server_listen || $fh == $server_listen6) {
+ } elsif (($server_listen && $fh == $server_listen) || ($server_listen6 && $fh == $server_listen6)) {
do_new_server($sock, $buf);
}
}
@@ -355,33 +366,42 @@ sub do_new_client {
if ($buf =~ /^ID:(\w+)/) {
my $id = $1;
+ if (exists $ID{$id} && exists $ID{$id}{client} && $ID{$id}{client} eq "0") {
+ if (!established($ID{$id}{sock})) {
+ lprint("server socket for ID:$id is no longer established, closing it.");
+ close $ID{$id}{sock};
+ delete $ID{$id};
+ } else {
+ lprint("server socket for ID:$id is still established.");
+ }
+ }
if (exists $ID{$id}) {
if ($ID{$id}{client}) {
my $ref = $refuse;
if ($ref && !established($ID{$id}{sock})) {
- print "socket for ID:$id is no longer established, closing it.\n";
+ lprint("socket for ID:$id is no longer established, closing it.");
$ref = 0;
}
if ($ref) {
- print "refusing extra vnc client for ID:$id\n";
+ lprint("refusing extra vnc client for ID:$id.");
close $sock;
return;
} else {
- print "closing and deleting previous vnc client with ID:$id\n";
+ lprint("closing and deleting previous vnc client with ID:$id.");
close $ID{$id}{sock};
- print "storing new vnc client with ID:$id\n";
+ lprint("storing new vnc client with ID:$id.");
$ID{$id}{client} = 1;
$ID{$id}{sock} = $sock;
}
} else {
- print "hooking up new vnc client with existing vnc server for ID:$id\n";
+ lprint("hooking up new vnc client with existing vnc server for ID:$id.");
my $sock2 = $ID{$id}{sock};
delete $ID{$id};
hookup($sock, $sock2, "ID:$id");
}
} else {
- print "storing new vnc client with ID:$id\n";
+ lprint("storing new vnc client with ID:$id.");
$ID{$id}{client} = 1;
$ID{$id}{sock} = $sock;
}
@@ -400,32 +420,32 @@ sub do_new_client {
}
if ($port < 0) {
my $pnew = -$port;
- print "resetting port from $port to $pnew\n";
+ lprint("resetting port from $port to $pnew.");
$port = $pnew;
} elsif ($port < 200) {
my $pnew = $port + 5900;
- print "resetting port from $port to $pnew\n";
+ lprint("resetting port from $port to $pnew.");
$port = $pnew;
}
- print "making vnc client connection directly to vnc server host='$host' port='$port'\n";
+ lprint("making vnc client connection directly to vnc server host='$host' port='$port'.");
my $sock2 = IO::Socket::INET->new(
PeerAddr => $host,
PeerPort => $port,
Proto => "tcp"
);
if (! $sock2 && $have_inet6) {
- print "IPv4 connect error: $!, trying IPv6 ...\n";
+ lprint("IPv4 connect error: $!, trying IPv6 ...");
eval{$sock2 = IO::Socket::INET6->new(
PeerAddr => $host,
PeerPort => $port,
Proto => "tcp"
);};
- print "IPv6 connect error: $!\n" if !$sock2;
+ lprint("IPv6 connect error: $!") if !$sock2;
} else {
- print "IPv4 connect error: $!\n" if !$sock2;
+ lprint("IPv4 connect error: $!") if !$sock2;
}
if (!$sock2) {
- print "failed to connect to $host:$port\n";
+ lprint("failed to connect to $host:$port.");
close $sock;
return;
}
@@ -439,48 +459,79 @@ sub do_new_server {
if ($buf =~ /^ID:(\w+)/) {
my $id = $1;
my $store = 1;
+ if (exists $ID{$id} && exists $ID{$id}{client} && $ID{$id}{client} eq "1") {
+ if (!established($ID{$id}{sock})) {
+ lprint("client socket for ID:$id is no longer established, closing it.");
+ close $ID{$id}{sock};
+ delete $ID{$id};
+ } else {
+ lprint("client socket for ID:$id is still established.");
+ }
+ }
if (exists $ID{$id}) {
if (! $ID{$id}{client}) {
my $ref = $refuse;
if ($ref && !established($ID{$id}{sock})) {
- print "socket for ID:$id is no longer established, closing it.\n";
+ lprint("socket for ID:$id is no longer established, closing it.");
$ref = 0;
}
if ($ref) {
- print "refusing extra vnc server for ID:$id\n";
+ lprint("refusing extra vnc server for ID:$id.");
close $sock;
return;
} else {
- print "closing and deleting previous vnc server with ID:$id\n";
+ lprint("closing and deleting previous vnc server with ID:$id.");
close $ID{$id}{sock};
- print "storing new vnc server with ID:$id\n";
+ lprint("storing new vnc server with ID:$id.");
$ID{$id}{client} = 0;
$ID{$id}{sock} = $sock;
}
} else {
- print "hooking up new vnc server with existing vnc client for ID:$id\n";
+ lprint("hooking up new vnc server with existing vnc client for ID:$id.");
my $sock2 = $ID{$id}{sock};
delete $ID{$id};
hookup($sock, $sock2, "ID:$id");
}
} else {
- print "storing new vnc server with ID:$id\n";
+ lprint("storing new vnc server with ID:$id.");
$ID{$id}{client} = 0;
$ID{$id}{sock} = $sock;
}
} else {
- print "invalid ID:NNNNN string for vnc server: $buf\n";
+ lprint("invalid ID:NNNNN string for vnc server: $buf");
close $sock;
return;
}
}
sub established {
+ my $fh = shift;
+
+ return established_linux_proc($fh);
+
+ # not working:
+ my $est = 1;
+ my $str = "Z";
+ my $res;
+ #$res = recv($fh, $str, 1, MSG_PEEK | MSG_DONTWAIT);
+ if (defined($res)) {
+ lprint("established OK: $! '$str'.");
+ $est = 1;
+ } else {
+ # would check for EAGAIN here to decide ...
+ lprint("established err: $! '$str'.");
+ $est = 1;
+ }
+ return $est;
+}
+
+
+sub established_linux_proc {
# hack for Linux to see if remote side has gone away:
my $fh = shift;
- # if we can't figure things out, we return true.
+ # if we can't figure things out, we must return true.
if ($uname !~ /Linux/) {
return 1;
}
@@ -549,7 +600,7 @@ sub established {
}
sub handler {
- print STDERR "$prog\[$$/$CURR]: got SIGTERM.\n";
+ lprint("\[$$/$CURR] got SIGTERM.");
close $SOCK1 if $SOCK1;
close $SOCK2 if $SOCK2;
exit;
@@ -561,7 +612,7 @@ sub hookup {
my $worker = fork();
if (! defined $worker) {
- print "failed to fork worker: $!\n";
+ lprint("failed to fork worker: $!");
close $sock1;
close $sock2;
return;
@@ -604,10 +655,10 @@ sub xfer {
my $len = sysread($in, $buf, 8192);
if (! defined($len)) {
next if $! =~ /^Interrupted/;
- print STDERR "$prog\[$$/$CURR]: $!\n";
+ lprint("\[$$/$CURR] $!");
last;
} elsif ($len == 0) {
- print STDERR "$prog\[$$/$CURR]: Input is EOF.\n";
+ lprint("\[$$/$CURR] Input is EOF.");
last;
}
my $offset = 0;
@@ -615,7 +666,7 @@ sub xfer {
while ($len) {
my $written = syswrite($out, $buf, $len, $offset);
if (! defined $written) {
- print STDERR "$prog\[$$/$CURR]: Output is EOF. $!\n";
+ lprint("\[$$/$CURR] Output is EOF. $!");
$quit = 1;
last;
}
@@ -626,7 +677,7 @@ sub xfer {
}
close($out);
close($in);
- print STDERR "$prog\[$$/$CURR]: finished xfer.\n";
+ lprint("\[$$/$CURR] finished xfer.");
}
sub xfer_both {
@@ -637,7 +688,7 @@ sub xfer_both {
my $child = fork();
if (! defined $child) {
- print STDERR "$prog\[$$/$CURR] failed to fork: $!\n";
+ lprint("$prog\[$$/$CURR] failed to fork: $!");
return;
}
@@ -645,30 +696,30 @@ sub xfer_both {
$SIG{INT} = "handler";
if ($child) {
- print STDERR "$prog parent[$$/$CURR] 1 -> 2\n";
+ lprint("[$$/$CURR] parent 1 -> 2.");
xfer($sock1, $sock2);
select(undef, undef, undef, 0.25);
if (kill 0, $child) {
select(undef, undef, undef, 0.9);
if (kill 0, $child) {
- print STDERR "$prog\[$$/$CURR]: kill TERM child $child\n";
+ lprint("\[$$/$CURR] kill TERM child $child");
kill "TERM", $child;
} else {
- print STDERR "$prog\[$$/$CURR]: child $child gone.\n";
+ lprint("\[$$/$CURR] child $child gone.");
}
}
} else {
select(undef, undef, undef, 0.05);
- print STDERR "$prog child [$$/$CURR] 2 -> 1\n";
+ lprint("[$$/$CURR] child 2 -> 1.");
xfer($sock2, $sock1);
select(undef, undef, undef, 0.25);
if (kill 0, $parent) {
select(undef, undef, undef, 0.8);
if (kill 0, $parent) {
- print STDERR "$prog\[$$/$CURR]: kill TERM parent $parent\n";
+ lprint("\[$$/$CURR] kill TERM parent $parent.");
kill "TERM", $parent;
} else {
- print STDERR "$prog\[$$/$CURR]: parent $parent gone.\n";
+ lprint("\[$$/$CURR] parent $parent gone.");
}
}
}
diff --git a/x11vnc/sslhelper.c b/x11vnc/sslhelper.c
index 0cb120c..a363eee 100644
--- a/x11vnc/sslhelper.c
+++ b/x11vnc/sslhelper.c
@@ -1923,6 +1923,8 @@ static void pr_ssl_info(int verb) {
static void ssl_timeout (int sig) {
int i;
rfbLog("sig: %d, ssl_init[%d] timed out.\n", sig, getpid());
+ rfbLog("To increase the SSL initialization timeout use, e.g.:\n");
+ rfbLog(" -env SSL_INIT_TIMEOUT=120 (for 120 seconds)\n");
for (i=0; i < 256; i++) {
close(i);
}
@@ -1944,10 +1946,17 @@ static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
if (getenv("SSL_DEBUG")) {
db = atoi(getenv("SSL_DEBUG"));
}
+ usleep(100 * 1000);
if (getenv("SSL_INIT_TIMEOUT")) {
timeout = atoi(getenv("SSL_INIT_TIMEOUT"));
+ } else if (client_connect != NULL && strstr(client_connect, "repeater")) {
+ rfbLog("SSL: ssl_init[%d]: detected 'repeater' in connect string.\n", getpid());
+ rfbLog("SSL: setting timeout to 1 hour: -env SSL_INIT_TIMEOUT=3600\n");
+ rfbLog("SSL: use that option to set a different timeout value,\n");
+ rfbLog("SSL: however note that with Windows UltraVNC repeater it\n");
+ rfbLog("SSL: may timeout before your setting due to other reasons.\n");
+ timeout = 3600;
}
- if (db) fprintf(stderr, "ssl_init: %d/%d\n", s_in, s_out);
if (skip_vnc_tls) {
rfbLog("SSL: ssl_helper[%d]: HTTPS mode, skipping check_vnc_tls_mode()\n",
@@ -1955,6 +1964,8 @@ static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
} else if (!check_vnc_tls_mode(s_in, s_out, last_https)) {
return 0;
}
+ rfbLog("SSL: ssl_init[%d]: %d/%d initialization timeout: %d secs.\n",
+ getpid(), s_in, s_out, timeout);
ssl = SSL_new(ctx);
if (ssl == NULL) {
@@ -2026,32 +2037,32 @@ static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
} else if (err == SSL_ERROR_WANT_READ) {
if (db) fprintf(stderr, "got SSL_ERROR_WANT_READ\n");
- rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n",
- getpid(), name, peerport);
+ rfbLog("SSL: ssl_helper[%d]: %s() failed for: %s:%d 1\n",
+ getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", name, peerport);
pr_ssl_info(1);
return 0;
} else if (err == SSL_ERROR_WANT_WRITE) {
if (db) fprintf(stderr, "got SSL_ERROR_WANT_WRITE\n");
- rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n",
- getpid(), name, peerport);
+ rfbLog("SSL: ssl_helper[%d]: %s() failed for: %s:%d 2\n",
+ getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", name, peerport);
pr_ssl_info(1);
return 0;
} else if (err == SSL_ERROR_SYSCALL) {
if (db) fprintf(stderr, "got SSL_ERROR_SYSCALL\n");
- rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n",
- getpid(), name, peerport);
+ rfbLog("SSL: ssl_helper[%d]: %s() failed for: %s:%d 3\n",
+ getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", name, peerport);
pr_ssl_info(1);
return 0;
} else if (err == SSL_ERROR_ZERO_RETURN) {
if (db) fprintf(stderr, "got SSL_ERROR_ZERO_RETURN\n");
- rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n",
- getpid(), name, peerport);
+ rfbLog("SSL: ssl_helper[%d]: %s() failed for: %s:%d 4\n",
+ getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", name, peerport);
pr_ssl_info(1);
return 0;
@@ -2059,7 +2070,8 @@ static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
unsigned long err;
int cnt = 0;
- rfbLog("SSL: ssl_helper[%d]: SSL_accept() *FATAL: %d SSL FAILED\n", getpid(), rc);
+ rfbLog("SSL: ssl_helper[%d]: %s() *FATAL: %d SSL FAILED\n",
+ getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", rc);
while ((err = ERR_get_error()) != 0) {
rfbLog("SSL: %s\n", ERR_error_string(err, NULL));
if (cnt++ > 100) {
@@ -2071,8 +2083,8 @@ static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
} else if (dnow() > start + 3.0) {
- rfbLog("SSL: ssl_helper[%d]: timeout looping SSL_accept() "
- "fatal.\n", getpid());
+ rfbLog("SSL: ssl_helper[%d]: timeout looping %s() "
+ "fatal.\n", getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept");
pr_ssl_info(1);
return 0;
diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1
index 05a5683..2b09a19 100644
--- a/x11vnc/x11vnc.1
+++ b/x11vnc/x11vnc.1
@@ -2,7 +2,7 @@
.TH X11VNC "1" "April 2010" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
- version: 0.9.10, lastmod: 2010-04-22
+ version: 0.9.10, lastmod: 2010-04-28
.SH SYNOPSIS
.B x11vnc
[OPTION]...
@@ -697,6 +697,28 @@ newline and carriage return. "\\c" is expanded to
See also the \fB-proxy\fR option below for additional ways
to plumb reverse connections.
.IP
+Reverse SSL: using \fB-connect\fR in \fB-ssl\fR mode makes x11vnc
+act as an SSL client (initiates SSL connection) rather
+than an SSL server. The idea is x11vnc might be
+connecting to stunnel on the viewer side with the
+viewer in listening mode. If you do not want this
+behavior, use \fB-env\fR X11VNC_DISABLE_SSL_CLIENT_MODE=1.
+With this the viewer side can act as the SSL client
+as it normally does for forward connections.
+.IP
+Reverse SSL Repeater mode: This will work, but note
+that if the VNC Client does any sort of a 'Fetch Cert'
+action before connecting, then the Repeater will
+likely drop the connection and both sides will need
+to restart. Consider the use of \fB-connect_or_exit\fR
+and \fB-loop300,2\fR to have x11vnc reconnect once to the
+repeater after the fetch. You will probably also want
+to supply \fB-sslonly\fR to avoid x11vnc thinking the delay
+in response means the connection is VeNCrypt. The env
+var X11VNC_DISABLE_SSL_CLIENT_MODE=1 discussed above
+may also be useful (i.e. the viewer can do a forward
+connection as it normally does.)
+.IP
IPv6: as of x11vnc 0.9.10 the \fB-connect\fR option should
connect to IPv6 hosts properly. If there are problems
you can disable IPv6 by setting \fB-DX11VNC_IPV6=0\fR
diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c
index ee335cf..1e03394 100644
--- a/x11vnc/x11vnc_defs.c
+++ b/x11vnc/x11vnc_defs.c
@@ -47,7 +47,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
-char lastmod[] = "0.9.10 lastmod: 2010-04-22";
+char lastmod[] = "0.9.10 lastmod: 2010-04-28";
/* X display info */
diff --git a/x11vnc/xrecord.c b/x11vnc/xrecord.c
index ab32fbe..4f79dce 100644
--- a/x11vnc/xrecord.c
+++ b/x11vnc/xrecord.c
@@ -535,12 +535,13 @@ static double xrecord_start = 0.0;
static void record_CA(XPointer ptr, XRecordInterceptData *rec_data) {
xCopyAreaReq *req;
Window src = None, dst = None, c;
- XWindowAttributes attr;
- int src_x, src_y, dst_x, dst_y, rx, ry;
- int good = 1, dx, dy, k=0, i;
+ XWindowAttributes attr, attr2;
+ int src_x, src_y, dst_x, dst_y, rx, ry, rx2, ry2;
+ int good = 1, dx = 0, dy = 0, k=0, i;
unsigned int w, h;
int dba = 0, db = debug_scroll;
int cache_index, next_index, valid;
+ static int must_equal = -1;
if (dba || db) {
if (rec_data->category == XRecordFromClient) {
@@ -584,6 +585,13 @@ if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
}
if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
+ if (must_equal < 0) {
+ must_equal = 0;
+ if (getenv("X11VNC_SCROLL_MUST_EQUAL")) {
+ must_equal = 1;
+ }
+ }
+
/*
xterm, gnome-terminal, others.
@@ -618,25 +626,36 @@ short period of time with a painting error: two cursors, one above the other.
h = req->height;
if (w*h < (unsigned int) scrollcopyrect_min_area) {
+ if (db > 1) fprintf(stderr, "record_CA scroll area too small.\n");
good = 0;
} else if (!src || !dst) {
- good = 0;
- } else if (src != dst) {
+ if (db > 1) fprintf(stderr, "record_CA null src or dst.\n");
good = 0;
} else if (scr_ev_cnt >= SCR_EV_MAX) {
+ if (db > 1) fprintf(stderr, "record_CA null too many scr events.\n");
+ good = 0;
+ } else if (must_equal && src != dst) {
+ if (db > 1) fprintf(stderr, "record_CA src not equal dst.\n");
good = 0;
}
- dx = dst_x - src_x;
- dy = dst_y - src_y;
+ if (src == dst) {
+ dx = dst_x - src_x;
+ dy = dst_y - src_y;
- if (dx != 0 && dy != 0) {
- good = 0;
+ if (dx != 0 && dy != 0) {
+ good = 0;
+ }
}
+if (!good && (dba || db > 1)) fprintf(stderr, "record_CA-x src_x: %d src_y: %d "
+ "dst_x: %d dst_y: %d w: %d h: %d scr_ev_cnt: %d 0x%lx/0x%lx\n",
+ src_x, src_y, dst_x, dst_y, w, h, scr_ev_cnt, src, dst);
+
if (! good) {
return;
}
+
if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
/*
@@ -687,14 +706,84 @@ if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
}
if (! valid) {
+ if (db > 1) fprintf(stderr, "record_CA not valid-1.\n");
return;
}
if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
if (attr.map_state != IsViewable) {
+ if (db > 1) fprintf(stderr, "record_CA not viewable-1.\n");
return;
}
+ /* recent gdk/gtk windows use different src and dst. for compositing? */
+ if (src != dst) {
+ if (lookup_attr_cache(dst, &cache_index, &next_index)) {
+ i = cache_index;
+ attr2.x = scr_attr_cache[i].x;
+ attr2.y = scr_attr_cache[i].y;
+ attr2.width = scr_attr_cache[i].width;
+ attr2.height = scr_attr_cache[i].height;
+ attr2.map_state = scr_attr_cache[i].map_state;
+ rx2 = scr_attr_cache[i].rx;
+ ry2 = scr_attr_cache[i].ry;
+ valid = scr_attr_cache[i].valid;
+
+ } else {
+ valid = valid_window(dst, &attr2, 1);
+
+ if (valid) {
+ if (!xtranslate(dst, rootwin, 0, 0, &rx2, &ry2, &c, 1)) {
+ valid = 0;
+ }
+ }
+ if (next_index >= 0) {
+ i = next_index;
+ scr_attr_cache[i].win = dst;
+ scr_attr_cache[i].fetched = 1;
+ scr_attr_cache[i].valid = valid;
+ scr_attr_cache[i].time = dnow();
+ if (valid) {
+ scr_attr_cache[i].x = attr2.x;
+ scr_attr_cache[i].y = attr2.y;
+ scr_attr_cache[i].width = attr2.width;
+ scr_attr_cache[i].height = attr2.height;
+ scr_attr_cache[i].border_width = attr2.border_width;
+ scr_attr_cache[i].depth = attr2.depth;
+ scr_attr_cache[i].class = attr2.class;
+ scr_attr_cache[i].backing_store =
+ attr2.backing_store;
+ scr_attr_cache[i].map_state = attr2.map_state;
+
+ scr_attr_cache[i].rx = rx2;
+ scr_attr_cache[i].ry = ry2;
+ }
+ }
+ }
+
+if (dba || db > 1) fprintf(stderr, "record_CA-? src_x: %d src_y: %d "
+ "dst_x: %d dst_y: %d w: %d h: %d scr_ev_cnt: %d 0x%lx/0x%lx\n",
+ src_x, src_y, dst_x, dst_y, w, h, scr_ev_cnt, src, dst);
+
+ if (! valid) {
+ if (db > 1) fprintf(stderr, "record_CA not valid-2.\n");
+ return;
+ }
+ if (attr2.map_state != IsViewable) {
+ if (db > 1) fprintf(stderr, "record_CA not viewable-2.\n");
+ return;
+ }
+ dst_x = dst_x - (rx - rx2);
+ dst_y = dst_y - (ry - ry2);
+
+ dx = dst_x - src_x;
+ dy = dst_y - src_y;
+
+ if (dx != 0 && dy != 0) {
+ return;
+ }
+ }
+
if (0 || dba || db) {
double st, dt;
@@ -1546,14 +1635,30 @@ void check_xrecord_reset(int force) {
#endif
}
-#define RECORD_ERROR_MSG \
+#define RECORD_ERROR_MSG(tag) \
if (! quiet) { \
- rfbLog("trapped RECORD XError: %s %d/%d/%d (0x%lx)\n", \
- xerror_string(trapped_record_xerror_event), \
- (int) trapped_record_xerror_event->error_code, \
- (int) trapped_record_xerror_event->request_code, \
- (int) trapped_record_xerror_event->minor_code, \
- (int) trapped_record_xerror_event->resourceid); \
+ static int cnt = 0; \
+ static time_t last = 0; \
+ int show = 0; \
+ cnt++; \
+ if (debug_scroll || cnt < 20) { \
+ show = 1; \
+ } else if (cnt == 20) { \
+ last = time(NULL); \
+ rfbLog("disabling RECORD XError messages for 600s\n"); \
+ show = 1; \
+ } else if (time(NULL) > last + 600) { \
+ cnt = 0; \
+ show = 1; \
+ } \
+ if (show) { \
+ rfbLog("trapped RECORD XError: %s %s %d/%d/%d (0x%lx)\n", \
+ tag, xerror_string(trapped_record_xerror_event), \
+ (int) trapped_record_xerror_event->error_code, \
+ (int) trapped_record_xerror_event->request_code, \
+ (int) trapped_record_xerror_event->minor_code, \
+ (int) trapped_record_xerror_event->resourceid); \
+ } \
}
void xrecord_watch(int start, int setby) {
@@ -1659,7 +1764,7 @@ if (db > 1) fprintf(stderr, "=== shutdown-scroll 0x%lx\n", rc_scroll);
XRecordProcessReplies(rdpy_data);
if (trapped_record_xerror) {
- RECORD_ERROR_MSG;
+ RECORD_ERROR_MSG("shutdown");
last_error = now;
}
@@ -1683,7 +1788,7 @@ if (db > 1) fprintf(stderr, "=== disab-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scr
XRecordProcessReplies(rdpy_data);
if (trapped_record_xerror) {
- RECORD_ERROR_MSG;
+ RECORD_ERROR_MSG("disable");
shutdown_record_context(rc_scroll,
0, reopen_dpys);
@@ -1906,7 +2011,7 @@ if (db > 1) fprintf(stderr, "=-= reg-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scr
if (db) fprintf(stderr, "rc_scroll: 0x%lx\n", rc_scroll);
if (trapped_record_xerror) {
- RECORD_ERROR_MSG;
+ RECORD_ERROR_MSG("register");
}
if (! rc_scroll) {
@@ -1955,7 +2060,7 @@ if (db) fprintf(stderr, "rc_scroll: 0x%lx\n", rc_scroll);
rfbLog("failed to enable RECORD context "
"rc_scroll: 0x%lx rc: %d\n", rc_scroll, rc);
if (trapped_record_xerror) {
- RECORD_ERROR_MSG;
+ RECORD_ERROR_MSG("enable-failed");
}
}
shutdown_record_context(rc_scroll, 0, reopen_dpys);