SSL patch for Java viewer. https support for x11vnc.

pull/1/head
runge 18 years ago
parent 10c61b53c2
commit 5920dc18d7

@ -1,3 +1,8 @@
2006-03-28 Karl Runge <runge@karlrunge.com>
* classes/ssl: patch to tightvnc Java viewer for SSL support
plus other fixes (richcursor colors, Tab keysym, etc).
* libvncserver/httpd.c: add missing \r in 200 OK.
2006-03-27 Steven Carr <scarr@jsa-usa.com>
* rfbserver.c: Zlib encoding cannot have a limit via
maxRectsPerUpdate

@ -1,2 +1,5 @@
EXTRA_DIST=VncViewer.jar index.vnc javaviewer.pseudo_proxy.patch
SUBDIRS = ssl
DIST_SUBDIRS = ssl

@ -0,0 +1,2 @@
EXTRA_DIST=VncViewer.jar index.vnc

Binary file not shown.

@ -0,0 +1,26 @@
<!--
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.
-->
<HTML>
<TITLE>
$USER's $DESKTOP desktop ($DISPLAY)
</TITLE>
<APPLET CODE=VncViewer.class ARCHIVE=VncViewer.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>

@ -0,0 +1,57 @@
--- vnc_javasrc.orig/VncCanvas.java 2004-10-10 02:15:54.000000000 -0400
+++ vnc_javasrc/VncCanvas.java 2006-03-27 22:34:02.000000000 -0500
@@ -28,6 +28,7 @@
import java.lang.*;
import java.util.zip.*;
+import java.util.Collections;
//
// VncCanvas is a subclass of Canvas which draws a VNC desktop on it.
@@ -81,6 +82,20 @@
cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
+ // kludge to not show any Java cursor in the canvas since we are
+ // showing the soft cursor (should be a user setting...)
+ Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor(
+ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0),
+ "dot");
+ this.setCursor(dot);
+
+ // while we are at it... get rid of the keyboard traversals that
+ // make it so we can't type a Tab character:
+ this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+ Collections.EMPTY_SET);
+ this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
+ Collections.EMPTY_SET);
+
colors = new Color[256];
for (int i = 0; i < 256; i++)
colors[i] = new Color(cm8.getRGB(i));
@@ -1387,9 +1402,9 @@
result = cm8.getRGB(pixBuf[i]);
} else {
result = 0xFF000000 |
- (pixBuf[i * 4 + 1] & 0xFF) << 16 |
- (pixBuf[i * 4 + 2] & 0xFF) << 8 |
- (pixBuf[i * 4 + 3] & 0xFF);
+ (pixBuf[i * 4 + 2] & 0xFF) << 16 |
+ (pixBuf[i * 4 + 1] & 0xFF) << 8 |
+ (pixBuf[i * 4 + 0] & 0xFF);
}
} else {
result = 0; // Transparent pixel
@@ -1403,9 +1418,9 @@
result = cm8.getRGB(pixBuf[i]);
} else {
result = 0xFF000000 |
- (pixBuf[i * 4 + 1] & 0xFF) << 16 |
- (pixBuf[i * 4 + 2] & 0xFF) << 8 |
- (pixBuf[i * 4 + 3] & 0xFF);
+ (pixBuf[i * 4 + 2] & 0xFF) << 16 |
+ (pixBuf[i * 4 + 1] & 0xFF) << 8 |
+ (pixBuf[i * 4 + 0] & 0xFF);
}
} else {
result = 0; // Transparent pixel

@ -0,0 +1,573 @@
diff -x VncCanvas.java -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile
--- vnc_javasrc.orig/Makefile 2004-03-04 08:34:25.000000000 -0500
+++ vnc_javasrc/Makefile 2006-03-26 17:29:25.000000000 -0500
@@ -15,25 +15,29 @@
DesCipher.class CapabilityInfo.class CapsContainer.class \
RecordingFrame.class SessionRecorder.class AuthUnixLoginPanel.class \
SocketFactory.class HTTPConnectSocketFactory.class \
- HTTPConnectSocket.class ReloginPanel.class
+ HTTPConnectSocket.class ReloginPanel.class \
+ SSLSocketToMe.class
+
+SSL_CLASSES = SSLSocketToMe*.class TrustDialog.class
SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \
OptionsFrame.java ClipboardFrame.java ButtonPanel.java \
DesCipher.java CapabilityInfo.java CapsContainer.java \
RecordingFrame.java SessionRecorder.java AuthUnixLoginPanel.java \
SocketFactory.java HTTPConnectSocketFactory.java \
- HTTPConnectSocket.java ReloginPanel.java
+ HTTPConnectSocket.java ReloginPanel.java \
+ SSLSocketToMe.java
all: $(CLASSES) $(ARCHIVE)
$(CLASSES): $(SOURCES)
- $(JC) -target 1.1 -O $(SOURCES)
+ $(JC) -target 1.4 -O $(SOURCES)
$(ARCHIVE): $(CLASSES) $(MANIFEST)
- $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES)
+ $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) $(SSL_CLASSES)
install: $(CLASSES) $(ARCHIVE)
- $(CP) $(CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR)
+ $(CP) $(CLASSES) $(SSL_CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR)
export:: $(CLASSES) $(ARCHIVE) $(PAGES)
@$(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
@@ -199,7 +199,21 @@
host = h;
port = p;
- if (viewer.socketFactory == null) {
+ if (! viewer.disableSSL) {
+ System.out.println("new SSLSocketToMe");
+ SSLSocketToMe ssl;
+ try {
+ ssl = new SSLSocketToMe(host, port, v);
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+
+ try {
+ sock = ssl.connectSock();
+ } catch (Exception es) {
+ throw new IOException(es.getMessage());
+ }
+ } else if (viewer.socketFactory == null) {
sock = new Socket(host, port);
} else {
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 @@
+/*
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
+ *
+ * Copyright (c) 2006 Karl J. Runge <runge@karlrunge.com>
+ * All rights reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ */
+
+import java.net.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.cert.*;
+import java.util.Vector;
+
+import java.awt.*;
+import java.awt.event.*;
+
+public class SSLSocketToMe {
+
+ /* basic member data: */
+ String host;
+ int port;
+ VncViewer viewer;
+ boolean debug = true;
+
+ /* sockets */
+ SSLSocket socket = null;
+ SSLSocketFactory factory;
+
+ /* trust contexts */
+ SSLContext trustall_ctx;
+ SSLContext trustone_ctx;
+ TrustManager[] trustAllCerts;
+ TrustManager[] trustOneCert;
+
+ /* cert(s) we retrieve from VNC server */
+ java.security.cert.Certificate[] serverCerts = null;
+
+ SSLSocketToMe(String h, int p, VncViewer v) throws Exception {
+ host = h;
+ port = p;
+ viewer = v;
+
+ /* we will first try default factory for certification: */
+
+ factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+
+ dbg("SSL startup: " + host + " " + port);
+
+ /* create trust managers used if initial handshake fails: */
+
+ trustAllCerts = new TrustManager[] {
+ /*
+ * this one accepts everything.
+ */
+ new X509TrustManager() {
+ public java.security.cert.X509Certificate[]
+ getAcceptedIssuers() {
+ return null;
+ }
+ public void checkClientTrusted(
+ java.security.cert.X509Certificate[] certs,
+ String authType) {
+ /* empty */
+ }
+ public void checkServerTrusted(
+ java.security.cert.X509Certificate[] certs,
+ String authType) {
+ /* empty */
+ }
+ }
+ };
+
+ trustOneCert = new TrustManager[] {
+ /*
+ * this one accepts only the retrieved server cert.
+ */
+ 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 (serverCerts == null) {
+ throw new CertificateException(
+ "No Server Certs array.");
+ }
+ if (serverCerts.length < 1) {
+ throw new CertificateException(
+ "No Server Certs.");
+ }
+ if (! serverCerts[0].equals(certs[0])) {
+ throw new CertificateException(
+ "Server Cert Changed.");
+ }
+ dbg("serverCerts[0] matches certs[0]");
+ }
+ }
+ };
+
+ /*
+ * They are used:
+ *
+ * 1) to retrieve the server cert in case of failure to
+ * display it to the user.
+ * 2) to subsequently connect to the server if user agrees.
+ */
+
+ /* trust all certs: */
+ try {
+ trustall_ctx = SSLContext.getInstance("SSL");
+ trustall_ctx.init(null, trustAllCerts, new
+ java.security.SecureRandom());
+
+ } catch (Exception e) {
+ String msg = "SSL trustall_ctx FAILED.";
+ dbg(msg);
+ throw new Exception(msg);
+ }
+
+ /* trust the one cert from server: */
+ try {
+ trustone_ctx = SSLContext.getInstance("SSL");
+ trustone_ctx.init(null, trustOneCert, new
+ java.security.SecureRandom());
+
+ } catch (Exception e) {
+ String msg = "SSL trustone_ctx FAILED.";
+ dbg(msg);
+ throw new Exception(msg);
+ }
+ }
+
+ public Socket connectSock() throws IOException {
+
+ /* now connect to host:port */
+ socket = (SSLSocket) factory.createSocket(host, port);
+
+ 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.");
+
+ } catch (Exception ehand) {
+ dbg("Could not automatically verify Server.");
+
+ socket.close();
+
+ /*
+ * Reconnect, trusting any cert, so we can grab
+ * the cert to show it to the user. The connection
+ * is not used for anything else.
+ */
+ factory = trustall_ctx.getSocketFactory();
+ socket = (SSLSocket) factory.createSocket(host, port);
+
+ try {
+ socket.startHandshake();
+ dbg("TrustAll Server Connection Verified.");
+
+ /* grab the cert: */
+ try {
+ SSLSession sess = socket.getSession();
+ serverCerts = 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();
+
+ /* dialog with user to accept cert or not: */
+
+ TrustDialog td= new TrustDialog(host, port,
+ serverCerts);
+
+ 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.");
+
+ throw new IOException(ehand2.getMessage());
+ }
+
+ /*
+ * Now connect a 3rd time, using the cert
+ * retrieved during connection 2 (that the user
+ * likely blindly agreed to).
+ */
+
+ factory = trustone_ctx.getSocketFactory();
+ socket = (SSLSocket) factory.createSocket(host, port);
+
+ try {
+ socket.startHandshake();
+ dbg("TrustAll Server Connection Verified #3.");
+
+ } catch (Exception ehand3) {
+ dbg("** Could not TrustAll Verify Server #3.");
+
+ throw new IOException(ehand3.getMessage());
+ }
+ }
+
+ dbg("SSL returning socket to caller.");
+ return (Socket) socket;
+ }
+
+ private void dbg(String s) {
+ if (debug) {
+ System.out.println(s);
+ }
+ }
+}
+
+class TrustDialog implements ActionListener {
+ String msg, host, text;
+ int port;
+ java.security.cert.Certificate[] serverCerts = null;
+ boolean viewing_cert = false;
+ boolean trust_this_session = false;
+
+ /*
+ * 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, cancel, viewcert;
+ TextArea textarea;
+ Checkbox accept, deny;
+ Dialog dialog;
+
+ String s1 = "Accept this certificate temporarily for this session";
+ String s2 = "Do not accept this certificate and do not connect to"
+ + " this VNC server";
+ String ln = "\n---------------------------------------------------\n\n";
+
+ TrustDialog (String h, int p, java.security.cert.Certificate[] certs) {
+ host = h;
+ port = p;
+ serverCerts = certs;
+
+ 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);
+
+ text = "\n"
++ "Unable to verify the identity of\n"
++ "\n"
++ " " + host + ":" + port + "\n"
++ "\n"
++ get_certinfo()
++ "\n"
++ "as a trusted VNC server.\n"
++ "\n"
++ "This may be due to:\n"
++ "\n"
++ " - The VNC server using a Self-Signed Certificate.\n"
++ "\n"
++ " - The VNC server using a Certificate Authority not recognized by your\n"
++ " Java applet runtime.\n"
++ "\n"
++ " - A Man-In-The-Middle attack impersonating as the VNC server you wish\n"
++ " to connect to.\n"
++ "\n"
++ "By copying the VNC server's Certificate (or using a common Certificate\n"
++ "Authority certificate) you can configure your Java applet runtime to\n"
++ "automatically authenticate the Server.\n"
+;
+
+ /* the accept / do-not-accept radio buttons: */
+ CheckboxGroup checkbox = new CheckboxGroup();
+ accept = new Checkbox(s1, true, checkbox);
+ deny = new Checkbox(s2, false, checkbox);
+
+ /* put the checkboxes in a panel: */
+ Panel check = new Panel();
+ check.setLayout(new GridLayout(2, 1));
+
+ check.add(accept);
+ check.add(deny);
+
+ /* make the 3 buttons: */
+ ok = new Button("OK");
+ cancel = new Button("Cancel");
+ viewcert = new Button("View Certificate");
+
+ ok.addActionListener(this);
+ cancel.addActionListener(this);
+ viewcert.addActionListener(this);
+
+ /* put the buttons in their own panel: */
+ Panel buttonrow = new Panel();
+ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT));
+ buttonrow.add(viewcert);
+ buttonrow.add(ok);
+ buttonrow.add(cancel);
+
+ /* label at the top: */
+ Label label = new Label(msg, Label.CENTER);
+ label.setFont(new Font("Helvetica", Font.BOLD, 16));
+
+ /* textarea in the middle */
+ textarea = new TextArea(text, 28, 64,
+ TextArea.SCROLLBARS_VERTICAL_ONLY);
+ textarea.setEditable(false);
+
+ /* put the two panels in their own panel at bottom: */
+ Panel bot = new Panel();
+ bot.setLayout(new GridLayout(2, 1));
+ bot.add(check);
+ bot.add(buttonrow);
+
+ /* now arrange things inside the dialog: */
+ dialog.setLayout(new BorderLayout());
+
+ dialog.add("North", label);
+ dialog.add("South", bot);
+ dialog.add("Center", textarea);
+
+ dialog.pack();
+ dialog.resize(dialog.preferredSize());
+
+ dialog.show(); /* block here til OK or Cancel pressed. */
+
+ return trust_this_session;
+ }
+
+ public synchronized void actionPerformed(ActionEvent evt) {
+
+ if (evt.getSource() == viewcert) {
+ /* View Certificate button clicked */
+ if (viewing_cert) {
+ /* show the original info text: */
+ textarea.setText(text);
+ viewcert.setLabel("View Certificate");
+ viewing_cert = false;
+ } else {
+ int i;
+ /* show all (likely just one) certs: */
+ textarea.setText("");
+ for (i=0; i < serverCerts.length; i++) {
+ int j = i + 1;
+ textarea.append("Certificate[" +
+ j + "]\n\n");
+ textarea.append(
+ serverCerts[i].toString());
+ textarea.append(ln);
+ }
+ viewcert.setLabel("View Info");
+ viewing_cert = true;
+
+ textarea.setCaretPosition(0);
+ }
+
+ } else if (evt.getSource() == ok) {
+ /* OK button clicked */
+ if (accept.getState()) {
+ trust_this_session = true;
+ } else {
+ trust_this_session = false;
+ }
+ dialog.dispose();
+
+ } else if (evt.getSource() == cancel) {
+ /* Cancel button clicked */
+ trust_this_session = false;
+
+ dialog.dispose();
+ }
+ }
+
+ String get_certinfo() {
+ String all = "";
+ String fields[] = {"CN", "OU", "O", "L", "C"};
+ int i;
+ if (serverCerts.length < 1) {
+ all = "";
+ return all;
+ }
+ String cert = serverCerts[0].toString();
+
+ /*
+ * 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 = cert.indexOf(mat, 0);
+ if (f > 0) {
+ t1 = cert.indexOf(", ", f);
+ t2 = cert.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 = cert.substring(f, t);
+ all = all + " " + sub + "\n";
+ }
+ }
+ }
+ return all;
+ }
+}
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
@@ -87,6 +87,7 @@
int deferScreenUpdates;
int deferCursorUpdates;
int deferUpdateRequests;
+ boolean disableSSL;
// Reference to this applet for inter-applet communication.
public static java.applet.Applet refApplet;
@@ -626,6 +627,12 @@
// SocketFactory.
socketFactory = readParameter("SocketFactory", false);
+
+ // SSL
+ disableSSL = false;
+ str = readParameter("DisableSSL", false);
+ if (str != null && str.equalsIgnoreCase("Yes"))
+ disableSSL = true;
}
public String readParameter(String name, boolean required) {

@ -184,30 +184,36 @@ if test "$X_CFLAGS" != "-DX_DISPLAY_MISSING"; then
if test -z "$HAVE_LIBC_CRYPT"; then
AC_CHECK_LIB(crypt, crypt,
X_PRELIBS="$X_PRELIBS -lcrypt"
[AC_DEFINE(HAVE_LIBCRYPT)], ,
$X_LIBS $X_PRELIBS -lcrypt $X_EXTRA_LIBS)
[AC_DEFINE(HAVE_LIBCRYPT)], ,)
fi
fi
AH_TEMPLATE(HAVE_LIBSSL, [openssl libssl library present])
AC_ARG_WITH(ssl,
[ --without-ssl disable support for openssl libssl],,)
if test "x$with_ssl" != "xno"; then
AC_CHECK_LIB(ssl, SSL_library_init,
X_PRELIBS="$X_PRELIBS -lssl"
[AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], ,
$X_LIBS $X_PRELIBS -lssl $X_EXTRA_LIBS)
fi
# some OS's need both -lssl and -lcrypto on link line:
AH_TEMPLATE(HAVE_LIBCRYPTO, [openssl libcrypto library present])
AC_ARG_WITH(crypto,
[ --without-crypto disable support for openssl libcrypto],,)
# some OS's need both -lssl and -lcrypto
if test "x$HAVE_LIBSSL" = "xtrue"; then
AC_CHECK_LIB(crypto, RAND_load_file,
X_PRELIBS="$X_PRELIBS -lcrypto"
[AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], ,
$X_LIBS $X_PRELIBS -lcrypto $X_EXTRA_LIBS)
AH_TEMPLATE(HAVE_LIBSSL, [openssl libssl library present])
AC_ARG_WITH(ssl,
[ --without-ssl disable support for openssl libssl],,)
if test "x$with_crypto" != "xno" -a "x$with_ssl" != "xno"; then
AC_CHECK_LIB(crypto, RAND_file_name,
[AC_DEFINE(HAVE_LIBCRYPTO) HAVE_LIBCRYPTO="true"], ,)
fi
if test "x$with_ssl" != "xno"; then
if test "x$HAVE_LIBCRYPTO" = "xtrue"; then
AC_CHECK_LIB(ssl, SSL_library_init,
X_PRELIBS="$X_PRELIBS -lssl -lcrypto"
[AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], ,
-lcrypto)
else
AC_CHECK_LIB(ssl, SSL_library_init,
X_PRELIBS="$X_PRELIBS -lssl"
[AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], ,)
fi
fi
X_LIBS="$X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS"
fi
@ -452,6 +458,7 @@ AC_CONFIG_FILES([Makefile
examples/Makefile
vncterm/Makefile
classes/Makefile
classes/ssl/Makefile
libvncclient/Makefile
client_examples/Makefile
test/Makefile

@ -67,7 +67,11 @@
"<HEAD><TITLE>Invalid Request</TITLE></HEAD>\n" \
"<BODY><H1>Invalid request</H1></BODY>\n"
#define OK_STR "HTTP/1.0 200 OK\nContent-Type: text/html\r\n\r\n"
#if 1
#define OK_STR "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
#else
#define OK_STR "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n"
#endif
static void httpProcessInput(rfbScreenInfoPtr screen);
static rfbBool compareAndSkip(char **ptr, const char *str);

@ -58,6 +58,12 @@ cp classes/Makefile.am classes/Makefile.am.LibVNCServer
echo 'pkgdatadir = $(datadir)/@PACKAGE@/classes' >> classes/Makefile.am
echo 'pkgdata_DATA=VncViewer.jar index.vnc' >> classes/Makefile.am
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
mv acinclude.m4 acinclude.m4.LibVNCServer
cat acinclude.m4.LibVNCServer | \
@ -65,7 +71,7 @@ sed -e "s/^\(_PKG.*\)\$PACKAGE\(.*\)$/\1LibVNCServer\2/" \
> acinclude.m4
make x11vnc-${VERSION}.tar.gz
for f in configure.ac Makefile.am libvncserver/Makefile.am classes/Makefile.am acinclude.m4 README; do
for f in configure.ac Makefile.am libvncserver/Makefile.am classes/Makefile.am classes/ssl/Makefile.am acinclude.m4 README; do
mv -f $f.LibVNCServer $f
done

@ -1,3 +1,11 @@
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
port. Look for classes/ssl under -http. add Java URL messages
to final output lines. make -inetd work with -ssl (even for
https). fix -unixpw login prompt under -scale. guard against
clientData = NULL.
2006-03-11 Karl Runge <runge@karlrunge.com>
* x11vnc: add -ssl mode using libssl. Include Xdummy in misc.
a few more macros for smallerfoot, etc.

File diff suppressed because it is too large Load Diff

@ -135,7 +135,7 @@ void clean_up_exit (int ret) {
}
stop_stunnel();
if (use_openssl) {
ssh_helper_pid(0, 0); /* killall */
ssl_helper_pid(0, 0); /* killall */
}
X_LOCK;

