diff options
35 files changed, 4359 insertions, 589 deletions
@@ -1,3 +1,8 @@ +2006-04-05 Karl Runge <runge@karlrunge.com> + * classes/ssl: SSL Java viewer workarounds for firewall + proxies (signed applet as last resort, proxy.vnc). + include ssl_vncviewer stunnel wrapper script. + 2006-03-28 Steven Carr <scarr@jsa-usa.com> * SDLvncviewer.c, rfbproto.c, vncviewer.c, main.c, rfbserver.c, rfb.h, rfbclient.h, rfbproto.h: add new encoding: KeyboardLedState diff --git a/classes/ssl/Makefile.am b/classes/ssl/Makefile.am index 66c8719..f7ac523 100644 --- a/classes/ssl/Makefile.am +++ b/classes/ssl/Makefile.am @@ -1,2 +1,2 @@ -EXTRA_DIST=VncViewer.jar index.vnc +EXTRA_DIST=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc README ssl_vncviewer diff --git a/classes/ssl/README b/classes/ssl/README new file mode 100644 index 0000000..884e34a --- /dev/null +++ b/classes/ssl/README @@ -0,0 +1,72 @@ +This directory contains a patched Java applet VNC viewer that is SSL +enabled. + +The patches in the *.patch files are relative to the source tarball: + + tightvnc-1.3dev7_javasrc.tar.gz + +currently (4/06) available here: + + http://prdownloads.sourceforge.net/vnc-tight/tightvnc-1.3dev7_javasrc.tar.gz?download + +It also includes some simple patches to: + + - fix richcursor colors + + - make the Java Applet cursor (not the cursor drawn to the canvas + framebuffer) invisible when it is inside the canvas. + + - allow Tab (and some other) keystrokes to be sent to the vnc + server instead of doing widget traversal. + + +This SSL applet should work with any VNC viewer that has an SSL tunnel in +front of it. It has been tested on x11vnc and using the stunnel tunnel +to other VNC servers. + +By default this Vnc Viewer will only do SSL. To do unencrypted traffic +see the "DisableSSL" applet parameter (e.g. set it to Yes in index.vnc). + +Proxies: they are a general problem with java socket applets (a socket +connection does not go through the proxy). See the info in the proxy.vnc +file for a workaround. It uses SignedVncViewer.jar which is simply +a signed version of VncViewer.jar. The basic idea is the user clicks +"Yes" to trust the applet and then it can connect directly to the proxy +and issue a CONNECT request. + +This applet has been tested on versions 1.4.2 and 1.5.0 of the Sun +Java plugin. It may not work on older releases or different vendor VM's. +Send full Java Console output for failures. + +--------------------------------------------------------------- +Tips: + +When doing single-port proxy connections (e.g. both VNC and HTTPS +thru port 5900) it helps to move through the 'do you trust this site' +dialogs quickly. x11vnc has to wait to see if the traffic is VNC or +HTTP and this can cause timeouts if you don't move thru them quickly. + +You may have to restart your browser completely if it gets into a +weird state. For one case we saw the JVM requesting VncViewer.class +even when no such file exists. + + +--------------------------------------------------------------- +Extras: + +ssl_vncviewer (not Java): + + Wrapper script for native VNC viewer to connect to x11vnc in + SSL mode. Script launches stunnel(8) and then connects to it + via localhost which in turn is then redirected to x11vnc via an + SSL tunnel. stunnel(8) must be installed and available in PATH. + + +Running Java SSL VncViewer from the command line: + + From this directory: + + java -cp ./VncViewer.jar VncViewer HOST <thehost> PORT <theport> + + substitute <thehost> and <theport> with the actual values. + diff --git a/classes/ssl/SignedVncViewer.jar b/classes/ssl/SignedVncViewer.jar Binary files differnew file mode 100644 index 0000000..20b3ddc --- /dev/null +++ b/classes/ssl/SignedVncViewer.jar diff --git a/classes/ssl/VncViewer.jar b/classes/ssl/VncViewer.jar Binary files differindex 7e36267..116f49c 100644 --- a/classes/ssl/VncViewer.jar +++ b/classes/ssl/VncViewer.jar diff --git a/classes/ssl/proxy.vnc b/classes/ssl/proxy.vnc new file mode 100644 index 0000000..9bb30e4 --- /dev/null +++ b/classes/ssl/proxy.vnc @@ -0,0 +1,70 @@ +<!-- + index.vnc - default HTML page for TightVNC Java viewer applet, to be + used with Xvnc. On any file ending in .vnc, the HTTP server embedded in + Xvnc will substitute the following variables when preceded by a dollar: + USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT, + PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated + HTML page. + + NOTE: the $PARAMS variable is not supported by the standard VNC, so + make sure you have TightVNC on the server side, if you're using this + variable. +--> + +<!-- +The idea behind using the signed applet in SignedVncViewer.jar for +firewall proxies: + +Java socket applets and http proxies do not get along well. + +Java security allows the applet to connect back via a socket to the +originating host, but the browser/plugin Proxy settings are not used for +socket connections (only http and the like). So the socket connection +fails in the proxy environment. + +The applet is not allowed to open a socket connection to the proxy (since +that would let it connect to just about any host, e.g. CONNECT method). + +This is indpendent of SSL but of course fails for that socket connection +as well. I.e. this is a problem for non-SSL VNC Viewers as well. + +Solution? Sign the applet and have the user click on "Yes" that they +fully trust the applet. Then the applet can connect to any host via +sockets, in particular the proxy. It next issues the request + + CONNECT host:port HTTP/1.1 + Host: host:port + +and if the proxy supports the CONNECT method we are finally connected to +the VNC server. + +For SSL connections, SSL is layered on top of this socket. However note +this scheme will work for non-SSL applet proxy tunnelling as well. + +It should be able to get non-SSL VNC connections to work via GET +command but that has not been done yet. + +Note that some proxies only allow CONNECT to only these the ports 443 +(HTTPS) and 563 (SNEWS). So you would have to run the VNC server on +those ports. + +SignedVncViewer.jar is just a signed version of VncViewer.jar + +The URL to use for this file: https://host:port/proxy.vnc + +--> + + +<HTML> +<TITLE> +$USER's $DESKTOP desktop ($DISPLAY) +</TITLE> +<APPLET CODE=VncViewer.class ARCHIVE=SignedVncViewer.jar + WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT> +<param name=PORT value=$PORT> +<param name="Open New Window" value=yes> +$PARAMS +</APPLET> +<BR> +<A href="http://www.tightvnc.com/">TightVNC site</A> +</HTML> diff --git a/classes/ssl/ssl_vncviewer b/classes/ssl/ssl_vncviewer new file mode 100755 index 0000000..4f69a1c --- /dev/null +++ b/classes/ssl/ssl_vncviewer @@ -0,0 +1,142 @@ +#!/bin/sh +# +# ssl_vncviewer: wrapper for vncviewer to use stunnel SSL tunnel. +# +# You must have stunnel(8) installed on the system and in your +# PATH (n.b. stunnel is usually in an sbin subdir). +# +# You should have "x11vnc -ssl ..." or "x11vnc -stunnel ..." +# running as the VNC server. +# +# usage: ssl_vncviewer [cert-args] host:display <vncviewer-args> +# +# e.g.: ssl_vncviewer snoopy:0 +# ssl_vncviewer snoopy:0 -encodings "copyrect tight zrle hextile" +# +# [cert-args] can be: +# -verify /path/to/cacert.pem +# -mycert /path/to/mycert.pem +# +# -verify specifies a CA cert PEM file (or a self-signed one) for +# authenticating the VNC server. +# +# -mycert specifies this client's cert+key PEM file for the VNC server to +# authenticate this client. +# + +VNCVIEWERCMD="vncviewer" +PATH=$PATH:/usr/sbin:/usr/local/sbin:/dist/sbin; export PATH + +help() { + head -26 $0 | tail +2 +} + +# grab our cmdline options: +while [ "X$1" != "X" ] +do + case $1 in + "-verify") shift; verify="$1" + ;; + "-mycert") shift; mycert="$1" + ;; + "-h"*) help; exit 0 + ;; + *) break + ;; + esac + shift +done + +orig="$1" +shift + +# play around with host:display port: +if ! echo "$orig" | grep ':' > /dev/null; then + orig="$orig:0" +fi + +host=`echo "$orig" | awk -F: '{print $1}'` +disp=`echo "$orig" | awk -F: '{print $2}'` +if [ $disp -lt 200 ]; then + port=`expr $disp + 5900` +fi + +# try to find an open listening port via netstat(1): +use="" +if uname | grep Linux > /dev/null; then + inuse=`netstat -ant | grep LISTEN | awk '{print $4}' | sed 's/^.*://'` + try=5920 + while [ $try -lt 6000 ] + do + if ! echo "$inuse" | grep -w $try > /dev/null; then + use=$try + break + fi + try=`expr $try + 1` + done +fi +if [ "X$use" = "X" ]; then + # otherwise choose a "random" one: + use=`date +%S` + use=`expr $use + 5920` +fi + +# create the stunnel config file: +if [ "X$verify" != "X" ]; then + if [ -d $verify ]; then + verify="CApath = $verify" + else + verify="CAfile = $verify" + fi + verify="$verify +verify = 2" +fi +if [ "X$mycert" != "X" ]; then + cert="cert = $mycert" +fi + +##debug = 7 +tmp=/tmp/ssl_vncviewer.$$ +cat > $tmp <<END +foreground = yes +pid = +client = yes +$verify +$cert + +[vnc_stunnel] +accept = $use +connect= $host:$port +END + +echo "" +echo "Using this stunnel configuration:" +cat $tmp +echo "" +sleep 1 + +echo "running: stunnel $tmp" +stunnel $tmp < /dev/tty > /dev/tty & +pid=$! +echo "" + +# pause here to let the user supply a possible passphrase for the +# mycert key: +if [ "X$mycert" != "X" ]; then + sleep 4 +fi +sleep 2 +rm -f $tmp + +if [ $use -ge 5900 ]; then + n=`expr $use - 5900` +fi + +if echo "$0" | grep vncip > /dev/null; then + # hack for runge's special wrapper script vncip. + vncip "$@" localhost:$n +else + $VNCVIEWERCMD "$@" localhost:$n +fi + +kill $pid diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch index 48f0dc4..298f7f9 100644 --- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch +++ b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch @@ -38,7 +38,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile @$(ExportJavaClasses) 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/RfbProto.java 2006-03-27 22:26:25.000000000 -0500 ++++ vnc_javasrc/RfbProto.java 2006-04-03 11:22:30.000000000 -0400 @@ -199,7 +199,21 @@ host = h; port = p; @@ -64,8 +64,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto try { 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/SSLSocketToMe.java 2006-03-27 20:45:59.000000000 -0500 -@@ -0,0 +1,481 @@ ++++ vnc_javasrc/SSLSocketToMe.java 2006-04-04 13:17:39.000000000 -0400 +@@ -0,0 +1,1040 @@ +/* + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. + * @@ -92,7 +92,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL +import java.io.*; +import javax.net.ssl.*; +import java.security.cert.*; -+import java.util.Vector; ++import java.util.*; + +import java.awt.*; +import java.awt.event.*; @@ -109,14 +109,32 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + SSLSocket socket = null; + SSLSocketFactory factory; + ++ /* fallback for Proxy connection */ ++ boolean proxy_in_use = false; ++ boolean proxy_failure = false; ++ public DataInputStream is = null; ++ public OutputStream os = null; ++ ++ Socket proxySock; ++ DataInputStream proxy_is; ++ OutputStream proxy_os; ++ + /* trust contexts */ ++ SSLContext trustloc_ctx; + SSLContext trustall_ctx; ++ SSLContext trusturl_ctx; + SSLContext trustone_ctx; ++ + TrustManager[] trustAllCerts; ++ TrustManager[] trustUrlCert; + TrustManager[] trustOneCert; + ++ boolean use_url_cert_for_auth = true; ++ boolean user_wants_to_see_cert = true; ++ + /* cert(s) we retrieve from VNC server */ -+ java.security.cert.Certificate[] serverCerts = null; ++ java.security.cert.Certificate[] trustallCerts = null; ++ java.security.cert.Certificate[] trusturlCerts = null; + + SSLSocketToMe(String h, int p, VncViewer v) throws Exception { + host = h; @@ -131,6 +149,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + + /* create trust managers used if initial handshake fails: */ + ++ + trustAllCerts = new TrustManager[] { + /* + * this one accepts everything. @@ -149,13 +168,65 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + java.security.cert.X509Certificate[] certs, + String authType) { + /* empty */ ++ dbg("ALL: an untrusted connect to grab cert."); + } + } + }; + ++ trustUrlCert = new TrustManager[] { ++ /* ++ * this one accepts only the retrieved server cert ++ * by SSLSocket by this applet. ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ throw new CertificateException("No Clients"); ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ if (trusturlCerts == null) { ++ throw new CertificateException( ++ "No Trust url Certs array."); ++ } ++ if (trusturlCerts.length < 1) { ++ throw new CertificateException( ++ "No Trust url Certs."); ++ } ++ if (trusturlCerts.length > 1) { ++ throw new CertificateException( ++ "Too many Trust url Certs."); ++ } ++ if (certs == null) { ++ throw new CertificateException( ++ "No this-certs array."); ++ } ++ if (certs.length < 1) { ++ throw new CertificateException( ++ "No this-certs Certs."); ++ } ++ if (certs.length > 1) { ++ throw new CertificateException( ++ "Too many this-certs."); ++ } ++ if (! trusturlCerts[0].equals(certs[0])) { ++ throw new CertificateException( ++ "Server Cert Changed != URL."); ++ } ++ dbg("URL: trusturlCerts[0] matches certs[0]"); ++ } ++ } ++ }; + trustOneCert = new TrustManager[] { + /* -+ * this one accepts only the retrieved server cert. ++ * this one accepts only the retrieved server cert ++ * by SSLSocket by this applet. + */ + new X509TrustManager() { + public java.security.cert.X509Certificate[] @@ -170,19 +241,35 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, + String authType) throws CertificateException { -+ if (serverCerts == null) { ++ if (trustallCerts == null) { ++ throw new CertificateException( ++ "No Trust All Server Certs array."); ++ } ++ if (trustallCerts.length < 1) { ++ throw new CertificateException( ++ "No Trust All Server Certs."); ++ } ++ if (trustallCerts.length > 1) { ++ throw new CertificateException( ++ "Too many Trust All Server Certs."); ++ } ++ if (certs == null) { + throw new CertificateException( -+ "No Server Certs array."); ++ "No this-certs array."); + } -+ if (serverCerts.length < 1) { ++ if (certs.length < 1) { + throw new CertificateException( -+ "No Server Certs."); ++ "No this-certs Certs."); + } -+ if (! serverCerts[0].equals(certs[0])) { ++ if (certs.length > 1) { + throw new CertificateException( -+ "Server Cert Changed."); ++ "Too many this-certs."); + } -+ dbg("serverCerts[0] matches certs[0]"); ++ if (! trustallCerts[0].equals(certs[0])) { ++ throw new CertificateException( ++ "Server Cert Changed != TRUSTALL."); ++ } ++ dbg("ONE: trustallCerts[0] matches certs[0]"); + } + } + }; @@ -195,6 +282,18 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + * 2) to subsequently connect to the server if user agrees. + */ + ++ /* trust loc certs: */ ++ try { ++ trustloc_ctx = SSLContext.getInstance("SSL"); ++ trustloc_ctx.init(null, null, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trustloc_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ + /* trust all certs: */ + try { + trustall_ctx = SSLContext.getInstance("SSL"); @@ -207,6 +306,18 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + throw new Exception(msg); + } + ++ /* trust url certs: */ ++ try { ++ trusturl_ctx = SSLContext.getInstance("SSL"); ++ trusturl_ctx.init(null, trustUrlCert, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trusturl_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ + /* trust the one cert from server: */ + try { + trustone_ctx = SSLContext.getInstance("SSL"); @@ -220,23 +331,121 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + } + ++ boolean browser_cert_match() { ++ String msg = "Browser URL accept previously accepted cert"; ++ ++ if (user_wants_to_see_cert) { ++ return false; ++ } ++ ++ if (trustallCerts != null && trusturlCerts != null) { ++ if (trustallCerts.length == 1 && trusturlCerts.length == 1) { ++ if (trustallCerts[0].equals(trusturlCerts[0])) { ++ System.out.println(msg); ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ + public Socket connectSock() throws IOException { + -+ /* now connect to host:port */ -+ socket = (SSLSocket) factory.createSocket(host, port); ++ /* ++ * 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 { ++ HttpsURLConnection https = (HttpsURLConnection) ++ url.openConnection(); ++ ++ https.setUseCaches(false); ++ https.setRequestMethod("GET"); ++ https.setRequestProperty("Pragma", "No-Cache"); ++ https.setRequestProperty("Proxy-Connection", ++ "Keep-Alive"); ++ https.setDoInput(true); ++ ++ https.connect(); ++ ++ trusturlCerts = https.getServerCertificates(); ++ ++ if (https.usingProxy()) { ++ proxy_in_use = true; ++ dbg("HTTPS proxy in use. There may be connection problems."); ++ } ++ Object output = https.getContent(); ++ https.disconnect(); ++ ++ } catch(Exception e) { ++ trusturlCerts = null; ++ } ++ ++ if (use_url_cert_for_auth && trusturlCerts != null) { ++ factory = trusturl_ctx.getSocketFactory(); ++ } else { ++ factory = trustloc_ctx.getSocketFactory(); ++ } ++ ++ socket = null; ++ try { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } catch (Exception esock) { ++ if (proxy_in_use) { ++ proxy_failure = true; ++ dbg("HTTPS proxy in use. Trying to go with it."); ++ try { ++ socket = proxy_socket(factory); ++ } catch (Exception e) { ++ dbg("err proxy_socket: " + e.getMessage()); ++ } ++ } ++ } + + try { -+ /* -+ * Verified the first time! How can that be? ;-) -+ * They actually went thru the trouble to set it up? -+ */ + socket.startHandshake(); -+ dbg("Server Connection Verified."); ++ dbg("Server Connection Verified on 1st try."); ++ ++ java.security.cert.Certificate[] currentTrustedCerts; ++ BrowserCertsDialog bcd; ++ ++ SSLSession sess = socket.getSession(); ++ currentTrustedCerts = sess.getPeerCertificates(); ++ ++ if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { ++ socket.close(); ++ socket = null; ++ throw new SSLHandshakeException("no current certs"); ++ } ++ ++ String serv = ""; ++ try { ++ CertInfo ci = new CertInfo(currentTrustedCerts[0]); ++ serv = ci.get_certinfo("CN"); ++ } catch (Exception e) { ++ ; ++ } ++ ++ bcd = new BrowserCertsDialog(serv, host + ":" + port); ++ bcd.queryUser(); ++ if (bcd.showCertDialog) { ++ String msg = "user wants to see cert"; ++ dbg(msg); ++ user_wants_to_see_cert = true; ++ throw new SSLHandshakeException(msg); ++ } else { ++ user_wants_to_see_cert = false; ++ dbg("bcd: user said yes, accept it"); ++ } + -+ } catch (Exception ehand) { ++ } catch (SSLHandshakeException eh) { + dbg("Could not automatically verify Server."); ++ dbg("msg: " + eh.getMessage()); + + socket.close(); ++ socket = null; + + /* + * Reconnect, trusting any cert, so we can grab @@ -244,7 +453,11 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + * is not used for anything else. + */ + factory = trustall_ctx.getSocketFactory(); -+ socket = (SSLSocket) factory.createSocket(host, port); ++ if (proxy_failure) { ++ socket = proxy_socket(factory); ++ } else { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } + + try { + socket.startHandshake(); @@ -253,33 +466,32 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + /* grab the cert: */ + try { + SSLSession sess = socket.getSession(); -+ serverCerts = sess.getPeerCertificates(); ++ trustallCerts = sess.getPeerCertificates(); + } catch (Exception e) { + throw new Exception("Could not get " + + "Peer Certificate"); + } + -+ /* -+ * close socket now, we will reopen after -+ * dialog if user agrees to use the cert. -+ */ -+ socket.close(); ++ if (! browser_cert_match()) { ++ /* ++ * close socket now, we will reopen after ++ * dialog if user agrees to use the cert. ++ */ ++ socket.close(); ++ socket = null; + -+ /* dialog with user to accept cert or not: */ ++ /* dialog with user to accept cert or not: */ + -+ TrustDialog td= new TrustDialog(host, port, -+ serverCerts); ++ TrustDialog td= new TrustDialog(host, port, ++ trustallCerts); + -+ if (! td.queryUser()) { -+ String msg = "User decided against it."; -+ dbg(msg); -+ throw new IOException(msg); ++ if (! td.queryUser()) { ++ String msg = "User decided against it."; ++ dbg(msg); ++ throw new IOException(msg); ++ } + } + -+ // idea to save certs for reconnections. -+ // not working (RfbProto thread terminates). -+ //viewer.acceptedCerts.addCerts(serverCerts); -+ + } catch (Exception ehand2) { + dbg("** Could not TrustAll Verify Server."); + @@ -293,7 +505,11 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + */ + + factory = trustone_ctx.getSocketFactory(); -+ socket = (SSLSocket) factory.createSocket(host, port); ++ if (proxy_failure) { ++ socket = proxy_socket(factory); ++ } else { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } + + try { + socket.startHandshake(); @@ -315,12 +531,171 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + System.out.println(s); + } + } ++ ++ public SSLSocket proxy_socket(SSLSocketFactory factory) { ++ Properties props = null; ++ String proxyHost = null; ++ int proxyPort = 0; ++ ++ /* see if we can guess the proxy info from Properties: */ ++ try { ++ props = System.getProperties(); ++ } catch (Exception e) { ++ dbg("props failed: " + e.getMessage()); ++ } ++ if (props != null) { ++ dbg("\n---------------\nAll props:"); ++ props.list(System.out); ++ dbg("\n---------------\n\n"); ++ ++ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { ++ String s = (String) e.nextElement(); ++ String v = System.getProperty(s); ++ String l1 = s.toLowerCase(); ++ String l2 = v.toLowerCase(); ++ ++ if (l1.indexOf("proxy") < 0 && l2.indexOf("proxy") < 0) { ++ continue; ++ } ++ if (l2.indexOf("https") < 0) { ++ continue; ++ } ++ ++ String[] pieces = v.split("[,;]"); ++ for (int i = 0; i < pieces.length; i++) { ++ String p = pieces[i]; ++ int j = p.indexOf("https"); ++ if (j < 0) { ++ continue; ++ } ++ j = p.indexOf("=", j); ++ if (j < 0) { ++ continue; ++ } ++ p = p.substring(j+1); ++ String [] hp = p.split(":"); ++ if (hp.length != 2) { ++ continue; ++ } ++ if (hp[0].length() > 1 && hp[1].length() > 1) { ++ try { ++ Integer I = new Integer(hp[1]); ++ proxyPort = I.intValue(); ++ } catch (Exception ex) { ++ continue; ++ } ++ proxyHost = new String(hp[0]); ++ break; ++ } ++ } ++ } ++ } ++ 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(); ++ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); ++ } ++ ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("1 sadly, returning a null socket"); ++ return null; ++ } ++ String hp = host + ":" + port; ++ ++ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" ++ + "Host: " + hp + "\r\n\r\n"; ++ ++ /* not working for SSL yet: */ ++ String req2 = "GET https://" + hp ++ + "/request.https.proxy.connection HTTP/1.1\r\n" ++ + "Host: " + hp + "\r\n\r\n"; ++ ++ dbg("requesting: " + req1); ++ ++ try { ++ proxy_os.write(req1.getBytes()); ++ String reply = readline(proxy_is); ++ ++ 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 sadly, returning a null socket"); ++ return null; ++ } ++ dbg("requesting: " + req2); ++ proxy_os.write(req2.getBytes()); ++ ++ reply = readline(proxy_is); ++ ++ dbg("proxy replied: " + reply); ++ } ++ } catch(Exception e) { ++ dbg("sock prob: " + e.getMessage()); ++ } ++ ++ while (true) { ++ String line = readline(proxy_is); ++ dbg("proxy line: " + line); ++ if (line.equals("\r\n") || line.equals("\n")) { ++ break; ++ } ++ } ++ ++ Socket sslsock = null; ++ try { ++ sslsock = factory.createSocket(proxySock, host, port, true); ++ } catch(Exception e) { ++ dbg("sslsock prob: " + e.getMessage()); ++ dbg("3 sadly, returning a null socket"); ++ } ++ ++ return (SSLSocket) sslsock; ++ } ++ ++ Socket psocket(String h, int p) { ++ Socket psock = null; ++ try { ++ psock = new Socket(h, p); ++ proxy_is = new DataInputStream(new BufferedInputStream( ++ psock.getInputStream(), 16384)); ++ proxy_os = psock.getOutputStream(); ++ } catch(Exception e) { ++ dbg("psocket prob: " + e.getMessage()); ++ return null; ++ } ++ ++ return psock; ++ } ++ ++ String readline(DataInputStream i) { ++ byte[] ba = new byte[1]; ++ String s = new String(""); ++ ba[0] = 0; ++ try { ++ while (ba[0] != 0xa) { ++ ba[0] = (byte) i.readUnsignedByte(); ++ s += new String(ba); ++ } ++ } catch (Exception e) { ++ ; ++ } ++ return s; ++ } +} + +class TrustDialog implements ActionListener { + String msg, host, text; + int port; -+ java.security.cert.Certificate[] serverCerts = null; ++ java.security.cert.Certificate[] trustallCerts = null; + boolean viewing_cert = false; + boolean trust_this_session = false; + @@ -339,51 +714,34 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + + " this VNC server"; + String ln = "\n---------------------------------------------------\n\n"; + -+ TrustDialog (String h, int p, java.security.cert.Certificate[] certs) { ++ TrustDialog (String h, int p, java.security.cert.Certificate[] s) { + host = h; + port = p; -+ serverCerts = certs; ++ trustallCerts = s; + + msg = "VNC Server " + host + ":" + port + " Not Verified"; + } + + public boolean queryUser() { + -+// idea to save certs between connections. not working, everything is -+// cleared after each new connection. -+// -+// public boolean queryUser(VncViewer viewer) { -+// int i, j; -+// java.security.cert.Certificate cert; -+// -+// for (i=0; i < viewer.acceptedCerts.allCerts.size(); i++) { -+// System.out.println("try " + i); -+// -+// cert = (java.security.cert.Certificate) -+// viewer.acceptedCerts.allCerts.elementAt(i); -+// -+// for (j=0; j < serverCerts.length; j++) { -+// System.out.println("try " + i + " " + j); -+// if (serverCerts[j].equals(cert)) { -+// System.out.println("accept previously accepted cert"); -+// /* matched, no need for dialog */ -+// return true; -+// } -+// } -+// } -+ + /* create and display the dialog for unverified cert. */ + + Frame frame = new Frame(msg); + + dialog = new Dialog(frame, true); + ++ String infostr = ""; ++ if (trustallCerts.length == 1) { ++ CertInfo ci = new CertInfo(trustallCerts[0]); ++ infostr = ci.get_certinfo("all"); ++ } ++ + text = "\n" ++ "Unable to verify the identity of\n" ++ "\n" ++ " " + host + ":" + port + "\n" ++ "\n" -++ get_certinfo() +++ infostr ++ "\n" ++ "as a trusted VNC server.\n" ++ "\n" @@ -473,12 +831,12 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + int i; + /* show all (likely just one) certs: */ + textarea.setText(""); -+ for (i=0; i < serverCerts.length; i++) { ++ for (i=0; i < trustallCerts.length; i++) { + int j = i + 1; + textarea.append("Certificate[" + + j + "]\n\n"); + textarea.append( -+ serverCerts[i].toString()); ++ trustallCerts[i].toString()); + textarea.append(ln); + } + viewcert.setLabel("View Info"); @@ -508,11 +866,11 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + String all = ""; + String fields[] = {"CN", "OU", "O", "L", "C"}; + int i; -+ if (serverCerts.length < 1) { ++ if (trustallCerts.length < 1) { + all = ""; + return all; + } -+ String cert = serverCerts[0].toString(); ++ String cert = trustallCerts[0].toString(); + + /* + * For now we simply scrape the cert string, there must @@ -547,6 +905,207 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + return all; + } +} ++ ++class ProxyDialog implements ActionListener { ++ String guessedHost = null; ++ String guessedPort = null; ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry; ++ String reply = ""; ++ ++ ProxyDialog (String h, int p) { ++ guessedHost = h; ++ try { ++ guessedPort = Integer.toString(p); ++ } catch (Exception e) { ++ guessedPort = "8080"; ++ } ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Need Proxy host:port"); ++ ++ dialog = new Dialog(frame, true); ++ ++ ++ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); ++ //label.setFont(new Font("Helvetica", Font.BOLD, 16)); ++ entry = new TextField(30); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ String guess = ""; ++ if (guessedHost != null) { ++ guess = guessedHost + ":" + guessedPort; ++ } ++ entry.setText(guess); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry); ++ dialog.add("South", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return; ++ } ++ ++ public String getHost() { ++ int i = reply.indexOf(":"); ++ if (i < 0) { ++ return "unknown"; ++ } ++ String h = reply.substring(0, i); ++ return h; ++ } ++ ++ public int getPort() { ++ int i = reply.indexOf(":"); ++ int p = 8080; ++ if (i < 0) { ++ return p; ++ } ++ i++; ++ String ps = reply.substring(i); ++ try { ++ Integer I = new Integer(ps); ++ p = I.intValue(); ++ } catch (Exception e) { ++ ; ++ } ++ return p; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply = entry.getText(); ++ dialog.dispose(); ++ } ++ } ++} ++ ++class BrowserCertsDialog implements ActionListener { ++ Button yes, no; ++ Dialog dialog; ++ String vncServer; ++ String hostport; ++ public boolean showCertDialog = true; ++ ++ BrowserCertsDialog(String serv, String hp) { ++ vncServer = serv; ++ hostport = hp; ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Use Browser/JVM Certs?"); ++ ++ dialog = new Dialog(frame, true); ++ ++ String m = "\nShould this VNC Viewer applet use your Browser/JVM certs to\n"; ++ m += "authenticate the VNC Server:\n"; ++ m += "\n " + hostport + "\n\n " + vncServer + "\n\n"; ++ m += "(NOTE: this *includes* any certs you have Just Now accepted in a\n"; ++ m += "dialog box with your Web Browser or Java Applet Plugin)\n\n"; ++ ++ TextArea textarea = new TextArea(m, 12, 64, ++ TextArea.SCROLLBARS_VERTICAL_ONLY); ++ textarea.setEditable(false); ++ yes = new Button("Yes"); ++ yes.addActionListener(this); ++ no = new Button("No, Let Me See the Certificate."); ++ no.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", textarea); ++ dialog.add("Center", yes); ++ dialog.add("South", no); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til Yes or No pressed. */ ++ return; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == yes) { ++ showCertDialog = false; ++ dialog.dispose(); ++ } else if (evt.getSource() == no) { ++ showCertDialog = true; ++ dialog.dispose(); ++ } ++ } ++} ++ ++class CertInfo { ++ String fields[] = {"CN", "OU", "O", "L", "C"}; ++ java.security.cert.Certificate cert; ++ String certString = ""; ++ ++ CertInfo(java.security.cert.Certificate c) { ++ cert = c; ++ certString = cert.toString(); ++ } ++ ++ String get_certinfo(String which) { ++ int i; ++ String cs = new String(certString); ++ String all = ""; ++ ++ /* ++ * For now we simply scrape the cert string, there must ++ * be an API for this... perhaps optionValue? ++ */ ++ for (i=0; i < fields.length; i++) { ++ int f, t, t1, t2; ++ String sub, mat = fields[i] + "="; ++ ++ f = cs.indexOf(mat, 0); ++ if (f > 0) { ++ t1 = cs.indexOf(", ", f); ++ t2 = cs.indexOf("\n", f); ++ if (t1 < 0 && t2 < 0) { ++ continue; ++ } else if (t1 < 0) { ++ t = t2; ++ } else if (t2 < 0) { ++ t = t1; ++ } else if (t1 < t2) { ++ t = t1; ++ } else { ++ t = t2; ++ } ++ if (t > f) { ++ sub = cs.substring(f, t); ++ all = all + " " + sub + "\n"; ++ if (which.equals(fields[i])) { ++ return sub; ++ } ++ } ++ } ++ } ++ if (which.equals("all")) { ++ return all; ++ } else { ++ return ""; ++ } ++ } ++} 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/VncViewer.java 2006-03-27 22:20:19.000000000 -0500 diff --git a/configure.ac b/configure.ac index 49d2b1b..54bc547 100644 --- a/configure.ac +++ b/configure.ac @@ -59,6 +59,7 @@ AH_TEMPLATE(HAVE_LIBXTRAP, [DEC-XTRAP extension build environment present]) AH_TEMPLATE(HAVE_RECORD, [RECORD extension build environment present]) AH_TEMPLATE(HAVE_SOLARIS_XREADSCREEN, [Solaris XReadScreen available]) AH_TEMPLATE(HAVE_IRIX_XREADDISPLAY, [IRIX XReadDisplay available]) +AH_TEMPLATE(HAVE_FBPM, [FBPM extension build environment present]) AC_ARG_WITH(xkeyboard, [ --without-xkeyboard disable xkeyboard extension support],,) @@ -74,6 +75,8 @@ AC_ARG_WITH(xtrap, [ --without-xtrap disable xtrap extension support],,) AC_ARG_WITH(xrecord, [ --without-xrecord disable xrecord extension support],,) +AC_ARG_WITH(fbpm, +[ --without-fbpm disable fbpm extension support],,) if test "$X_CFLAGS" != "-DX_DISPLAY_MISSING"; then AC_CHECK_LIB(X11, XGetImage, HAVE_X="true", @@ -95,6 +98,11 @@ if test "$X_CFLAGS" != "-DX_DISPLAY_MISSING"; then [AC_DEFINE(HAVE_IRIX_XREADDISPLAY)], , [#include <X11/Xlib.h>]) + AC_CHECK_HEADER(X11/extensions/fbpm.h, + [AC_DEFINE(HAVE_FBPM)], , + [#include <X11/Xlib.h> +#include <X11/Xmd.h>]) + AC_CHECK_LIB(Xtst, XTestGrabControl, X_PRELIBS="-lXtst $X_PRELIBS" [AC_DEFINE(HAVE_XTESTGRABCONTROL) HAVE_XTESTGRABCONTROL="true"], , diff --git a/prepare_x11vnc_dist.sh b/prepare_x11vnc_dist.sh index 014519c..08e03a4 100644 --- a/prepare_x11vnc_dist.sh +++ b/prepare_x11vnc_dist.sh @@ -62,7 +62,7 @@ cp classes/ssl/Makefile.am classes/ssl/Makefile.am.LibVNCServer sed -e 's/EXTRA_DIST=/EXTRA_DIST=tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch /' \ classes/ssl/Makefile.am.LibVNCServer > classes/ssl/Makefile.am echo 'pkgdatadir = $(datadir)/@PACKAGE@/classes/ssl' >> classes/ssl/Makefile.am -echo 'pkgdata_DATA=VncViewer.jar index.vnc' >> classes/ssl/Makefile.am +echo 'pkgdata_DATA=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc ssl_vncviewer README' >> classes/ssl/Makefile.am mv acinclude.m4 acinclude.m4.LibVNCServer diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index b661ba6..c8722d3 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,10 @@ +2006-04-05 Karl Runge <runge@karlrunge.com> + * x11vnc: add FBPM support (-fbpm) for Suns. -rawfb ZERO for + testing. Basic key+cert management utilities: -sslGenCA, + -sslGenCert, -sslEncKey, -sslDelCert, -sslCertInfo, and + addln features. SSL proxy connection. -storepasswd with + no args or pw echo. + 2006-03-26 Karl Runge <runge@karlrunge.com> * x11vnc: -xinerama now on by default. In -ssl mode accept https applet downloads thru VNC port. -https option for 2nd https diff --git a/x11vnc/Makefile.am b/x11vnc/Makefile.am index ccb22ed..8f2e880 100644 --- a/x11vnc/Makefile.am +++ b/x11vnc/Makefile.am @@ -13,7 +13,7 @@ endif if HAVE_X bin_PROGRAMS=x11vnc -x11vnc_SOURCES = 8to24.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c options.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c unixpw.c user.c userinput.c util.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h blackout_t.h cleanup.h connections.h cursor.h enums.h gui.h help.h inet.h keyboard.h options.h params.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h tkx11vnc.h unixpw.h user.h userinput.h util.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h +x11vnc_SOURCES = 8to24.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c options.c pm.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c unixpw.c user.c userinput.c util.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h blackout_t.h cleanup.h connections.h cursor.h enums.h gui.h help.h inet.h keyboard.h options.h params.h pm.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h ssltools.h tkx11vnc.h unixpw.h user.h userinput.h util.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h INCLUDES=@X_CFLAGS@ x11vnc_LDADD=$(LDADD) @X_LIBS@ $(LD_CYGIPC) endif diff --git a/x11vnc/README b/x11vnc/README index 7772c6c..17d5eed 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Mon Mar 27 23:19:59 EST 2006 +x11vnc README file Date: Wed Apr 5 14:16:10 EDT 2006 The following information is taken from these URLs: @@ -736,9 +736,9 @@ make protocol.) I suggest using xsetroot, dtstyle or similar utility to set a solid background while using x11vnc. You can turn the pretty background image back on when you are using the display directly. - Update: As of Feb/2005 in the libvncserver CVS, x11vnc has the - [92]-solid [color] option that works on recent GNOME, KDE, and CDE and - also on classic X (background image is on the root window). + Update: As of Feb/2005 x11vnc has the [92]-solid [color] option that + works on recent GNOME, KDE, and CDE and also on classic X (background + image is on the root window). I also find the [93]TightVNC encoding gives the best response for my usage (Unix <-> Unix over cable modem). One needs a tightvnc-aware @@ -1721,35 +1721,35 @@ x11vnc -wait 50 -localhost -rfbauth $HOME/.vnc/passwd -display :0 $* a similar thing can be done via aliases in your shell (bash, tcsh, csh, etc..). - Or as of Jun/2004 in the libvncserver CVS you can use the simple - $HOME/.x11vncrc config file support. If that file exists, each line is - taken as a command line option. E.g. the above would be: + Or as of Jun/2004 you can use the simple $HOME/.x11vncrc config file + support. If that file exists, each line is taken as a command line + option. E.g. the above would be: # this is a comment in my ~/.x11vncrc file wait 50 # this is a comment to the end of the line. -localhost # note: the leading "-" is optional. rfbauth /home/fred/.vnc/passwd display :0 - As of Dec/2004 in the libvncserver CVS there is now a simple Tcl/Tk - GUI based on the remote-control functionality ("-R") that was added. - The /usr/bin/wish program is needed for operation. The gui is not - particularly user-friendly, it just provides a point and click mode to - set all the many x11vnc parameters and obtain help on them. See the - [225]-gui option for more info. Examples: "x11vnc ... -gui" and - "x11vnc ... -gui other:0" in the latter case the gui is displayed on - other:0, not the X display x11vnc is polling. There is also a - "[226]-gui tray" system tray mode. + As of Dec/2004 there is now a simple Tcl/Tk GUI based on the + remote-control functionality ("-R") that was added. The /usr/bin/wish + program is needed for operation. The gui is not particularly + user-friendly, it just provides a point and click mode to set all the + many x11vnc parameters and obtain help on them. See the [225]-gui + option for more info. Examples: "x11vnc ... -gui" and "x11vnc ... -gui + other:0" in the latter case the gui is displayed on other:0, not the X + display x11vnc is polling. There is also a "[226]-gui tray" system + tray mode. Q-9: How can I get the GUI to run in the System Tray, or at least be a smaller, simpler icon? - As of Jul/2005 in the libvncserver CVS the gui can run in a more - friendly small icon mode "-gui icon" or in the system tray: "-gui - tray". It has balloon status, a simple menu, and a Properities dialog. - The full, complicated, gui is only available under "Advanced". Other - improvements were added as well. Try "Misc -> simple_gui" for a gui - with fewer esoteric menu items. + As of Jul/2005 the gui can run in a more friendly small icon mode + "-gui icon" or in the system tray: "-gui tray". It has balloon status, + a simple menu, and a Properities dialog. The full, complicated, gui is + only available under "Advanced". Other improvements were added as + well. Try "Misc -> simple_gui" for a gui with fewer esoteric menu + items. If the gui fails to embed itself in the system tray, do a retry via "Window View -> icon" followed by "Window View -> tray" with the popup @@ -1776,9 +1776,9 @@ display :0 the error message like: "Broken pipe". I'm using the -forever mode and I want x11vnc to keep running. - As of Jan/2004 in the libvncserver CVS the SIGPIPE signal is ignored. - So if a viewer client terminates abruptly, libvncserver will notice on - the next I/O operation and will close the connection and continue on. + As of Jan/2004 the SIGPIPE signal is ignored. So if a viewer client + terminates abruptly, libvncserver will notice on the next I/O + operation and will close the connection and continue on. Up until of Apr/2004 the above fix only works for BSD signal systems (Linux, FreeBSD, ...) For SYSV systems there is a workaround in place @@ -1843,7 +1843,7 @@ display :0 On some systems is seems you need to set LC_ALL=C for configure to work properly... - Be careful the the following two variables: HARDWIRE_PASSWD and + Be careful the following two variables: HARDWIRE_PASSWD and HARDWIRE_VIEWPASSWD. If set (remember to include the double quotes around the string), they will be used as default values for the -passwd and -viewpasswd options. Of course the strings will exist @@ -1894,11 +1894,11 @@ display :0 If so, there are a couple options. 1) Can you set the default visual on your display to be depth 24 TrueColor? Sun machines often have 8+24 overlay/multi-depth visuals, and you can make the default visual depth - 24 TrueColor (see fbconfig(1) and Xsun(1)). 2) As of Feb/2004, in the - libvncserver CVS, x11vnc has the [240]-visual option to allow you to - force the framebuffer visual to whatever you want (this usually messes - up the colors unless you are very clever). In this case, the option - provides a convenient workaround for the Win2VNC bug: + 24 TrueColor (see fbconfig(1) and Xsun(1)). 2) As of Feb/2004 x11vnc + has the [240]-visual option to allow you to force the framebuffer + visual to whatever you want (this usually messes up the colors unless + you are very clever). In this case, the option provides a convenient + workaround for the Win2VNC bug: x11vnc -nofb -visual TrueColor -display :0 ... So the visual will be set to 8bpp TrueColor and Win2VNC can handle @@ -2063,10 +2063,10 @@ TrueColor defdepth 24 visual and depth of the window printed out is often useful in debugging x11vnc [255]color problems. - Also, as of Dec/2004 libvncserver CVS you can use "[256]-id pick" to - have x11vnc run xwininfo(1) for you and after you click the window it - extracts the windowid. Besides "pick" there is also "id:root" to allow - you to go back to root window when doing remote-control. + Also, as of Dec/2004 you can use "[256]-id pick" to have x11vnc run + xwininfo(1) for you and after you click the window it extracts the + windowid. Besides "pick" there is also "id:root" to allow you to go + back to root window when doing remote-control. Q-18: Why don't menus or other transient windows come up when I am @@ -2231,11 +2231,10 @@ TrueColor defdepth 24 Q-23: How do I stop x11vnc once it is running in the background? - As of Dec/2004 in the libvncserver CVS there is a remote control - feature. It can change a huge amount of things on the fly: see the - [266]-remote and [267]-query options. To shut down the running x11vnc - server just type "x11vnc -R stop". To disconnect all clients do - "x11vnc -R disconnect:all", etc. + As of Dec/2004 there is a remote control feature. It can change a huge + amount of things on the fly: see the [266]-remote and [267]-query + options. To shut down the running x11vnc server just type "x11vnc -R + stop". To disconnect all clients do "x11vnc -R disconnect:all", etc. If the [268]-forever option has not been supplied, x11vnc will automatically exit after the first client disconnects. In general you @@ -2262,15 +2261,14 @@ TrueColor defdepth 24 Can I remote control it? Look at the [272]-remote (same as -R) and [273]-query (same as -Q) - options added in the Dec/2004 libvncserver CVS. They allow nearly - everything to be changed dynamically and settings to be queried. - Examples: "x11vnc -R shared", "x11vnc -R forever", "x11vnc -R - scale:3/4", "x11vnc -Q modtweak", "x11vnc -R stop", "x11vnc -R - disconnect:all", etc.. These commands do not start a x11vnc server, - but rather communicate with one that is already running. The X display - (X11VNC_REMOTE property) is used as the communication channel, so the - X permissions and DISPLAY must be set up correctly for communication - to be possible. + options added in Dec/2004. They allow nearly everything to be changed + dynamically and settings to be queried. Examples: "x11vnc -R shared", + "x11vnc -R forever", "x11vnc -R scale:3/4", "x11vnc -Q modtweak", + "x11vnc -R stop", "x11vnc -R disconnect:all", etc.. These commands do + not start a x11vnc server, but rather communicate with one that is + already running. The X display (X11VNC_REMOTE property) is used as the + communication channel, so the X permissions and DISPLAY must be set up + correctly for communication to be possible. There is also a simple Tcl/Tk gui based on this remote control mechanism. See the [274]-gui option for more info. You will need to @@ -2285,72 +2283,60 @@ TrueColor defdepth 24 You may already have one in $HOME/.vnc/passwd if you have used, say, the vncserver program from the regular RealVNC or TightVNC packages (i.e. launching the Xvnc server). Otherwise, you could use the - vncpasswd(1) program from those packages. The libvncserver package - also comes with a simple program: storepasswd in the examples - directory. And as of Jun/2004 in the libvncserver CVS x11vnc supports - the -storepasswd "pass" "file" [275]option, which is the the same - functionality of storepasswd. Be sure to quote the "pass" if it - contains shell meta characters, spaces, etc. Example: + vncpasswd(1) program from those packages. + + As of Jun/2004 x11vnc supports the -storepasswd "pass" "file" + [275]option, which is the same functionality of storepasswd. Be sure + to quote the "pass" if it contains shell meta characters, spaces, etc. + Example: x11vnc -storepasswd 'sword*fish' $HOME/myvncpasswd - You then use the password via the x11vnc option: [276]-rfbauth - $HOME/myvncpasswd + You then use the password via the x11vnc option: "[276]-rfbauth + $HOME/myvncpasswd" + + If you do not supply any arguments: + x11vnc -storepasswd - Compared to vncpasswd(1) the latter two methods are a somewhat unsafe - because the password is specified on the command line and so someone - may see it by using ps(1) or looking over your shoulder. Also watch - out for the command winding up in your shell's history file (history - -c is often a way to clear it). + you will be prompted for a password to save to ~/.vnc/passwd (your + keystrokes when entering the password will not be echoed to the + screen). x11vnc also has the [277]-passwdfile and -passwd/-viewpasswd plain text (i.e. not obscured like the -rfbauth VNC passwords) password options. + You can use the [278]-usepw option to automatically use any password + file you have in ~/.vnc/passwd or ~/.vnc/passwdfile (the latter is + used with the -passwdfile option). - Q-26: Can I make it so -storepasswd doesn't show my password on the - screen? - - You can use the vncpasswd program from RealVNC or TightVNC mentioned - above.. - - Alternatively, this script should keep your [278]-storepasswd more - private: -#!/bin/sh -# usage: x11vnc_pw [file] (default: ~/.vnc/passwd) - -if [ "X$1" = "X" ]; then - file=$HOME/.vnc/passwd -else - file=$1 -fi + x11vnc -usepw -display :0 ... -stty -echo -printf "Password: " -read pw1; echo "" -printf "Verify: " -read pw2; echo "" -stty echo + If neither file exists you are prompted to store a password in + ~/.vnc/passwd. If a password file cannot be found or created x11vnc + exits immediately. -if [ "X$pw1" != "X$pw2" ]; then - echo "passwords do not match." - exit 1 -fi -x11vnc -help > /dev/null 2>&1 -x11vnc -storepasswd "$pw1" "$file" -ls -l "$file" + Q-26: Can I make it so -storepasswd doesn't show my password on the + screen? - Note that there is a tiny window of time when x11vnc -storepasswd is - running that someone could snoop the value using ps(1). + You can use the vncpasswd program from RealVNC or TightVNC mentioned + above. As of Jan/2006 the -storepasswd option without any arguments + will not echo your password as you type it and save the file to + ~/.vnc/passwd: + # x11vnc -storepasswd + Enter VNC password: + Verify password: + Write password to /home/myname/.vnc/passwd? [y]/n + Password written to: /home/myname/.vnc/passwd Q-27: Can I have two passwords for VNC viewers, one for full access and the other for view-only access to the display? - Yes, as of May/2004 in the libvncserver CVS there is the - [279]-viewpasswd option to supply the view-only password. Note the - full-access password option [280]-passwd must be supplied at the same - time. E.g.: -passwd sword -viewpasswd fish. + Yes, as of May/2004 there is the [279]-viewpasswd option to supply the + view-only password. Note the full-access password option [280]-passwd + must be supplied at the same time. E.g.: -passwd sword -viewpasswd + fish. To avoid specifying the passwords on the command line (where they could be observed via the ps(1) command by any user) you can use the @@ -2460,12 +2446,11 @@ ls -l "$file" internal LAN) rather than having it listen on all network interfaces and relying on -allow to filter unwanted connections out? - As of Mar/2005 in the libvncserver CVS, there is the "[294]-listen - ipaddr" option that enables this. For ipaddr either supply the desired - network interface's IP address (or use a hostname that resolves to it) - or use the string "localhost". For additional filtering simultaneously - use the "[295]-allow host1,..." option to allow only specific hosts - in. + As of Mar/2005 there is the "[294]-listen ipaddr" option that enables + this. For ipaddr either supply the desired network interface's IP + address (or use a hostname that resolves to it) or use the string + "localhost". For additional filtering simultaneously use the + "[295]-allow host1,..." option to allow only specific hosts in. This option is useful if you want to insure that no one can even begin a dialog with x11vnc from untrusted network interfaces (e.g. ppp0). @@ -2651,7 +2636,7 @@ connect = 5900 One nice thing about version 4 is often the PEM file does not need to be specified because stunnel finds it in its installed area. One other - gotcha the the PEM file is usually only readable by root (it has the + gotcha the PEM file is usually only readable by root (it has the private key afterall), so you'll need to relax the permissions or make a copy that the user running x11vnc/stunnel can read. @@ -2699,10 +2684,10 @@ connect = 5900 PORT=5900 SSLPORT=5900 - The PEM file does not be supplied if the openssl(1) command is - available in PATH to create a self-signed, temporary certificate good - only for the single x11vnc session (this may take a while on slow - machines). + The PEM file does not need to be supplied if the openssl(1) command is + available in PATH, in that case a self-signed, temporary certificate + good only for the single x11vnc session is created (this may take a + while on slow machines). Otherwise you will have to create a certificate menually via openssl or the Java keytool utilities (or some other source). Then supply the @@ -3217,7 +3202,7 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg Continuously. Have x11vnc reattach each time the X server is restarted (i.e. after each logout): - To make x11vnc always attached to the the X server including the login + To make x11vnc always attached to the X server including the login screen you will need to add a command to a display manager startup script. @@ -3462,13 +3447,12 @@ service x11vncservice Q-48: Are reverse connections (i.e. the VNC server connecting to the VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? - As of Mar/2004 in the libvncserver CVS x11vnc supports reverse - connections. On Unix one starts the VNC viewer in listen mode: - vncviewer -listen (see your documentation for Windows, etc), and then - starts up x11vnc with the [369]-connect option. To connect immediately - at x11vnc startup time use the "-connect host:port" option (use commas - for a list of hosts to connect to). The ":port" is optional (default - is 5500). + As of Mar/2004 x11vnc supports reverse connections. On Unix one starts + the VNC viewer in listen mode: vncviewer -listen (see your + documentation for Windows, etc), and then starts up x11vnc with the + [369]-connect option. To connect immediately at x11vnc startup time + use the "-connect host:port" option (use commas for a list of hosts to + connect to). The ":port" is optional (default is 5500). If a file is specified instead: -connect /path/to/some/file then that file is checked periodically (about once a second) for new hosts to @@ -3791,10 +3775,10 @@ ied) Q-55: Does x11vnc support the X DAMAGE Xserver extension to find modified regions of the screen quickly and efficiently? - Yes, as of Mar/2005 in the libvncserver CVS x11vnc will use the X - DAMAGE extension by default if it is available on the display. This - requires libXdamage to be available in the build environment as well - (recent Linux distros and Solaris 10 have it). + Yes, as of Mar/2005 x11vnc will use the X DAMAGE extension by default + if it is available on the display. This requires libXdamage to be + available in the build environment as well (recent Linux distros and + Solaris 10 have it). The DAMAGE extension enables the X server to report changed regions of the screen back to x11vnc. So x11vnc doesn't have to guess where the @@ -3850,11 +3834,11 @@ ied) respect to that (updates are only packaged and sent when viewers ask for them). - As of Jan/2004 there are some improvements in the libvncserver CVS - tree. The default should now be much better than before and dragging - small windows around should no longer be a huge pain. If for some - reason these changes make matters worse, you can go back to the old - way via the "[409]-pointer_mode 1" option. + As of Jan/2004 there are some improvements to libvncserver. The + default should now be much better than before and dragging small + windows around should no longer be a huge pain. If for some reason + these changes make matters worse, you can go back to the old way via + the "[409]-pointer_mode 1" option. Also added was the [410]-nodragging option that disables all screen updates while dragging with the mouse (i.e. mouse motion with a button @@ -3862,9 +3846,9 @@ ied) in some circumstances when you want to see the visual feedback while dragging (e.g. menu traversal or text selection). - As of Dec/2004 in the libvncserver CVS the [411]-pointer_mode n option - was introduced. n=1 is the original mode, n=2 an improvement, etc.. - See the -pointer_mode n help for more info. + As of Dec/2004 the [411]-pointer_mode n option was introduced. n=1 is + the original mode, n=2 an improvement, etc.. See the -pointer_mode n + help for more info. Also, in some circumstances the [412]-threads option can improve response considerably. Be forewarned that if more than one vncviewer @@ -3872,27 +3856,27 @@ ied) (try to get the viewers to use different VNC encodings, e.g. tight and ZRLE). - As of Apr/2005 in the libvncserver CVS two new options (see the - [413]wireframe FAQ and [414]scrollcopyrect FAQ below) provide schemes - to sweep this problem under the rug for window moves or resizes and - for some (but not all) window scrolls. + As of Apr/2005 two new options (see the [413]wireframe FAQ and + [414]scrollcopyrect FAQ below) provide schemes to sweep this problem + under the rug for window moves or resizes and for some (but not all) + window scrolls. Q-57: Why not do something like wireframe animations to avoid the windows "lurching" when being moved or resized? - Nice idea for a hack! As of Apr/2005 in the libvncserver CVS x11vnc by - default will apply heuristics to try to guess if a window is being - (opaquely) moved or resized. If such a change is detected framebuffer - polling and updates will be suspended and only an animated "wireframe" - (a rectangle outline drawn where the moved/resized window would be) is - shown. When the window move/resize stops, it returns to normal - processing: you should only see the window appear in the new position. - This spares you from interacting with a "lurching" window between all - of the intermediate steps. BTW the lurching is due to [415]slow video - card read rates (see [416]here too). A displacement, even a small one, - of a large window requires a non-negligible amount of time, a good - fraction of a second, to read in from the hardware framebuffer. + Nice idea for a hack! As of Apr/2005 x11vnc by default will apply + heuristics to try to guess if a window is being (opaquely) moved or + resized. If such a change is detected framebuffer polling and updates + will be suspended and only an animated "wireframe" (a rectangle + outline drawn where the moved/resized window would be) is shown. When + the window move/resize stops, it returns to normal processing: you + should only see the window appear in the new position. This spares you + from interacting with a "lurching" window between all of the + intermediate steps. BTW the lurching is due to [415]slow video card + read rates (see [416]here too). A displacement, even a small one, of a + large window requires a non-negligible amount of time, a good fraction + of a second, to read in from the hardware framebuffer. Note that Opaque Moves/Resizes must be Enabled by your window manager for -wireframe to do any good. @@ -3983,14 +3967,14 @@ ied) Q-58: Can x11vnc try to apply heuristics to detect when an window is scrolling its contents and use the CopyRect encoding for a speedup? - Another nice idea for a hack! As of May/2005 in the libvncserver CVS - x11vnc will by default apply heuristics to try to detect if the the - window that has the input focus is scrolling its contents (but only - when x11vnc is feeding user input, keystroke or pointer, to the X - server). So, when detected, scrolls induced by dragging on a scrollbar - or by typing (e.g. Up or Down arrows, hitting Return in a terminal - window, etc), will show up much more quickly than via the standard - x11vnc screen polling update mechanism. + Another nice idea for a hack! As of May/2005 x11vnc will by default + apply heuristics to try to detect if the window that has the input + focus is scrolling its contents (but only when x11vnc is feeding user + input, keystroke or pointer, to the X server). So, when detected, + scrolls induced by dragging on a scrollbar or by typing (e.g. Up or + Down arrows, hitting Return in a terminal window, etc), will show up + much more quickly than via the standard x11vnc screen polling update + mechanism. There will be a speedup for both slow and fast links to viewers. For slow links the speedup is mostly due to the CopyRect encoding not @@ -4134,17 +4118,16 @@ ied) work for those cases. Also see the "[430]-cursor some" option for additional kludges. - Note that as of Aug/2004 in the libvncserver CVS, on Solaris using the - SUN_OVL overlay extension and IRIX, x11vnc can show the correct mouse - cursor when the [431]-overlay option is supplied. See [432]this FAQ - for more info. + Note that as of Aug/2004 on Solaris using the SUN_OVL overlay + extension and IRIX, x11vnc can show the correct mouse cursor when the + [431]-overlay option is supplied. See [432]this FAQ for more info. - Also as of Dec/2004 in the libvncserver CVS XFIXES X extension support - has been added to allow exact extraction of the mouse cursor shape. - XFIXES fixes the problem of the cursor-shape being write-only: x11vnc - can now query the X server for the current shape and send it back to - the connected viewers. XFIXES is available on recent Linux Xorg based - distros and [433]Solaris 10. + Also as of Dec/2004 XFIXES X extension support has been added to allow + exact extraction of the mouse cursor shape. XFIXES fixes the problem + of the cursor-shape being write-only: x11vnc can now query the X + server for the current shape and send it back to the connected + viewers. XFIXES is available on recent Linux Xorg based distros and + [433]Solaris 10. The only XFIXES issue is the handling of alpha channel transparency in cursors. If a cursor has any translucency then in general it must be @@ -4216,17 +4199,17 @@ ied) Q-61: In XFIXES mode, are there any hacks to handle cursor transparency ("alpha channel") exactly? - As of Jan/2005 in the CVS, libvncserver has been modified to allow an - alpha channel (i.e. RGBA data) for Rich Cursors. So x11vnc can now - send the alpha channel data to libvncserver. However, this data will - only be used for VNC clients that do not support the - CursorShapeUpdates VNC extension (or have disabled it). It can be - disabled for all clients with the [438]-nocursorshape x11vnc option. - In this case the cursor is drawn, correctly blended with the - background, into the VNC framebuffer before being sent out to the - client. So the alpha blending is done on the x11vnc side. Use the - [439]-noalphablend option to disable this behavior (always approximate - transparent cursors with opaque RGB values). + As of Jan/2005 libvncserver has been modified to allow an alpha + channel (i.e. RGBA data) for Rich Cursors. So x11vnc can now send the + alpha channel data to libvncserver. However, this data will only be + used for VNC clients that do not support the CursorShapeUpdates VNC + extension (or have disabled it). It can be disabled for all clients + with the [438]-nocursorshape x11vnc option. In this case the cursor is + drawn, correctly blended with the background, into the VNC framebuffer + before being sent out to the client. So the alpha blending is done on + the x11vnc side. Use the [439]-noalphablend option to disable this + behavior (always approximate transparent cursors with opaque RGB + values). The CursorShapeUpdates VNC extension complicates matters because the cursor shape is sent to the VNC viewers supporting it, and the viewers @@ -4258,10 +4241,10 @@ ied) the local VNC viewer. You may disable it with the [441]-nocursor option to x11vnc if your viewer does not have this extension. - Note: as of Aug/2004 in the libvncserver CVS this should be fixed: the - default for non-tightvnc viewers (or ones that do not support - CursorShapeUpdates) will be to draw the moving cursor into the x11vnc - framebuffer. This can also be disabled via -nocursor. + Note: as of Aug/2004 this should be fixed: the default for + non-tightvnc viewers (or ones that do not support CursorShapeUpdates) + will be to draw the moving cursor into the x11vnc framebuffer. This + can also be disabled via -nocursor. Q-63: Can I take advantage of the TightVNC extension to the VNC @@ -4271,9 +4254,8 @@ ied) Use the [442]-cursorpos option when starting x11vnc. A VNC viewer must support the Cursor Positions Updates for the user to see the mouse - motions (the TightVNC viewers support this). As of Aug/2004 in the - libvncserver CVS -cursorpos is the default. See also [443]-nocursorpos - and [444]-nocursorshape. + motions (the TightVNC viewers support this). As of Aug/2004 -cursorpos + is the default. See also [443]-nocursorpos and [444]-nocursorshape. Q-64: Is it possible to swap the mouse buttons (e.g. left-handed @@ -4345,14 +4327,13 @@ ied) correct keycode to send, possibly by sending fake modifier key presses and releases in addition to the actual keystroke. - Update: As of Jul/2004 in the libvncserver CVS, -modtweak is now the - default (use -nomodtweak to get the old behavior). This was done - because it was noticed on newer XFree86 setups even on bland "us" - keyboards like "pc104 us" XFree86 included a "ghost" key with both "<" - and ">" it. This key does not exist on the keyboard (see [449]this FAQ - for more info). Without -modtweak there was then an ambiguity in the - reverse map keysym => keycode, making it so the "<" symbol could not - be typed. + Update: As of Jul/2004 -modtweak is now the default (use -nomodtweak + to get the old behavior). This was done because it was noticed on + newer XFree86 setups even on bland "us" keyboards like "pc104 us" + XFree86 included a "ghost" key with both "<" and ">" it. This key does + not exist on the keyboard (see [449]this FAQ for more info). Without + -modtweak there was then an ambiguity in the reverse map keysym => + keycode, making it so the "<" symbol could not be typed. Also see the [450]FAQ about the -xkb option for a more powerful method of modifier tweaking for use on X servers with the XKEYBOARD @@ -4475,8 +4456,7 @@ ied) can't find the keysym "@" anywhere in the keymapping! (even though it is in the XKEYBOARD extended keymapping). - How to Solve: As of Jul/2004 in the libvncserver CVS x11vnc has two - changes: + How to Solve: As of Jul/2004 x11vnc has two changes: * -modtweak (tweak Modifier keys) is now the default (use -nomodtweak to go back to the old way) * there is a new option -xkb to use the XKEYBOARD extension API to @@ -4688,12 +4668,12 @@ ied) Q-75: Does x11vnc support server-side framebuffer scaling? (E.g. to make the desktop smaller). - As of Jun/2004 in the libvncserver CVS x11vnc provides basic - server-side scaling. It is a global scaling of the desktop, not a - per-client setting. To enable it use the "[479]-scale fraction" - option. "fraction" can either be a floating point number (e.g. -scale - 0.5) or the alternative m/n fraction notation (e.g. -scale 2/3). Note - that if fraction is greater than one the display is magnified. + As of Jun/2004 x11vnc provides basic server-side scaling. It is a + global scaling of the desktop, not a per-client setting. To enable it + use the "[479]-scale fraction" option. "fraction" can either be a + floating point number (e.g. -scale 0.5) or the alternative m/n + fraction notation (e.g. -scale 2/3). Note that if fraction is greater + than one the display is magnified. Extra resources (CPU, memory I/O, and memory) are required to do the scaling. If the machine is slow where x11vnc is run with scaling @@ -4749,11 +4729,11 @@ ied) gui process. Otherwise they all share the same X property channels: VNC_CONNECT and X11VNC_REMOTE. - Update: As of Mar/2005 in the libvncserver CVS x11vnc now scales the - mouse cursor with the same scale factor as the screen. If you don't - want that, use the [484]"-scale_cursor frac" option to set the cursor - scaling to a different factor (e.g. use "-scale_cursor 1" to keep the - cursor at its natural unscaled size). + Update: As of Mar/2005 x11vnc now scales the mouse cursor with the + same scale factor as the screen. If you don't want that, use the + [484]"-scale_cursor frac" option to set the cursor scaling to a + different factor (e.g. use "-scale_cursor 1" to keep the cursor at its + natural unscaled size). Q-76: Does x11vnc work with Xinerama? (i.e. multiple monitors joined @@ -4816,11 +4796,11 @@ ied) Q-78: Can x11vnc show only a portion of the display? (E.g. for a special purpose rfb application). - As of Mar/2005 in the libvncserver CVS x11vnc has the "[491]-clip - WxH+X+Y" option to select a rectangle of width W, height H and offset - (X, Y). Thus the VNC screen will be the clipped sub-region of the - display and be only WxH in size. One user used -clip to split up a - large [492]Xinerama screen into two more managable smaller screens. + As of Mar/2005 x11vnc has the "[491]-clip WxH+X+Y" option to select a + rectangle of width W, height H and offset (X, Y). Thus the VNC screen + will be the clipped sub-region of the display and be only WxH in size. + One user used -clip to split up a large [492]Xinerama screen into two + more managable smaller screens. This also works to view a sub-region of a single application window if the [493]-id or [494]-sid options are used. The offset is measured @@ -4831,11 +4811,11 @@ ied) extension? Whenever I rotate or resize the screen x11vnc just seems to crash. - As of Dec/2004 in the libvncserver CVS x11vnc supports XRANDR. You - enable it with the [495]-xrandr option to make x11vnc monitor XRANDR - events and also trap X server errors if the screen change occurred in - the middle of an X call like XGetImage. Once it traps the screen - change it will create a new framebuffer using the new screen. + As of Dec/2004 x11vnc supports XRANDR. You enable it with the + [495]-xrandr option to make x11vnc monitor XRANDR events and also trap + X server errors if the screen change occurred in the middle of an X + call like XGetImage. Once it traps the screen change it will create a + new framebuffer using the new screen. If the connected vnc viewers support the NewFBSize VNC extension (Windows TightVNC viewer and RealVNC 4.0 windows and Unix viewers do) @@ -4934,11 +4914,10 @@ ied) Q-83: Can non-X devices (e.g. a raw framebuffer) be viewed and/or controlled by x11vnc? - As of Apr/2005 in the libvncserver CVS there is rudimentary support - for this. Two options were added: "-rawfb string" (to indicate the raw - framembuffer and its parameters) and "-pipeinput cmd" (to provide an - external program that will inject or otherwise process mouse and - keystroke input). + As of Apr/2005 there is rudimentary support for this. Two options were + added: "-rawfb string" (to indicate the raw framembuffer and its + parameters) and "-pipeinput cmd" (to provide an external program that + will inject or otherwise process mouse and keystroke input). This non-X mode for x11vnc is experimental because it is so removed in scope from the intended usage of the tool. Little attempt is made to @@ -5098,13 +5077,12 @@ ied) Q-85: Does the Clipboard/Selection get transferred between the vncviewer and the X display? - As of Jan/2004 in the libvncserver CVS x11vnc supports the "CutText" - part of the rfb protocol. Furthermore, x11vnc is able to hold the - PRIMARY selection (Xvnc does not seem to do this). If you don't want - the Clipboard/Selection exchanged use the [504]-nosel option. If you - don't want the PRIMARY selection to be polled for changes use the - [505]-noprimary option. You can also fine-tune it a bit with the - [506]-seldir dir option. + As of Jan/2004 x11vnc supports the "CutText" part of the rfb protocol. + Furthermore, x11vnc is able to hold the PRIMARY selection (Xvnc does + not seem to do this). If you don't want the Clipboard/Selection + exchanged use the [504]-nosel option. If you don't want the PRIMARY + selection to be polled for changes use the [505]-noprimary option. You + can also fine-tune it a bit with the [506]-seldir dir option. You may need to watch out for desktop utilities such as KDE's "Klipper" that do odd things with the selection, clipboard, and @@ -5122,10 +5100,10 @@ ied) Q-87: Why don't I hear the "Beeps" in my X session (e.g. when typing tput bel in an xterm)? - As of Dec/2003 in the libvncserver CVS "Beep" XBell events are tracked - by default. The X server must support the XKEYBOARD extension (this is - not on by default in Solaris, see Xserver(1) for how to turn it on via - +kb), and so you won't hear them if the extension is not present. + As of Dec/2003 "Beep" XBell events are tracked by default. The X + server must support the XKEYBOARD extension (this is not on by default + in Solaris, see Xserver(1) for how to turn it on via +kb), and so you + won't hear them if the extension is not present. If you don't want to hear the beeps use the [508]-nobell option. If you want to hear the audio from the remote applications, consider @@ -5423,7 +5401,7 @@ References 275. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-storepasswd 276. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbauth 277. http://www.karlrunge.com/x11vnc/index.html#faq-passwdfile - 278. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-storepasswd + 278. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-usepw 279. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-viewpasswd 280. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-passwd 281. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-passwdfile @@ -5666,7 +5644,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.8.1 lastmod: 2006-03-27 +x11vnc: allow VNC connections to real X11 displays. 0.8.1 lastmod: 2006-04-05 x11vnc options: -display disp -auth file -id windowid @@ -5680,7 +5658,9 @@ x11vnc options: -vncconnect -novncconnect -allow host1[,host2..] -localhost -nolookup -input string -viewpasswd string -passwdfile filename -unixpw [list] - -unixpw_nis [list] -ssl [pem] -sslverify [path] + -unixpw_nis [list] -ssl [pem] -ssldir [dir] + -sslverify [path] -sslGenCA [dir] -sslGenCert type name + -sslEncKey [pem] -sslCertInfo [pem] -sslDelCert [pem] -stunnel [pem] -stunnel3 [pem] -https [port] -usepw -storepasswd pass file -nopw -accept string -afteraccept string -gone string @@ -5715,16 +5695,16 @@ x11vnc options: -debug_keyboard -defer time -wait time -wait_ui factor -nowait_bog -slow_fb time -readtimeout n -nap -nonap - -sb time -noxdamage -xd_area A - -xd_mem f -sigpipe string -threads - -nothreads -fs f -gaps n - -grow n -fuzz n -debug_tiles - -snapfb -rawfb string -pipeinput cmd - -gui [gui-opts] -remote command -query variable - -QD variable -sync -noremote - -yesremote -unsafe -safer - -privremote -nocmds -deny_all - + -sb time -nofbpm -fbpm + -noxdamage -xd_area A -xd_mem f + -sigpipe string -threads -nothreads + -fs f -gaps n -grow n + -fuzz n -debug_tiles -snapfb + -rawfb string -pipeinput cmd -gui [gui-opts] + -remote command -query variable -QD variable + -sync -noremote -yesremote + -unsafe -safer -privremote + -nocmds -deny_all libvncserver options: -rfbport port TCP port for RFB protocol @@ -5756,7 +5736,7 @@ libvncserver-tight-extension options: % x11vnc -help -x11vnc: allow VNC connections to real X11 displays. 0.8.1 lastmod: 2006-03-27 +x11vnc: allow VNC connections to real X11 displays. 0.8.1 lastmod: 2006-04-05 (type "x11vnc -opts" to just list the options.) @@ -6267,14 +6247,14 @@ Options: -unixpw_nis [list] As -unixpw above, however do not use su(1) but rather use the traditional getpwnam(3) + crypt(3) method to verify passwords instead. This requires that the - encrpyted passwords be readable. Passwords stored + encrypted passwords be readable. Passwords stored in /etc/shadow will be inaccessible unless x11vnc is run as root. This is called "NIS" mode simply because in most NIS setups the user encrypted passwords are accessible (e.g. "ypcat passwd"). NIS is not required for this - mode to work (only that getpwnam(3) return the encrpyted + mode to work (only that getpwnam(3) return the encrypted password is required), but it is unlikely it will work for any other modern environment. All of the -unixpw options and contraints apply. @@ -6288,18 +6268,19 @@ Options: [pem] is optional, use "-ssl /path/to/mycert.pem" to specify a PEM certificate file to use to identify - and provide a key for this server. See openssl(1) - for what a PEM can be. + and provide a key for this server. See openssl(1) for + more info about PEMs and the -sslGenCert option below. - Connecting VNC viewer SSL tunnels can optionally + The connecting VNC viewer SSL tunnel can optionally authenticate this server if they have the public key part of the certificate (or a common certificate authority, CA, is a more sophisicated way to verify - this server's cert). This is used to prevent - man-in-the-middle attacks. Otherwise, if the VNC - viewer accepts this server's key without verification, - at least the traffic is protected from passive sniffing - on the network (but NOT from man-in-the-middle attacks). + this server's cert, see -sslGenCA below). This is + used to prevent man-in-the-middle attacks. Otherwise, + if the VNC viewer accepts this server's key without + verification, at least the traffic is protected + from passive sniffing on the network (but NOT from + man-in-the-middle attacks). If [pem] is not supplied and the openssl(1) utility command exists in PATH, then a temporary, self-signed @@ -6312,15 +6293,34 @@ Options: temporary certificate, the public part of it will be displayed to stderr (e.g. one could copy it to the client-side to provide authentication of the server to - VNC viewers.) + VNC viewers.) See following paragraphs for how to save + keys to reuse when x11vnc is restarted. Set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc print out the entire certificate, including the PRIVATE KEY part, to stderr. One could reuse this cert if saved in a [pem] file. Similarly, set X11VNC_KEEP_TMP_PEM=1 to not delete the temporary PEM file: the file name - will be printed to stderr (so one could move it to a - safe place for reuse). + will be printed to stderr (so one could move it to + a safe place for reuse). You will be prompted for a + passphrase for the private key. + + If [pem] is "SAVE" then the certificate will be saved + to the file ~/.vnc/certs/server.pem, or if that file + exists it will be used directly. Similarly, if [pem] + is "SAVE_PROMPT" the server.pem certificate will be + made based on your answers to its prompts for info such + as OrganizationalName, CommonName, etc. + + Use "SAVE-<string>" and "SAVE_PROMPT-<string>" + to refer to the file ~/.vnc/certs/server-<string>.pem + instead. E.g. "SAVE-charlie" will store to the file + ~/.vnc/certs/server-charlie.pem + + See -ssldir below to use a directory besides the + default ~/.vnc/certs + + Example: x11vnc -ssl SAVE -display :0 ... Reverse connections are disabled in -ssl mode because there is no way to ensure that data channel will @@ -6328,33 +6328,368 @@ Options: override this. Your VNC viewer will also need to be able to connect - via SSL. See the discussion below under -stunnel - and the FAQ for how this might be achieved. E.g. on - Unix it is easy to write a shell script that starts up - stunnel and then vncviewer. Also in the x11vnc source - a SSL enabled Java VNC Viewer applet is provided in - the classes/ssl directory. + via SSL. See the discussion below under -stunnel and + the FAQ (ssl_vncviewer script) for how this might be + achieved. E.g. on Unix it is easy to write a shell + script that starts up stunnel and then vncviewer. + Also in the x11vnc source a SSL enabled Java VNC Viewer + applet is provided in the classes/ssl directory. + +-ssldir [dir] Use [dir] as an alternate ssl certificate and key + management toplevel directory. The default is + ~/.vnc/certs + + This directory is used to store server and other + certificates and keys and also other materials. E.g. in + the simplest case, "-ssl SAVE" will store the x11vnc + server cert in [dir]/server.pem + + Use of alternate directories via -ssldir allows you to + manage multiple VNC Certificate Authority (CA) keys. + Another use is if ~/.vnc/cert is on an NFS share you + might want your certificates and keys to be on a local + filesystem to prevent network snooping (for example + -ssldir /var/lib/x11vnc-certs). + + -ssldir effects the other -ssl* options. In the case + of maintenance commands where the VNC server is not run + (e.g. -sslGenCA), the -ssldir option must precede the + command. E.g. x11vnc -ssldir ~/mydir -sslCertInfo LIST -sslverify [path] For either of the -ssl or -stunnel modes, use [path] to provide certificates to authenticate incoming VNC - client connections. This can be used as a method to - replace standard password authentication of clients. + *Client* connections (normally only the server is + authenticated in SSL.) This can be used as a method + to replace standard password authentication of clients. If [path] is a directory it contains the client (or CA) - certificates in separate files. If [path] is a file, it - contains multiple certificates. These correspond to the - "CApath = dir" and "CAfile = file" stunnel options. - See the stunnel(8) manpage for details. + certificates in separate files. If [path] is a file, + it contains multiple certificates. See special tokens + below. These correspond to the "CApath = dir" and + "CAfile = file" stunnel options. See the stunnel(8) + manpage for details. + + Examples: + x11vnc -ssl -sslverify ~/my.pem + x11vnc -ssl -sslverify ~/my_pem_dir/ + + Note that if [path] is a directory, it must contain + the certs in separate files named like <HASH>.0, where + the value of <HASH> is found by running the command + "openssl x509 -hash -noout -in file.crt". Evidently + one uses <HASH>.1 if there is a collision... + + The the key-management utility "-sslCertInfo HASHON" + and "-sslCertInfo HASHOFF" will create/delete these + hashes for you automatically (via symlink) in the HASH + subdirs it manages. Then you can point -sslverify to + the HASH subdir. + + Special tokens: in -ssl mode, if [path] is not a file or + a directory, it is taken as a comma separated list of + tokens that are interpreted as follows: + + If a token is "CA" that means load the CA/cacert.pem + file from the ssl directory. If a token is "clients" + then all the files clients/*.crt in the ssl directory + are loaded. Otherwise the file clients/token.crt + is attempted to be loaded. As a kludge, use a token + like ../server-foo to load a server cert if you find + that necessary. + + Use -ssldir to use a directory different from the + ~/.vnc/certs default. + + Note that if the "CA" cert is loaded you do not need + to load any of the certs that have been signed by it. + You will need to load any additional self-signed certs + however. + + Examples: + x11vnc -ssl -sslverify CA + x11vnc -ssl -sslverify self:fred,self:jim + x11vnc -ssl -sslverify CA,clients + + Usually "-sslverify CA" is the most effective. + See the -sslGenCA and -sslGenCert options below for + how to set up and manage the CA framework. + + + + NOTE: the following utilities, -sslGenCA, -sslGenCert, + -sslEncKey, and -sslCertInfo are provided for + completeness, but for casual usage they are overkill. + + They provide VNC Certificate Authority (CA) key creation + and server / client key generation and signing. So they + provide a basic Public Key management framework for + VNC-ing with x11vnc. (note that they require openssl(1) + be installed on the system) + + However, the simplest usage mode (where x11vnc + automatically generates its own, self-signed, temporary + key and the VNC viewers always accept it, e.g. accepting + via a dialog box) is probably safe enough for most + scenarios. CA management is not needed. + + To protect against Man-In-The-Middle attacks the + simplest mode can be improved by using "-ssl SAVE" + to have x11vnc create a longer term self-signed + certificate, and then (safely) copy the corresponding + public key cert to the desired client machines (care + must be taken the private key part is not stolen; + you will be prompted for a passphrase). + + So keep in mind no CA key creation or management + (-sslGenCA and -sslGenCert) is needed for either of + the above two common usage modes. + + One might want to use -sslGenCA and -sslGenCert + if you had a large number of VNC client and server + workstations. That way the administrator could generate + a single CA key with -sslGenCA and distribute its + certificate part to all of the workstations. + + Next, he could create signed VNC server keys + (-sslGenCert server ...) for each workstation or user + that then x11vnc would use to authenticate itself to + any VNC client that has the CA cert. + + Optionally, the admin could also make it so the + VNC clients themselves are authenticated to x11vnc + (-sslGenCert client ...) For this -sslverify would be + pointed to the CA cert (and/or self-signed certs). + + x11vnc will be able to use all of these cert and + key files. On the VNC client side, they will need to + be "imported" somehow. Web browsers have "Manage + Certificates" actions as does the Java applet plugin + Control Panel. stunnel can also use these files (see + the ssl_vncviewer example script in the FAQ.) + +-sslGenCA [dir] Generate your own Certificate Authority private key, + certificate, and other files in directory [dir]. + + If [dir] is not supplied, a -ssldir setting is used, + or otherwise ~/.vnc/certs is used. + + This command also creates directories where server and + client certs and keys will be stored. The openssl(1) + program must be installed on the system and available + in PATH. + + After the CA files and directories are created the + command exits; the VNC server is not run. + + You will be prompted for information to put into the CA + certificate. The info does not have to be accurate just + as long as clients accept the cert for VNC connections. + You will also need to supply a passphrase of at least + 4 characters for the CA private key. + + Once you have generated the CA you can distribute + its certificate part, [dir]/CA/cacert.pem, to other + workstations where VNC viewers will be run. One will + need to "import" this certicate in the applications, + e.g. Web browser, Java applet plugin, stunnel, etc. + Next, you can create and sign keys using the CA with + the -sslGenCert option below. + + Examples: + x11vnc -sslGenCA + x11vnc -sslGenCA ~/myCAdir + x11vnc -ssldir ~/myCAdir -sslGenCA + + (the last two lines are equivalent) + +-sslGenCert type name Generate a VNC server or client certificate and private + key pair signed by the CA created previously with + -sslGenCA. The openssl(1) program must be installed + on the system and available in PATH. + + After the Certificate is generated the command exits; + the VNC server is not run. + + The type of key to be generated is the string "type". + It is either "server" (i.e. for use by x11vnc) or + "client" (for a VNC viewer). Note that typically + only "server" is used: the VNC clients authenticate + themselves by a non-public-key method (e.g. VNC or + unix password). "type" is required. + + An arbitrary default name you want to associate with + the key is supplied by the "name" string. You can + change it at the various prompts when creating the key. + "name" is optional. + + If name is left blank for clients keys then "nobody" + is used. If left blank for server keys, then the + primary server key: "server.pem" is created (this + is the saved one referenced by "-ssl SAVE" when the + server is started) + + If "name" begins with the string "self:" then + a self-signed certificate is created instead of one + signed by your CA key. + + If "name" begins with the string "req:" then only a + key (.key) and a certificate signing *request* (.req) + are generated. You can then send the .req file to + an external CA (even a professional one, e.g. Thawte) + and then combine the .key and the received cert into + the .pem file with the same basename. + + The distinction between "server" and "client" is + simply the choice of output filenames and sub-directory. + This makes it so the -ssl SAVE-name option can easily + pick up the x11vnc PEM file this option generates. + And similarly makes it easy for the -sslverify option + to pick up your client certs. + + There is nothing special about the filename or directory + location of either the "server" and "client" certs. + You can rename the files or move them to wherever + you like. + + Precede this option with -ssldir [dir] to use a + directory other than the default ~/.vnc/certs You will + need to run -sslGenCA on that directory first before + doing any -sslGenCert key creation. + + Note you cannot recreate a cert with exactly the same + distiguished name (DN) as an existing one. To do so, + you will need to edit the [dir]/CA/index.txt file to + delete the line. + + Similar to -sslGenCA, you will be prompted to fill + in some information that will be recorded in the + certificate when it is created. Tip: if you know + the fully-quailified hostname other people will be + connecting to you can use that as the CommonName "CN" + to avoid some applications (e.g. web browsers and java + plugin) complaining it does not match the hostname. + + You will also need to supply the CA private key + passphrase to unlock the private key created from + -sslGenCA. This private key is used to sign the server + or client certicate. + + The "server" certs can be used by x11vnc directly by + pointing to them via the -ssl [pem] option. The default + file will be ~/.vnc/certs/server.pem. This one would + be used by simply typing -ssl SAVE. The pem file + contains both the certificate and the private key. + server.crt file contains the cert only. + + The "client" cert + private key file will need + to be copied and imported into the VNC viewer + side applications (Web browser, Java plugin, + stunnel, etc.) Once that is done you can delete the + "client" private key file on this machine since + it is only needed on the VNC viewer side. The, + e.g. ~/.vnc/certs/clients/<name>.pem contains both + the cert and private key. The <name>.crt contains the + certificate only. + + NOTE: It is very important to know one should always + generate new keys with a passphrase. Otherwise if an + untrusted user steals the key file he could use it to + masquerade as the x11vnc server (or VNC viewer client). + You will be prompted whether to encrypt the key with + a passphrase or not. It is recommended that you do. + One inconvenience to a passphrase is that it must + be suppled every time x11vnc or the client app is + started up. + + Examples: + + x11vnc -sslGenCert server + x11vnc -ssl SAVE -display :0 ... + + and then on viewer using ssl_vncviewer stunnel wrapper + (see the FAQ): + ssl_vncviewer -verify ./cacert.crt hostname:0 + + (this assumes the cacert.crt cert from -sslGenCA + was safely copied to the VNC viewer machine where + ssl_vncviewer is run) + + Example using a name: + + x11vnc -sslGenCert server charlie + x11vnc -ssl SAVE-charlie -display :0 ... + + Example for a client certificate (rarely used): + + x11vnc -sslGenCert client roger + scp ~/.vnc/certs/clients/roger.pem somehost:. + rm ~/.vnc/certs/clients/roger.pem + + x11vnc is then started with the the option -sslverify + ~/.vnc/certs/clients/roger.crt (or simply -sslverify + roger), and on the viewer user on somehost could do + for example: + + ssl_vncviewer -mycert ./roger.pem hostname:0 + +-sslEncKey [pem] Utility to encrypt an existing PEM file with a + passphrase you supply when prompted. For that key to be + used (e.g. by x11vnc) the passphrase must be supplied + each time. + + The "SAVE" notation described under -ssl applies as + well. (precede this option with -ssldir [dir] to refer + a directory besides the default ~/.vnc/certs) + + The openssl(1) program must be installed on the system + and available in PATH. After the Key file is encrypted + the command exits; the VNC server is not run. + + Examples: + x11vnc -sslEncKey /path/to/foo.pem + x11vnc -sslEncKey SAVE + x11vnc -sslEncKey SAVE-charlie + +-sslCertInfo [pem] Prints out information about an existing PEM file. + In addition the public certificate is also printed. + The openssl(1) program must be in PATH. Basically the + command "openssl x509 -text" is run on the pem. + + The "SAVE" notation described under -ssl applies + as well. + + Using "LIST" will give a list of all certs being + managed (in the ~/.vnc/certs dir, use -ssldir to refer + to another dir). "ALL" will print out the info for + every managed key (this can be very long). Giving a + client or server cert shortname will also try a lookup + (e.g. -sslCertInfo charlie). Use "LISTL" or "LL" + for a long (ls -l style) listing. + + Using "HASHON" will create subdirs [dir]/HASH and + [dir]/HASH with OpenSSL hash filenames (e.g. 0d5fbbf1.0) + symlinks pointing up to the corresponding *.crt file. + ([dir] is ~/.vnc/certs or one given by -ssldir.) + This is a useful way for other OpenSSL applications + (e.g. stunnel) to access all of the certs without + having to concatenate them. x11vnc will not use them + unless you specifically reference them. "HASHOFF" + removes these HASH subdirs. + + The LIST, LISTL, LL, ALL, HASHON, HASHOFF words can + also be lowercase, e.g. "list". + +-sslDelCert [pem] Prompts you to delete all .crt .pem .key .req files + associated with [pem]. "SAVE" and lookups as in + -sslCertInfo apply as well. - To create certificates for all sorts of authentications - (clients, servers, via CA, etc) see the openssl(1) - command. Of particular usefulness is the "x509" - subcommand of openssl(1). -stunnel [pem] Use the stunnel(8) (www.stunnel.org) to provide an - encrypted SSL tunnel between viewers and x11vnc. This - was implemented prior to the integrated -ssl encrpytion. - It works well. This requires stunnel to be installed + encrypted SSL tunnel between viewers and x11vnc. + + This external tunnel method was implemented prior to the + integrated -ssl encryption described above. It still + works well. This requires stunnel to be installed on the system and available via PATH (n.b. stunnel is often installed in sbin directories). Version 4.x of stunnel is assumed (but see -stunnel3 below.) @@ -6380,14 +6715,13 @@ Options: SSL. Unfortunately not too many do this. UltraVNC has an encryption plugin but it does not seem to be SSL. - In the x11vnc distribution, a patched TightVNC Java - applet is provided in classes/ssl that does SSL + Also, in the x11vnc distribution, a patched TightVNC + Java applet is provided in classes/ssl that does SSL connections (only). It is also not too difficult to set up an stunnel or - other SSL tunnel on the viewer side. - - A simple example on Unix using stunnel 3.x is: + other SSL tunnel on the viewer side. A simple example + on Unix using stunnel 3.x is: % stunnel -c -d localhost:5901 -r remotehost:5900 % vncviewer localhost:1 @@ -6419,9 +6753,9 @@ Options: or VNC Viewer applet. That's right 3 separate "Are you sure you want to connect" dialogs!) - So use the -https option to provide a separate, - more reliable HTTPS port that x11vnc will listen on. - If [port] is not provided, one is autoselected. + So use the -https option to provide a separate, more + reliable HTTPS port that x11vnc will listen on. If + [port] is not provided (or is 0), one is autoselected. The URL to use is printed out at startup. The SSL Java applet directory is specified via the @@ -6443,9 +6777,10 @@ Options: file "file". Once the password is stored the program exits. Use the password via "-rfbauth file" - If called with no arguments, i.e., "-storepasswd", + If called with no arguments, "x11vnc -storepasswd", the user is prompted for a password and it is stored - in the file ~/.vnc/passwd + in the file ~/.vnc/passwd. Called with one argument, + that will be the file to store the prompted password in. -nopw Disable the big warning message when you use x11vnc without some sort of password. @@ -7449,6 +7784,22 @@ Options: to really throttle down the screen polls (i.e. sleep for about 1.5 secs). Use 0 to disable. Default: 60 +-nofbpm If the system supports the FBPM (Frame Buffer Power +-fbpm Management) extension (i.e. some Sun systems), then + prevent the video h/w from going into a reduced power + state when VNC clients are connected. + + FBPM capable video h/w save energy when the workstation + is idle by going into low power states (similar to DPMS + for monitors). This interferes with x11vnc's polling + of the framebuffer data. + + "-nofbpm" means prevent FBPM low power states whenever + VNC clients are connected, while "-fbpm" means to not + monitor the FBPM state at all. See the xset(1) manpage + for details. -nofbpm is basically the same as running + "xset fbpm force on" periodically. Default: -fbpm + -noxdamage Do not use the X DAMAGE extension to detect framebuffer changes even if it is available. Use -xdamage if your default is to have it off. @@ -7901,6 +8252,8 @@ n nap enable -nap mode. nonap disable -nap mode. sb:n set -sb to n s, same as screen_blank:n + fbpm disable -nofbpm mode. + nofbpm enable -nofbpm mode. xdamage enable xdamage polling hints. noxdamage disable xdamage polling hints. xd_area:A set -xd_area max pixel area to "A" @@ -8021,8 +8374,8 @@ n debug_pointer dp nodebug_pointer nodp debug_keyboard dk nodebug_keyboard nodk deferupdate defer wait_ui wait_bog nowait_bog slow_fb wait readtimeout nap nonap - sb screen_blank fs gaps grow fuzz snapfb nosnapfb - rawfb progressive rfbport http nohttp httpport + sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb + nosnapfb rawfb progressive rfbport http nohttp httpport httpdir enablehttpproxy noenablehttpproxy alwaysshared noalwaysshared nevershared noalwaysshared dontdisconnect nodontdisconnect desktop debug_xevents nodebug_xevents @@ -8037,9 +8390,9 @@ n http_url auth xauth users rootshift clipshift scale_str scaled_x scaled_y scale_numer scale_denom scale_fac scaling_blend scaling_nomult4 scaling_pad - scaling_interpolate inetd privremote unsafe safer - nocmds passwdfile unixpw unixpw_nis unixpw_list ssl - ssl_pem sslverify stunnel stunnel_pem usepw using_shm + scaling_interpolate inetd privremote unsafe safer nocmds + passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem + sslverify stunnel stunnel_pem https usepw using_shm logfile o flag rc norc h help V version lastmod bg sigpipe threads readrate netrate netlatency pipeinput clients client_count pid ext_xtest ext_xtrap ext_xrecord diff --git a/x11vnc/cleanup.c b/x11vnc/cleanup.c index 23e810c..e966d61 100644 --- a/x11vnc/cleanup.c +++ b/x11vnc/cleanup.c @@ -33,6 +33,7 @@ int trap_getimage_xerror(Display *d, XErrorEvent *error); char *xerror_string(XErrorEvent *error); void initialize_crash_handler(void); void initialize_signals(void); +void unset_signals(void); int known_sigpipe_mode(char *s); @@ -107,8 +108,13 @@ static void clean_icon_mode(void) { * Normal exiting */ void clean_up_exit (int ret) { + static int depth = 0; exit_flag = 1; + if (depth++ > 2) { + exit(ret); + } + if (icon_mode) { clean_icon_mode(); } @@ -427,6 +433,19 @@ void initialize_signals(void) { X_UNLOCK; } +void unset_signals(void) { + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGABRT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGPIPE, SIG_DFL); +} + + int known_sigpipe_mode(char *s) { /* * skip, ignore, exit diff --git a/x11vnc/cleanup.h b/x11vnc/cleanup.h index c34b7e5..c0b02d2 100644 --- a/x11vnc/cleanup.h +++ b/x11vnc/cleanup.h @@ -20,6 +20,7 @@ extern int trap_getimage_xerror(Display *d, XErrorEvent *error); extern char *xerror_string(XErrorEvent *error); extern void initialize_crash_handler(void); extern void initialize_signals(void); +extern void unset_signals(void); extern int known_sigpipe_mode(char *s); #endif /* _X11VNC_CLEANUP_H */ diff --git a/x11vnc/connections.c b/x11vnc/connections.c index baf1e84..7d23c42 100644 --- a/x11vnc/connections.c +++ b/x11vnc/connections.c @@ -2190,4 +2190,3 @@ void check_new_clients(void) { } } - diff --git a/x11vnc/help.c b/x11vnc/help.c index 544d26b..409ecd9 100644 --- a/x11vnc/help.c +++ b/x11vnc/help.c @@ -528,14 +528,14 @@ void print_help(int mode) { "-unixpw_nis [list] As -unixpw above, however do not use su(1) but rather\n" " use the traditional getpwnam(3) + crypt(3) method to\n" " verify passwords instead. This requires that the\n" -" encrpyted passwords be readable. Passwords stored\n" +" encrypted passwords be readable. Passwords stored\n" " in /etc/shadow will be inaccessible unless x11vnc\n" " is run as root.\n" "\n" " This is called \"NIS\" mode simply because in most\n" " NIS setups the user encrypted passwords are accessible\n" " (e.g. \"ypcat passwd\"). NIS is not required for this\n" -" mode to work (only that getpwnam(3) return the encrpyted\n" +" mode to work (only that getpwnam(3) return the encrypted\n" " password is required), but it is unlikely it will work\n" " for any other modern environment. All of the -unixpw\n" " options and contraints apply.\n" @@ -549,18 +549,19 @@ void print_help(int mode) { "\n" " [pem] is optional, use \"-ssl /path/to/mycert.pem\"\n" " to specify a PEM certificate file to use to identify\n" -" and provide a key for this server. See openssl(1)\n" -" for what a PEM can be.\n" +" and provide a key for this server. See openssl(1) for\n" +" more info about PEMs and the -sslGenCert option below.\n" "\n" -" Connecting VNC viewer SSL tunnels can optionally\n" +" The connecting VNC viewer SSL tunnel can optionally\n" " authenticate this server if they have the public\n" " key part of the certificate (or a common certificate\n" " authority, CA, is a more sophisicated way to verify\n" -" this server's cert). This is used to prevent\n" -" man-in-the-middle attacks. Otherwise, if the VNC\n" -" viewer accepts this server's key without verification,\n" -" at least the traffic is protected from passive sniffing\n" -" on the network (but NOT from man-in-the-middle attacks).\n" +" this server's cert, see -sslGenCA below). This is\n" +" used to prevent man-in-the-middle attacks. Otherwise,\n" +" if the VNC viewer accepts this server's key without\n" +" verification, at least the traffic is protected\n" +" from passive sniffing on the network (but NOT from\n" +" man-in-the-middle attacks).\n" "\n" " If [pem] is not supplied and the openssl(1) utility\n" " command exists in PATH, then a temporary, self-signed\n" @@ -573,15 +574,34 @@ void print_help(int mode) { " temporary certificate, the public part of it will be\n" " displayed to stderr (e.g. one could copy it to the\n" " client-side to provide authentication of the server to\n" -" VNC viewers.)\n" +" VNC viewers.) See following paragraphs for how to save\n" +" keys to reuse when x11vnc is restarted.\n" "\n" " Set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc\n" " print out the entire certificate, including the PRIVATE\n" " KEY part, to stderr. One could reuse this cert if saved\n" " in a [pem] file. Similarly, set X11VNC_KEEP_TMP_PEM=1\n" " to not delete the temporary PEM file: the file name\n" -" will be printed to stderr (so one could move it to a\n" -" safe place for reuse).\n" +" will be printed to stderr (so one could move it to\n" +" a safe place for reuse). You will be prompted for a\n" +" passphrase for the private key.\n" +"\n" +" If [pem] is \"SAVE\" then the certificate will be saved\n" +" to the file ~/.vnc/certs/server.pem, or if that file\n" +" exists it will be used directly. Similarly, if [pem]\n" +" is \"SAVE_PROMPT\" the server.pem certificate will be\n" +" made based on your answers to its prompts for info such\n" +" as OrganizationalName, CommonName, etc.\n" +"\n" +" Use \"SAVE-<string>\" and \"SAVE_PROMPT-<string>\"\n" +" to refer to the file ~/.vnc/certs/server-<string>.pem\n" +" instead. E.g. \"SAVE-charlie\" will store to the file\n" +" ~/.vnc/certs/server-charlie.pem\n" +"\n" +" See -ssldir below to use a directory besides the\n" +" default ~/.vnc/certs\n" +"\n" +" Example: x11vnc -ssl SAVE -display :0 ...\n" "\n" " Reverse connections are disabled in -ssl mode because\n" " there is no way to ensure that data channel will\n" @@ -589,33 +609,369 @@ void print_help(int mode) { " override this.\n" "\n" " Your VNC viewer will also need to be able to connect\n" -" via SSL. See the discussion below under -stunnel\n" -" and the FAQ for how this might be achieved. E.g. on\n" -" Unix it is easy to write a shell script that starts up\n" -" stunnel and then vncviewer. Also in the x11vnc source\n" -" a SSL enabled Java VNC Viewer applet is provided in\n" -" the classes/ssl directory.\n" +" via SSL. See the discussion below under -stunnel and\n" +" the FAQ (ssl_vncviewer script) for how this might be\n" +" achieved. E.g. on Unix it is easy to write a shell\n" +" script that starts up stunnel and then vncviewer.\n" +" Also in the x11vnc source a SSL enabled Java VNC Viewer\n" +" applet is provided in the classes/ssl directory.\n" +"\n" +"-ssldir [dir] Use [dir] as an alternate ssl certificate and key\n" +" management toplevel directory. The default is\n" +" ~/.vnc/certs\n" +"\n" +" This directory is used to store server and other\n" +" certificates and keys and also other materials. E.g. in\n" +" the simplest case, \"-ssl SAVE\" will store the x11vnc\n" +" server cert in [dir]/server.pem\n" +"\n" +" Use of alternate directories via -ssldir allows you to\n" +" manage multiple VNC Certificate Authority (CA) keys.\n" +" Another use is if ~/.vnc/cert is on an NFS share you\n" +" might want your certificates and keys to be on a local\n" +" filesystem to prevent network snooping (for example\n" +" -ssldir /var/lib/x11vnc-certs).\n" +"\n" +" -ssldir effects the other -ssl* options. In the case\n" +" of maintenance commands where the VNC server is not run\n" +" (e.g. -sslGenCA), the -ssldir option must precede the\n" +" command. E.g. x11vnc -ssldir ~/mydir -sslCertInfo LIST\n" "\n" "-sslverify [path] For either of the -ssl or -stunnel modes, use [path]\n" " to provide certificates to authenticate incoming VNC\n" -" client connections. This can be used as a method to\n" -" replace standard password authentication of clients.\n" +" *Client* connections (normally only the server is\n" +" authenticated in SSL.) This can be used as a method\n" +" to replace standard password authentication of clients.\n" "\n" " If [path] is a directory it contains the client (or CA)\n" -" certificates in separate files. If [path] is a file, it\n" -" contains multiple certificates. These correspond to the\n" -" \"CApath = dir\" and \"CAfile = file\" stunnel options.\n" -" See the stunnel(8) manpage for details.\n" +" certificates in separate files. If [path] is a file,\n" +" it contains multiple certificates. See special tokens\n" +" below. These correspond to the \"CApath = dir\" and\n" +" \"CAfile = file\" stunnel options. See the stunnel(8)\n" +" manpage for details.\n" +"\n" +" Examples:\n" +" x11vnc -ssl -sslverify ~/my.pem\n" +" x11vnc -ssl -sslverify ~/my_pem_dir/\n" +"\n" +" Note that if [path] is a directory, it must contain\n" +" the certs in separate files named like <HASH>.0, where\n" +" the value of <HASH> is found by running the command\n" +" \"openssl x509 -hash -noout -in file.crt\". Evidently\n" +" one uses <HASH>.1 if there is a collision...\n" +"\n" +" The the key-management utility \"-sslCertInfo HASHON\"\n" +" and \"-sslCertInfo HASHOFF\" will create/delete these\n" +" hashes for you automatically (via symlink) in the HASH\n" +" subdirs it manages. Then you can point -sslverify to\n" +" the HASH subdir.\n" +"\n" +" Special tokens: in -ssl mode, if [path] is not a file or\n" +" a directory, it is taken as a comma separated list of\n" +" tokens that are interpreted as follows:\n" +"\n" +" If a token is \"CA\" that means load the CA/cacert.pem\n" +" file from the ssl directory. If a token is \"clients\"\n" +" then all the files clients/*.crt in the ssl directory\n" +" are loaded. Otherwise the file clients/token.crt\n" +" is attempted to be loaded. As a kludge, use a token\n" +" like ../server-foo to load a server cert if you find\n" +" that necessary.\n" +" \n" +" Use -ssldir to use a directory different from the\n" +" ~/.vnc/certs default.\n" +" \n" +" Note that if the \"CA\" cert is loaded you do not need\n" +" to load any of the certs that have been signed by it.\n" +" You will need to load any additional self-signed certs\n" +" however.\n" +" \n" +" Examples:\n" +" x11vnc -ssl -sslverify CA\n" +" x11vnc -ssl -sslverify self:fred,self:jim\n" +" x11vnc -ssl -sslverify CA,clients\n" +" \n" +" Usually \"-sslverify CA\" is the most effective.\n" +" See the -sslGenCA and -sslGenCert options below for\n" +" how to set up and manage the CA framework.\n" +" \n" +"\n" +"\n" +" NOTE: the following utilities, -sslGenCA, -sslGenCert,\n" +" -sslEncKey, and -sslCertInfo are provided for\n" +" completeness, but for casual usage they are overkill.\n" +"\n" +" They provide VNC Certificate Authority (CA) key creation\n" +" and server / client key generation and signing. So they\n" +" provide a basic Public Key management framework for\n" +" VNC-ing with x11vnc. (note that they require openssl(1)\n" +" be installed on the system)\n" +"\n" +" However, the simplest usage mode (where x11vnc\n" +" automatically generates its own, self-signed, temporary\n" +" key and the VNC viewers always accept it, e.g. accepting\n" +" via a dialog box) is probably safe enough for most\n" +" scenarios. CA management is not needed.\n" +"\n" +" To protect against Man-In-The-Middle attacks the\n" +" simplest mode can be improved by using \"-ssl SAVE\"\n" +" to have x11vnc create a longer term self-signed\n" +" certificate, and then (safely) copy the corresponding\n" +" public key cert to the desired client machines (care\n" +" must be taken the private key part is not stolen;\n" +" you will be prompted for a passphrase).\n" +"\n" +" So keep in mind no CA key creation or management\n" +" (-sslGenCA and -sslGenCert) is needed for either of\n" +" the above two common usage modes.\n" +"\n" +" One might want to use -sslGenCA and -sslGenCert\n" +" if you had a large number of VNC client and server\n" +" workstations. That way the administrator could generate\n" +" a single CA key with -sslGenCA and distribute its\n" +" certificate part to all of the workstations.\n" +"\n" +" Next, he could create signed VNC server keys\n" +" (-sslGenCert server ...) for each workstation or user\n" +" that then x11vnc would use to authenticate itself to\n" +" any VNC client that has the CA cert.\n" +"\n" +" Optionally, the admin could also make it so the\n" +" VNC clients themselves are authenticated to x11vnc\n" +" (-sslGenCert client ...) For this -sslverify would be\n" +" pointed to the CA cert (and/or self-signed certs).\n" +"\n" +" x11vnc will be able to use all of these cert and\n" +" key files. On the VNC client side, they will need to\n" +" be \"imported\" somehow. Web browsers have \"Manage\n" +" Certificates\" actions as does the Java applet plugin\n" +" Control Panel. stunnel can also use these files (see\n" +" the ssl_vncviewer example script in the FAQ.)\n" +"\n" +"-sslGenCA [dir] Generate your own Certificate Authority private key,\n" +" certificate, and other files in directory [dir].\n" +"\n" +" If [dir] is not supplied, a -ssldir setting is used,\n" +" or otherwise ~/.vnc/certs is used.\n" +"\n" +" This command also creates directories where server and\n" +" client certs and keys will be stored. The openssl(1)\n" +" program must be installed on the system and available\n" +" in PATH.\n" +"\n" +" After the CA files and directories are created the\n" +" command exits; the VNC server is not run.\n" +"\n" +" You will be prompted for information to put into the CA\n" +" certificate. The info does not have to be accurate just\n" +" as long as clients accept the cert for VNC connections.\n" +" You will also need to supply a passphrase of at least\n" +" 4 characters for the CA private key.\n" +"\n" +" Once you have generated the CA you can distribute\n" +" its certificate part, [dir]/CA/cacert.pem, to other\n" +" workstations where VNC viewers will be run. One will\n" +" need to \"import\" this certicate in the applications,\n" +" e.g. Web browser, Java applet plugin, stunnel, etc.\n" +" Next, you can create and sign keys using the CA with\n" +" the -sslGenCert option below.\n" +"\n" +" Examples:\n" +" x11vnc -sslGenCA\n" +" x11vnc -sslGenCA ~/myCAdir\n" +" x11vnc -ssldir ~/myCAdir -sslGenCA\n" +"\n" +" (the last two lines are equivalent)\n" +"\n" +"-sslGenCert type name Generate a VNC server or client certificate and private\n" +" key pair signed by the CA created previously with\n" +" -sslGenCA. The openssl(1) program must be installed\n" +" on the system and available in PATH.\n" +"\n" +" After the Certificate is generated the command exits;\n" +" the VNC server is not run.\n" +"\n" +" The type of key to be generated is the string \"type\".\n" +" It is either \"server\" (i.e. for use by x11vnc) or\n" +" \"client\" (for a VNC viewer). Note that typically\n" +" only \"server\" is used: the VNC clients authenticate\n" +" themselves by a non-public-key method (e.g. VNC or\n" +" unix password). \"type\" is required.\n" +"\n" +" An arbitrary default name you want to associate with\n" +" the key is supplied by the \"name\" string. You can\n" +" change it at the various prompts when creating the key.\n" +" \"name\" is optional.\n" +"\n" +" If name is left blank for clients keys then \"nobody\"\n" +" is used. If left blank for server keys, then the\n" +" primary server key: \"server.pem\" is created (this\n" +" is the saved one referenced by \"-ssl SAVE\" when the\n" +" server is started)\n" +"\n" +" If \"name\" begins with the string \"self:\" then\n" +" a self-signed certificate is created instead of one\n" +" signed by your CA key.\n" +"\n" +" If \"name\" begins with the string \"req:\" then only a\n" +" key (.key) and a certificate signing *request* (.req)\n" +" are generated. You can then send the .req file to\n" +" an external CA (even a professional one, e.g. Thawte)\n" +" and then combine the .key and the received cert into\n" +" the .pem file with the same basename.\n" +"\n" +" The distinction between \"server\" and \"client\" is\n" +" simply the choice of output filenames and sub-directory.\n" +" This makes it so the -ssl SAVE-name option can easily\n" +" pick up the x11vnc PEM file this option generates.\n" +" And similarly makes it easy for the -sslverify option\n" +" to pick up your client certs.\n" +"\n" +" There is nothing special about the filename or directory\n" +" location of either the \"server\" and \"client\" certs.\n" +" You can rename the files or move them to wherever\n" +" you like.\n" +"\n" +" Precede this option with -ssldir [dir] to use a\n" +" directory other than the default ~/.vnc/certs You will\n" +" need to run -sslGenCA on that directory first before\n" +" doing any -sslGenCert key creation.\n" +"\n" +" Note you cannot recreate a cert with exactly the same\n" +" distiguished name (DN) as an existing one. To do so,\n" +" you will need to edit the [dir]/CA/index.txt file to\n" +" delete the line.\n" +"\n" +" Similar to -sslGenCA, you will be prompted to fill\n" +" in some information that will be recorded in the\n" +" certificate when it is created. Tip: if you know\n" +" the fully-quailified hostname other people will be\n" +" connecting to you can use that as the CommonName \"CN\"\n" +" to avoid some applications (e.g. web browsers and java\n" +" plugin) complaining it does not match the hostname.\n" +"\n" +" You will also need to supply the CA private key\n" +" passphrase to unlock the private key created from\n" +" -sslGenCA. This private key is used to sign the server\n" +" or client certicate.\n" +"\n" +" The \"server\" certs can be used by x11vnc directly by\n" +" pointing to them via the -ssl [pem] option. The default\n" +" file will be ~/.vnc/certs/server.pem. This one would\n" +" be used by simply typing -ssl SAVE. The pem file\n" +" contains both the certificate and the private key.\n" +" server.crt file contains the cert only.\n" +"\n" +" The \"client\" cert + private key file will need\n" +" to be copied and imported into the VNC viewer\n" +" side applications (Web browser, Java plugin,\n" +" stunnel, etc.) Once that is done you can delete the\n" +" \"client\" private key file on this machine since\n" +" it is only needed on the VNC viewer side. The,\n" +" e.g. ~/.vnc/certs/clients/<name>.pem contains both\n" +" the cert and private key. The <name>.crt contains the\n" +" certificate only.\n" +"\n" +" NOTE: It is very important to know one should always\n" +" generate new keys with a passphrase. Otherwise if an\n" +" untrusted user steals the key file he could use it to\n" +" masquerade as the x11vnc server (or VNC viewer client).\n" +" You will be prompted whether to encrypt the key with\n" +" a passphrase or not. It is recommended that you do.\n" +" One inconvenience to a passphrase is that it must\n" +" be suppled every time x11vnc or the client app is\n" +" started up.\n" +"\n" +" Examples:\n" +"\n" +" x11vnc -sslGenCert server\n" +" x11vnc -ssl SAVE -display :0 ...\n" +"\n" +" and then on viewer using ssl_vncviewer stunnel wrapper\n" +" (see the FAQ):\n" + +" ssl_vncviewer -verify ./cacert.crt hostname:0\n" +"\n" +" (this assumes the cacert.crt cert from -sslGenCA\n" +" was safely copied to the VNC viewer machine where\n" +" ssl_vncviewer is run)\n" +"\n" +" Example using a name:\n" +"\n" +" x11vnc -sslGenCert server charlie\n" +" x11vnc -ssl SAVE-charlie -display :0 ...\n" +"\n" +" Example for a client certificate (rarely used):\n" +"\n" +" x11vnc -sslGenCert client roger\n" +" scp ~/.vnc/certs/clients/roger.pem somehost:.\n" +" rm ~/.vnc/certs/clients/roger.pem\n" +"\n" +" x11vnc is then started with the the option -sslverify\n" +" ~/.vnc/certs/clients/roger.crt (or simply -sslverify\n" +" roger), and on the viewer user on somehost could do\n" +" for example:\n" +"\n" +" ssl_vncviewer -mycert ./roger.pem hostname:0\n" +"\n" +"-sslEncKey [pem] Utility to encrypt an existing PEM file with a\n" +" passphrase you supply when prompted. For that key to be\n" +" used (e.g. by x11vnc) the passphrase must be supplied\n" +" each time.\n" +"\n" +" The \"SAVE\" notation described under -ssl applies as\n" +" well. (precede this option with -ssldir [dir] to refer\n" +" a directory besides the default ~/.vnc/certs)\n" +"\n" +" The openssl(1) program must be installed on the system\n" +" and available in PATH. After the Key file is encrypted\n" +" the command exits; the VNC server is not run.\n" +"\n" +" Examples:\n" +" x11vnc -sslEncKey /path/to/foo.pem\n" +" x11vnc -sslEncKey SAVE\n" +" x11vnc -sslEncKey SAVE-charlie\n" +"\n" +"-sslCertInfo [pem] Prints out information about an existing PEM file.\n" +" In addition the public certificate is also printed.\n" +" The openssl(1) program must be in PATH. Basically the\n" +" command \"openssl x509 -text\" is run on the pem.\n" +"\n" +" The \"SAVE\" notation described under -ssl applies\n" +" as well.\n" +"\n" +" Using \"LIST\" will give a list of all certs being\n" +" managed (in the ~/.vnc/certs dir, use -ssldir to refer\n" +" to another dir). \"ALL\" will print out the info for\n" +" every managed key (this can be very long). Giving a\n" +" client or server cert shortname will also try a lookup\n" +" (e.g. -sslCertInfo charlie). Use \"LISTL\" or \"LL\"\n" +" for a long (ls -l style) listing.\n" +"\n" +" Using \"HASHON\" will create subdirs [dir]/HASH and\n" +" [dir]/HASH with OpenSSL hash filenames (e.g. 0d5fbbf1.0)\n" +" symlinks pointing up to the corresponding *.crt file.\n" +" ([dir] is ~/.vnc/certs or one given by -ssldir.)\n" +" This is a useful way for other OpenSSL applications\n" +" (e.g. stunnel) to access all of the certs without\n" +" having to concatenate them. x11vnc will not use them\n" +" unless you specifically reference them. \"HASHOFF\"\n" +" removes these HASH subdirs.\n" +"\n" +" The LIST, LISTL, LL, ALL, HASHON, HASHOFF words can\n" +" also be lowercase, e.g. \"list\".\n" +"\n" +"-sslDelCert [pem] Prompts you to delete all .crt .pem .key .req files\n" +" associated with [pem]. \"SAVE\" and lookups as in\n" +" -sslCertInfo apply as well.\n" "\n" -" To create certificates for all sorts of authentications\n" -" (clients, servers, via CA, etc) see the openssl(1)\n" -" command. Of particular usefulness is the \"x509\"\n" -" subcommand of openssl(1).\n" "\n" "-stunnel [pem] Use the stunnel(8) (www.stunnel.org) to provide an\n" -" encrypted SSL tunnel between viewers and x11vnc. This\n" -" was implemented prior to the integrated -ssl encrpytion.\n" -" It works well. This requires stunnel to be installed\n" +" encrypted SSL tunnel between viewers and x11vnc.\n" +"\n" +" This external tunnel method was implemented prior to the\n" +" integrated -ssl encryption described above. It still\n" +" works well. This requires stunnel to be installed\n" " on the system and available via PATH (n.b. stunnel is\n" " often installed in sbin directories). Version 4.x of\n" " stunnel is assumed (but see -stunnel3 below.)\n" @@ -641,14 +997,13 @@ void print_help(int mode) { " SSL. Unfortunately not too many do this. UltraVNC has\n" " an encryption plugin but it does not seem to be SSL.\n" "\n" -" In the x11vnc distribution, a patched TightVNC Java\n" -" applet is provided in classes/ssl that does SSL\n" +" Also, in the x11vnc distribution, a patched TightVNC\n" +" Java applet is provided in classes/ssl that does SSL\n" " connections (only).\n" "\n" " It is also not too difficult to set up an stunnel or\n" -" other SSL tunnel on the viewer side.\n" -"\n" -" A simple example on Unix using stunnel 3.x is:\n" +" other SSL tunnel on the viewer side. A simple example\n" +" on Unix using stunnel 3.x is:\n" "\n" " %% stunnel -c -d localhost:5901 -r remotehost:5900\n" " %% vncviewer localhost:1\n" @@ -704,9 +1059,10 @@ void print_help(int mode) { " file \"file\". Once the password is stored the\n" " program exits. Use the password via \"-rfbauth file\"\n" "\n" -" If called with no arguments, i.e., \"-storepasswd\",\n" +" If called with no arguments, \"x11vnc -storepasswd\",\n" " the user is prompted for a password and it is stored\n" -" in the file ~/.vnc/passwd\n" +" in the file ~/.vnc/passwd. Called with one argument,\n" +" that will be the file to store the prompted password in.\n" "\n" "-nopw Disable the big warning message when you use x11vnc\n" " without some sort of password.\n" @@ -1718,6 +2074,22 @@ void print_help(int mode) { " to really throttle down the screen polls (i.e. sleep\n" " for about 1.5 secs). Use 0 to disable. Default: %d\n" "\n" +"-nofbpm If the system supports the FBPM (Frame Buffer Power\n" +"-fbpm Management) extension (i.e. some Sun systems), then\n" +" prevent the video h/w from going into a reduced power\n" +" state when VNC clients are connected.\n" +"\n" +" FBPM capable video h/w save energy when the workstation\n" +" is idle by going into low power states (similar to DPMS\n" +" for monitors). This interferes with x11vnc's polling\n" +" of the framebuffer data.\n" +"\n" +" \"-nofbpm\" means prevent FBPM low power states whenever\n" +" VNC clients are connected, while \"-fbpm\" means to not\n" +" monitor the FBPM state at all. See the xset(1) manpage\n" +" for details. -nofbpm is basically the same as running\n" +" \"xset fbpm force on\" periodically. Default: %s\n" +"\n" "-noxdamage Do not use the X DAMAGE extension to detect framebuffer\n" " changes even if it is available. Use -xdamage if your\n" " default is to have it off.\n" @@ -2176,6 +2548,8 @@ void print_help(int mode) { " nap enable -nap mode.\n" " nonap disable -nap mode.\n" " sb:n set -sb to n s, same as screen_blank:n\n" +" fbpm disable -nofbpm mode.\n" +" nofbpm enable -nofbpm mode.\n" " xdamage enable xdamage polling hints.\n" " noxdamage disable xdamage polling hints.\n" " xd_area:A set -xd_area max pixel area to \"A\"\n" @@ -2296,8 +2670,8 @@ void print_help(int mode) { " debug_pointer dp nodebug_pointer nodp debug_keyboard\n" " dk nodebug_keyboard nodk deferupdate defer wait_ui\n" " wait_bog nowait_bog slow_fb wait readtimeout nap nonap\n" -" sb screen_blank fs gaps grow fuzz snapfb nosnapfb\n" -" rawfb progressive rfbport http nohttp httpport\n" +" sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb\n" +" nosnapfb rawfb progressive rfbport http nohttp httpport\n" " httpdir enablehttpproxy noenablehttpproxy alwaysshared\n" " noalwaysshared nevershared noalwaysshared dontdisconnect\n" " nodontdisconnect desktop debug_xevents nodebug_xevents\n" @@ -2458,6 +2832,7 @@ void print_help(int mode) { rfbMaxClientWait/1000, take_naps ? "take naps":"no naps", screen_blank, + watch_fbpm ? "-nofbpm":"-fbpm", xdamage_max_area, NSCAN, xdamage_memory, use_threads ? "-threads":"-nothreads", fs_frac, @@ -2574,17 +2949,28 @@ void nopassword_warning_msg(int gotloc) { "#@ @#\n" "#@ an existing ~/.vnc/passwd file will work too. @#\n" "#@ @#\n" +"#@ Running \"x11vnc -storepasswd\" with no arguments @#\n" +"#@ will prompt for a passwd to store in ~/.vnc/passwd. @#\n" +"#@ @#\n" "#@ You can also use the -passwdfile or -passwd options. @#\n" "#@ (note -passwd is unsafe if local users are not trusted) @#\n" "#@ @#\n" "#@ Make sure any -rfbauth and -passwdfile password files @#\n" "#@ cannot be read by untrusted users. @#\n" "#@ @#\n" +"#@ Use x11vnc -usepw to automatically use your @#\n" +"#@ ~/.vnc/passwd or ~/.vnc/passwdfile password files. @#\n" +"#@ (and prompt you to create ~/.vnc/passwd if neither @#\n" +"#@ file exists.) @#\n" +"#@ @#\n" +"#@ @#\n" "#@ Even with a password, the subsequent VNC traffic is @#\n" "#@ sent in the clear. Consider tunnelling via ssh(1): @#\n" "#@ @#\n" "#@ http://www.karlrunge.com/x11vnc/#tunnelling @#\n" "#@ @#\n" +"#@ Or using the x11vnc SSL options: -ssl and -stunnel @#\n" +"#@ @#\n" "#@ Please Read the documention for more info about @#\n" "#@ passwords, security, and encryption. @#\n" "#@ @#\n" diff --git a/x11vnc/options.c b/x11vnc/options.c index ec51880..a4ddee5 100644 --- a/x11vnc/options.c +++ b/x11vnc/options.c @@ -23,6 +23,7 @@ int stunnel_port = 0; char *stunnel_pem = NULL; int use_openssl = 0; char *openssl_pem = NULL; +char *ssl_certs_dir = NULL; int https_port_num = -1; char *ssl_verify = NULL; int ssl_initialized = 0; @@ -279,6 +280,13 @@ int napfac = 4; /* time = napfac*waitms, cut load with extra waits */ int napmax = 1500; /* longest nap in ms. */ int ui_skip = 10; /* see watchloop. negative means ignore input */ + +#if LIBVNCSERVER_HAVE_FBPM +int watch_fbpm = 1; /* -nofbpm */ +#else +int watch_fbpm = 0; +#endif + int watch_selection = 1; /* normal selection/cutbuffer maintenance */ int watch_primary = 1; /* more dicey, poll for changes in PRIMARY */ int watch_clipboard = 1; diff --git a/x11vnc/options.h b/x11vnc/options.h index 2daf4e0..a0976af 100644 --- a/x11vnc/options.h +++ b/x11vnc/options.h @@ -23,6 +23,7 @@ extern int stunnel_port; extern char *stunnel_pem; extern int use_openssl; extern char *openssl_pem; +extern char *ssl_certs_dir; extern int https_port_num; extern char *ssl_verify; extern int ssl_initialized; @@ -208,6 +209,8 @@ extern int napfac; extern int napmax; extern int ui_skip; +extern int watch_fbpm; + extern int watch_selection; extern int watch_primary; extern int watch_clipboard; diff --git a/x11vnc/pm.c b/x11vnc/pm.c new file mode 100644 index 0000000..8b3eab5 --- /dev/null +++ b/x11vnc/pm.c @@ -0,0 +1,93 @@ +/* -- pm.c -- */ +#include "x11vnc.h" +#include "cleanup.h" + +void check_pm(void); +static void check_fbpm(void); + +#if LIBVNCSERVER_HAVE_FBPM +#include <X11/Xmd.h> +#include <X11/extensions/fbpm.h> +#endif + +void check_pm(void) { + check_fbpm(); + /* someday dpms activities? */ +} + +static void check_fbpm(void) { + static int init_fbpm = 0; +#if LIBVNCSERVER_HAVE_FBPM + static int fbpm_capable = 0; + static time_t last_fbpm = 0; + int db = 1; + + CARD16 level; + BOOL enabled; + + if (raw_fb && ! dpy) return; /* raw_fb hack */ + + if (! init_fbpm) { + if (FBPMCapable(dpy)) { + fbpm_capable = 1; + rfbLog("X display is capable of FBPM.\n"); + if (watch_fbpm) { + rfbLog("Preventing low-power FBPM modes when" + " VNC clients are connected.\n"); + } + } else { + rfbLog("X display is not capable of FBPM.\n"); + fbpm_capable = 0; + } + init_fbpm = 1; + } + + if (! watch_fbpm) { + return; + } + if (! fbpm_capable) { + return; + } + if (! client_count) { + return; + } + if (time(0) < last_fbpm + 5) { + return; + } + last_fbpm = time(0); + + if (FBPMInfo(dpy, &level, &enabled)) { + if (db) fprintf(stderr, "FBPMInfo level: %d enabled: %d\n", level, enabled); + + if (enabled && level != FBPMModeOn) { + char *from = "unknown-fbpm-state"; + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + + if (level == FBPMModeStandby) { + from = "FBPMModeStandby"; + } else if (level == FBPMModeSuspend) { + from = "FBPMModeSuspend"; + } else if (level == FBPMModeOff) { + from = "FBPMModeOff"; + } + + rfbLog("switching FBPM state from %s to FBPMModeOn\n", from); + + FBPMForceLevel(dpy, FBPMModeOn); + + XSetErrorHandler(old_handler); + trapped_xerror = 0; + } + } else { + if (db) fprintf(stderr, "FBPMInfo failed.\n"); + } +#else + if (raw_fb && ! dpy) return; /* raw_fb hack */ + if (! init_fbpm) { + rfbLog("X FBPM extension not supported.\n"); + init_fbpm = 1; + } +#endif +} + diff --git a/x11vnc/pm.h b/x11vnc/pm.h new file mode 100644 index 0000000..4b046d4 --- /dev/null +++ b/x11vnc/pm.h @@ -0,0 +1,7 @@ +#ifndef _X11VNC_PM_H +#define _X11VNC_PM_H + +/* -- pm.h -- */ +extern void check_pm(void); + +#endif /* _X11VNC_PM_H */ diff --git a/x11vnc/remote.c b/x11vnc/remote.c index 4080554..7c68493 100644 --- a/x11vnc/remote.c +++ b/x11vnc/remote.c @@ -3173,6 +3173,21 @@ char *process_remote_cmd(char *cmd, int stringonly) { screen_blank, w); screen_blank = w; + } else if (!strcmp(p, "fbpm")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, !watch_fbpm); + goto qry; + } + rfbLog("remote_cmd: turning off -nofbpm mode.\n"); + watch_fbpm = 0; + } else if (!strcmp(p, "nofbpm")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, watch_fbpm); + goto qry; + } + rfbLog("remote_cmd: turning on -nofbpm mode.\n"); + watch_fbpm = 1; + } else if (strstr(p, "fs") == p) { COLON_CHECK("fs:") if (query) { diff --git a/x11vnc/scan.c b/x11vnc/scan.c index c35f823..c6dc481 100644 --- a/x11vnc/scan.c +++ b/x11vnc/scan.c @@ -2148,7 +2148,6 @@ static void ping_clients(int tile_cnt) { last_send = now; } else if (now - last_send > 2) { /* Send small heartbeat to client */ -if (0) fprintf(stderr, "ping_clients 2\n"); mark_rect_as_modified(0, 0, 1, 1, 1); last_send = now; } diff --git a/x11vnc/screen.c b/x11vnc/screen.c index 9858ba3..3eaeb87 100644 --- a/x11vnc/screen.c +++ b/x11vnc/screen.c @@ -704,7 +704,9 @@ static XImage *initialize_raw_fb(void) { if (! raw_fb_str) { return NULL; } - + if (!strcasecmp(raw_fb_str, "NULL") || !strcasecmp(raw_fb_str, "ZERO")) { + raw_fb_str = strdup("map:/dev/zero@640x480x32"); + } if ( (q = strstr(raw_fb_str, "setup:")) == raw_fb_str) { FILE *pipe; diff --git a/x11vnc/sslcmds.c b/x11vnc/sslcmds.c index 4b05a7d..f00232f 100644 --- a/x11vnc/sslcmds.c +++ b/x11vnc/sslcmds.c @@ -3,6 +3,8 @@ #include "x11vnc.h" #include "inet.h" #include "cleanup.h" +#include "sslhelper.h" +#include "ssltools.h" #if LIBVNCSERVER_HAVE_FORK #if LIBVNCSERVER_HAVE_SYS_WAIT_H @@ -17,6 +19,10 @@ void check_stunnel(void); int start_stunnel(int stunnel_port, int x11vnc_port); void stop_stunnel(void); void setup_stunnel(int rport, int *argc, char **argv); +char *get_Cert_dir(char *cdir_in, char **tmp_in); +void sslGenCA(char *cdir); +void sslGenCert(char *ty, char *nm); +void sslEncKey(char *path, int info_only); static pid_t stunnel_pid = 0; @@ -293,3 +299,381 @@ void setup_stunnel(int rport, int *argc, char **argv) { clean_up_exit(1); } +char *get_Cert_dir(char *cdir_in, char **tmp_in) { + char *cdir, *home, *tmp; + struct stat sbuf; + int i; + char *cases1[] = {"/.vnc", "/.vnc/certs", "/.vnc/certs/CA"}; + char *cases2[] = {"", "/CA", "/tmp"}; + + if (cdir_in != NULL) { + cdir = cdir_in; + } else { + cdir = ssl_certs_dir; + } + + if (cdir == NULL) { + home = get_home_dir(); + if (! home) { + return NULL; + } + cdir = (char *) malloc(strlen(home) + strlen("/.vnc/certs/CA") + 1); + for (i=0; i<3; i++) { + sprintf(cdir, "%s%s", home, cases1[i]); + if (stat(cdir, &sbuf) != 0) { + rfbLog("creating dir: %s\n", cdir); + if (mkdir(cdir, 0755) != 0) { + rfbLog("could not create directory %s\n", cdir); + rfbLogPerror("mkdir"); + return NULL; + } + } else if (! S_ISDIR(sbuf.st_mode)) { + rfbLog("not a directory: %s\n", cdir); + return NULL; + } + } + sprintf(cdir, "%s%s", home, cases1[1]); + } + + tmp = (char *) malloc(strlen(cdir) + 10); + for (i=0; i<3; i++) { + int ret; + sprintf(tmp, "%s%s", cdir, cases2[i]); + if (stat(tmp, &sbuf) != 0) { + rfbLog("creating dir: %s\n", tmp); + if (! strcmp(cases2[i], "/tmp")) { + ret = mkdir(tmp, 0700); + } else { + ret = mkdir(tmp, 0755); + } + + if (ret != 0) { + rfbLog("could not create directory %s\n", tmp); + rfbLogPerror("mkdir"); + return NULL; + } + } else if (! S_ISDIR(sbuf.st_mode)) { + rfbLog("not a directory: %s\n", tmp); + return NULL; + } + } + sprintf(tmp, "%s/tmp", cdir); + *tmp_in = tmp; + return cdir; +} + +void sslGenCA(char *cdir) { + char *openssl = find_openssl_bin(); + char *tmp, *cmd, *scr, *cdir_use; + FILE *out; + + if (! openssl) { + exit(1); + } + + cdir_use = get_Cert_dir(cdir, &tmp); + if (! cdir_use) { + exit(1); + } + + cmd = (char *) malloc(strlen(tmp) + 100); + scr = (char *) malloc(strlen(tmp) + 100); + + sprintf(cmd, "%s/genca.%d.sh", tmp, getpid()); + out = fopen(cmd, "w"); + if (! out) { + rfbLog("could not open: %s\n", cmd); + rfbLogPerror("fopen"); + exit(1); + } + fprintf(out, "%s", genCA); + fclose(out); + + sprintf(scr, "/bin/sh %s", cmd); + + rfbLog("Using openssl: %s\n", openssl); + rfbLog("Using certs dir: %s\n", cdir_use); + fprintf(stderr, "\n"); + + set_env("BASE_DIR", cdir_use); + set_env("OPENSSL", openssl); + + system(scr); + unlink(cmd); +} + +void sslGenCert(char *ty, char *nm) { + char *openssl = find_openssl_bin(); + char *tmp, *cmd, *scr, *cdir_use; + FILE *out; + + if (! openssl) { + exit(1); + } + + cdir_use = get_Cert_dir(NULL, &tmp); + if (! cdir_use) { + exit(1); + } + + cmd = (char *) malloc(strlen(tmp) + 100); + scr = (char *) malloc(strlen(tmp) + 100); + + sprintf(cmd, "%s/gencert.%d.sh", tmp, getpid()); + out = fopen(cmd, "w"); + if (! out) { + rfbLog("could not open: %s\n", cmd); + rfbLogPerror("fopen"); + exit(1); + } + fprintf(out, "%s", genCert); + fclose(out); + + sprintf(scr, "/bin/sh %s", cmd); + + rfbLog("Using openssl: %s\n", openssl); + rfbLog("Using certs dir: %s\n", cdir_use); + fprintf(stderr, "\n"); + + set_env("BASE_DIR", cdir_use); + set_env("OPENSSL", openssl); + if (! ty) { + set_env("TYPE", ""); + } else { + set_env("TYPE", ty); + } + if (! nm) { + set_env("NAME", ""); + } else { + char *q = strstr(nm, "SAVE-"); + if (!strcmp(nm, "SAVE")) { + set_env("NAME", ""); + } else if (q == nm) { + q += strlen("SAVE-"); + set_env("NAME", q); + } else { + set_env("NAME", nm); + } + } + + system(scr); + unlink(cmd); +} + +void sslEncKey(char *path, int mode) { + char *openssl = find_openssl_bin(); + char *scr, *cert = NULL, *tca; + char line[1024], tmp[] = "/tmp/x11vnc-tmp.XXXXXX"; + char *cdir = NULL; + int tmp_fd, incert, info_only = 0, delete_only = 0; + int listlong = 0; + struct stat sbuf; + FILE *file; + static int depth = 0; + + if (depth > 0) { + /* get_saved_pem may call us back. */ + return; + } + depth++; + + if (mode == 1) { + info_only = 1; + } else if (mode == 2) { + delete_only = 1; + } + + if (! openssl) { + exit(1); + } + cdir = get_Cert_dir(NULL, &tca); + if (! cdir) { + fprintf(stderr, "could not find Cert dir\n"); + exit(1); + } + + if (!strcasecmp(path, "LL") || !strcasecmp(path, "LISTL")) { + listlong = 1; + path = "LIST"; + } + + if (strstr(path, "SAVE") == path) { + char *p = get_saved_pem(path, 0); + if (p == NULL) { + fprintf(stderr, "could not find saved pem matching: %s\n", path); + exit(1); + } + path = p; + + } else if (!strcmp(path, "CA") && cdir) { + tca = (char *) malloc(strlen(cdir) + strlen("/CA/cacert.pem") + 1); + sprintf(tca, "%s/CA/cacert.pem", cdir); + path = tca; + + } else if (info_only && (!strcasecmp(path, "LIST") || + !strcasecmp(path, "ALL"))) { + if (! cdir || strchr(cdir, '\'')) { + fprintf(stderr, "bad certdir char: %s\n", cdir ? cdir : "null"); + exit(1); + } + tca = (char *) malloc(2*strlen(cdir) + strlen(program_name) + 1000); + sprintf(tca, "find '%s' -type f | egrep '\\.(crt|pem|key|req)$' " + "| grep -v CA/newcerts", cdir); + if (!strcasecmp(path, "ALL")) { + /* ugh.. */ + strcat(tca, " | grep -v private/cakey.pem | xargs -n1 "); + strcat(tca, program_name); + strcat(tca, " -ssldir '"); + strcat(tca, cdir); + strcat(tca, "' -sslCertInfo 2>&1 "); + } else if (listlong) { + strcat(tca, " | xargs ls -l "); + } + system(tca); + return; + + } else if (info_only && (!strcasecmp(path, "HASHON") || + !strcasecmp(path, "HASHOFF"))) { + + tmp_fd = mkstemp(tmp); + if (tmp_fd < 0) { + exit(1); + } + + write(tmp_fd, genCert, strlen(genCert)); + close(tmp_fd); + + scr = (char *) malloc(strlen(tmp) + 100); + sprintf(scr, "/bin/sh %s", tmp); + + set_env("BASE_DIR", cdir); + set_env("OPENSSL", openssl); + set_env("TYPE", "server"); + if (!strcasecmp(path, "HASHON")) { + set_env("HASHON", "1"); + } else { + set_env("HASHOFF", "1"); + } + system(scr); + unlink(tmp); + return; + } + + if (stat(path, &sbuf) != 0) { + if (strstr(path, "client") || strchr(path, '/') == NULL) { + int i; + tca = (char *) malloc(strlen(cdir) + strlen("/clients") + + strlen(path) + 100); + for (i = 1; i <= 15; i++) { + tca[0] = '\0'; + if ( i == 1) { + sprintf(tca, "%s/%s", cdir, path); + } else if (i == 2 && mode > 0) { + sprintf(tca, "%s/%s.crt", cdir, path); + } else if (i == 3) { + sprintf(tca, "%s/%s.pem", cdir, path); + } else if (i == 4 && mode > 1) { + sprintf(tca, "%s/%s.req", cdir, path); + } else if (i == 5 && mode > 1) { + sprintf(tca, "%s/%s.key", cdir, path); + } else if (i == 6) { + sprintf(tca, "%s/clients/%s", cdir, path); + } else if (i == 7 && mode > 0) { + sprintf(tca, "%s/clients/%s.crt", cdir, path); + } else if (i == 8) { + sprintf(tca, "%s/clients/%s.pem", cdir, path); + } else if (i == 9 && mode > 1) { + sprintf(tca, "%s/clients/%s.req", cdir, path); + } else if (i == 10 && mode > 1) { + sprintf(tca, "%s/clients/%s.key", cdir, path); + } else if (i == 11) { + sprintf(tca, "%s/server-%s", cdir, path); + } else if (i == 12 && mode > 0) { + sprintf(tca, "%s/server-%s.crt", cdir, path); + } else if (i == 13) { + sprintf(tca, "%s/server-%s.pem", cdir, path); + } else if (i == 14 && mode > 1) { + sprintf(tca, "%s/server-%s.req", cdir, path); + } else if (i == 15 && mode > 1) { + sprintf(tca, "%s/server-%s.key", cdir, path); + } + if (tca[0] == '\0') { + continue; + } + if (stat(tca, &sbuf) == 0) { + path = tca; + break; + } + } + } + } + + if (stat(path, &sbuf) != 0) { + rfbLog("sslEncKey: %s\n", path); + rfbLogPerror("stat"); + exit(1); + } + + if (! info_only) { + cert = (char *) malloc(2*sbuf.st_size); + file = fopen(path, "r"); + if (file == NULL) { + rfbLog("sslEncKey: %s\n", path); + rfbLogPerror("fopen"); + exit(1); + } + incert = 0; + cert[0] = '\0'; + while (fgets(line, 1024, file) != NULL) { + if (strstr(line, "-----BEGIN CERTIFICATE-----") == line) { + incert = 1; + } + if (incert) { + strcat(cert, line); + } + if (strstr(line, "-----END CERTIFICATE-----") == line) { + incert = 0; + } + } + fclose(file); + } + + tmp_fd = mkstemp(tmp); + if (tmp_fd < 0) { + exit(1); + } + + write(tmp_fd, genCert, strlen(genCert)); + close(tmp_fd); + + scr = (char *) malloc(strlen(tmp) + 100); + sprintf(scr, "/bin/sh %s", tmp); + + set_env("BASE_DIR", "/no/such/dir"); + set_env("OPENSSL", openssl); + set_env("TYPE", "server"); + if (info_only) { + set_env("INFO_ONLY", path); + } else if (delete_only) { + set_env("DELETE_ONLY", path); + } else { + set_env("ENCRYPT_ONLY", path); + } + system(scr); + unlink(tmp); + + if (! mode && cert && cert[0] != '\0') { + file = fopen(path, "a"); + if (file == NULL) { + rfbLog("sslEncKey: %s\n", path); + rfbLogPerror("fopen"); + exit(1); + } + fprintf(file, cert); + fclose(file); + free(cert); + } + + depth--; +} + diff --git a/x11vnc/sslcmds.h b/x11vnc/sslcmds.h index e75af7c..4573ef0 100644 --- a/x11vnc/sslcmds.h +++ b/x11vnc/sslcmds.h @@ -7,6 +7,10 @@ extern void check_stunnel(void); extern int start_stunnel(int stunnel_port, int x11vnc_port); extern void stop_stunnel(void); extern void setup_stunnel(int rport, int *argc, char **argv); +extern char *get_Cert_dir(char *cdir_in, char **tmp_in); +extern void sslGenCA(char *cdir); +extern void sslGenCert(char *ty, char *nm); +extern void sslEncKey(char *path, int info_only); #endif /* _X11VNC_SSLCMDS_H */ diff --git a/x11vnc/sslhelper.c b/x11vnc/sslhelper.c index 53249db..cc84f3c 100644 --- a/x11vnc/sslhelper.c +++ b/x11vnc/sslhelper.c @@ -6,6 +6,7 @@ #include "screen.h" #include "scan.h" #include "connections.h" +#include "sslcmds.h" #define OPENSSL_INETD 1 #define OPENSSL_VNC 2 @@ -24,16 +25,21 @@ pid_t openssl_last_helper_pid = 0; #if !LIBVNCSERVER_HAVE_LIBSSL int openssl_present(void) {return 0;} -void openssl_init(void) { - rfbLog("not compiled with libssl support.\n"); +static void badnews(void) { + use_openssl = 0; + use_stunnel = 0; + rfbLog("** not compiled with libssl OpenSSL support **\n"); clean_up_exit(1); } -void openssl_port(void) {} -void https_port(void) {} -void check_openssl(void) {} -void check_https(void) {} -void ssl_helper_pid(pid_t pid, int sock) {sock = pid;} -void accept_openssl(int mode) {mode = 0; clean_up_exit(1);} +void openssl_init(void) {badnews();} +void openssl_port(void) {badnews();} +void https_port(void) {badnews();} +void check_openssl(void) {badnews();} +void check_https(void) {badnews();} +void ssl_helper_pid(pid_t pid, int sock) {badnews(); sock = pid;} +void accept_openssl(int mode) {mode = 0; badnews();} +char *find_openssl_bin(void) {badnews(); return NULL;} +char *get_saved_pem(char *string, int create) {badnews(); return NULL;} #else #include <openssl/ssl.h> @@ -47,6 +53,8 @@ void check_openssl(void); void check_https(void); void ssl_helper_pid(pid_t pid, int sock); void accept_openssl(int mode); +char *find_openssl_bin(void); +char *get_saved_pem(char *string, int create); static SSL_CTX *ctx = NULL; static RSA *rsa_512 = NULL; @@ -56,8 +64,9 @@ static SSL *ssl = NULL; static void init_prng(void); static void sslerrexit(void); -static char *create_tmp_pem(void); +static char *create_tmp_pem(char *path, int prompt); static int ssl_init(int s_in, int s_out); +static void raw_xfer(int csock, int s_in, int s_out); static void ssl_xfer(int csock, int s_in, int s_out, int is_https); #ifndef FORK_OK @@ -81,47 +90,169 @@ static void sslerrexit(void) { clean_up_exit(1); } +char *get_saved_pem(char *save, int create) { + char *s = NULL, *path, *cdir, *tmp; + int prompt = 0, len; + struct stat sbuf; + + if (strstr(save, "SAVE_PROMPT") == save) { + prompt = 1; + s = save + strlen("SAVE_PROMPT"); + } else if (strstr(save, "SAVE") == save) { + s = save + strlen("SAVE"); + } else { + rfbLog("get_saved_pem: invalid save string: %s\n", save); + clean_up_exit(1); + } + if (strchr(s, '/')) { + rfbLog("get_saved_pem: invalid save string: %s\n", s); + clean_up_exit(1); + } + + cdir = get_Cert_dir(NULL, &tmp); + if (! cdir) { + rfbLog("get_saved_pem: could not find Cert dir.\n"); + clean_up_exit(1); + } + len = strlen(cdir) + strlen("/server.pem") + strlen(s) + 1; + path = (char *) malloc(len); + sprintf(path, "%s/server%s.pem", cdir, s); + + if (stat(path, &sbuf) != 0) { + char *new = NULL; + if (create) { + new = create_tmp_pem(path, prompt); + sslEncKey(new, 0); + } + return new; + } else { + return strdup(path); + } +} + +static char *get_input(char *tag, char **in) { + char line[1024], *str; + fprintf(stderr, "%s:\n [%s] ", tag, *in); + if (fgets(line, 1024, stdin) == NULL) { + rfbLog("could not read stdin!\n"); + rfbLogPerror("fgets"); + clean_up_exit(1); + } + if ((str = strrchr(line, '\n')) != NULL) { + *str = '\0'; + } + str = lblanks(line); + if (! strcmp(str, "")) { + return *in; + } else if (0 && !strcmp(str, "none")) { + free(*in); + return strdup(""); + } else { + free(*in); + return strdup(line); + } +} + +char *find_openssl_bin(void) { + char *path, *exe, *p; + struct stat sbuf; + int found_openssl = 0; + char extra[] = ":/usr/bin:/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/sfw/bin"; + + if (! getenv("PATH")) { + fprintf(stderr, "could not find openssl(1) program in PATH.\n"); + return NULL; + } + path = (char *) malloc(strlen(getenv("PATH")) + strlen(extra) + 1); + strcpy(path, getenv("PATH")); + strcat(path, extra); + + /* find openssl binary: */ + exe = (char *) malloc(strlen(path) + strlen("/openssl") + 1); + p = strtok(path, ":"); + + while (p) { + sprintf(exe, "%s/openssl", p); + if (stat(exe, &sbuf) == 0) { + if (! S_ISDIR(sbuf.st_mode)) { + found_openssl = 1; + break; + } + } + p = strtok(NULL, ":"); + } + free(path); + + if (! found_openssl) { + fprintf(stderr, "could not find openssl(1) program in PATH.\n"); + fprintf(stderr, "(also checked: %s)\n", extra); + return NULL; + } + return exe; +} + /* uses /usr/bin/openssl to create a tmp cert */ -static char *create_tmp_pem(void) { +static char *create_tmp_pem(char *pathin, int prompt) { pid_t pid, pidw; FILE *in, *out; char cnf[] = "/tmp/x11vnc-cnf.XXXXXX"; char pem[] = "/tmp/x11vnc-pem.XXXXXX"; - char str[4096], line[1024], *path, *p, *exe; - int found_openssl = 0, cnf_fd, pem_fd, status, show_cert = 1; - struct stat sbuf; + char str[7*1024], line[1024], *exe; + int cnf_fd, pem_fd, status, show_cert = 1; + char *days; + char *C, *L, *OU, *O, *CN, *EM; char tmpl[] = "[ req ]\n" "prompt = no\n" -"default_bits = 1024\n" +"default_bits = 2048\n" "encrypt_key = yes\n" "distinguished_name = req_dn\n" "x509_extensions = cert_type\n" "\n" "[ req_dn ]\n" -"countryName=AU\n" +"countryName=%s\n" "localityName=%s\n" -"organizationalUnitName=%s-%f\n" -"organizationName=x11vnc\n" -"commonName=x11vnc-SELF-SIGNED-TEMPORARY-CERT-%d\n" -"emailAddress=nobody@x11vnc.server\n" +"organizationalUnitName=%s\n" +"organizationName=%s\n" +"commonName=%s\n" +"emailAddress=%s\n" "\n" "[ cert_type ]\n" "nsCertType = server\n" ; + C = strdup("AU"); + L = strdup(UT.sysname); + snprintf(line, 1024, "%s-%f", UT.nodename, dnow()); + line[1024-1] = '\0'; + OU = strdup(line); + O = strdup("x11vnc"); + if (pathin) { + snprintf(line, 1024, "x11vnc-SELF-SIGNED-CERT-%d", getpid()); + } else { + snprintf(line, 1024, "x11vnc-SELF-SIGNED-TEMPORARY-CERT-%d", getpid()); + } + line[1024-1] = '\0'; + CN = strdup(line); + EM = strdup("x11vnc@server.nowhere"); + if (no_external_cmds) { rfbLog("create_tmp_pem: cannot run external commands.\n"); return NULL; } rfbLog("\n"); - rfbLog("Creating a temporary, self-signed PEM certificate...\n"); + if (pathin) { + rfbLog("Creating a self-signed PEM certificate...\n"); + } else { + rfbLog("Creating a temporary, self-signed PEM certificate...\n"); + } rfbLog("\n"); rfbLog("This will NOT prevent man-in-the-middle attacks UNLESS you\n"); rfbLog("get the certificate information to the VNC viewers SSL\n"); - rfbLog("tunnel configuration. However, it will prevent passive\n"); - rfbLog("network sniffing.\n"); + rfbLog("tunnel configuration or you take the extra steps to sign it\n"); + rfbLog("with a CA key. However, it will prevent passive network\n"); + rfbLog("sniffing.\n"); rfbLog("\n"); rfbLog("The cert inside -----BEGIN CERTIFICATE-----\n"); rfbLog(" ....\n"); @@ -132,31 +263,27 @@ static char *create_tmp_pem(void) { rfbLog("server certificate.\n"); rfbLog("\n"); - if (! getenv("PATH")) { - return NULL; - } - path = strdup(getenv("PATH")); - - /* find openssl binary: */ - exe = (char *) malloc(strlen(path) + strlen("/openssl") + 1); - p = strtok(path, ":"); - while (p) { - sprintf(exe, "%s/openssl", p); - if (stat(exe, &sbuf) == 0) { - if (! S_ISDIR(sbuf.st_mode)) { - found_openssl = 1; - break; - } - } - p = strtok(NULL, ":"); - } - free(path); - - if (! found_openssl) { + exe = find_openssl_bin(); + if (exe == NULL) { return NULL; } + /* create template file with our made up stuff: */ + if (prompt) { + fprintf(stderr, "\nReply to the following prompts to set" + " your Certificate parameters.\n"); + fprintf(stderr, "(press Enter to accept the default in [...], " + "or type in the value you want)\n\n"); + C = get_input("CountryName", &C); + L = get_input("LocalityName", &L); + OU = get_input("OrganizationalUnitName", &OU); + O = get_input("OrganizationalName", &O); + CN = get_input("CommonName", &CN); + EM = get_input("EmailAddress", &EM); + } + sprintf(str, tmpl, C, L, OU, O, CN, EM); + cnf_fd = mkstemp(cnf); pem_fd = mkstemp(pem); @@ -166,11 +293,15 @@ static char *create_tmp_pem(void) { close(pem_fd); - /* create template file with our made up stuff: */ - sprintf(str, tmpl, UT.sysname, UT.nodename, dnow(), (int) getpid()); write(cnf_fd, str, strlen(str)); close(cnf_fd); + if (pathin) { + days = "365"; + } else { + days = "30"; + } + /* make RSA key */ pid = fork(); if (pid < 0) { @@ -181,7 +312,8 @@ static char *create_tmp_pem(void) { close(i); } execlp(exe, exe, "req", "-new", "-x509", "-nodes", - "-config", cnf, "-out", pem, "-keyout", pem, (char *)0); + "-days", days, "-config", cnf, "-out", pem, + "-keyout", pem, (char *)0); exit(1); } pidw = waitpid(pid, &status, 0); @@ -194,6 +326,7 @@ static char *create_tmp_pem(void) { return NULL; } +#if DO_DH /* make DH parameters */ pid = fork(); if (pid < 0) { @@ -203,6 +336,7 @@ static char *create_tmp_pem(void) { for (i=0; i<256; i++) { close(i); } + /* rather slow at 1024 */ execlp(exe, exe, "dhparam", "-out", cnf, "512", (char *)0); exit(1); } @@ -231,10 +365,67 @@ static char *create_tmp_pem(void) { } fclose(in); fclose(out); +#endif unlink(cnf); free(exe); + if (pathin != NULL) { + char *q, *pathcrt = strdup(pathin); + FILE *crt = NULL; + int on = 0; + + q = strrchr(pathcrt, '/'); + if (q) { + q = strstr(q, ".pem"); + if (q) { + *(q+1) = 'c'; + *(q+2) = 'r'; + *(q+3) = 't'; + crt = fopen(pathcrt, "w"); + } + } + if (crt == NULL) { + rfbLog("could not open: %s\n", pathcrt); + rfbLogPerror("fopen"); + return NULL; + } + out = fopen(pathin, "w"); + if (out == NULL) { + rfbLog("could not open: %s\n", pathin); + rfbLogPerror("fopen"); + fclose(crt); + return NULL; + } + chmod(pathin, 0600); + + in = fopen(pem, "r"); + if (in == NULL) { + rfbLog("could not open: %s\n", pem); + rfbLogPerror("fopen"); + fclose(out); + fclose(crt); + unlink(pathin); + unlink(pathcrt); + return NULL; + } + while (fgets(line, 1024, in) != NULL) { + if (strstr(line, "-----BEGIN CERTIFICATE-----")) { + on = 1; + } + fprintf(out, "%s", line); + if (on) { + fprintf(crt, "%s", line); + } + if (strstr(line, "-----END CERTIFICATE-----")) { + on = 0; + } + } + fclose(in); + fclose(out); + fclose(crt); + } + if (show_cert) { char cmd[100]; if (inetd) { @@ -247,15 +438,172 @@ static char *create_tmp_pem(void) { fprintf(stderr, "\n"); } - return strdup(pem); + if (pathin) { + unlink(pem); + return strdup(pathin); + } else { + return strdup(pem); + } +} + +static int pem_passwd_callback(char *buf, int size, int rwflag, + void *userdata) { + char *q, line[1024]; + + fprintf(stderr, "\nA passphrase is needed to unlock an OpenSSL " + "private key (PEM file).\n"); + fprintf(stderr, "Enter passphrase> "); + system("stty -echo"); + if(fgets(line, 1024, stdin) == NULL) { + fprintf(stdout, "\n"); + system("stty echo"); + exit(1); + } + system("stty echo"); + fprintf(stdout, "\n\n"); + q = strrchr(line, '\n'); + if (q) { + *q = '\0'; + } + line[1024 - 1] = '\0'; + strncpy(buf, line, size); + buf[size - 1] = '\0'; + + if (0) rwflag = 0; /* compiler warning. */ + if (0) userdata = 0; /* compiler warning. */ + + return strlen(buf); +} + +static int appendfile(FILE *out, char *infile) { + char line[1024]; + FILE *in = fopen(infile, "r"); + + if (in == NULL) { + rfbLog("appendfile: %s\n", infile); + rfbLogPerror("fopen"); + return 0; + } + + while (fgets(line, 1024, in) != NULL) { + fprintf(out, "%s", line); + } + fclose(in); + return 1; +} + +static char *get_ssl_verify_file(char *str_in) { + char *p, *str, *cdir, *tmp; + char *tfile, *tfile2; + FILE *file; + struct stat sbuf; + int count = 0; + + if (! str_in) { + rfbLog("get_ssl_verify_file: no filename\n"); + exit(1); + } + + if (stat(str_in, &sbuf) == 0) { + /* assume he knows what he is doing. */ + return str_in; + } + + str = strdup(str_in); + p = strtok(str, ","); + + cdir = get_Cert_dir(NULL, &tmp); + if (! cdir) { + rfbLog("get_ssl_verify_file: invalid cert-dir.\n"); + exit(1); + } + + tfile = (char *) malloc(strlen(tmp) + 1024); + tfile2 = (char *) malloc(strlen(tmp) + 1024); + + sprintf(tfile, "%s/sslverify-load-%d.crts", tmp, getpid()); + + file = fopen(tfile, "w"); + if (file == NULL) { + rfbLog("get_ssl_verify_file: %s\n", tfile); + rfbLogPerror("fopen"); + exit(1); + } + chmod(tfile, 0600); + + while (p) { + if (!strcmp(p, "CA")) { + sprintf(tfile2, "%s/CA/cacert.pem", cdir); + if (! appendfile(file, tfile2)) { + unlink(tfile); + exit(1); + } + fprintf(stderr, "sslverify: loaded %s\n", tfile2); + count++; + } else if (!strcmp(p, "clients")) { + DIR *dir; + struct dirent *dp; + sprintf(tfile2, "%s/clients", cdir); + dir = opendir(tfile2); + if (! dir) { + rfbLog("get_ssl_verify_file: %s\n", tfile2); + rfbLogPerror("opendir"); + unlink(tfile); + exit(1); + } + while ( (dp = readdir(dir)) != NULL) { + char *n = dp->d_name; + char *q = strstr(n, ".crt"); + if (! q || strlen(q) != strlen(".crt")) { + continue; + } + sprintf(tfile2, "%s/clients/%s", cdir, n); + if (! appendfile(file, tfile2)) { + unlink(tfile); + exit(1); + } + fprintf(stderr, "sslverify: loaded %s\n", tfile2); + count++; + } + closedir(dir); + + } else { + if (strlen(p) > 512) { + unlink(tfile); + exit(1); + } + sprintf(tfile2, "%s/clients/%s.crt", cdir, p); + if (stat(tfile2, &sbuf) != 0) { + sprintf(tfile2, "%s/clients/%s", cdir, p); + } + if (! appendfile(file, tfile2)) { + unlink(tfile); + exit(1); + } + fprintf(stderr, "sslverify: loaded %s\n", tfile2); + count++; + } + p = strtok(NULL, ","); + } + fclose(file); + free(tfile2); + free(str); + fprintf(stderr, "sslverify: using %d client certs in %s\n", count, tfile); + return tfile; } void openssl_init(void) { - int db = 0, tmp_pem = 0, do_dh = 1; + int db = 0, tmp_pem = 0, do_dh; FILE *in; double ds; long mode; +#if DO_DH + do_dh = 1; +#else + do_dh = 0; +#endif + if (! quiet) { rfbLog("\n"); rfbLog("Initializing SSL.\n"); @@ -314,17 +662,27 @@ void openssl_init(void) { ds = dnow(); if (! openssl_pem) { - openssl_pem = create_tmp_pem(); + openssl_pem = create_tmp_pem(NULL, 0); if (! openssl_pem) { rfbLog("openssl_init: could not create temporary," " self-signed PEM.\n"); clean_up_exit(1); } tmp_pem = 1; + } else if (strstr(openssl_pem, "SAVE") == openssl_pem) { + openssl_pem = get_saved_pem(openssl_pem, 1); + if (! openssl_pem) { + rfbLog("openssl_init: could not create or open" + " saved PEM:\n", openssl_pem); + clean_up_exit(1); + } + tmp_pem = 0; } rfbLog("using PEM %s %.3fs\n", openssl_pem, dnow() - ds); + SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_callback); + if (do_dh) { DH *dh; BIO *bio; @@ -387,23 +745,23 @@ void openssl_init(void) { if (ssl_verify) { struct stat sbuf; + char *file; int lvl; - if (stat(ssl_verify, &sbuf) != 0) { + file = get_ssl_verify_file(ssl_verify); + if (stat(file, &sbuf) != 0) { rfbLog("openssl_init: -sslverify does not exists %s.\n", - ssl_verify); + file); rfbLogPerror("stat"); clean_up_exit(1); } if (! S_ISDIR(sbuf.st_mode)) { - if (! SSL_CTX_load_verify_locations(ctx, ssl_verify, - NULL)) { + if (! SSL_CTX_load_verify_locations(ctx, file, NULL)) { rfbLog("openssl_init: SSL_CTX_load_verify_" "locations() failed.\n"); sslerrexit(); } } else { - if (! SSL_CTX_load_verify_locations(ctx, NULL, - ssl_verify)) { + if (! SSL_CTX_load_verify_locations(ctx, NULL, file)) { rfbLog("openssl_init: SSL_CTX_load_verify_" "locations() failed.\n"); sslerrexit(); @@ -411,6 +769,10 @@ void openssl_init(void) { } lvl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER; SSL_CTX_set_verify(ctx, lvl, NULL); + if (strstr(file, "tmp/sslverify-load-")) { + /* temporary file */ + unlink(file); + } } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); } @@ -511,10 +873,6 @@ static void lose_ram(void) { free(snap_fb); snap_fb = NULL; } - if (raw_fb) { - free(raw_fb); - raw_fb = NULL; - } free_tiles(); } @@ -645,6 +1003,7 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get, tv.tv_sec = 4; } } +if (1) fprintf(stderr, "tv_sec: %d - %s\n", (int) tv.tv_sec, last_get); FD_ZERO(&rd); FD_SET(s_in, &rd); @@ -662,10 +1021,10 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get, } #define BSIZE 16384 -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; - char *buf = *buf_a; - int db = 0; + char *buf; + int db = 1; /* * 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 @@ -674,6 +1033,7 @@ static int watch_for_http_traffic(char **buf_a, int *n_a) { * *buf_a is BSIZE+1 long and zeroed. */ + buf = (char *) calloc(sizeof(BSIZE+1), 1); *n_a = 0; n = SSL_read(ssl, buf, 2); @@ -681,6 +1041,7 @@ static int watch_for_http_traffic(char **buf_a, int *n_a) { if (err != SSL_ERROR_NONE || n < 2) { if (n > 0) { + strncpy(buf_a, buf, n); *n_a = n; } return -1; @@ -708,6 +1069,9 @@ static int watch_for_http_traffic(char **buf_a, int *n_a) { n += n2; } *n_a = n; + if (n > 0) { + strncpy(buf_a, buf, n); + } return is_http; } @@ -720,8 +1084,91 @@ static void csock_timeout (int sig) { } } +static int wait_conn(int sock) { + int conn; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + + signal(SIGALRM, csock_timeout); + csock_timeout_sock = sock; + + alarm(15); + conn = accept(sock, (struct sockaddr *)&addr, &addrlen); + alarm(0); + + signal(SIGALRM, SIG_DFL); + return conn; +} + +int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie, + int mode) { + char reply[] = "HTTP/1.1 200 OK\r\n" + "Content-Type: octet-stream\r\n" + "Pragma: no-cache\r\n\r\n"; + char reply0[] = "HTTP/1.0 200 OK\r\n" + "Content-Type: octet-stream\r\n" + "Content-Length: 9\r\n" + "Pragma: no-cache\r\n\r\nGO_AHEAD\n"; + int sock1, db = 0; + + rfbLog("SSL: accept_openssl: detected https proxied connection" + " request.\n"); + + SSL_write(ssl, reply0, strlen(reply0)); + SSL_shutdown(ssl); + SSL_shutdown(ssl); + close(s_in); + close(s_out); + SSL_free(ssl); + + if (mode == OPENSSL_VNC) { + listen = openssl_sock; + } else if (mode == OPENSSL_HTTPS) { + listen = https_sock; + } else { + return 0; + } + sock1 = wait_conn(listen); + + if (csock_timeout_sock < 0 || sock1 < 0) { + close(sock1); + return 0; + } +if (db) fprintf(stderr, "got applet input sock1: %d\n", sock1); + + if (! ssl_init(sock1, sock1)) { +if (db) fprintf(stderr, "ssl_init FAILED\n"); + exit(1); + } + SSL_write(ssl, reply, strlen(reply)); + + { + char *buf; + int n, ptr; + + buf = (char *) calloc((8192+1), 1); + n = 0; + ptr = 0; + while (ptr < 8192) { + n = SSL_read(ssl, buf + ptr, 8192 - ptr); + if (n > 0) { + ptr += n; + } +if (db) fprintf(stderr, "buf: '%s'\n", buf); + if (strstr(buf, "\r\n\r\n") || strstr(buf, "\n\n")) { + break; + } + } + } + + write(vncsock, cookie, strlen(cookie)); + ssl_xfer(vncsock, sock1, sock1, 0); + + return 1; +} + void accept_openssl(int mode) { - int sock = -1, cport, csock, vsock; + int sock = -1, cport, csock, vsock, listen = -1; int status, n, i, db = 0; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); @@ -751,6 +1198,7 @@ void accept_openssl(int mode) { } else if (mode == OPENSSL_VNC && openssl_sock >= 0) { sock = accept(openssl_sock, (struct sockaddr *)&addr, &addrlen); + listen = openssl_sock; if (sock < 0) { rfbLog("SSL: accept_openssl: accept connection failed\n"); rfbLogPerror("accept"); @@ -759,6 +1207,7 @@ void accept_openssl(int mode) { } else if (mode == OPENSSL_HTTPS && https_sock >= 0) { sock = accept(https_sock, (struct sockaddr *)&addr, &addrlen); + listen = https_sock; if (sock < 0) { rfbLog("SSL: accept_openssl: accept connection failed\n"); rfbLogPerror("accept"); @@ -834,21 +1283,25 @@ void accept_openssl(int mode) { int f_out = fileno(stdout); /* reset all handlers to default (no interrupted() calls) */ - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); + unset_signals(); /* close all non-essential fd's */ for (i=0; i<256; i++) { - if (i != sslsock && i != 2) { - if (mode == OPENSSL_INETD) { - if (i == f_in || i == f_out) { - continue; - } + if (mode == OPENSSL_INETD) { + if (i == f_in || i == f_out) { + continue; } - close(i); } + if (i == sslsock) { + continue; + } + if (i == 2) { + continue; + } + if (i == listen) { + continue; + } + close(i); } /* @@ -861,6 +1314,7 @@ void accept_openssl(int mode) { /* now connect back to parent socket: */ vncsock = rfbConnectToTcpAddr("127.0.0.1", cport); if (vncsock < 0) { + rfbLog("SSL: ssl_helper: could not connect back to: %d\n", cport); close(vncsock); exit(1); } @@ -898,11 +1352,10 @@ void accept_openssl(int mode) { int n, is_http; int hport = screen->httpPort; char *iface = NULL; - static char *buf = NULL; + char *buf, *tbuf; - if (buf == NULL) { - buf = (char *) calloc(sizeof(BSIZE+1), 1); - } + buf = (char *) calloc((BSIZE+1), 1); + tbuf = (char *) calloc((2*BSIZE+1), 1); if (mode == OPENSSL_HTTPS) { /* @@ -918,6 +1371,7 @@ void accept_openssl(int mode) { * Check if there is stuff to read from remote end * 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, mode)) { goto write_cookie; @@ -930,7 +1384,8 @@ void accept_openssl(int mode) { * is ever sent. So often we timeout here. */ - is_http = watch_for_http_traffic(&buf, &n); + if (1) fprintf(stderr, "watch_for_http_traffic\n"); + is_http = watch_for_http_traffic(buf, &n); if (is_http < 0 || is_http == 0) { /* @@ -943,7 +1398,38 @@ void accept_openssl(int mode) { } goto wrote_cookie; } + if (1) fprintf(stderr, "buf: '%s'\n", buf); + + if (strstr(buf, "/request.https.proxy.connection")) { + /* + * special case proxy coming thru https + * instead of a direct SSL connection. + */ + if (! proxy_hack(vncsock, listen, s_in, s_out, + cookie, mode)) { + strcpy(tbuf, uniq); + strcat(tbuf, cookie); + write(vncsock, tbuf, strlen(tbuf)); + close(vncsock); + } + exit(0); + + } else if (strstr(buf, "/check.https.proxy.connection")) { + char reply[] = "HTTP/1.0 200 OK\r\n" + "Connection: close\r\n" + "Content-Type: octet-stream\r\n" + "Pragma: no-cache\r\n\r\n"; + + SSL_write(ssl, reply, strlen(reply)); + SSL_shutdown(ssl); + strcpy(tbuf, uniq); + strcat(tbuf, cookie); + write(vncsock, tbuf, strlen(tbuf)); + close(vncsock); + + exit(0); + } connect_to_httpd: /* @@ -953,18 +1439,19 @@ void accept_openssl(int mode) { */ /* send the failure tag: */ - write(vncsock, uniq, strlen(uniq)); + strcpy(tbuf, uniq); if (strstr(buf, "HTTP/") != NULL) { + char *q, *str; /* * Also send back the GET line for heuristics. * (last_https, get file). */ - char *q, *str = strdup(buf); + str = strdup(buf); q = strstr(str, "HTTP/"); if (q != NULL) { *q = '\0'; - write(vncsock, str, strlen(str)); + strcat(tbuf, str); } free(str); } @@ -975,11 +1462,13 @@ void accept_openssl(int mode) { * Since this is the failure case, it does not * matter that we send more than strlen(cookie). */ - write(vncsock, cookie, strlen(cookie)); + strcat(tbuf, cookie); + write(vncsock, tbuf, strlen(tbuf)); + usleep(150*1000); +if (db) fprintf(stderr, "close vncsock: %d\n", vncsock); close(vncsock); - /* now, finally, connect to the libvncserver httpd: */ if (screen->listenInterface == htonl(INADDR_ANY) || screen->listenInterface == htonl(INADDR_NONE)) { @@ -992,6 +1481,7 @@ void accept_openssl(int mode) { if (iface == NULL || !strcmp(iface, "")) { iface = "127.0.0.1"; } +if (db) fprintf(stderr, "iface: %s\n", iface); usleep(150*1000); httpsock = rfbConnectToTcpAddr(iface, hport); @@ -1069,7 +1559,7 @@ void accept_openssl(int mode) { if (strstr(rcookie, uniq) == rcookie) { int i; - rfbLog("SSL: https for helper process succeeded.\n"); + rfbLog("SSL: but https for helper process succeeded.\n"); if (mode != OPENSSL_HTTPS) { last_https = time(0); for (i=0; i<128; i++) { @@ -1081,6 +1571,7 @@ void accept_openssl(int mode) { ssl_helper_pid(pid, -2); if (mode == OPENSSL_INETD) { + double start; /* to expand $PORT correctly in index.vnc */ if (screen->port == 0) { int fd = fileno(stdin); @@ -1097,7 +1588,7 @@ void accept_openssl(int mode) { rfbLog("SSL: screen->port %d\n", screen->port); /* kludge for https fetch via inetd */ - double start = dnow(); + start = dnow(); while (dnow() < start + 10.0) { rfbPE(10000); usleep(10000); @@ -1127,6 +1618,7 @@ void accept_openssl(int mode) { openssl_last_helper_pid = pid; ssl_helper_pid(pid, vsock); + client = rfbNewClient(screen, vsock); openssl_last_helper_pid = 0; @@ -1159,17 +1651,19 @@ static void ssl_timeout (int sig) { static int ssl_init(int s_in, int s_out) { unsigned char *sid = (unsigned char *) "x11vnc SID"; char *name; - int db = 0, rc, err; + int db = 1, rc, err; int ssock = s_in; double start = dnow(); int timeout = 20; if (db) fprintf(stderr, "ssl_init: %d/%d\n", s_in, s_out); + ssl = SSL_new(ctx); if (ssl == NULL) { fprintf(stderr, "SSL_new failed\n"); return 0; } +if (db > 1) fprintf(stderr, "a\n"); SSL_set_session_id_context(ssl, sid, strlen((char *)sid)); @@ -1188,10 +1682,13 @@ static int ssl_init(int s_in, int s_out) { return 0; } } +if (db > 1) fprintf(stderr, "b\n"); SSL_set_accept_state(ssl); +if (db > 1) fprintf(stderr, "c\n"); name = get_remote_host(ssock); +if (db > 1) fprintf(stderr, "d\n"); while (1) { if (db) fprintf(stderr, "calling SSL_accept...\n"); @@ -1258,9 +1755,9 @@ static int ssl_init(int s_in, int s_out) { return 1; } -static void ssl_xfer_debug(int csock, int s_in, int s_out) { - char buf[2048]; - int sz = 2048, n, m, status; +static void raw_xfer(int csock, int s_in, int s_out) { + char buf[8192]; + int sz = 8192, n, m, status; pid_t pid = fork(); int db = 1; @@ -1269,7 +1766,7 @@ static void ssl_xfer_debug(int csock, int s_in, int s_out) { exit(1); } if (pid) { - if (db) fprintf(stderr, "ssl_xfer start: %d -> %d/%d\n", csock, s_in, s_out); + if (db) fprintf(stderr, "raw_xfer start: %d -> %d/%d\n", csock, s_in, s_out); while (1) { n = read(csock, buf, sz); @@ -1277,8 +1774,9 @@ static void ssl_xfer_debug(int csock, int s_in, int s_out) { break; } else if (n > 0) { m = write(s_out, buf, n); +if (db > 1) write(2, buf, n); if (m != n) { - if (db) fprintf(stderr, "ssl_xfer bad write: %d -> %d | %d/%d\n", csock, s_out, m, n); + if (db) fprintf(stderr, "raw_xfer bad write: %d -> %d | %d/%d\n", csock, s_out, m, n); break; } @@ -1286,10 +1784,10 @@ static void ssl_xfer_debug(int csock, int s_in, int s_out) { } kill(pid, SIGTERM); waitpid(pid, &status, WNOHANG); - if (db) fprintf(stderr, "ssl_xfer done: %d -> %d\n", csock, s_out); + if (db) fprintf(stderr, "raw_xfer done: %d -> %d\n", csock, s_out); } else { - if (db) fprintf(stderr, "ssl_xfer start: %d <- %d\n", csock, s_in); + if (db) fprintf(stderr, "raw_xfer start: %d <- %d\n", csock, s_in); while (1) { n = read(s_in, buf, sz); @@ -1297,19 +1795,19 @@ static void ssl_xfer_debug(int csock, int s_in, int s_out) { break; } else if (n > 0) { m = write(csock, buf, n); +if (db > 1) write(2, buf, n); if (m != n) { - if (db) fprintf(stderr, "ssl_xfer bad write: %d <- %d | %d/%d\n", csock, s_in, m, n); + if (db) fprintf(stderr, "raw_xfer bad write: %d <- %d | %d/%d\n", csock, s_in, m, n); break; } } } - if (db) fprintf(stderr, "ssl_xfer done: %d <- %d\n", csock, s_in); + if (db) fprintf(stderr, "raw_xfer done: %d <- %d\n", csock, s_in); } close(csock); close(s_in); close(s_out); - exit(0); } static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { @@ -1321,16 +1819,18 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { int ssock; if (dbxfer) { - ssl_xfer_debug(csock, s_in, s_out); + raw_xfer(csock, s_in, s_out); return; } +if (db) fprintf(stderr, "ssl_xfer begin\n"); + /* * csock: clear text socket with libvncserver. "C" * ssock: ssl data socket with remote vnc viewer. "S" * - * to cover inetd mode, we have s_in and s_out, but in non-ssl mode they - * both ssock. + * to cover inetd mode, we have s_in and s_out, but in non-inetd + * mode they both ssock. * * cbuf[] is data from csock that we have read but not passed on to ssl * sbuf[] is data from ssl that we have read but not passed on to csock @@ -1428,9 +1928,9 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { } if (is_https) { - tv.tv_sec = 45; + tv.tv_sec = 50; } else { - tv.tv_sec = 20; + tv.tv_sec = 35; } tv.tv_usec = 0; diff --git a/x11vnc/sslhelper.h b/x11vnc/sslhelper.h index f8561ad..7aa7db0 100644 --- a/x11vnc/sslhelper.h +++ b/x11vnc/sslhelper.h @@ -8,6 +8,8 @@ #define OPENSSL_VNC 2 #define OPENSSL_HTTPS 3 +#define DO_DH 0 + extern int openssl_sock; extern int openssl_port_num; extern int https_sock; @@ -21,6 +23,8 @@ extern void check_openssl(void); extern void check_https(void); extern void ssl_helper_pid(pid_t pid, int sock); extern void accept_openssl(int mode); +extern char *find_openssl_bin(void); +extern char *get_saved_pem(char *string, int create); #endif /* _X11VNC_SSLHELPER_H */ diff --git a/x11vnc/ssltools.h b/x11vnc/ssltools.h new file mode 100644 index 0000000..42f68eb --- /dev/null +++ b/x11vnc/ssltools.h @@ -0,0 +1,674 @@ +#ifndef _SSLTOOLS_H +#define _SSLTOOLS_H + +/* quoted scripts, edit source not this file. */ + + +char genCA[] = +"#!/bin/sh\n" +"\n" +"DIR=$BASE_DIR\n" +"if [ \"x$DIR\" = \"x\" ]; then\n" +" DIR=\"$HOME/dotkjr_vnc/certs\"\n" +" rm -rf \"$DIR\"\n" +"fi\n" +"if echo \"$DIR\" | grep '^/' > /dev/null; then\n" +" :\n" +"else\n" +" DIR=\"`pwd`/$DIR\"\n" +"fi\n" +"\n" +"PATH=/usr/bin:/bin:/usr/sbin:$PATH; export PATH\n" +"if [ \"x$OPENSSL\" = \"x\" ]; then\n" +" OPENSSL=\"openssl\"\n" +"fi\n" +"\n" +"type \"$OPENSSL\" > /dev/null || exit 1\n" +"\n" +"if [ -f \"$DIR/CA/cacert.pem\" ]; then\n" +" echo \"Files will be overwritten in $DIR/CA\"\n" +" printf \"Continue? [y]/n \"\n" +" read x\n" +" if [ \"x$x\" = \"xn\" ]; then\n" +" exit 1;\n" +" fi\n" +"fi\n" +"\n" +"#mkdir -p \"$DIR/HASH\" || exit 1\n" +"mkdir -p \"$DIR/clients\" || exit 1\n" +"#mkdir -p \"$DIR/clients/HASH\" || exit 1\n" +"mkdir -p \"$DIR/CA/certs\" || exit 1\n" +"mkdir -p \"$DIR/CA/crl\" || exit 1\n" +"mkdir -p \"$DIR/CA/newcerts\" || exit 1\n" +"mkdir -p \"$DIR/CA/private\" || exit 1\n" +"chmod go-rwx \"$DIR/CA/private\" || exit 1\n" +"mkdir -p \"$DIR/tmp\" || exit 1\n" +"chmod go-rwx \"$DIR/tmp\" || exit 1\n" +"touch \"$DIR/CA/index.txt\" || exit 1\n" +"if [ ! -f \"$DIR/CA/serial\" ]; then\n" +" echo \"01\" > \"$DIR/CA/serial\" || exit 1\n" +"fi\n" +"\n" +"cnf='\n" +"HOME = .\n" +"RANDFILE = $ENV::HOME/.rnd\n" +"\n" +"####################################################################\n" +"[ ca ]\n" +"default_ca = CA_default # The default ca section\n" +"\n" +"####################################################################\n" +"[ CA_default ]\n" +"\n" +"dir = ./CA # Where everything is kept\n" +"certs = $dir/certs # Where the issued certs are kept\n" +"crl_dir = $dir/crl # Where the issued crl are kept\n" +"database = $dir/index.txt # database index file.\n" +"new_certs_dir = $dir/newcerts # default place for new certs.\n" +"certificate = $dir/cacert.pem # The CA certificate\n" +"serial = $dir/serial # The current serial number\n" +"crl = $dir/crl.pem # The current CRL\n" +"private_key = $dir/private/cakey.pem # The private key\n" +"RANDFILE = $dir/private/.rand # private random number file\n" +"\n" +"x509_extensions = usr_cert # The extentions to add to the cert\n" +"\n" +"name_opt = ca_default # Subject Name options\n" +"cert_opt = ca_default # Certificate field options\n" +"\n" +"default_days = 365 # how long to certify for\n" +"default_crl_days= 30 # how long before next CRL\n" +"default_md = md5 # which md to use.\n" +"preserve = no # keep passed DN ordering\n" +"\n" +"policy = policy_match\n" +"\n" +"# For the CA policy\n" +"[ policy_match ]\n" +"countryName = match\n" +"stateOrProvinceName = match\n" +"organizationName = match\n" +"organizationalUnitName = optional\n" +"commonName = supplied\n" +"emailAddress = optional\n" +"\n" +"[ policy_anything ]\n" +"countryName = optional\n" +"stateOrProvinceName = optional\n" +"localityName = optional\n" +"organizationName = optional\n" +"organizationalUnitName = optional\n" +"commonName = supplied\n" +"emailAddress = optional\n" +"\n" +"####################################################################\n" +"[ req ]\n" +"default_bits = 2048\n" +"default_keyfile = privkey.pem\n" +"distinguished_name = req_distinguished_name\n" +"attributes = req_attributes\n" +"x509_extensions = v3_ca # The extentions to add to the self signed cert\n" +"\n" +"string_mask = nombstr\n" +"\n" +"# req_extensions = v3_req # The extensions to add to a certificate request\n" +"\n" +"[ req_distinguished_name ]\n" +"countryName = Country Name (2 letter code)\n" +"countryName_default = AU\n" +"countryName_min = 2\n" +"countryName_max = 2\n" +"\n" +"stateOrProvinceName = State or Province Name (full name)\n" +"stateOrProvinceName_default = mystate\n" +"\n" +"localityName = Locality Name (eg, city)\n" +"\n" +"0.organizationName = Organization Name (eg, company)\n" +"0.organizationName_default = x11vnc server CA\n" +"\n" +"organizationalUnitName = Organizational Unit Name (eg, section)\n" +"\n" +"commonName = Common Name (eg, YOUR name)\n" +"commonName_default = %USER x11vnc server CA\n" +"commonName_max = 64\n" +"\n" +"emailAddress = Email Address\n" +"emailAddress_default = x11vnc@CA.nowhere\n" +"emailAddress_max = 64\n" +"\n" +"[ req_attributes ]\n" +"challengePassword = A challenge password\n" +"challengePassword_min = 4\n" +"challengePassword_max = 20\n" +"\n" +"unstructuredName = An optional company name\n" +"\n" +"[ usr_cert ]\n" +"\n" +"basicConstraints=CA:FALSE\n" +"\n" +"nsComment = \"OpenSSL Generated Certificate\"\n" +"\n" +"subjectKeyIdentifier=hash\n" +"authorityKeyIdentifier=keyid,issuer:always\n" +"\n" +"[ v3_req ]\n" +"\n" +"basicConstraints = CA:FALSE\n" +"keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n" +"\n" +"[ v3_ca ]\n" +"\n" +"subjectKeyIdentifier=hash\n" +"\n" +"authorityKeyIdentifier=keyid:always,issuer:always\n" +"\n" +"basicConstraints = CA:true\n" +"\n" +"[ crl_ext ]\n" +"\n" +"authorityKeyIdentifier=keyid:always,issuer:always\n" +"\n" +"'\n" +"selfcnf='\n" +"####################################################################\n" +"[ req ]\n" +"default_bits = 2048\n" +"encrypt_key = yes\n" +"distinguished_name = req_distinguished_name\n" +"x509_extensions = cert_type\n" +"\n" +"[ req_distinguished_name ]\n" +"countryName = Country Name (2 letter code)\n" +"countryName_default = AU\n" +"countryName_min = 2\n" +"countryName_max = 2\n" +"\n" +"stateOrProvinceName = State or Province Name (full name)\n" +"stateOrProvinceName_default = mystate\n" +"\n" +"localityName = Locality Name (eg, city)\n" +"\n" +"0.organizationName = Organization Name (eg, company)\n" +"0.organizationName_default = x11vnc server self-signed\n" +"\n" +"organizationalUnitName = Organizational Unit Name (eg, section)\n" +"\n" +"commonName = Common Name (eg, YOUR name)\n" +"commonName_default = x11vnc server self-signed %NAME\n" +"commonName_max = 64\n" +"\n" +"emailAddress = Email Address\n" +"emailAddress_default = x11vnc@self-signed.nowhere\n" +"emailAddress_max = 64\n" +"\n" +"[ cert_type ]\n" +"nsCertType = server\n" +"\n" +"'\n" +"echo \"$cnf\" | sed -e \"s/%USER/$USER/\" \\\n" +" > \"$DIR/CA/ssl.cnf\" || exit 1\n" +"echo \"$cnf\" | sed -e \"s/%USER *//\" -e 's/server CA/server %NAME/g' -e 's/@CA/@server/' \\\n" +" > \"$DIR/CA/ssl.cnf.server\" || exit 1\n" +"echo \"$cnf\" | sed -e \"s/%USER *//\" -e 's/server CA/client %NAME/g' -e 's/@CA/@client/' \\\n" +" > \"$DIR/CA/ssl.cnf.client\" || exit 1\n" +"\n" +"echo \"$selfcnf\" > \"$DIR/CA/self.cnf.server\" || exit 1\n" +"echo \"$selfcnf\" | sed -e 's/ server/ client/g' \\\n" +" > \"$DIR/CA/self.cnf.client\" || exit 1\n" +"\n" +"cd \"$DIR\" || exit 1\n" +"\n" +"echo \"\"\n" +"echo \"----------------------------------------------------------------------\"\n" +"echo \"Generating your x11vnc CA (certificate authority) key and certificate:\"\n" +"echo \"\"\n" +"echo \"Please supply a passphrase and any other information you care to.\"\n" +"echo \"----------------------------------------------------------------------\"\n" +"echo \"\"\n" +"\n" +"\"$OPENSSL\" req -config \"$DIR/CA/ssl.cnf\" -new -x509 \\\n" +" -keyout \"$DIR/CA/private/cakey.pem\" \\\n" +" -out \"$DIR/CA/cacert.pem\"\n" +"\n" +"chmod go-rwx \"$DIR/CA/private/cakey.pem\"\n" +"\n" +"if [ $? != 0 ]; then\n" +" echo \"openssl failed.\"\n" +" exit 1\n" +"fi\n" +"\n" +"echo \"\"\n" +"echo \"----------------------------------------------------------------------\"\n" +"echo \"Your public x11vnc CA cert is:\"\n" +"echo \"\"\n" +"echo \" $DIR/CA/cacert.pem\"\n" +"echo \"\"\n" +"echo \" It may be copied to other applications, e.g. Web browser, Java\"\n" +"echo \" Applet keystore, or stunnel cfg, to use to verify signed server\"\n" +"echo \" or client certs, etc.\"\n" +"echo \"\"\n" +"echo \"Your private x11vnc CA key is:\"\n" +"echo \"\"\n" +"echo \" $DIR/CA/private/cakey.pem\"\n" +"echo \"\"\n" +"echo \" It will be used to sign server or client certs, keep it secret.\"\n" +"echo \"----------------------------------------------------------------------\"\n" +"echo \"\"\n" +"printf \"Press Enter to print the cacert.pem certificate to the screen: \"\n" +"read x\n" +"echo \"\"\n" +"cat \"$DIR/CA/cacert.pem\"\n" +; + +char genCert[] = +"#!/bin/sh\n" +"\n" +"direrror() {\n" +" echo \"\"\n" +" if echo \"$DIR\" | grep '/\\.vnc/certs' > /dev/null; then\n" +" echo \"You need first to run: x11vnc -sslGenCA\"\n" +" else\n" +" echo \"You need first to run: x11vnc -sslGenCA $DIR\"\n" +" fi\n" +" echo \"to create the CA cert file and other needed config files and directories.\"\n" +" echo \"\"\n" +" if [ \"X$1\" != \"X\" ]; then\n" +" echo \"(missing: $1)\"\n" +" echo \"\"\n" +" fi\n" +" exit 1\n" +"}\n" +"\n" +"make_HASH() {\n" +" crt=\"$1\"\n" +" remove=\"$2\"\n" +" if [ ! -f \"$crt\" ]; then\n" +" return\n" +" fi\n" +" dirhash=`dirname \"$crt\"`/HASH\n" +" bashash=`basename \"$crt\"`\n" +" if [ ! -d \"$dirhash\" ]; then\n" +" return\n" +" fi\n" +" hash=`\"$OPENSSL\" x509 -hash -noout -in \"$crt\" 2>/dev/null | head -1`\n" +" if [ \"X$hash\" != \"X\" ]; then\n" +" for i in 0 1 2 3 4 5 6 7 8 9\n" +" do\n" +" lnk=\"$dirhash/$hash.$i\"\n" +" if [ \"X$remove\" = \"X1\" ]; then\n" +" if [ -h \"$lnk\" ]; then\n" +" if cmp \"$lnk\" \"$crt\" > /dev/null 2>&1; then\n" +" ls -l \"$lnk\"\n" +" rm -i \"$lnk\"\n" +" fi\n" +" fi\n" +" else\n" +" if [ -h \"$lnk\" ]; then\n" +" if [ ! -f \"$lnk\" ]; then\n" +" rm -f \"$lnk\" 1>/dev/null 2>&1\n" +" else\n" +" continue\n" +" fi\n" +" fi\n" +" if [ \"x$HASH_verbose\" = \"x1\" ]; then\n" +" echo \"creating: $lnk -> ../$bashash\"\n" +" fi\n" +" ln -s \"../$bashash\" \"$lnk\"\n" +" break\n" +" fi\n" +" done\n" +" fi\n" +"}\n" +"\n" +"create_key() {\n" +" \n" +" echo \"----------------------------------------------------------------------\"\n" +" echo \"Creating new x11vnc certificate and key for name: $type $name0\"\n" +" echo \"\"\n" +"\n" +" cnf=\"$DIR/tmp/cnf.$$\"\n" +" trap \"rm -f \\\"$cnf\\\"\" 0 1 2 15\n" +"\n" +" rm -f \"$DIR/$dest.key\" \"$DIR/$dest.crt\" \"$DIR/$dest.req\"\n" +"\n" +" if [ \"x$self\" = \"x1\" ]; then\n" +" if [ ! -f \"$DIR/CA/self.cnf.$type\" ]; then\n" +" direrror \"$DIR/CA/self.cnf.$type\"\n" +" fi\n" +" cat \"$DIR/CA/self.cnf.$type\" | sed -e \"s/%NAME/$name0/\" > \"$cnf\" || exit 1\n" +" \"$OPENSSL\" req -config \"$cnf\" -nodes -new -newkey rsa:2048 -x509 \\\n" +" -keyout \"$DIR/$dest.key\" \\\n" +" -out \"$DIR/$dest.crt\"\n" +" else\n" +" if [ ! -f \"$DIR/CA/ssl.cnf.$type\" ]; then\n" +" direrror \"$DIR/CA/ssl.cnf.$type\"\n" +" fi\n" +" cat \"$DIR/CA/ssl.cnf.$type\" | sed -e \"s/%NAME/$name0/\" > \"$cnf\" || exit 1\n" +" \"$OPENSSL\" req -config \"$cnf\" -nodes -new -newkey rsa:2048 \\\n" +" -keyout \"$DIR/$dest.key\" \\\n" +" -out \"$DIR/$dest.req\"\n" +" fi\n" +" rc=$?\n" +" if [ -f \"$DIR/$dest.key\" ]; then\n" +" chmod go-rwx \"$DIR/$dest.key\"\n" +" fi\n" +"\n" +"\n" +"\n" +" if [ $rc != 0 ]; then\n" +" echo \"openssl 'req' command failed\"\n" +" rm -f \"$DIR/$dest.key\" \"$DIR/$dest.crt\" \"$DIR/$dest.req\"\n" +" exit 1\n" +" fi\n" +"}\n" +"\n" +"enc_key() {\n" +" \n" +" echo \"\"\n" +" echo \"----------------------------------------------------------------------\"\n" +" echo \"Do you want to protect the generated private key with a passphrase?\"\n" +" echo \"Doing so will significantly decrease the chances someone could steal\"\n" +" if [ \"x$type\" = \"xserver\" ]; then\n" +" echo \"the key and pretend to be your x11vnc server. The downside is it is\"\n" +" else\n" +" echo \"the key and pretend to be your VNC client. The downside is it is\"\n" +" fi\n" +" echo \"inconvenient because you will have to supply the passphrase every\"\n" +" if [ \"x$type\" = \"xserver\" ]; then\n" +" echo \"time you start x11vnc using this key.\"\n" +" else\n" +" echo \"time you start the VNC viewer SSL tunnel using this key.\"\n" +" fi\n" +" echo \"\"\n" +" printf \"Protect key with a passphrase? [y]/n \"\n" +" read x\n" +" estr=\" *unencrypted*\"\n" +" if [ \"x$ENCRYPT_ONLY\" != \"x\" ]; then\n" +" target=\"$ENCRYPT_ONLY\"\n" +" else\n" +" target=\"$DIR/$dest.key\"\n" +" bdir=`dirname \"$DIR/$dest.key\"`\n" +" if [ ! -d \"$bdir\" ]; then\n" +" direrror \"$bdir\"\n" +" fi\n" +" fi\n" +" if [ \"x$x\" != \"xn\" ]; then\n" +" \"$OPENSSL\" rsa -in \"$target\" -des3 -out \"$target\"\n" +" if [ $? != 0 ]; then\n" +" echo \"openssl 'rsa' command failed\"\n" +" rm -f \"$DIR/$dest.key\" \"$DIR/$dest.crt\" \"$DIR/$dest.req\"\n" +" exit 1\n" +" fi\n" +" estr=\" encrypted\"\n" +" fi\n" +" echo \"\"\n" +"}\n" +"\n" +"sign_key() {\n" +" cd \"$DIR\" || exit 1\n" +"\n" +" if [ \"x$self\" = \"x1\" ]; then\n" +" :\n" +" else\n" +" if echo \"$name0\" | grep '^req:' > /dev/null; then\n" +" echo \"\"\n" +" echo \"----------------------------------------------------------------------\"\n" +" echo \"Your x11vnc $type certificate request is:\"\n" +" echo \"\"\n" +" echo \" $DIR/$dest.req\"\n" +" echo \"\"\n" +" echo \" It may be sent to an external CA for signing, afterward you can\"\n" +" echo \" save the cert they send you in:\"\n" +" echo \"\"\n" +" echo \" $DIR/$dest.crt\"\n" +" echo \"\"\n" +" echo \"Your$estr private x11vnc $type key is:\"\n" +" echo \"\"\n" +" echo \" $DIR/$dest.key\"\n" +" echo \"\"\n" +" echo \" You should combine it and the received cert in the file:\"\n" +" echo \"\"\n" +" echo \" $DIR/$dest.pem\"\n" +" echo \"\"\n" +" echo \" It will be needed by applications to identify themselves.\"\n" +" echo \" This file should be kept secret.\"\n" +" echo \"----------------------------------------------------------------------\"\n" +" echo \"\"\n" +" printf \"Press Enter to print the $dest.req cert request to the screen: \"\n" +" read x\n" +" echo \"\"\n" +" cat \"$DIR/$dest.req\"\n" +" exit 0\n" +" fi\n" +" echo \"\"\n" +" echo \"\"\n" +" echo \"----------------------------------------------------------------------\"\n" +" echo \"Now signing the new key with CA private key. You will need to supply\"\n" +" echo \"the CA key passphrase and reply \\\"y\\\" to sign and commit the key.\"\n" +" echo \"\"\n" +" \"$OPENSSL\" ca -config \"$cnf\" -policy policy_anything -notext \\\n" +" -in \"$DIR/$dest.req\" \\\n" +" -out \"$DIR/$dest.crt\"\n" +" if [ $? != 0 ]; then\n" +" echo \"\"\n" +" echo \"openssl 'ca' command failed\"\n" +" echo \"\"\n" +" echo \" You may have a duplicate DN entry for this name in:\"\n" +" echo \"\"\n" +" echo \" $DIR/CA/index.txt\"\n" +" echo \"\"\n" +" echo \" remove the duplicate in that file and try again.\"\n" +" echo \"\"\n" +" rm -f \"$DIR/$dest.key\" \"$DIR/$dest.crt\" \"$DIR/$dest.req\"\n" +" exit 1\n" +" fi\n" +" fi\n" +"\n" +" cat \"$DIR/$dest.key\" \"$DIR/$dest.crt\" \\\n" +" > \"$DIR/$dest.pem\" || exit 1 \n" +"\n" +" make_HASH \"$DIR/$dest.crt\" 0\n" +"\n" +" rm -f \"$DIR/$dest.key\" \"$DIR/$dest.req\" || exit 1\n" +" chmod go-rwx \"$DIR/$dest.pem\" || exit 1\n" +"\n" +" if [ \"x$type\" = \"xserver\" -o \"x$type\" = \"xclient\" ]; then\n" +" echo \"\"\n" +" echo \"----------------------------------------------------------------------\"\n" +" echo \"Your public x11vnc $type cert is:\"\n" +" echo \"\"\n" +" echo \" $DIR/$dest.crt\"\n" +" echo \"\"\n" +" echo \" It may be copied to other machines / applications to be used for\"\n" +" echo \" authentication. However, since it is signed with the x11vnc CA\"\n" +" echo \" key, all the applications need is the x11vnc CA certificate.\"\n" +" echo \"\"\n" +" echo \"Your$estr private x11vnc $type key is:\"\n" +" echo \"\"\n" +" echo \" $DIR/$dest.pem\"\n" +" echo \"\"\n" +" echo \" It will be needed by applications to identify themselves.\"\n" +" echo \" This file should be kept secret.\"\n" +" echo \"----------------------------------------------------------------------\"\n" +" echo \"\"\n" +" fi\n" +"\n" +" printf \"Press Enter to print the $dest.crt certificate to the screen: \"\n" +" read x\n" +" echo \"\"\n" +" cat \"$DIR/$dest.crt\"\n" +"}\n" +"\n" +"DIR=$BASE_DIR\n" +"if [ \"x$DIR\" = \"x\" ]; then\n" +" DIR=\"$HOME/dotkjr_vnc/certs\"\n" +"fi\n" +"if echo \"$DIR\" | grep '^/' > /dev/null; then\n" +" :\n" +"else\n" +" DIR=\"`pwd`/$DIR\"\n" +"fi\n" +"\n" +"if [ \"x$HASHON\" != \"x\" ]; then\n" +" for dir in \"$DIR/HASH\" \"$DIR/clients/HASH\"\n" +" do\n" +" if [ -d \"$dir\" ]; then\n" +" rm -rf \"$dir\"\n" +" fi\n" +" done\n" +" dir=\"$DIR/HASH\"\n" +" mkdir -p \"$dir\" || exit 1\n" +" dir=\"$DIR/clients/HASH\"\n" +" mkdir -p \"$dir\" || exit 1\n" +" HASH_verbose=1\n" +" for f in \"$DIR\"/*.crt \"$DIR\"/clients/*.crt\n" +" do\n" +" if [ -f \"$f\" ]; then\n" +" make_HASH \"$f\" 0\n" +" fi\n" +" done\n" +" exit\n" +"fi\n" +"if [ \"x$HASHOFF\" != \"x\" ]; then\n" +" dir=\"$DIR/HASH\"\n" +" for dir in \"$DIR/HASH\" \"$DIR/clients/HASH\"\n" +" do\n" +" if [ -d \"$dir\" ]; then\n" +" for f in \"$dir\"/*\n" +" do\n" +" if [ -f \"$f\" ]; then\n" +" echo \"deleting: $f\"\n" +" rm -f \"$f\"\n" +" fi\n" +" done\n" +" rm -rf \"$dir\"\n" +" fi\n" +" done\n" +" exit\n" +"fi\n" +"\n" +"PATH=/usr/bin:/bin:/usr/sbin:$PATH; export PATH\n" +"if [ \"x$OPENSSL\" = \"x\" ]; then\n" +" OPENSSL=\"openssl\"\n" +"fi\n" +"\n" +"type \"$OPENSSL\" > /dev/null || exit 1\n" +"\n" +"self=\"\"\n" +"if [ \"x$SELF\" != \"x\" ]; then\n" +" self=1\n" +"elif [ \"x$1\" = \"x-self\" ]; then\n" +" shift\n" +" self=1\n" +"fi\n" +"\n" +"if [ \"x$TYPE\" != \"x\" ]; then\n" +" type=\"$TYPE\"\n" +"else\n" +" if [ \"X$1\" != \"X\" ]; then\n" +" type=\"$1\"\n" +" shift\n" +" fi\n" +"fi\n" +"if [ \"x$NAME\" != \"x\" ]; then\n" +" name=\"$NAME\"\n" +"else\n" +" if [ \"X$1\" != \"X\" ]; then\n" +" name=\"$1\"\n" +" shift\n" +" fi\n" +"fi\n" +"\n" +"if echo \"$name\" | grep '^self:' > /dev/null; then\n" +" self=1\n" +"fi\n" +"\n" +"if [ \"x$type\" = \"xserver\" ]; then\n" +" name0=\"$name\"\n" +" if echo \"$name\" | grep '^-' > /dev/null; then\n" +" :\n" +" elif [ \"x$name\" != \"x\" ]; then\n" +" name=\"-$name\";\n" +" fi\n" +" dest=\"server$name\"\n" +"elif [ \"x$type\" = \"xclient\" ]; then\n" +" if [ \"x$name\" = \"x\" ]; then\n" +" name=\"nobody\"\n" +" fi\n" +" name0=\"$name\"\n" +" dest=\"clients/$name\"\n" +"else\n" +" exit 1\n" +"fi\n" +"\n" +"#set -xv\n" +"\n" +"if [ \"x$INFO_ONLY\" != \"x\" ]; then\n" +" echo \"\"\n" +" echo \"VNC Certificate file:\"\n" +" echo \" $INFO_ONLY\"\n" +" echo \"\"\n" +" \"$OPENSSL\" x509 -text -in \"$INFO_ONLY\"\n" +" exit \n" +"elif [ \"x$DELETE_ONLY\" != \"x\" ]; then\n" +" echo \"\"\n" +" echo \"VNC Certificate file:\"\n" +" echo \" $DELETE_ONLY\"\n" +" echo \"\"\n" +" \n" +" base=`echo \"$DELETE_ONLY\" | sed -e 's/\\....$//'`\n" +" for suff in crt pem key req\n" +" do\n" +" try=\"$base.$suff\"\n" +" if [ -f \"$try\" ]; then\n" +" make_HASH \"$try\" 1\n" +" rm -i \"$try\"\n" +" fi\n" +" done\n" +" if echo \"$base\" | grep 'CA/cacert$' > /dev/null; then\n" +" base2=`echo \"$base\" | sed -e 's,cacert$,private/cakey,'`\n" +" else\n" +" echo \"\"\n" +" exit\n" +" fi\n" +" echo \"\"\n" +" for suff in crt pem key req\n" +" do\n" +" try=\"$base2.$suff\"\n" +" if [ -f \"$try\" ]; then\n" +" make_HASH \"$try\" 1\n" +" rm -i \"$try\"\n" +" fi\n" +" done\n" +" echo \"\"\n" +" exit \n" +"elif [ \"x$ENCRYPT_ONLY\" != \"x\" ]; then\n" +" if [ \"x$type\" = \"x\" ]; then\n" +" type=\"server\"\n" +" fi\n" +" echo \"\"\n" +" echo \"Key PEM file:\"\n" +" echo \" $ENCRYPT_ONLY\"\n" +" enc_key\n" +" exit\n" +"fi\n" +"\n" +"if [ ! -d \"$DIR/tmp\" ]; then\n" +" direrror \"$DIR/tmp\"\n" +"fi\n" +"bdir=`dirname \"$DIR/$dest.key\"`\n" +"if [ ! -d \"$bdir\" ]; then\n" +" direrror \"$bdir\"\n" +"fi\n" +"if [ ! -f \"$DIR/CA/cacert.pem\" ]; then\n" +" direrror \"$DIR/CA/cacert.pem\"\n" +"fi\n" +"\n" +"create_key\n" +"enc_key\n" +"sign_key\n" +; + +#endif /* _SSLTOOLS_H */ diff --git a/x11vnc/tkx11vnc b/x11vnc/tkx11vnc index 0073910..8e178ee 100755 --- a/x11vnc/tkx11vnc +++ b/x11vnc/tkx11vnc @@ -294,6 +294,7 @@ Permissions =F ssl_pem: stunnel =F stunnel_pem: + =F ssldir: =F sslverify: https: =GAL LOFF @@ -358,6 +359,7 @@ Tuning threads wmdt: rfbwait: + nofbpm =GAL LOFF " } diff --git a/x11vnc/tkx11vnc.h b/x11vnc/tkx11vnc.h index 82a6a81..8bbffc9 100644 --- a/x11vnc/tkx11vnc.h +++ b/x11vnc/tkx11vnc.h @@ -305,6 +305,7 @@ char gui_code[] = ""; " =F ssl_pem:\n" " stunnel\n" " =F stunnel_pem:\n" +" =F ssldir:\n" " =F sslverify:\n" " https:\n" " =GAL LOFF\n" @@ -369,6 +370,7 @@ char gui_code[] = ""; " threads\n" " wmdt:\n" " rfbwait:\n" +" nofbpm\n" " =GAL LOFF\n" "\"\n" "}\n" diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index a2db39e..fcf2d6b 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -1,8 +1,8 @@ .\" This file was automatically generated from x11vnc -help output. -.TH X11VNC "1" "March 2006" "x11vnc " "User Commands" +.TH X11VNC "1" "April 2006" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.8.1, lastmod: 2006-03-27 + version: 0.8.1, lastmod: 2006-04-05 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -638,7 +638,7 @@ use the traditional .IR crypt (3) method to verify passwords instead. This requires that the -encrpyted passwords be readable. Passwords stored +encrypted passwords be readable. Passwords stored in /etc/shadow will be inaccessible unless x11vnc is run as root. .IP @@ -647,7 +647,7 @@ NIS setups the user encrypted passwords are accessible (e.g. "ypcat passwd"). NIS is not required for this mode to work (only that .IR getpwnam (3) -return the encrpyted +return the encrypted password is required), but it is unlikely it will work for any other modern environment. All of the \fB-unixpw\fR options and contraints apply. @@ -665,17 +665,19 @@ is prescribed. to specify a PEM certificate file to use to identify and provide a key for this server. See .IR openssl (1) -for what a PEM can be. +for +more info about PEMs and the \fB-sslGenCert\fR option below. .IP -Connecting VNC viewer SSL tunnels can optionally +The connecting VNC viewer SSL tunnel can optionally authenticate this server if they have the public key part of the certificate (or a common certificate authority, CA, is a more sophisicated way to verify -this server's cert). This is used to prevent -man-in-the-middle attacks. Otherwise, if the VNC -viewer accepts this server's key without verification, -at least the traffic is protected from passive sniffing -on the network (but NOT from man-in-the-middle attacks). +this server's cert, see \fB-sslGenCA\fR below). This is +used to prevent man-in-the-middle attacks. Otherwise, +if the VNC viewer accepts this server's key without +verification, at least the traffic is protected +from passive sniffing on the network (but NOT from +man-in-the-middle attacks). .IP If [pem] is not supplied and the .IR openssl (1) @@ -693,15 +695,34 @@ to generate a temporary certificate, the public part of it will be displayed to stderr (e.g. one could copy it to the client-side to provide authentication of the server to -VNC viewers.) +VNC viewers.) See following paragraphs for how to save +keys to reuse when x11vnc is restarted. .IP Set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc print out the entire certificate, including the PRIVATE KEY part, to stderr. One could reuse this cert if saved in a [pem] file. Similarly, set X11VNC_KEEP_TMP_PEM=1 to not delete the temporary PEM file: the file name -will be printed to stderr (so one could move it to a -safe place for reuse). +will be printed to stderr (so one could move it to +a safe place for reuse). You will be prompted for a +passphrase for the private key. +.IP +If [pem] is "SAVE" then the certificate will be saved +to the file ~/.vnc/certs/server.pem, or if that file +exists it will be used directly. Similarly, if [pem] +is "SAVE_PROMPT" the server.pem certificate will be +made based on your answers to its prompts for info such +as OrganizationalName, CommonName, etc. +.IP +Use "SAVE-<string>" and "SAVE_PROMPT-<string>" +to refer to the file ~/.vnc/certs/server-<string>.pem +instead. E.g. "SAVE-charlie" will store to the file +~/.vnc/certs/server-charlie.pem +.IP +See \fB-ssldir\fR below to use a directory besides the +default ~/.vnc/certs +.IP +Example: x11vnc \fB-ssl\fR SAVE \fB-display\fR :0 ... .IP Reverse connections are disabled in \fB-ssl\fR mode because there is no way to ensure that data channel will @@ -709,43 +730,392 @@ be encrypted. Set X11VNC_SSL_ALLOW_REVERSE=1 to override this. .IP Your VNC viewer will also need to be able to connect -via SSL. See the discussion below under \fB-stunnel\fR -and the FAQ for how this might be achieved. E.g. on -Unix it is easy to write a shell script that starts up -stunnel and then vncviewer. Also in the x11vnc source -a SSL enabled Java VNC Viewer applet is provided in -the classes/ssl directory. +via SSL. See the discussion below under \fB-stunnel\fR and +the FAQ (ssl_vncviewer script) for how this might be +achieved. E.g. on Unix it is easy to write a shell +script that starts up stunnel and then vncviewer. +Also in the x11vnc source a SSL enabled Java VNC Viewer +applet is provided in the classes/ssl directory. +.PP +\fB-ssldir\fR \fI[dir]\fR +.IP +Use [dir] as an alternate ssl certificate and key +management toplevel directory. The default is +~/.vnc/certs +.IP +This directory is used to store server and other +certificates and keys and also other materials. E.g. in +the simplest case, "\fB-ssl\fR \fISAVE\fR" will store the x11vnc +server cert in [dir]/server.pem +.IP +Use of alternate directories via \fB-ssldir\fR allows you to +manage multiple VNC Certificate Authority (CA) keys. +Another use is if ~/.vnc/cert is on an NFS share you +might want your certificates and keys to be on a local +filesystem to prevent network snooping (for example +\fB-ssldir\fR /var/lib/x11vnc-certs). +.IP +\fB-ssldir\fR effects the other \fB-ssl*\fR options. In the case +of maintenance commands where the VNC server is not run +(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 \fB-sslverify\fR \fI[path]\fR .IP For either of the \fB-ssl\fR or \fB-stunnel\fR modes, use [path] to provide certificates to authenticate incoming VNC -client connections. This can be used as a method to -replace standard password authentication of clients. +*Client* connections (normally only the server is +authenticated in SSL.) This can be used as a method +to replace standard password authentication of clients. .IP If [path] is a directory it contains the client (or CA) -certificates in separate files. If [path] is a file, it -contains multiple certificates. These correspond to the -"CApath = dir" and "CAfile = file" stunnel options. -See the +certificates in separate files. If [path] is a file, +it contains multiple certificates. See special tokens +below. These correspond to the "CApath = dir" and +"CAfile = file" stunnel options. See the .IR stunnel (8) manpage for details. .IP -To create certificates for all sorts of authentications -(clients, servers, via CA, etc) see the +Examples: +x11vnc \fB-ssl\fR \fB-sslverify\fR ~/my.pem +x11vnc \fB-ssl\fR \fB-sslverify\fR ~/my_pem_dir/ +.IP +Note that if [path] is a directory, it must contain +the certs in separate files named like <HASH>.0, where +the value of <HASH> is found by running the command +"openssl x509 \fB-hash\fR \fB-noout\fR \fB-in\fR file.crt". Evidently +one uses <HASH>.1 if there is a collision... +.IP +The the key-management utility "\fB-sslCertInfo\fR \fIHASHON\fR" +and "\fB-sslCertInfo\fR \fIHASHOFF\fR" will create/delete these +hashes for you automatically (via symlink) in the HASH +subdirs it manages. Then you can point \fB-sslverify\fR to +the HASH subdir. +.IP +Special tokens: in \fB-ssl\fR mode, if [path] is not a file or +a directory, it is taken as a comma separated list of +tokens that are interpreted as follows: +.IP +If a token is "CA" that means load the CA/cacert.pem +file from the ssl directory. If a token is "clients" +then all the files clients/*.crt in the ssl directory +are loaded. Otherwise the file clients/token.crt +is attempted to be loaded. As a kludge, use a token +like ../server-foo to load a server cert if you find +that necessary. +.IP +Use \fB-ssldir\fR to use a directory different from the +~/.vnc/certs default. +.IP +Note that if the "CA" cert is loaded you do not need +to load any of the certs that have been signed by it. +You will need to load any additional self-signed certs +however. +.IP +Examples: +x11vnc \fB-ssl\fR \fB-sslverify\fR CA +x11vnc \fB-ssl\fR \fB-sslverify\fR self:fred,self:jim +x11vnc \fB-ssl\fR \fB-sslverify\fR CA,clients +.IP +Usually "\fB-sslverify\fR \fICA\fR" is the most effective. +See the \fB-sslGenCA\fR and \fB-sslGenCert\fR options below for +how to set up and manage the CA framework. +.IP +NOTE: the following utilities, \fB-sslGenCA,\fR \fB-sslGenCert,\fR +\fB-sslEncKey,\fR and \fB-sslCertInfo\fR are provided for +completeness, but for casual usage they are overkill. +.IP +They provide VNC Certificate Authority (CA) key creation +and server / client key generation and signing. So they +provide a basic Public Key management framework for +VNC-ing with x11vnc. (note that they require .IR openssl (1) -command. Of particular usefulness is the "x509" -subcommand of -.IR openssl (1). +be installed on the system) +.IP +However, the simplest usage mode (where x11vnc +automatically generates its own, self-signed, temporary +key and the VNC viewers always accept it, e.g. accepting +via a dialog box) is probably safe enough for most +scenarios. CA management is not needed. +.IP +To protect against Man-In-The-Middle attacks the +simplest mode can be improved by using "\fB-ssl\fR \fISAVE\fR" +to have x11vnc create a longer term self-signed +certificate, and then (safely) copy the corresponding +public key cert to the desired client machines (care +must be taken the private key part is not stolen; +you will be prompted for a passphrase). +.IP +So keep in mind no CA key creation or management +(-sslGenCA and \fB-sslGenCert)\fR is needed for either of +the above two common usage modes. +.IP +One might want to use \fB-sslGenCA\fR and \fB-sslGenCert\fR +if you had a large number of VNC client and server +workstations. That way the administrator could generate +a single CA key with \fB-sslGenCA\fR and distribute its +certificate part to all of the workstations. +.IP +Next, he could create signed VNC server keys +(-sslGenCert server ...) for each workstation or user +that then x11vnc would use to authenticate itself to +any VNC client that has the CA cert. +.IP +Optionally, the admin could also make it so the +VNC clients themselves are authenticated to x11vnc +(-sslGenCert client ...) For this \fB-sslverify\fR would be +pointed to the CA cert (and/or self-signed certs). +.IP +x11vnc will be able to use all of these cert and +key files. On the VNC client side, they will need to +be "imported" somehow. Web browsers have "Manage +Certificates" actions as does the Java applet plugin +Control Panel. stunnel can also use these files (see +the ssl_vncviewer example script in the FAQ.) +.PP +\fB-sslGenCA\fR \fI[dir]\fR +.IP +Generate your own Certificate Authority private key, +certificate, and other files in directory [dir]. +.IP +If [dir] is not supplied, a \fB-ssldir\fR setting is used, +or otherwise ~/.vnc/certs is used. +.IP +This command also creates directories where server and +client certs and keys will be stored. The +.IR openssl (1) +program must be installed on the system and available +in PATH. +.IP +After the CA files and directories are created the +command exits; the VNC server is not run. +.IP +You will be prompted for information to put into the CA +certificate. The info does not have to be accurate just +as long as clients accept the cert for VNC connections. +You will also need to supply a passphrase of at least +4 characters for the CA private key. +.IP +Once you have generated the CA you can distribute +its certificate part, [dir]/CA/cacert.pem, to other +workstations where VNC viewers will be run. One will +need to "import" this certicate in the applications, +e.g. Web browser, Java applet plugin, stunnel, etc. +Next, you can create and sign keys using the CA with +the \fB-sslGenCert\fR option below. +.IP +Examples: +x11vnc \fB-sslGenCA\fR +x11vnc \fB-sslGenCA\fR ~/myCAdir +x11vnc \fB-ssldir\fR ~/myCAdir \fB-sslGenCA\fR +.IP +(the last two lines are equivalent) +.PP +\fB-sslGenCert\fR \fItype\fR \fIname\fR +.IP +Generate a VNC server or client certificate and private +key pair signed by the CA created previously with +\fB-sslGenCA.\fR The +.IR openssl (1) +program must be installed +on the system and available in PATH. +.IP +After the Certificate is generated the command exits; +the VNC server is not run. +.IP +The type of key to be generated is the string \fItype\fR. +It is either "server" (i.e. for use by x11vnc) or +"client" (for a VNC viewer). Note that typically +only "server" is used: the VNC clients authenticate +themselves by a non-public-key method (e.g. VNC or +unix password). \fItype\fR is required. +.IP +An arbitrary default name you want to associate with +the key is supplied by the \fIname\fR string. You can +change it at the various prompts when creating the key. +\fIname\fR is optional. +.IP +If name is left blank for clients keys then "nobody" +is used. If left blank for server keys, then the +primary server key: "server.pem" is created (this +is the saved one referenced by "\fB-ssl\fR \fISAVE\fR" when the +server is started) +.IP +If \fIname\fR begins with the string "self:" then +a self-signed certificate is created instead of one +signed by your CA key. +.IP +If \fIname\fR begins with the string "req:" then only a +key (.key) and a certificate signing *request* (.req) +are generated. You can then send the .req file to +an external CA (even a professional one, e.g. Thawte) +and then combine the .key and the received cert into +the .pem file with the same basename. +.IP +The distinction between "server" and "client" is +simply the choice of output filenames and sub-directory. +This makes it so the \fB-ssl\fR SAVE-name option can easily +pick up the x11vnc PEM file this option generates. +And similarly makes it easy for the \fB-sslverify\fR option +to pick up your client certs. +.IP +There is nothing special about the filename or directory +location of either the "server" and "client" certs. +You can rename the files or move them to wherever +you like. +.IP +Precede this option with \fB-ssldir\fR [dir] to use a +directory other than the default ~/.vnc/certs You will +need to run \fB-sslGenCA\fR on that directory first before +doing any \fB-sslGenCert\fR key creation. +.IP +Note you cannot recreate a cert with exactly the same +distiguished name (DN) as an existing one. To do so, +you will need to edit the [dir]/CA/index.txt file to +delete the line. +.IP +Similar to \fB-sslGenCA,\fR you will be prompted to fill +in some information that will be recorded in the +certificate when it is created. Tip: if you know +the fully-quailified hostname other people will be +connecting to you can use that as the CommonName "CN" +to avoid some applications (e.g. web browsers and java +plugin) complaining it does not match the hostname. +.IP +You will also need to supply the CA private key +passphrase to unlock the private key created from +\fB-sslGenCA.\fR This private key is used to sign the server +or client certicate. +.IP +The "server" certs can be used by x11vnc directly by +pointing to them via the \fB-ssl\fR [pem] option. The default +file will be ~/.vnc/certs/server.pem. This one would +be used by simply typing \fB-ssl\fR SAVE. The pem file +contains both the certificate and the private key. +server.crt file contains the cert only. +.IP +The "client" cert + private key file will need +to be copied and imported into the VNC viewer +side applications (Web browser, Java plugin, +stunnel, etc.) Once that is done you can delete the +"client" private key file on this machine since +it is only needed on the VNC viewer side. The, +e.g. ~/.vnc/certs/clients/<name>.pem contains both +the cert and private key. The <name>.crt contains the +certificate only. +.IP +NOTE: It is very important to know one should always +generate new keys with a passphrase. Otherwise if an +untrusted user steals the key file he could use it to +masquerade as the x11vnc server (or VNC viewer client). +You will be prompted whether to encrypt the key with +a passphrase or not. It is recommended that you do. +One inconvenience to a passphrase is that it must +be suppled every time x11vnc or the client app is +started up. +.IP +Examples: +.IP +x11vnc \fB-sslGenCert\fR server +x11vnc \fB-ssl\fR SAVE \fB-display\fR :0 ... +.IP +and then on viewer using ssl_vncviewer stunnel wrapper +(see the FAQ): +ssl_vncviewer \fB-verify\fR ./cacert.crt hostname:0 +.IP +(this assumes the cacert.crt cert from \fB-sslGenCA\fR +was safely copied to the VNC viewer machine where +ssl_vncviewer is run) +.IP +Example using a name: +.IP +x11vnc \fB-sslGenCert\fR server charlie +x11vnc \fB-ssl\fR SAVE-charlie \fB-display\fR :0 ... +.IP +Example for a client certificate (rarely used): +.IP +x11vnc \fB-sslGenCert\fR client roger +scp ~/.vnc/certs/clients/roger.pem somehost:. +rm ~/.vnc/certs/clients/roger.pem +.IP +x11vnc is then started with the the option \fB-sslverify\fR +~/.vnc/certs/clients/roger.crt (or simply \fB-sslverify\fR +roger), and on the viewer user on somehost could do +for example: +.IP +ssl_vncviewer \fB-mycert\fR ./roger.pem hostname:0 +.PP +\fB-sslEncKey\fR \fI[pem]\fR +.IP +Utility to encrypt an existing PEM file with a +passphrase you supply when prompted. For that key to be +used (e.g. by x11vnc) the passphrase must be supplied +each time. +.IP +The "SAVE" notation described under \fB-ssl\fR applies as +well. (precede this option with \fB-ssldir\fR [dir] to refer +a directory besides the default ~/.vnc/certs) +.IP +The +.IR openssl (1) +program must be installed on the system +and available in PATH. After the Key file is encrypted +the command exits; the VNC server is not run. +.IP +Examples: +x11vnc \fB-sslEncKey\fR /path/to/foo.pem +x11vnc \fB-sslEncKey\fR SAVE +x11vnc \fB-sslEncKey\fR SAVE-charlie +.PP +\fB-sslCertInfo\fR \fI[pem]\fR +.IP +Prints out information about an existing PEM file. +In addition the public certificate is also printed. +The +.IR openssl (1) +program must be in PATH. Basically the +command "openssl x509 \fB-text"\fR is run on the pem. +.IP +The "SAVE" notation described under \fB-ssl\fR applies +as well. +.IP +Using "LIST" will give a list of all certs being +managed (in the ~/.vnc/certs dir, use \fB-ssldir\fR to refer +to another dir). "ALL" will print out the info for +every managed key (this can be very long). Giving a +client or server cert shortname will also try a lookup +(e.g. \fB-sslCertInfo\fR charlie). Use "LISTL" or "LL" +for a long (ls \fB-l\fR style) listing. +.IP +Using "HASHON" will create subdirs [dir]/HASH and +[dir]/HASH with OpenSSL hash filenames (e.g. 0d5fbbf1.0) +symlinks pointing up to the corresponding *.crt file. +([dir] is ~/.vnc/certs or one given by \fB-ssldir.)\fR +This is a useful way for other OpenSSL applications +(e.g. stunnel) to access all of the certs without +having to concatenate them. x11vnc will not use them +unless you specifically reference them. "HASHOFF" +removes these HASH subdirs. +.IP +The LIST, LISTL, LL, ALL, HASHON, HASHOFF words can +also be lowercase, e.g. "list". +.PP +\fB-sslDelCert\fR \fI[pem]\fR +.IP +Prompts you to delete all .crt .pem .key .req files +associated with [pem]. "SAVE" and lookups as in +\fB-sslCertInfo\fR apply as well. .PP \fB-stunnel\fR \fI[pem]\fR .IP Use the .IR stunnel (8) (www.stunnel.org) to provide an -encrypted SSL tunnel between viewers and x11vnc. This -was implemented prior to the integrated \fB-ssl\fR encrpytion. -It works well. This requires stunnel to be installed +encrypted SSL tunnel between viewers and x11vnc. +.IP +This external tunnel method was implemented prior to the +integrated \fB-ssl\fR encryption described above. It still +works well. This requires stunnel to be installed on the system and available via PATH (n.b. stunnel is often installed in sbin directories). Version 4.x of stunnel is assumed (but see \fB-stunnel3\fR below.) @@ -771,14 +1141,13 @@ Your VNC viewer will also need to be able to connect via SSL. Unfortunately not too many do this. UltraVNC has an encryption plugin but it does not seem to be SSL. .IP -In the x11vnc distribution, a patched TightVNC Java -applet is provided in classes/ssl that does SSL +Also, in the x11vnc distribution, a patched TightVNC +Java applet is provided in classes/ssl that does SSL connections (only). .IP It is also not too difficult to set up an stunnel or -other SSL tunnel on the viewer side. -.IP -A simple example on Unix using stunnel 3.x is: +other SSL tunnel on the viewer side. A simple example +on Unix using stunnel 3.x is: .IP % stunnel \fB-c\fR \fB-d\fR localhost:5901 \fB-r\fR remotehost:5900 % vncviewer localhost:1 @@ -842,9 +1211,10 @@ Store password \fIpass\fR as the VNC password in the file \fIfile\fR. Once the password is stored the program exits. Use the password via "\fB-rfbauth\fR \fIfile\fR" .IP -If called with no arguments, i.e., "\fB-storepasswd\fR", +If called with no arguments, "x11vnc \fB-storepasswd",\fR the user is prompted for a password and it is stored -in the file ~/.vnc/passwd +in the file ~/.vnc/passwd. Called with one argument, +that will be the file to store the prompted password in. .PP \fB-nopw\fR .IP @@ -1078,12 +1448,9 @@ each rectangle. If one of the items on the list is the string "noptr" the mouse pointer will not be allowed to go into a blacked out region. .PP -\fB-xinerama\fR +\fB-xinerama,\fR \fB-noxinerama\fR .IP If your screen is composed of multiple monitors -.PP -\fB-noxinerama\fR -.IP glued together via XINERAMA, and that screen is not a rectangle this option will try to guess the areas to black out (if your system has libXinerama). @@ -2086,12 +2453,9 @@ slow links that take a long time to paint the first screen libvncserver may hit the timeout and drop the connection. Default: 20 seconds. .PP -\fB-nap\fR +\fB-nap,\fR \fB-nonap\fR .IP Monitor activity and if it is low take longer naps -.PP -\fB-nonap\fR -.IP between screen polls to really cut down load when idle. Default: take naps .PP @@ -2101,6 +2465,26 @@ Time in seconds after NO activity (e.g. screen blank) to really throttle down the screen polls (i.e. sleep for about 1.5 secs). Use 0 to disable. Default: 60 .PP +\fB-nofbpm,\fR \fB-fbpm\fR +.IP +If the system supports the FBPM (Frame Buffer Power +Management) extension (i.e. some Sun systems), then +prevent the video h/w from going into a reduced power +state when VNC clients are connected. +.IP +FBPM capable video h/w save energy when the workstation +is idle by going into low power states (similar to DPMS +for monitors). This interferes with x11vnc's polling +of the framebuffer data. +.IP +"\fB-nofbpm\fR" means prevent FBPM low power states whenever +VNC clients are connected, while "\fB-fbpm\fR" means to not +monitor the FBPM state at all. See the +.IR xset (1) +manpage +for details. \fB-nofbpm\fR is basically the same as running +"xset fbpm force on" periodically. Default: \fB-fbpm\fR +.PP \fB-noxdamage\fR .IP Do not use the X DAMAGE extension to detect framebuffer @@ -2760,6 +3144,10 @@ nonap disable \fB-nap\fR mode. .IP sb:n set \fB-sb\fR to n s, same as screen_blank:n .IP +fbpm disable \fB-nofbpm\fR mode. +.IP +nofbpm enable \fB-nofbpm\fR mode. +.IP xdamage enable xdamage polling hints. .IP noxdamage disable xdamage polling hints. @@ -2937,8 +3325,8 @@ pm input_skip input client_input speeds wmdt debug_pointer dp nodebug_pointer nodp debug_keyboard dk nodebug_keyboard nodk deferupdate defer wait_ui wait_bog nowait_bog slow_fb wait readtimeout nap nonap -sb screen_blank fs gaps grow fuzz snapfb nosnapfb -rawfb progressive rfbport http nohttp httpport +sb screen_blank fbpm nofbpm fs gaps grow fuzz snapfb +nosnapfb rawfb progressive rfbport http nohttp httpport httpdir enablehttpproxy noenablehttpproxy alwaysshared noalwaysshared nevershared noalwaysshared dontdisconnect nodontdisconnect desktop debug_xevents nodebug_xevents diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 58a7f41..e29101e 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -142,6 +142,7 @@ #include "sslcmds.h" #include "sslhelper.h" #include "selection.h" +#include "pm.h" /* * main routine for the x11vnc program @@ -468,6 +469,7 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret); check_new_clients(); check_xevents(); check_autorepeat(); + check_pm(); check_keycode_state(); check_connect_inputs(); check_gui_inputs(); @@ -1161,6 +1163,7 @@ static void print_settings(int try_http, int bg, char *gui_str) { fprintf(stderr, " readtimeout: %d\n", rfbMaxClientWait/1000); fprintf(stderr, " take_naps: %d\n", take_naps); fprintf(stderr, " sb: %d\n", screen_blank); + fprintf(stderr, " fbpm: %d\n", !watch_fbpm); fprintf(stderr, " xdamage: %d\n", use_xdamage); fprintf(stderr, " xd_area: %d\n", xdamage_max_area); fprintf(stderr, " xd_mem: %.3f\n", xdamage_memory); @@ -1268,7 +1271,7 @@ static void check_loop_mode(int argc, char* argv[]) { #endif } } -static void store_homedir_passwd(void) { +static void store_homedir_passwd(char *file) { char str1[32], str2[32], *p, *h, *f; struct stat sbuf; @@ -1311,27 +1314,32 @@ static void store_homedir_passwd(void) { exit(1); } - h = getenv("HOME"); - if (! h) { - fprintf(stderr, "** $HOME not set.\n"); - exit(1); - } + if (file != NULL) { + f = file; + } else { + + h = getenv("HOME"); + if (! h) { + fprintf(stderr, "** $HOME not set.\n"); + exit(1); + } - f = (char *) malloc(strlen(h) + strlen("/.vnc/passwd") + 1); - sprintf(f, "%s/.vnc", h); + f = (char *) malloc(strlen(h) + strlen("/.vnc/passwd") + 1); + sprintf(f, "%s/.vnc", h); - if (stat(f, &sbuf) != 0) { - if (mkdir(f, 0755) != 0) { - fprintf(stderr, "** could not create directory %s\n", f); - perror("mkdir"); + if (stat(f, &sbuf) != 0) { + if (mkdir(f, 0755) != 0) { + fprintf(stderr, "** could not create directory %s\n", f); + perror("mkdir"); + exit(1); + } + } else if (! S_ISDIR(sbuf.st_mode)) { + fprintf(stderr, "** not a directory %s\n", f); exit(1); } - } else if (! S_ISDIR(sbuf.st_mode)) { - fprintf(stderr, "** not a directory %s\n", f); - exit(1); - } - sprintf(f, "%s/.vnc/passwd", h); + sprintf(f, "%s/.vnc/passwd", h); + } fprintf(stderr, "Write password to %s? [y]/n ", f); if (fgets(str2, 32, stdin) == NULL) { @@ -1597,9 +1605,64 @@ int main(int argc, char* argv[]) { i++; } } + } else if (!strcmp(arg, "-ssldir")) { + CHECK_ARGC + ssl_certs_dir = strdup(argv[++i]); + } else if (!strcmp(arg, "-sslverify")) { CHECK_ARGC ssl_verify = strdup(argv[++i]); + + } else if (!strcmp(arg, "-sslGenCA")) { + char *cdir = NULL; + if (i < argc-1) { + char *s = argv[i+1]; + if (s[0] != '-') { + cdir = strdup(s); + i++; + } + } + sslGenCA(cdir); + exit(0); + } else if (!strcmp(arg, "-sslGenCert")) { + char *ty, *nm = NULL; + if (i >= argc-1) { + fprintf(stderr, "Must be:\n"); + fprintf(stderr, " x11vnc -sslGenCert server ...\n"); + fprintf(stderr, "or x11vnc -sslGenCert client ...\n"); + exit(1); + } + ty = argv[i+1]; + if (strcmp(ty, "server") && strcmp(ty, "client")) { + fprintf(stderr, "Must be:\n"); + fprintf(stderr, " x11vnc -sslGenCert server ...\n"); + fprintf(stderr, "or x11vnc -sslGenCert client ...\n"); + exit(1); + } + if (i < argc-2) { + nm = argv[i+2]; + } + sslGenCert(ty, nm); + exit(0); + } else if (!strcmp(arg, "-sslEncKey")) { + if (i < argc-1) { + char *s = argv[i+1]; + sslEncKey(s, 0); + } + exit(0); + } else if (!strcmp(arg, "-sslCertInfo")) { + if (i < argc-1) { + char *s = argv[i+1]; + sslEncKey(s, 1); + } + exit(0); + } else if (!strcmp(arg, "-sslDelCert")) { + if (i < argc-1) { + char *s = argv[i+1]; + sslEncKey(s, 2); + } + exit(0); + } else if (!strcmp(arg, "-stunnel")) { use_stunnel = 1; if (i < argc-1) { @@ -1633,11 +1696,15 @@ int main(int argc, char* argv[]) { } else if (!strcmp(arg, "-usepw")) { usepw = 1; } else if (!strcmp(arg, "-storepasswd")) { - if (i+1 >= argc) { - store_homedir_passwd(); + if (argc == i+1) { + store_homedir_passwd(NULL); + exit(0); + } + if (argc == i+2) { + store_homedir_passwd(argv[i+1]); exit(0); } - if (i+2 >= argc || rfbEncryptAndStorePasswd(argv[i+1], + if (argc >= i+4 || rfbEncryptAndStorePasswd(argv[i+1], argv[i+2]) != 0) { fprintf(stderr, "-storepasswd failed\n"); exit(1); @@ -1964,6 +2031,10 @@ int main(int argc, char* argv[]) { } else if (!strcmp(arg, "-sb")) { CHECK_ARGC screen_blank = atoi(argv[++i]); + } else if (!strcmp(arg, "-nofbpm")) { + watch_fbpm = 1; + } else if (!strcmp(arg, "-fbpm")) { + watch_fbpm = 0; } else if (!strcmp(arg, "-xdamage")) { use_xdamage = 1; } else if (!strcmp(arg, "-noxdamage")) { @@ -2323,16 +2394,6 @@ int main(int argc, char* argv[]) { exit(1); } - if (ssl_verify) { - struct stat sbuf; - if (stat(ssl_verify, &sbuf) != 0) { - rfbLog("x11vnc: -sslverify %s does not exist\n", - ssl_verify); - rfbLogPerror("stat"); - exit(1); - } - } - /* * If -passwd was used, clear it out of argv. This does not * work on all UNIX, have to use execvp() in general... @@ -3031,6 +3092,7 @@ int main(int argc, char* argv[]) { } #endif + check_pm(); if (! quiet) { rfbLog("--------------------------------------------------------\n"); diff --git a/x11vnc/x11vnc.h b/x11vnc/x11vnc.h index 09370fe..2c69d1b 100644 --- a/x11vnc/x11vnc.h +++ b/x11vnc/x11vnc.h @@ -190,6 +190,8 @@ #include <X11/extensions/XShm.h> #endif +#include <dirent.h> + #if LIBVNCSERVER_HAVE_XTEST #include <X11/extensions/XTest.h> #endif diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index f6af73f..7c45af0 100644 --- a/x11vnc/x11vnc_defs.c +++ b/x11vnc/x11vnc_defs.c @@ -15,7 +15,7 @@ int xtrap_base_event_type = 0; int xdamage_base_event_type = 0; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.8.1 lastmod: 2006-03-27"; +char lastmod[] = "0.8.1 lastmod: 2006-04-05"; /* X display info */ |