@ -32,6 +32,7 @@ void close_all_clients(void);
void close_clients(char *str);
void set_client_input(char *str);
void set_child_info(void);
void client_gone(rfbClientPtr client);
void reverse_connect(char *str);
void set_vnc_connect_prop(char *str);
void read_vnc_connect_prop(int);
@ -48,7 +49,6 @@ void check_new_clients(void);
static rfbClientPtr *client_match(char *str);
static int run_user_command(char *cmd, rfbClientPtr client, char *mode);
static void free_client_data(rfbClientPtr client);
static void client_gone(rfbClientPtr client);
static int check_access(char *addr);
static void ugly_geom(char *p, int *x, int *y);
static int ugly_window(char *addr, char *userhost, int X, int Y,
@ -113,6 +113,9 @@ char *list_clients(void) {
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) {
continue;
}
if (*list != '\0') {
strcat(list, ",");
}
@ -199,6 +202,9 @@ static rfbClientPtr *client_match(char *str) {
unsigned int in;
int id;
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) {
continue;
}
if (sscanf(str, "0x%x", &in) != 1) {
if (hex_warn++) {
continue;
@ -289,6 +295,9 @@ void set_client_input(char *str) {
cp = cl_list;
while (*cp) {
ClientData *cd = (ClientData *) (*cp)->clientData;
if (! cd) {
continue;
}
cd->input[0] = '\0';
strcat(cd->input, "_");
strcat(cd->input, val);
@ -543,7 +552,7 @@ static int accepted_client = 0;
/*
* callback for when a client disconnects
*/
static void client_gone(rfbClientPtr client) {
void client_gone(rfbClientPtr client) {
ClientData *cd = NULL;
client_count--;
@ -571,15 +580,16 @@ static void client_gone(rfbClientPtr client) {
}
if (client->clientData) {
cd = (ClientData *) client->clientData;
if (cd->ssh_helper_pid > 0) {
if (cd->ssl_helper_pid > 0) {
int status;
rfbLog("sending SIGTERM to ssh_helper_pid: %d\n",
cd->ssh_helper_pid);
kill(cd->ssh_helper_pid, SIGTERM);
rfbLog("sending SIGTERM to ssl_helper_pid: %d\n",
cd->ssl_helper_pid);
kill(cd->ssl_helper_pid, SIGTERM);
usleep(200*1000);
#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID
waitpid(cd->ssh_helper_pid, &status, WNOHANG);
waitpid(cd->ssl_helper_pid, &status, WNOHANG);
#endif
ssh_helper_pid(cd->ssh_helper_pid, -1); /* delete */
ssl_helper_pid(cd->ssl_helper_pid, -1); /* delete */
}
}
if (gone_cmd && *gone_cmd != '\0') {
@ -1486,13 +1496,13 @@ static int do_reverse_connect(char *str) {
}
if (inetd && unixpw) {
if(strcmp(host, "localhost") && strcmp(host, "127.0.0.1")) {
if (! getenv("UNIXPW_DISABLE_LOCALHOST")) {
rfbLog("reverse_connect: in -inetd only localhost\n");
rfbLog("connections allowed under -unixpw\n");
return 0;
if(strcmp(host, "localhost") && strcmp(host, "127.0.0.1")) {
if (! getenv("UNIXPW_DISABLE_LOCALHOST")) {
rfbLog("reverse_connect: in -inetd only localhost\n");
rfbLog("connections allowed under -unixpw\n");
return 0;
}
}
}
if (! getenv("UNIXPW_DISABLE_SSL") && ! have_ssh_env()) {
rfbLog("reverse_connect: in -inetd stunnel/ssh\n");
rfbLog("required under -unixpw\n");
@ -1839,7 +1849,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
}
clients_served++;
if (0) fprintf(stderr, "new_client: %s %d\n", client->host, clients_served);
if (getenv("NEW_CLIENT")) fprintf(stderr, "new_client: %s %d\n", client->host, clients_served);
if (use_openssl || use_stunnel) {
if (! ssl_initialized) {
@ -1881,11 +1891,11 @@ if (0) fprintf(stderr, "new_client: %s %d\n", client->host, clients_served);
cd->input[0] = '-';
cd->login_viewonly = -1;
cd->login_time = time(0);
cd->ssh_helper_pid = 0;
cd->ssl_helper_pid = 0;
if (use_openssl && openssl_last_helper_pid) {
if (0) fprintf(stderr, "SET ssh_helper_pid: %d\n", openssl_last_helper_pid);
cd->ssh_helper_pid = openssl_last_helper_pid;
if (0) fprintf(stderr, "SET ssl_helper_pid: %d\n", openssl_last_helper_pid);
cd->ssl_helper_pid = openssl_last_helper_pid;
openssl_last_helper_pid = 0;
}
@ -2131,6 +2141,10 @@ void check_new_clients(void) {
ClientData *cd = (ClientData *) cl->clientData;
char *s;
if (! cd) {
continue;
}
if (cd->login_viewonly < 0) {
/* this is a general trigger to initialize things */
if (cl->viewOnly) {

@ -17,6 +17,7 @@ extern void close_all_clients(void);
extern void close_clients(char *str);
extern void set_client_input(char *str);
extern void set_child_info(void);
extern void client_gone(rfbClientPtr client);
extern void reverse_connect(char *str);
extern void set_vnc_connect_prop(char *str);
extern void read_vnc_connect_prop(int);

@ -799,6 +799,7 @@ static void setup_cursors(void) {
UNLOCK(screen->cursorMutex);
}
rfbLog(" done.\n");
rfbLog("\n");
}
void setup_cursors_and_push(void) {
@ -1541,6 +1542,9 @@ void restore_cursor_shape_updates(rfbScreenInfoPtr s) {
int changed = 0;
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) {
continue;
}
if (cd->had_cursor_shape_updates) {
rfbLog("restoring enableCursorShapeUpdates for client"
" 0x%x\n", cl);
@ -1578,14 +1582,18 @@ void disable_cursor_shape_updates(rfbScreenInfoPtr s) {
cd = (ClientData *) cl->clientData;
if (cl->enableCursorShapeUpdates) {
cd->had_cursor_shape_updates = 1;
if (cd) {
cd->had_cursor_shape_updates = 1;
}
count++;
if (debug_pointer) {
rfbLog("%s disable HCSU\n", cl->host);
}
}
if (cl->enableCursorPosUpdates) {
cd->had_cursor_pos_updates = 1;
if (cd) {
cd->had_cursor_pos_updates = 1;
}
count++;
if (debug_pointer) {
rfbLog("%s disable HCPU\n", cl->host);

@ -19,6 +19,8 @@ void print_help(int mode) {
"\n"
"x11vnc: allow VNC connections to real X11 displays. %s\n"
"\n"
"(type \"x11vnc -opts\" to just list the options.)\n"
"\n"
"Typical usage is:\n"
"\n"
" Run this command in a shell on the remote machine \"far-host\"\n"
@ -423,20 +425,22 @@ void print_help(int mode) {
" send one before a 25 second timeout. Existing clients\n"
" are view-only during this period.\n"
"\n"
" Since the detailed behavior of su(1) can vary from OS\n"
" to OS and for local configurations, please test the mode\n"
" Since the detailed behavior of su(1) can vary from\n"
" OS to OS and for local configurations, test the mode\n"
" carefully on your systems before using it in production.\n"
" E.g. try different combinations of valid/invalid\n"
" usernames and valid/invalid passwords to see if it\n"
" behaves correctly. x11vnc will be conservative and\n"
" reject a user if anything abnormal occurs.\n"
" \n"
" For example, on FreeBSD and the other BSD's by default\n"
" it is impossible for the user running x11vnc to validate\n"
" his *own* password via su(1) (evidently commenting\n"
" out the pam_self.so entry in /etc/pam.d/su eliminates\n"
" the problem). So the x11vnc login will always fail for\n"
" this case. A possible workaround would be to start\n"
" Test different combinations of valid/invalid usernames\n"
" and valid/invalid passwords to see if it behaves as\n"
" expected. x11vnc will attempt to be conservative and\n"
" reject a login if anything abnormal occurs.\n"
"\n"
" On FreeBSD and the other BSD's by default it is\n"
" impossible for the user running x11vnc to validate\n"
" his *own* password via su(1) (evidently commenting out\n"
" the pam_self.so entry in /etc/pam.d/su eliminates this\n"
" problem). So the x11vnc login will always *fail* for\n"
" this case (even when the correct password is supplied).\n"
"\n"
" A possible workaround for this would be to start\n"
" x11vnc as root with the \"-users +nobody\" option to\n"
" immediately switch to user nobody. Another source of\n"
" problems are PAM modules that prompt for extra info,\n"
@ -459,48 +463,50 @@ void print_help(int mode) {
" -stunnel SSL mode be used for encryption over the\n"
" network.(see the description of -stunnel below).\n"
"\n"
" As a convenience, if you ssh(1) in and start x11vnc it\n"
" will check if the environment variable SSH_CONNECTION\n"
" is set and appears reasonable. If it does, then the\n"
" -ssl or -stunnel requirement will be dropped since it is\n"
" assumed you are using ssh for the encrypted tunnelling.\n"
" -localhost is still enforced. Use -ssl or -stunnel to\n"
" force SSL usage for this case.\n"
" Note: as a convenience, if you ssh(1) in and start\n"
" x11vnc it will check if the environment variable\n"
" SSH_CONNECTION is set and appears reasonable. If it\n"
" does, then the -ssl or -stunnel requirement will be\n"
" dropped since it is assumed you are using ssh for the\n"
" encrypted tunnelling. -localhost is still enforced.\n"
" Use -ssl or -stunnel to force SSL usage even if\n"
" SSH_CONNECTION is set.\n"
"\n"
" To override these restrictions you can set environment\n"
" variables before starting x11vnc:\n"
" To override the above restrictions you can set\n"
" environment variables before starting x11vnc:\n"
"\n"
" Set UNIXPW_DISABLE_SSL=1 to disable requiring either\n"
" -ssl or -stunnel. Evidently you will be using a\n"
" different method to encrypt the data between the\n"
" vncviewer and x11vnc: e.g. ssh(1) or a VPN. Note that\n"
" use of -localhost with ssh(1) is roughly the same as\n"
" requiring a Unix user login (since a Unix password or\n"
" the user's public key authentication is used by sshd on\n"
" the machine where x11vnc runs and only local connections\n"
" are accepted)\n"
" vncviewer and x11vnc: perhaps ssh(1) or an IPSEC VPN.\n"
"\n"
" Note that use of -localhost with ssh(1) is roughly\n"
" the same as requiring a Unix user login (since a Unix\n"
" password or the user's public key authentication is\n"
" used by sshd on the machine where x11vnc runs and only\n"
" local connections from that machine are accepted)\n"
"\n"
" Set UNIXPW_DISABLE_LOCALHOST=1 to disable the -localhost\n"
" requirement in Method 2). One should never do this\n"
" (i.e. allow the Unix passwords to be sniffed on the\n"
" network).\n"
"\n"
" Regarding reverse connections (e.g. -R connect:host),\n"
" if the -localhost constraint is in effect then reverse\n"
" connections can only be used to connect to the same\n"
" machine x11vnc is running on (default port 5500).\n"
" Please use a ssh or stunnel port redirection to the\n"
" viewer machine to tunnel the reverse connection over\n"
" an encrypted channel. Note that in -ssl mode reverse\n"
" connection are disabled.\n"
"\n"
" XXX -inetd + -ssl\n"
" In -inetd mode the two settings are attempted to be\n"
" enforced for reverse connections. Be sure to also\n"
" use encryption from the viewer to inetd since x11vnc\n"
" cannot guess easily if it is encrpyted. Tip: you can\n"
" also have your own stunnel spawn x11vnc in -inetd mode\n"
" (i.e. bypassing inetd). See the FAQ for details.\n"
" Regarding reverse connections (e.g. -R connect:host\n"
" and -connect host), when the -localhost constraint is\n"
" in effect then reverse connections can only be used\n"
" to connect to the same machine x11vnc is running on\n"
" (default port 5500). Please use a ssh or stunnel port\n"
" redirection to the viewer machine to tunnel the reverse\n"
" connection over an encrypted channel. Note that in -ssl\n"
" mode reverse connection are disabled (see below).\n"
"\n"
" In -inetd mode the Method 1) will be enforced (not\n"
" Method 2). With -ssl in effect reverse connections\n"
" are disabled. If you override this via env. var, be\n"
" sure to also use encryption from the viewer to inetd.\n"
" Tip: you can also have your own stunnel spawn x11vnc\n"
" in -inetd mode (thereby bypassing inetd). See the FAQ\n"
" for details.\n"
"\n"
" The user names in the comma separated [list] can have\n"
" per-user options after a \":\", e.g. \"fred:opts\"\n"
@ -515,22 +521,24 @@ void print_help(int mode) {
" Use \"deny\" to explicitly deny some users if you use\n"
" \"*\" to set a global option.\n"
"\n"
" There are also some tools for testing password if [list]\n"
" starts with the \"%\" character. See the quick_pw()\n"
" function for details.\n"
" There are also some utilities for testing password\n"
" if [list] starts with the \"%\" character. See the\n"
" quick_pw() function in the source for details.\n"
"\n"
"-unixpw_nis [list] As -unixpw above, however do not use su(1) but rather\n"
" use the traditional getpwnam(3) + crypt(3) method\n"
" instead. This requires that the encrpyted passwords\n"
" be readable. Passwords stored in /etc/shadow will\n"
" be inaccessible unless run as root. This is called\n"
" \"NIS\" mode simply because in most NIS setups the\n"
" user encrypted passwords are accessible (e.g. \"ypcat\n"
" passwd\"). NIS is not required for this mode to work\n"
" (only that getpwnam(3) return the encrpyted password\n"
" is required), but it is unlikely it will work for any\n"
" other environment. All of the -unixpw options and\n"
" contraints apply.\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"
" 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"
" 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"
"\n"
"-ssl [pem] Use the openssl library (www.openssl.org) to provide a\n"
" built-in encrypted SSL tunnel between VNC viewers and\n"
@ -539,30 +547,33 @@ void print_help(int mode) {
" with libssl support it will exit immediately when -ssl\n"
" is prescribed.\n"
"\n"
" [pem] is optional, use \"-ssl /path/to/mycert.pem\" to\n"
" specify a PEM certificate file to use to identify and\n"
" provide a key for this server.\n"
"\n"
" Connecting VNC viewer SSL tunnels can authenticate\n"
" this server if they have the public key part of the\n"
" certificate (or a common certificate authority, CA,\n"
" verifies this server's cert). This is used to prevent\n"
" man-in-the-middle attacks. Otherwise, if the VNC viewer\n"
" accepts this server's key without verification, at\n"
" least the traffic is protected from passive sniffing\n"
" on the network.\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"
"\n"
" Connecting VNC viewer SSL tunnels 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"
"\n"
" If [pem] is not supplied and the openssl(1) utility\n"
" command exists in PATH, then a temporary, self-signed\n"
" certificate will be generated for this session (this\n"
" may take 5-20 seconds on slow machines). If openssl(1)\n"
" may take 5-30 seconds on slow machines). If openssl(1)\n"
" cannot be used to generate a temporary certificate\n"
" x11vnc exits immediately.\n"
"\n"
" If successful in using openssl(1) to generate a\n"
" certificate, the public part of it will be displayed\n"
" to stdout (e.g. one could copy it to the client-side\n"
" to provide authentication of the server to VNC viewers.)\n"
" 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"
"\n"
" Set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc\n"
" print out the entire certificate, including the PRIVATE\n"
@ -572,20 +583,23 @@ void print_help(int mode) {
" will be printed to stderr (so one could move it to a\n"
" safe place for reuse).\n"
"\n"
" Reverse connections are disabled in -ssl\n"
" mode because the data cannot be encrypted.\n"
" Set X11VNC_SSL_ALLOW_REVERSE=1 to override this.\n"
" Reverse connections are disabled in -ssl mode because\n"
" there is no way to ensure that data channel will\n"
" be encrypted. Set X11VNC_SSL_ALLOW_REVERSE=1 to\n"
" override this.\n"
"\n"
" Your VNC viewer will also need to be able to connect\n"
" via SSL. See the discussion below under -stunnel and\n"
" the FAQ for how this might be achieved. E.g. on Unix it\n"
" is easy to write a shell script that starts up stunnel\n"
" and then vncviewer.\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"
"\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.\n"
" 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"
@ -595,37 +609,44 @@ void print_help(int mode) {
"\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"
" 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\n"
" an encrypted SSL tunnel between viewers and x11vnc.\n"
" This requires stunnel to be installed on the system and\n"
" available via PATH (n.b. stunnel is often installed in\n"
" sbin directories). Version 4.x of stunnel is assumed\n"
" (but see -stunnel3 below.)\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"
" 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"
"\n"
" [pem] is optional, use \"-stunnel /path/to/stunnel.pem\"\n"
" to specify a PEM certificate file to pass to stunnel.\n"
" Whether one is needed or not depends on your stunnel\n"
" configuration. stunnel often generates one at install\n"
" time.\n"
" time. See the stunnel documentation for details.\n"
"\n"
" stunnel is started up as a child process of x11vnc and\n"
" any SSL connections stunnel receives are decrypted and\n"
" sent to x11vnc over a local socket. The strings\n"
" \"The SSL VNC desktop is ...\" and \"SSLPORT=...\"\n"
" are printed out at startup.\n"
" are printed out at startup to indicate this.\n"
"\n"
" The -localhost option is enforced by default to\n"
" avoid people routing around the SSL channel. Set\n"
" STUNNEL_DISABLE_LOCALHOST=1 to disable the requirement.\n"
" The -localhost option is enforced by default\n"
" to avoid people routing around the SSL channel.\n"
" Set STUNNEL_DISABLE_LOCALHOST=1 before starting x11vnc\n"
" to disable the requirement.\n"
"\n"
" Your VNC viewer will also need to be able to connect\n"
" via SSL. Unfortunately not too many do this. UltraVNC\n"
" seems to have an encryption plugin. It is not too\n"
" difficult to set up an stunnel or other SSL tunnel on\n"
" the viewer side.\n"
" Your VNC viewer will also need to be able to connect via\n"
" 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"
" 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"
"\n"
@ -639,6 +660,35 @@ void print_help(int mode) {
"-stunnel3 [pem] Use version 3.x stunnel command line syntax instead of\n"
" version 4.x\n"
"\n"
"-https [port] Choose a separate HTTPS port (-ssl mode only).\n"
"\n"
" In -ssl mode, it turns out you can use the\n"
" single VNC port (e.g. 5900) for both VNC and HTTPS\n"
" connections. (HTTPS is used to retrieve a SSL-aware\n"
" VncViewer.jar applet that is provided with x11vnc).\n"
" Since both use SSL the implementation was extended to\n"
" detect if HTTP traffic (i.e. GET) is taking place and\n"
" handle it accordingly. The URL would be, e.g.:\n"
"\n"
" https://mymachine.org:5900/\n"
"\n"
" This is convenient for firewalls, etc, because only one\n"
" port needs to be allowed in. However, this heuristic\n"
" adds a few seconds delay to each connection and can be\n"
" unreliable (especially if the user takes much time to\n"
" ponder the Certificate dialogs in his browser, Java VM,\n"
" or VNC Viewer applet. That's right 3 separate \"Are\n"
" you sure you want to connect\" dialogs!)\n"
"\n"
" So use the -https option to provide a separate, more\n"
" reliable HTTPS port that x11vnc will listen on. If\n"
" [port] is not provided (or is 0), one is autoselected.\n"
" The URL to use is printed out at startup.\n"
"\n"
" The SSL Java applet directory is specified via the\n"
" -httpdir option. If not supplied it will try to guess\n"
" the directory as though the -http option was supplied.\n"
"\n"
"-usepw If no other password method was supplied on the command\n"
" line, first look for ~/.vnc/passwd and if found use it\n"
" with -rfbauth; next, look for ~/.vnc/passwdfile and\n"
@ -844,9 +894,10 @@ void print_help(int mode) {
" string \"noptr\" the mouse pointer will not be allowed\n"
" to go into a blacked out region.\n"
"-xinerama If your screen is composed of multiple monitors\n"
" glued together via XINERAMA, and that screen is\n"
"-noxinerama glued together via XINERAMA, and that screen is\n"
" not a rectangle this option will try to guess the\n"
" areas to black out (if your system has libXinerama).\n"
" default: %s\n"
"\n"
" In general, we have noticed on XINERAMA displays you\n"
" may need to use the \"-xwarppointer\" option if the mouse\n"
@ -2261,9 +2312,9 @@ void print_help(int mode) {
" http_url auth xauth users rootshift clipshift\n"
" scale_str scaled_x scaled_y scale_numer scale_denom\n"
" scale_fac scaling_blend scaling_nomult4 scaling_pad\n"
" scaling_interpolate inetd privremote unsafe safer\n"
" nocmds passwdfile unixpw unixpw_nis unixpw_list ssl\n"
" ssl_pem sslverify stunnel stunnel_pem usepw using_shm\n"
" scaling_interpolate inetd privremote unsafe safer nocmds\n"
" passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem\n"
" sslverify stunnel stunnel_pem https usepw using_shm\n"
" logfile o flag rc norc h help V version lastmod bg\n"
" sigpipe threads readrate netrate netlatency pipeinput\n"
" clients client_count pid ext_xtest ext_xtrap ext_xrecord\n"
@ -2364,7 +2415,7 @@ void print_help(int mode) {
strncpy(tmp, p, w);
fprintf(stderr, " %s", tmp);
l++;
if (l % 2 == 0) {
if (l % 3 == 0) {
fprintf(stderr, "\n");
}
}
@ -2381,6 +2432,7 @@ void print_help(int mode) {
view_only ? "on":"off",
shared ? "on":"off",
vnc_connect ? "-vncconnect":"-novncconnect",
xinerama ? "-xinerama":"-noxinerama",
use_modifier_tweak ? "-modtweak":"-nomodtweak",
skip_duplicate_key_events ? "-skip_dups":"-noskip_dups",
add_keysyms ? "-add_keysyms":"-noadd_keysyms",

@ -2098,6 +2098,16 @@ void initialize_allowed_input(void) {
while( (cl = rfbClientIteratorNext(iter)) ) {
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) {
continue;
}
#if 0
rfbLog("cd: %p\n", cd);
rfbLog("cd->input: %s\n", cd->input);
rfbLog("cd->login_viewonly: %d\n", cd->login_viewonly);
rfbLog("allowed_input_view_only: %s\n", allowed_input_view_only);
#endif
if (cd->input[0] == '=') {
; /* custom setting */
} else if (cd->login_viewonly) {
@ -2366,6 +2376,10 @@ void get_allowed_input(rfbClientPtr client, allowed_input_t *input) {
cd = (ClientData *) client->clientData;
if (! cd) {
return;
}
if (cd->input[0] != '-') {
str = cd->input;
} else if (client->viewOnly) {
@ -2398,7 +2412,7 @@ void get_allowed_input(rfbClientPtr client, allowed_input_t *input) {
/* for -pipeinput mode */
static void pipe_keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
int can_input = 0, uid;
int can_input = 0, uid = 0;
allowed_input_t input;
char *name;
ClientData *cd = (ClientData *) client->clientData;
@ -2413,7 +2427,9 @@ static void pipe_keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
can_input = 1; /* XXX distinguish later */
}
}
uid = cd->uid;
if (cd) {
uid = cd->uid;
}
if (! can_input) {
uid = -uid;
}

@ -23,6 +23,7 @@ int stunnel_port = 0;
char *stunnel_pem = NULL;
int use_openssl = 0;
char *openssl_pem = NULL;
int https_port_num = -1;
char *ssl_verify = NULL;
int ssl_initialized = 0;
int usepw = USEPW;
@ -124,7 +125,7 @@ int debug_grabs = 0;
int debug_sel = 0;
int xtrap_input = 0; /* -xtrap for user input insertion */
int xinerama = 0; /* -xinerama */
int xinerama = XINERAMA; /* -xinerama */
int xrandr = 0; /* -xrandr */
char *xrandr_mode = NULL;
char *pad_geometry = NULL;

@ -23,6 +23,7 @@ extern int stunnel_port;
extern char *stunnel_pem;
extern int use_openssl;
extern char *openssl_pem;
extern int https_port_num;
extern char *ssl_verify;
extern int ssl_initialized;
extern int usepw;

@ -508,7 +508,7 @@ if (debug_scroll > 1) fprintf(stderr, "internal scrollbar: %dx%d\n", w, h);
static void pipe_pointer(int mask, int x, int y, rfbClientPtr client) {
int can_input = 0, uid;
int can_input = 0, uid = 0;
allowed_input_t input;
ClientData *cd = (ClientData *) client->clientData;
char hint[MAX_BUTTONS * 20];
@ -523,7 +523,9 @@ static void pipe_pointer(int mask, int x, int y, rfbClientPtr client) {
can_input = 1; /* XXX distinguish later */
}
}
uid = cd->uid;
if (cd) {
uid = cd->uid;
}
if (! can_input) {
uid = -uid;
}

@ -30,6 +30,9 @@ static int get_latency(void);
static void measure_display_hook(rfbClientPtr cl) {
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) {
return;
}
dtime0(&cd->timer);
}
@ -50,6 +53,9 @@ static int get_rate(int which) {
while( (cl = rfbClientIteratorNext(iter)) ) {
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) {
continue;
}
if (cl->state != RFB_NORMAL) {
continue;
}
@ -109,6 +115,9 @@ static int get_latency(void) {
while( (cl = rfbClientIteratorNext(iter)) ) {
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) {
continue;
}
if (cl->state != RFB_NORMAL) {
continue;
}
@ -335,6 +344,9 @@ db = 0;
int got_t2 = 0, got_t3 = 0;
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) {
continue;
}
if (cd->send_cmp_rate > 0.0) {
continue;
}

@ -310,6 +310,8 @@ int check_httpdir(void) {
* /path/to/bin/x11vnc
* /path/to/bin/../share/x11vnc/classes
* 12345678901234567
* /path/to/bin/../share/x11vnc/classes/ssl
* 123456789012345678901
*/
if ((q = strrchr(prog, '/')) == NULL) {
rfbLog("check_httpdir: bad program path: %s\n", prog);
@ -317,10 +319,14 @@ int check_httpdir(void) {
return 0;
}
len = strlen(prog) + 17 + 1;
len = strlen(prog) + 21 + 1;
*q = '\0';
httpdir = (char *) malloc(len);
snprintf(httpdir, len, "%s/../share/x11vnc/classes", prog);
if (use_openssl || use_stunnel) {
snprintf(httpdir, len, "%s/../share/x11vnc/classes/ssl", prog);
} else {
snprintf(httpdir, len, "%s/../share/x11vnc/classes", prog);
}
free(prog);
if (stat(httpdir, &sbuf) == 0) {
@ -331,16 +337,32 @@ int check_httpdir(void) {
return 1;
} else {
/* try some hardwires: */
if (stat("/usr/local/share/x11vnc/classes",
&sbuf) == 0) {
http_dir =
strdup("/usr/local/share/x11vnc/classes");
return 1;
int i;
char **use;
char *list[] = {
"/usr/local/share/x11vnc/classes",
"/usr/share/x11vnc/classes",
NULL
};
char *ssllist[] = {
"/usr/local/share/x11vnc/classes/ssl",
"/usr/share/x11vnc/classes/ssl",
NULL
};
if (use_openssl || use_stunnel) {
use = ssllist;
} else {
use = list;
}
if (stat("/usr/share/x11vnc/classes", &sbuf) == 0) {
http_dir = strdup("/usr/share/x11vnc/classes");
return 1;
i = 0;
while (use[i] != NULL) {
if (stat(use[i], &sbuf) == 0) {
http_dir = strdup(use[i]);
return 1;
}
i++;
}
rfbLog("check_httpdir: bad guess:\n");
rfbLog(" %s\n", httpdir);
return 0;
@ -354,6 +376,19 @@ void http_connections(int on) {
}
if (on) {
rfbLog("http_connections: turning on http service.\n");
if (inetd && use_openssl) {
/*
* try to work around rapid fire https requests
* in inetd mode... ugh.
*/
if (screen->httpPort == 0) {
int port = find_free_port(5800, 5850);
if (port) {
screen->httpPort = port;
}
}
}
screen->httpInitDone = FALSE;
screen->httpDir = http_dir;
if (check_httpdir()) {
@ -3785,6 +3820,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%d", p, use_stunnel);
} else if (!strcmp(p, "stunnel_pem")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(stunnel_pem));
} else if (!strcmp(p, "https")) {
snprintf(buf, bufn, "aro=%s:%d", p, https_port_num);
} else if (!strcmp(p, "usepw")) {
snprintf(buf, bufn, "aro=%s:%d", p, usepw);
} else if (!strcmp(p, "using_shm")) {

@ -1924,8 +1924,17 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
* at screen creation time.
*/
/* event callbacks: */
screen->newClientHook = new_client;
screen->kbdAddEvent = keyboard;
screen->ptrAddEvent = pointer;
screen->setXCutText = xcut_receive;
/* called from inetd, we need to treat stdio as our socket */
if (inetd) {
if (inetd && use_openssl) {
/* accept_openssl() called later */
screen->port = 0;
} else if (inetd) {
int fd = dup(0);
if (fd < 0) {
rfbLogEnable(1);
@ -1955,16 +1964,13 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
screen->deferUpdateTime = defer_update;
}
/* event callbacks: */
screen->newClientHook = new_client;
screen->kbdAddEvent = keyboard;
screen->ptrAddEvent = pointer;
screen->setXCutText = xcut_receive;
rfbInitServer(screen);
if (use_openssl) {
openssl_port();
if (https_port_num >= 0) {
https_port();
}
}
install_passwds();
@ -1976,9 +1982,9 @@ static void announce(int lport, int ssl, char *iface) {
char *tvdt;
if (! ssl) {
tvdt = "The VNC desktop";
tvdt = "The VNC desktop is: ";
} else {
tvdt = "The SSL VNC desktop";
tvdt = "The SSL VNC desktop is: ";
}
if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) {
@ -1993,18 +1999,18 @@ static void announce(int lport, int ssl, char *iface) {
if (lport >= 5900) {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport - 5900);
fprintf(stderr, "%s is %s\n", tvdt,
fprintf(stderr, "%s %s\n", tvdt,
vnc_desktop_name);
} else {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport);
fprintf(stderr, "%s is %s\n", tvdt,
fprintf(stderr, "%s %s\n", tvdt,
vnc_desktop_name);
}
} else if (lport >= 5900) {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport - 5900);
fprintf(stderr, "%s is %s\n", tvdt, vnc_desktop_name);
fprintf(stderr, "%s %s\n", tvdt, vnc_desktop_name);
if (lport >= 6000) {
rfbLog("possible aliases: %s:%d, "
"%s::%d\n", host, lport,
@ -2013,17 +2019,41 @@ static void announce(int lport, int ssl, char *iface) {
} else {
snprintf(vnc_desktop_name, sz, "%s:%d",
host, lport);
fprintf(stderr, "%s is %s\n", tvdt, vnc_desktop_name);
fprintf(stderr, "%s %s\n", tvdt, vnc_desktop_name);
rfbLog("possible alias: %s::%d\n",
host, lport);
}
}
}
static void announce_http(int lport, int ssl, char *iface) {
char *host = this_host();
char *jvu;
if (ssl == 1) {
jvu = "Java SSL viewer URL: https";
} else if (ssl == 2) {
jvu = "Java SSL viewer URL: http";
} else {
jvu = "Java viewer URL: http";
}
if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) {
host = iface;
}
if (host != NULL) {
if (! inetd) {
fprintf(stderr, "%s://%s:%d/\n", jvu, host, lport);
}
}
}
void set_vnc_desktop_name(void) {
sprintf(vnc_desktop_name, "unknown");
if (inetd) {
sprintf(vnc_desktop_name, "inetd-no-further-clients");
sprintf(vnc_desktop_name, "%s/inetd-no-further-clients",
this_host());
}
if (screen->port) {
@ -2031,10 +2061,28 @@ void set_vnc_desktop_name(void) {
rfbLog("\n");
}
announce(screen->port, 0, listen_str);
if (use_openssl) {
announce(screen->port, 1, listen_str);
} else {
announce(screen->port, 0, listen_str);
}
if (stunnel_port) {
announce(stunnel_port, 1, NULL);
}
if (screen->httpListenSock > -1 && screen->httpPort) {
if (use_openssl) {
announce_http(screen->port, 1, listen_str);
if (https_port_num >= 0) {
announce_http(https_port_num, 1,
listen_str);
}
announce_http(screen->httpPort, 2, listen_str);
} else if (use_stunnel) {
announce_http(screen->httpPort, 2, listen_str);
} else {
announce_http(screen->httpPort, 0, listen_str);
}
}
fflush(stderr);
if (inetd) {
@ -2043,6 +2091,8 @@ void set_vnc_desktop_name(void) {
fprintf(stdout, "PORT=%d\n", screen->port);
if (stunnel_port) {
fprintf(stdout, "SSLPORT=%d\n", stunnel_port);
} else if (use_openssl) {
fprintf(stdout, "SSLPORT=%d\n", screen->port);
}
fflush(stdout);
if (flagfile) {

@ -29,6 +29,8 @@ void check_stunnel(void) {
}
last_check = now;
/* double check that stunnel is still running: */
if (stunnel_pid > 0) {
int status;
waitpid(stunnel_pid, &status, WNOHANG);

File diff suppressed because it is too large Load Diff

@ -4,14 +4,23 @@
/* -- sslhelper.h -- */
#define OPENSSL_INETD 1
#define OPENSSL_VNC 2
#define OPENSSL_HTTPS 3
extern int openssl_sock;
extern int openssl_port_num;
extern int https_sock;
extern pid_t openssl_last_helper_pid;
extern int openssl_present(void);
extern void openssl_init(void);
extern void openssl_port(void);
extern void https_port(void);
extern void check_openssl(void);
extern void ssh_helper_pid(pid_t pid, int sock);
extern void check_https(void);
extern void ssl_helper_pid(pid_t pid, int sock);
extern void accept_openssl(int mode);
#endif /* _X11VNC_SSLHELPER_H */

@ -295,6 +295,7 @@ Permissions
stunnel
=F stunnel_pem:
=F sslverify:
https:
=GAL LOFF
=GAL Misc-Perms::
safer

@ -306,6 +306,7 @@ char gui_code[] = "";
" stunnel\n"
" =F stunnel_pem:\n"
" =F sslverify:\n"
" https:\n"
" =GAL LOFF\n"
" =GAL Misc-Perms::\n"
" safer\n"

@ -109,9 +109,16 @@ void unixpw_screen(int init) {
zero_fb(0, 0, dpy_x, dpy_y);
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
x = nfix(dpy_x / 2 - strlen(log) * char_w, dpy_x);
y = dpy_y / 4;
if (scaling) {
x = (int) (x * scale_fac);
y = (int) (y * scale_fac);
}
rfbDrawString(screen, &default8x16Font, x, y, log, white());
char_x = x;
@ -120,7 +127,11 @@ void unixpw_screen(int init) {
char_row = 0;
}
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
if (scaling) {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1);
} else {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
}
}
@ -322,7 +333,7 @@ int crypt_verify(char *user, char *pass) {
if (pass[n-1] == '\n') {
pass[n-1] = '\0';
}
cr = crypt(pass, realpw);
cr = (char *) crypt(pass, realpw);
if (cr == NULL) {
return 0;
}
@ -741,7 +752,11 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
char_col = strlen(log);
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
if (scaling) {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1);
} else {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
}
unixpw_last_try_time = time(0);
unixpw_keystroke(0, 0, 2);
@ -805,9 +820,20 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
user[u_cnt-1] = '\0';
x = text_x();
y = text_y();
zero_fb(x - char_w, y - char_h, x, y);
mark_rect_as_modified(x - char_w, y - char_h,
x, y, 0);
if (scaling) {
int x2 = x / scale_fac;
int y2 = y / scale_fac;
int w2 = char_w / scale_fac;
int h2 = char_h / scale_fac;
zero_fb(x2 - w2, y2 - h2, x2, y2);
mark_rect_as_modified(x2 - w2,
y2 - h2, x2, y2, 0);
} else {
zero_fb(x - char_w, y - char_h, x, y);
mark_rect_as_modified(x - char_w,
y - char_h, x, y, 0);
}
char_col--;
u_cnt--;
}
@ -836,7 +862,11 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
white());
char_col = strlen(pw);
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
if (scaling) {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1);
} else {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
}
return;
}
if (keysym <= ' ' || keysym >= 0x7f) {
@ -862,7 +892,11 @@ if (db && db <= 2) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x %s\n", u_cnt, x, y
keystr[1] = '\0';
rfbDrawString(screen, &default8x16Font, x, y, keystr, white());
mark_rect_as_modified(x, y-char_h, x+char_w, y, 0);
if (scaling) {
mark_rect_as_modified(x, y-char_h, x+char_w, y, 1);
} else {
mark_rect_as_modified(x, y-char_h, x+char_w, y, 0);
}
char_col++;
} else if (in_passwd) {
@ -921,6 +955,10 @@ static void apply_opts (char *user) {
rfbClientPtr cl = unixpw_client;
int i;
if (! cd) {
return;
}
if (user) {
if (cd->unixname) {
free(cd->unixname);
@ -1000,7 +1038,11 @@ void unixpw_deny(void) {
y = char_y + char_row * char_h;
rfbDrawString(screen, &default8x16Font, x, y, pd, white());
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
if (scaling) {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1);
} else {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
}
for (i=0; i<5; i++) {
rfbPE(-1);

@ -2,7 +2,7 @@
.TH X11VNC "1" "March 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.1, lastmod: 2006-03-11
version: 0.8.1, lastmod: 2006-03-27
.SH SYNOPSIS
.B x11vnc
[OPTION]...
@ -519,22 +519,24 @@ are view-only during this period.
.IP
Since the detailed behavior of
.IR su (1)
can vary from OS
to OS and for local configurations, please test the mode
can vary from
OS to OS and for local configurations, test the mode
carefully on your systems before using it in production.
E.g. try different combinations of valid/invalid
usernames and valid/invalid passwords to see if it
behaves correctly. x11vnc will be conservative and
reject a user if anything abnormal occurs.
Test different combinations of valid/invalid usernames
and valid/invalid passwords to see if it behaves as
expected. x11vnc will attempt to be conservative and
reject a login if anything abnormal occurs.
.IP
For example, on FreeBSD and the other BSD's by default
it is impossible for the user running x11vnc to validate
On FreeBSD and the other BSD's by default it is
impossible for the user running x11vnc to validate
his *own* password via
.IR su (1)
(evidently commenting
out the pam_self.so entry in /etc/pam.d/su eliminates
the problem). So the x11vnc login will always fail for
this case. A possible workaround would be to start
(evidently commenting out
the pam_self.so entry in /etc/pam.d/su eliminates this
problem). So the x11vnc login will always *fail* for
this case (even when the correct password is supplied).
.IP
A possible workaround for this would be to start
x11vnc as root with the "\fB-users\fR \fI+nobody\fR" option to
immediately switch to user nobody. Another source of
problems are PAM modules that prompt for extra info,
@ -557,54 +559,56 @@ to come from the same machine x11vnc is running on
\fB-stunnel\fR SSL mode be used for encryption over the
network.(see the description of \fB-stunnel\fR below).
.IP
As a convenience, if you
Note: as a convenience, if you
.IR ssh (1)
in and start x11vnc it
will check if the environment variable SSH_CONNECTION
is set and appears reasonable. If it does, then the
\fB-ssl\fR or \fB-stunnel\fR requirement will be dropped since it is
assumed you are using ssh for the encrypted tunnelling.
\fB-localhost\fR is still enforced. Use \fB-ssl\fR or \fB-stunnel\fR to
force SSL usage for this case.
.IP
To override these restrictions you can set environment
variables before starting x11vnc:
in and start
x11vnc it will check if the environment variable
SSH_CONNECTION is set and appears reasonable. If it
does, then the \fB-ssl\fR or \fB-stunnel\fR requirement will be
dropped since it is assumed you are using ssh for the
encrypted tunnelling. \fB-localhost\fR is still enforced.
Use \fB-ssl\fR or \fB-stunnel\fR to force SSL usage even if
SSH_CONNECTION is set.
.IP
To override the above restrictions you can set
environment variables before starting x11vnc:
.IP
Set UNIXPW_DISABLE_SSL=1 to disable requiring either
\fB-ssl\fR or \fB-stunnel.\fR Evidently you will be using a
different method to encrypt the data between the
vncviewer and x11vnc: e.g.
vncviewer and x11vnc: perhaps
.IR ssh (1)
or a VPN. Note that
use of \fB-localhost\fR with
or an IPSEC VPN.
.IP
Note that use of \fB-localhost\fR with
.IR ssh (1)
is roughly the same as
requiring a Unix user login (since a Unix password or
the user's public key authentication is used by sshd on
the machine where x11vnc runs and only local connections
are accepted)
is roughly
the same as requiring a Unix user login (since a Unix
password or the user's public key authentication is
used by sshd on the machine where x11vnc runs and only
local connections from that machine are accepted)
.IP
Set UNIXPW_DISABLE_LOCALHOST=1 to disable the \fB-localhost\fR
requirement in Method 2). One should never do this
(i.e. allow the Unix passwords to be sniffed on the
network).
.IP
Regarding reverse connections (e.g. \fB-R\fR connect:host),
if the \fB-localhost\fR constraint is in effect then reverse
connections can only be used to connect to the same
machine x11vnc is running on (default port 5500).
Please use a ssh or stunnel port redirection to the
viewer machine to tunnel the reverse connection over
an encrypted channel. Note that in \fB-ssl\fR mode reverse
connection are disabled.
.IP
XXX \fB-inetd\fR + \fB-ssl\fR
In \fB-inetd\fR mode the two settings are attempted to be
enforced for reverse connections. Be sure to also
use encryption from the viewer to inetd since x11vnc
cannot guess easily if it is encrpyted. Tip: you can
also have your own stunnel spawn x11vnc in \fB-inetd\fR mode
(i.e. bypassing inetd). See the FAQ for details.
Regarding reverse connections (e.g. \fB-R\fR connect:host
and \fB-connect\fR host), when the \fB-localhost\fR constraint is
in effect then reverse connections can only be used
to connect to the same machine x11vnc is running on
(default port 5500). Please use a ssh or stunnel port
redirection to the viewer machine to tunnel the reverse
connection over an encrypted channel. Note that in \fB-ssl\fR
mode reverse connection are disabled (see below).
.IP
In \fB-inetd\fR mode the Method 1) will be enforced (not
Method 2). With \fB-ssl\fR in effect reverse connections
are disabled. If you override this via env. var, be
sure to also use encryption from the viewer to inetd.
Tip: you can also have your own stunnel spawn x11vnc
in \fB-inetd\fR mode (thereby bypassing inetd). See the FAQ
for details.
.IP
The user names in the comma separated [list] can have
per-user options after a ":", e.g. "fred:opts"
@ -619,9 +623,9 @@ are allowed to log in after supplying a valid password.
Use "deny" to explicitly deny some users if you use
"*" to set a global option.
.IP
There are also some tools for testing password if [list]
starts with the "%" character. See the quick_pw()
function for details.
There are also some utilities for testing password
if [list] starts with the "%" character. See the
quick_pw() function in the source for details.
.PP
\fB-unixpw_nis\fR \fI[list]\fR
.IP
@ -632,19 +636,21 @@ use the traditional
.IR getpwnam (3)
+
.IR crypt (3)
method
instead. This requires that the encrpyted passwords
be readable. Passwords stored in /etc/shadow will
be inaccessible unless 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
method to
verify passwords instead. This requires that the
encrpyted passwords be readable. Passwords stored
in /etc/shadow will be inaccessible unless x11vnc
is run as root.
.IP
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
.IR getpwnam (3)
return the encrpyted password
is required), but it is unlikely it will work for any
other environment. All of the \fB-unixpw\fR options and
contraints apply.
return the encrpyted
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.
.PP
\fB-ssl\fR \fI[pem]\fR
.IP
@ -655,25 +661,28 @@ into x11vnc at build time. If x11vnc is not built
with libssl support it will exit immediately when \fB-ssl\fR
is prescribed.
.IP
[pem] is optional, use "\fB-ssl\fR \fI/path/to/mycert.pem\fR" to
specify a PEM certificate file to use to identify and
provide a key for this server.
.IP
Connecting VNC viewer SSL tunnels can authenticate
this server if they have the public key part of the
certificate (or a common certificate authority, CA,
verifies 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.
[pem] is optional, use "\fB-ssl\fR \fI/path/to/mycert.pem\fR"
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.
.IP
Connecting VNC viewer SSL tunnels 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).
.IP
If [pem] is not supplied and the
.IR openssl (1)
utility
command exists in PATH, then a temporary, self-signed
certificate will be generated for this session (this
may take 5-20 seconds on slow machines). If
may take 5-30 seconds on slow machines). If
.IR openssl (1)
cannot be used to generate a temporary certificate
x11vnc exits immediately.
@ -681,9 +690,10 @@ x11vnc exits immediately.
If successful in using
.IR openssl (1)
to generate a
certificate, the public part of it will be displayed
to stdout (e.g. one could copy it to the client-side
to provide authentication of the server to VNC viewers.)
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.)
.IP
Set the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc
print out the entire certificate, including the PRIVATE
@ -693,22 +703,25 @@ 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).
.IP
Reverse connections are disabled in \fB-ssl\fR
mode because the data cannot be encrypted.
Set X11VNC_SSL_ALLOW_REVERSE=1 to override this.
Reverse connections are disabled in \fB-ssl\fR mode because
there is no way to ensure that data channel will
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.
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.
.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.
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
@ -721,7 +734,7 @@ manpage for details.
To create certificates for all sorts of authentications
(clients, servers, via CA, etc) see the
.IR openssl (1)
command. Of particular usefulness is the x509
command. Of particular usefulness is the "x509"
subcommand of
.IR openssl (1).
.PP
@ -729,34 +742,41 @@ subcommand of
.IP
Use the
.IR stunnel (8)
(www.stunnel.org) to provide
an encrypted SSL tunnel between viewers and x11vnc.
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.)
(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
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.)
.IP
[pem] is optional, use "\fB-stunnel\fR \fI/path/to/stunnel.pem\fR"
to specify a PEM certificate file to pass to stunnel.
Whether one is needed or not depends on your stunnel
configuration. stunnel often generates one at install
time.
time. See the stunnel documentation for details.
.IP
stunnel is started up as a child process of x11vnc and
any SSL connections stunnel receives are decrypted and
sent to x11vnc over a local socket. The strings
"The SSL VNC desktop is ..." and "SSLPORT=..."
are printed out at startup.
are printed out at startup to indicate this.
.IP
The \fB-localhost\fR option is enforced by default to
avoid people routing around the SSL channel. Set
STUNNEL_DISABLE_LOCALHOST=1 to disable the requirement.
The \fB-localhost\fR option is enforced by default
to avoid people routing around the SSL channel.
Set STUNNEL_DISABLE_LOCALHOST=1 before starting x11vnc
to disable the requirement.
.IP
Your VNC viewer will also need to be able to connect
via SSL. Unfortunately not too many do this. UltraVNC
seems to have an encryption plugin. It is not too
difficult to set up an stunnel or other SSL tunnel on
the viewer side.
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
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:
.IP
@ -772,6 +792,37 @@ for more examples.
Use version 3.x stunnel command line syntax instead of
version 4.x
.PP
\fB-https\fR \fI[port]\fR
.IP
Choose a separate HTTPS port (-ssl mode only).
.IP
In \fB-ssl\fR mode, it turns out you can use the
single VNC port (e.g. 5900) for both VNC and HTTPS
connections. (HTTPS is used to retrieve a SSL-aware
VncViewer.jar applet that is provided with x11vnc).
Since both use SSL the implementation was extended to
detect if HTTP traffic (i.e. GET) is taking place and
handle it accordingly. The URL would be, e.g.:
.IP
https://mymachine.org:5900/
.IP
This is convenient for firewalls, etc, because only one
port needs to be allowed in. However, this heuristic
adds a few seconds delay to each connection and can be
unreliable (especially if the user takes much time to
ponder the Certificate dialogs in his browser, Java VM,
or VNC Viewer applet. That's right 3 separate "Are
you sure you want to connect" dialogs!)
.IP
So use the \fB-https\fR 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.
.IP
The SSL Java applet directory is specified via the
\fB-httpdir\fR option. If not supplied it will try to guess
the directory as though the \fB-http\fR option was supplied.
.PP
\fB-usepw\fR
.IP
If no other password method was supplied on the command
@ -1030,9 +1081,13 @@ to go into a blacked out region.
\fB-xinerama\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).
default: \fB-xinerama\fR
.IP
In general, we have noticed on XINERAMA displays you
may need to use the "\fB-xwarppointer\fR" option if the mouse
@ -2898,9 +2953,9 @@ aro= noop display vncdisplay desktopname guess_desktop
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

@ -473,6 +473,7 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
check_gui_inputs();
check_stunnel();
check_openssl();
check_https();
record_last_fb_update();
check_padded_fb();
check_fixscreen();
@ -1617,6 +1618,16 @@ int main(int argc, char* argv[]) {
i++;
}
}
} else if (!strcmp(arg, "-https")) {
https_port_num = 0;
try_http = 1;
if (i < argc-1) {
char *s = argv[i+1];
if (s[0] != '-') {
https_port_num = atoi(s);
i++;
}
}
} else if (!strcmp(arg, "-nopw")) {
nopw = 1;
} else if (!strcmp(arg, "-usepw")) {
@ -2403,7 +2414,10 @@ int main(int argc, char* argv[]) {
launch_gui = 0;
}
if (! inetd && unixpw) {
if (unixpw) {
if (inetd) {
use_stunnel = 0;
}
if (! use_stunnel && ! use_openssl) {
if (have_ssh_env()) {
char *s = getenv("SSH_CONNECTION");
@ -2426,6 +2440,9 @@ int main(int argc, char* argv[]) {
if (openssl_present()) {
rfbLog("set -ssl in -unixpw mode.\n");
use_openssl = 1;
} else if (inetd) {
rfbLog("could not set -ssl in -inetd + -unixpw mode.\n");
exit(1);
} else {
rfbLog("set -stunnel in -unixpw mode.\n");
use_stunnel = 1;
@ -2447,6 +2464,10 @@ int main(int argc, char* argv[]) {
rfbLog("-sslverify must be used with -ssl or -stunnel\n");
exit(1);
}
if (https_port_num >= 0 && ! use_openssl) {
rfbLog("-https must be used with -ssl\n");
exit(1);
}
/* fixup settings that do not make sense */
@ -2498,7 +2519,9 @@ int main(int argc, char* argv[]) {
shared = 0;
connect_once = 1;
bg = 0;
use_stunnel = 0;
if (use_stunnel) {
exit(1);
}
/* others? */
}
@ -3065,6 +3088,9 @@ int main(int argc, char* argv[]) {
initialize_allowed_input();
if (inetd && use_openssl) {
accept_openssl(OPENSSL_INETD);
}
if (! inetd && ! use_openssl) {
if (! screen->port || screen->listenSock < 0) {
rfbLogEnable(1);

@ -46,6 +46,7 @@
* -DVNCSHARED to have the vnc display shared by default.
* -DFOREVER to have -forever on by default.
* -DNOREPEAT=0 to have -repeat on by default.
* -DXINERAMA=0 to have -noxinerama on by default.
* -DADDKEYSYMS=0 to have -noadd_keysyms the default.
*
* -DREMOTE_DEFAULT=0 to disable remote-control on by default (-yesremote).
@ -93,6 +94,10 @@
#define REMOTE_CONTROL 1
#endif
#ifndef XINERAMA
#define XINERAMA 1
#endif
#ifndef NOPW
#define NOPW 0
#endif
@ -465,7 +470,7 @@ typedef struct _ClientData {
int login_viewonly;
time_t login_time;
pid_t ssh_helper_pid;
pid_t ssl_helper_pid;
int had_cursor_shape_updates;
int had_cursor_pos_updates;

@ -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-11";
char lastmod[] = "0.8.1 lastmod: 2006-03-27";
/* X display info */

@ -680,8 +680,10 @@ void disable_grabserver(Display *in_dpy, int change) {
}
}
if (! ok && ! didmsg) {
rfbLog("No XTEST or DEC-XTRAP protection from XGrabServer.\n");
rfbLog("Deadlock if your window manager calls XGrabServer!!\n");
rfbLog("*********************************************************\n");
rfbLog("* No XTEST or DEC-XTRAP protection from XGrabServer !!! *\n");
rfbLog("* DEADLOCK if your window manager calls XGrabServer !!! *\n");
rfbLog("*********************************************************\n");
}
XFlush(in_dpy);
}

Loading…
Cancel
Save