Commit 06a401f8 authored by runge's avatar runge

x11vnc: -display WAIT:cmd=FINDDISPLAY, HTTPONCE, -http_ssl option, Java fixes.

parent 7a3e2363
......@@ -73,8 +73,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto
serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java
--- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500
+++ vnc_javasrc/SSLSocketToMe.java 2006-04-16 11:21:30.000000000 -0400
@@ -0,0 +1,1204 @@
+++ vnc_javasrc/SSLSocketToMe.java 2006-06-12 00:00:28.000000000 -0400
@@ -0,0 +1,1276 @@
+/*
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
+ *
......@@ -212,8 +212,19 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ "No Trust url Certs.");
+ }
+ if (trusturlCerts.length > 1) {
+ throw new CertificateException(
+ "Too many Trust url Certs.");
+ int i;
+ boolean ok = true;
+ for (i = 0; i < trusturlCerts.length - 1; i++) {
+ if (! trusturlCerts[i].equals(trusturlCerts[i+1])) {
+ ok = false;
+ }
+ }
+ if (! ok) {
+ throw new CertificateException(
+ "Too many Trust url Certs: "
+ + trusturlCerts.length
+ );
+ }
+ }
+ if (certs == null) {
+ throw new CertificateException(
......@@ -224,8 +235,19 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ "No this-certs Certs.");
+ }
+ if (certs.length > 1) {
+ throw new CertificateException(
+ "Too many this-certs.");
+ int i;
+ boolean ok = true;
+ for (i = 0; i < certs.length - 1; i++) {
+ if (! certs[i].equals(certs[i+1])) {
+ ok = false;
+ }
+ }
+ if (! ok) {
+ throw new CertificateException(
+ "Too many this-certs: "
+ + certs.length
+ );
+ }
+ }
+ if (! trusturlCerts[0].equals(certs[0])) {
+ throw new CertificateException(
......@@ -262,8 +284,19 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ "No Trust All Server Certs.");
+ }
+ if (trustallCerts.length > 1) {
+ throw new CertificateException(
+ "Too many Trust All Server Certs.");
+ int i;
+ boolean ok = true;
+ for (i = 0; i < trustallCerts.length - 1; i++) {
+ if (! trustallCerts[i].equals(trustallCerts[i+1])) {
+ ok = false;
+ }
+ }
+ if (! ok) {
+ throw new CertificateException(
+ "Too many Trust All Server Certs: "
+ + trustallCerts.length
+ );
+ }
+ }
+ if (certs == null) {
+ throw new CertificateException(
......@@ -274,8 +307,19 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ "No this-certs Certs.");
+ }
+ if (certs.length > 1) {
+ throw new CertificateException(
+ "Too many this-certs.");
+ int i;
+ boolean ok = true;
+ for (i = 0; i < certs.length - 1; i++) {
+ if (! certs[i].equals(certs[i+1])) {
+ ok = false;
+ }
+ }
+ if (! ok) {
+ throw new CertificateException(
+ "Too many this-certs: "
+ + certs.length
+ );
+ }
+ }
+ if (! trustallCerts[0].equals(certs[0])) {
+ throw new CertificateException(
......@@ -920,17 +964,26 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
++ "\n"
++ "This may be due to:\n"
++ "\n"
++ " - Your requesting to View the Certificate before accepting.\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"
++ " Browser or Java Plugin runtime.\n"
++ "\n"
++ " - The use of an Apache SSL portal employing CONNECT proxying and the\n"
++ " Apache web server has a certificate different from the VNC server's. \n"
++ "\n"
++ " - A Man-In-The-Middle attack impersonating as the VNC server you wish\n"
++ " to connect to.\n"
++ " to connect to. (Wouldn't that be exciting!!)\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"
++ "By safely copying the VNC server's Certificate (or using a common\n"
++ "Certificate Authority certificate) you can configure your Web Browser or\n"
++ "Java Plugin to automatically authenticate this Server.\n"
++ "\n"
++ "If you do so, then you will only have to click \"Yes\" when this VNC\n"
++ "Viewer applet asks you whether to trust your Browser/Java Plugin's\n"
++ "acceptance of the certificate. (except for the Apache portal case above.)\n"
+;
+
+ /* the accept / do-not-accept radio buttons: */
......@@ -966,7 +1019,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ label.setFont(new Font("Helvetica", Font.BOLD, 16));
+
+ /* textarea in the middle */
+ textarea = new TextArea(text, 28, 64,
+ textarea = new TextArea(text, 36, 64,
+ TextArea.SCROLLBARS_VERTICAL_ONLY);
+ textarea.setEditable(false);
+
......@@ -1188,13 +1241,32 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+
+ 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,
+ String m = "";
+m += "\n";
+m += "This VNC Viewer applet does not have its own keystore to track\n";
+m += "SSL certificates, and so cannot authenticate the certificate\n";
+m += "of the VNC Server:\n";
+m += "\n";
+m += " " + hostport + "\n\n " + vncServer + "\n";
+m += "\n";
+m += "on its own.\n";
+m += "\n";
+m += "However, it has noticed that your Web Browser or Java VM Plugin\n";
+m += "has previously accepted the same certificate. You may have set\n";
+m += "this up permanently or just for this session, or the server\n";
+m += "certificate was signed by a CA cert that your Web Browser or\n";
+m += "Java VM Plugin has.\n";
+m += "\n";
+m += "Should this VNC Viewer applet now connect to the above VNC server?\n";
+m += "\n";
+
+// 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, 20, 64,
+ TextArea.SCROLLBARS_VERTICAL_ONLY);
+ textarea.setEditable(false);
+ yes = new Button("Yes");
......
2006-06-12 Karl Runge <runge@karlrunge.com>
* x11vnc: word tune SSL Java viewer; fix multi-certs bug. Add
-display WAIT:cmd=FINDDISPLAY builtin script and cmd=HTTPONCE
action. -http_ssl option for ssl subdir only. Add -rawfb RAND
test case. improve raw_xfer() for use in inetd https transfer.
fix bug SSH + -unixpw -> -localhost. fix bug setup cursors
in WAIT mode. Mac OS X pty tweak.
2006-06-09 Karl Runge <runge@karlrunge.com>
* x11vnc: make -display WAIT + -unixpw work on Solaris.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -316,7 +316,10 @@ void print_help(int mode) {
" where the Java vncviewer applet is, have x11vnc try\n"
" to *guess* where the directory is by looking relative\n"
" to the program location and in standard locations\n"
" (/usr/local/share/x11vnc/classes, etc).\n"
" (/usr/local/share/x11vnc/classes, etc). Under -ssl or\n"
" -stunnel the ssl classes subdirectory is sought.\n"
"-http_ssl As -http, but force lookup for ssl classes subdir.\n"
"\n"
"-connect string For use with \"vncviewer -listen\" reverse connections.\n"
" If \"string\" has the form \"host\" or \"host:port\"\n"
" the connection is made once at startup. Use commas\n"
......@@ -602,9 +605,22 @@ void print_help(int mode) {
" SSL helper process that will not switch, but it is only\n"
" encoding and decoding the stream at that point.\n"
"\n"
" As a special case, WAIT:cmd=FINDDISPLAY will run a\n"
" script that works on most Unixes to determine a user's\n"
" DISPLAY variable and xauthority data. this is TBD.\n"
" As a special case, WAIT:cmd=FINDDISPLAY will run\n"
" a script that works on most Unixes to determine a\n"
" user's DISPLAY variable and xauthority data. To have\n"
" this default script printed to stdout (e.g. for\n"
" customization) run with WAIT:cmd=FINDDISPLAY-print\n"
"\n"
" As another special case, WAIT:cmd=HTTPONCE will allow\n"
" x11vnc to service one http request and then exit.\n"
" This is usually done in -inetd mode to run on, say,\n"
" port 5800 and allow the Java vncviewer to be downloaded\n"
" by client web browsers. For example:\n"
"\n"
" 5815 stream tcp nowait root /usr/sbin/tcpd .../x11vnc \\\n"
" -inetd -q -http_ssl -display WAIT:cmd=HTTPONCE\n"
"\n"
" Is used in the Apache SSL-portal example (see FAQ).\n"
"\n"
" Finally, one can insert a geometry between colons,\n"
" e.g. WAIT:1280x1024:... to set the size of the display\n"
......@@ -1122,11 +1138,6 @@ void print_help(int mode) {
" the -rfbauth option. If none of these succeed x11vnc\n"
" exits immediately.\n"
"\n"
#ifndef REL81
" Note: -unixpw currently does not count as a password\n"
" method by this option.\n"
"\n"
#endif
"-storepasswd pass file Store password \"pass\" as the VNC password in the\n"
" file \"file\". Once the password is stored the\n"
" program exits. Use the password via \"-rfbauth file\"\n"
......
......@@ -23,6 +23,7 @@ int use_stunnel = 0; /* -stunnel */
int stunnel_port = 0;
char *stunnel_pem = NULL;
int use_openssl = 0;
int http_ssl = 0;
char *openssl_pem = NULL;
char *ssl_certs_dir = NULL;
int https_port_num = -1;
......
......@@ -23,6 +23,7 @@ extern int use_stunnel;
extern int stunnel_port;
extern char *stunnel_pem;
extern int use_openssl;
extern int http_ssl;
extern char *openssl_pem;
extern char *ssl_certs_dir;
extern int https_port_num;
......
......@@ -268,7 +268,7 @@ void check_black_fb(void) {
}
int check_httpdir(void) {
if (http_dir) {
if (http_dir && http_dir[0] != '\0') {
return 1;
} else {
char *prog = NULL, *httpdir, *q;
......@@ -324,7 +324,7 @@ int check_httpdir(void) {
len = strlen(prog) + 21 + 1;
*q = '\0';
httpdir = (char *) malloc(len);
if (use_openssl || use_stunnel) {
if (use_openssl || use_stunnel || http_ssl) {
snprintf(httpdir, len, "%s/../share/x11vnc/classes/ssl", prog);
} else {
snprintf(httpdir, len, "%s/../share/x11vnc/classes", prog);
......@@ -351,7 +351,7 @@ int check_httpdir(void) {
"/usr/share/x11vnc/classes/ssl",
NULL
};
if (use_openssl || use_stunnel) {
if (use_openssl || use_stunnel || http_ssl) {
use = ssllist;
} else {
use = list;
......@@ -392,8 +392,8 @@ void http_connections(int on) {
}
}
screen->httpInitDone = FALSE;
screen->httpDir = http_dir;
if (check_httpdir()) {
screen->httpDir = http_dir;
rfbHttpInitSockets(screen);
}
} else {
......
......@@ -874,6 +874,9 @@ if (db) fprintf(stderr, "initialize_raw_fb reset\n");
if (!strcasecmp(raw_fb_str, "NULL") || !strcasecmp(raw_fb_str, "ZERO")) {
raw_fb_str = strdup("map:/dev/zero@640x480x32");
}
if (!strcasecmp(raw_fb_str, "RAND")) {
raw_fb_str = strdup("file:/dev/urandom@128x128x16");
}
if ( (q = strstr(raw_fb_str, "setup:")) == raw_fb_str) {
FILE *pipe;
......
......@@ -32,6 +32,8 @@ int openssl_port_num = 0;
int https_sock = -1;
pid_t openssl_last_helper_pid = 0;
void raw_xfer(int csock, int s_in, int s_out);
#if !LIBVNCSERVER_HAVE_LIBSSL
int openssl_present(void) {return 0;}
static void badnews(void) {
......@@ -76,7 +78,6 @@ static void sslerrexit(void);
static char *get_input(char *tag, char **in);
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
......@@ -1057,6 +1058,7 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
strncpy(buf_a, buf, n);
*n_a = n;
}
if (db) fprintf(stderr, "watch_for_http_traffic ssl err: %d/%d\n", err, n);
return -1;
}
......@@ -1071,21 +1073,29 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
} else if (!strncmp("CO", buf, 2)) {
is_http = 1;
}
if (db) fprintf(stderr, "read: '%s'\n", buf);
if (db) fprintf(stderr, "watch_for_http_traffic read: '%s' %d\n", buf, n);
/*
* better read all we can and fwd it along to avoid blocking
* in ssl_xfer().
*/
n2 = SSL_read(ssl, buf + n, ABSIZE - n);
if (n2 >= 0) {
n += n2;
}
*n_a = n;
if (db) fprintf(stderr, "watch_for_http_traffic readmore: %d\n", n2);
if (n > 0) {
/* XXX memcpy? */
strncpy(buf_a, buf, n);
memcpy(buf_a, buf, n);
}
if (db > 1) {
fprintf(stderr, "watch_for_http_traffic readmore: ");
write(2, buf_a, *n_a);
fprintf(stderr, "\n");
}
if (db) fprintf(stderr, "watch_for_http_traffic return: %d\n", is_http);
return is_http;
}
......@@ -1814,61 +1824,6 @@ if (db > 1) fprintf(stderr, "ssl_init: 4\n");
return 1;
}
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;
/* this is for testing, no SSL just socket redir */
if (pid < 0) {
exit(1);
}
if (pid) {
if (db) fprintf(stderr, "raw_xfer start: %d -> %d/%d\n", csock, s_in, s_out);
while (1) {
n = read(csock, buf, sz);
if (n == 0 || (n < 0 && errno != EINTR) ) {
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, "raw_xfer bad write: %d -> %d | %d/%d\n", csock, s_out, m, n);
break;
}
}
}
kill(pid, SIGTERM);
waitpid(pid, &status, WNOHANG);
if (db) fprintf(stderr, "raw_xfer done: %d -> %d\n", csock, s_out);
} else {
if (db) fprintf(stderr, "raw_xfer start: %d <- %d\n", csock, s_in);
while (1) {
n = read(s_in, buf, sz);
if (n == 0 || (n < 0 && errno != EINTR) ) {
break;
} else if (n > 0) {
m = write(csock, buf, n);
if (db > 1) write(2, buf, n);
if (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, "raw_xfer done: %d <- %d\n", csock, s_in);
}
close(csock);
close(s_in);
close(s_out);
}
static void ssl_xfer(int csock, int s_in, int s_out, int is_https) {
int dbxfer = 0, db = 0, check_pending, fdmax, nfd, n, i, err;
char cbuf[ABSIZE], sbuf[ABSIZE];
......@@ -2306,3 +2261,79 @@ static void init_prng(void) {
#endif /* FORK_OK */
#endif /* LIBVNCSERVER_HAVE_LIBSSL */
void raw_xfer(int csock, int s_in, int s_out) {
char buf[8192];
int sz = 8192, n, m, status;
#ifdef FORK_OK
pid_t pid = fork();
int db = 1;
/* this is for testing, no SSL just socket redir */
if (pid < 0) {
exit(1);
}
if (pid) {
if (db) fprintf(stderr, "raw_xfer start: %d -> %d/%d\n", csock, s_in, s_out);
while (1) {
n = read(csock, buf, sz);
if (n == 0 || (n < 0 && errno != EINTR) ) {
break;
} else if (n > 0) {
int len = n;
char *src = buf;
if (db > 1) write(2, buf, n);
while (len > 0) {
m = write(s_out, src, len);
if (m > 0) {
src += m;
len -= m;
continue;
}
if (m < 0 && (errno == EINTR || errno == EAGAIN)) {
continue;
}
if (db) fprintf(stderr, "raw_xfer bad write: %d -> %d | %d/%d errno=%d\n", csock, s_out, m, n, errno);
break;
}
}
}
kill(pid, SIGTERM);
waitpid(pid, &status, WNOHANG);
if (db) fprintf(stderr, "raw_xfer done: %d -> %d\n", csock, s_out);
} else {
if (db) fprintf(stderr, "raw_xfer start: %d <- %d\n", csock, s_in);
while (1) {
n = read(s_in, buf, sz);
if (n == 0 || (n < 0 && errno != EINTR) ) {
break;
} else if (n > 0) {
int len = n;
char *src = buf;
if (db > 1) write(2, buf, n);
while (len > 0) {
m = write(csock, src, len);
if (m > 0) {
src += m;
len -= m;
continue;
}
if (m < 0 && (errno == EINTR || errno == EAGAIN)) {
continue;
}
if (db) fprintf(stderr, "raw_xfer bad write: %d <- %d | %d/%d errno=%d\n", csock, s_in, m, n, errno);
break;
}
}
}
if (db) fprintf(stderr, "raw_xfer done: %d <- %d\n", csock, s_in);
}
close(csock);
close(s_in);
close(s_out);
#endif
}
......@@ -676,4 +676,75 @@ char genCert[] =
"sign_key\n"
;
char find_display[] =
"#!/bin/sh\n"
"#\n"
"# Script for use in -display WAIT:cmd=FINDDISPLAY -unixpw mode.\n"
"# Attempts to find 1) DISPLAY and 2) XAUTH data for the user and\n"
"# returns them to caller.\n"
"#\n"
"# The idea is this script is run via su - user -c ... and returns\n"
"# display + xauth info to caller (x11vnc running as root or nobody).\n"
"# x11vnc then uses the info to open the display.\n"
"#\n"
"\n"
"#env; set -xv\n"
"PATH=$PATH:/bin:/usr/bin:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/ucb\n"
"export PATH\n"
"\n"
"# -n means no xauth, -f prescribes file to use.\n"
"showxauth=1\n"
"if [ \"X$1\" = \"X-n\" ]; then\n"
" showxauth=\"\"\n"
" shift\n"
"elif [ \"X$1\" = \"X-f\" ]; then\n"
" shift\n"
" showxauth=\"$1\"\n"
" shift\n"
"fi\n"
"\n"
"user=\"$1\" # cmd line arg takes precedence\n"
"if [ \"X$user\" = \"X\" ]; then\n"
" user=$X11VNC_USER # then X11VNC_USER\n"
"fi\n"
"if [ \"X$user\" = \"X\" ]; then\n"
" user=$USER # then USER\n"
"fi\n"
"if [ \"X$user\" = \"X\" ]; then\n"
" user=$LOGNAME # then LOGNAME\n"
"fi\n"
"if [ \"X$user\" = \"X\" ]; then\n"
" user=`whoami 2>/dev/null` # desperation whoami\n"
"fi\n"
"if [ \"X$user\" = \"X\" ]; then\n"
" echo \"\" # failure\n"
" exit 1\n"
"fi\n"
"\n"
"# Now try to match X DISPLAY to user:\n"
"\n"
"# who(1) output column 2:\n"
"display=`who | grep \"^${user}[ ][ ]*:[0-9]\" | head -1 | awk '{print $2}'`\n"
"\n"
"if [ \"X$display\" = \"X\" ]; then\n"
" # who(1) output, last column:\n"
" display=`who | grep \"^${user}[ ]\" | awk '{print $NF}' | grep '(:[0-9]' | sed -e 's/[()]//g' | head -1`\n"
" if [ \"X$display\" = \"X\" ]; then\n"
" echo \"\" # failure\n"
" exit 1\n"
" fi\n"
"fi\n"
"\n"
"echo \"DISPLAY=$display\"\n"
"if [ \"X$showxauth\" != \"X\" ]; then\n"
" if [ \"X$showxauth\" = \"X1\" ]; then\n"
" xauth extract - \"$display\" 2>/dev/null\n"
" else\n"
" xauth -f \"$showxauth\" extract - \"$display\" 2>/dev/null\n"
" fi\n"
"fi\n"
"\n"
"exit 0\n"
;
#endif /* _SSLTOOLS_H */
......@@ -39,6 +39,9 @@ extern char *crypt(const char*, const char *);
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
#define IS_BSD
#endif
#if (defined(__MACH__) && defined(__APPLE__))
#define IS_BSD
#endif
#ifdef REL81
#undef UNIXPW_SU
......@@ -49,6 +52,7 @@ void unixpw_screen(int init);
void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init);
void unixpw_accept(char *user);
void unixpw_deny(void);
void unixpw_msg(char *msg, int delay);
int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size);
int crypt_verify(char *user, char *pass);
......@@ -1195,3 +1199,26 @@ void unixpw_deny(void) {
copy_screen();
}
void unixpw_msg(char *msg, int delay) {
int x, y, i;
char_row += 2;
char_col = 0;
x = char_x + char_col * char_w;
y = char_y + char_row * char_h;
rfbDrawString(screen, &default8x16Font, x, y, msg, white());
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);
usleep(500 * 1000);
if (i >= delay) {
break;
}
}
}
......@@ -7,6 +7,7 @@ extern void unixpw_screen(int init);
extern void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init);
extern void unixpw_accept(char *user);
extern void unixpw_deny(void);
extern void unixpw_msg(char *msg, int delay);
extern int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size);
extern int crypt_verify(char *user, char *pass);
......
......@@ -943,6 +943,94 @@ void check_new_passwds(void) {
}
}
static void handle_one_http_request(void) {
rfbLog("handle_one_http_request: begin.\n");
if (screen->httpPort == 0) {
int port = find_free_port(5800, 5850);
if (port) {
screen->httpPort = port;
} else {
rfbLog("handle_one_http_request: no http port.\n");
clean_up_exit(1);
}
}
screen->autoPort = FALSE;
screen->port = 0;
http_connections(1);
rfbInitServer(screen);
if (! inetd) {
int conn = 0;
while (1) {
if (0) fprintf(stderr, "%d %d %d %d\n", conn, screen->listenSock, screen->httpSock, screen->httpListenSock);
usleep(10 * 1000);
rfbHttpCheckFds(screen);
if (conn) {
if (screen->httpSock < 0) {
break;
}
} else {
if (screen->httpSock >= 0) {
conn = 1;
}
}
if (!screen->httpDir) {
break;
}
if (screen->httpListenSock < 0) {
break;
}
}
rfbLog("handle_one_http_request: finished.\n");
return;
} else {
#if LIBVNCSERVER_HAVE_FORK
pid_t pid;
int s_in = screen->inetdSock;
if (s_in < 0) {
rfbLog("handle_one_http_request: inetdSock not set up.\n");
clean_up_exit(1);
}
pid = fork();
if (pid < 0) {
rfbLog("handle_one_http_request: could not fork.\n");
clean_up_exit(1);
} else if (pid > 0) {
int status;
pid_t pidw;
while (1) {
rfbHttpCheckFds(screen);
pidw = waitpid(pid, &status, WNOHANG);
if (pidw == pid && WIFEXITED(status)) {
break;
} else if (pidw < 0) {
break;
}
}
rfbLog("handle_one_http_request: finished.\n");
return;
} else {
int sock = rfbConnectToTcpAddr("127.0.0.1",
screen->httpPort);
if (sock < 0) {
exit(1);
}
raw_xfer(sock, s_in, s_in);
exit(0);
}
#else
rfbLog("handle_one_http_request: fork not supported.\n");
clean_up_exit(1);
#endif
}
}
extern char find_display[];
int wait_for_client(int *argc, char** argv, int http) {
static XImage ximage_struct;
XImage* fb_image;
......@@ -952,50 +1040,69 @@ int wait_for_client(int *argc, char** argv, int http) {
char *str, *q, *p;
char *cmd = NULL;
int db = 0;
char tmp[] = "/tmp/x11vnc-find_display.XXXXXX";
int tmp_fd = -1, dt = 0;
if (! use_dpy || strstr(use_dpy, "WAIT:") != use_dpy) {
return 0;
}
rfbLog("into wait_for_client.\n");
for (i=0; i< *argc; i++) {
if (!strcmp(argv[i], "-desktop")) {
dt = 1;
}
if (0) fprintf(stderr, "args %d %s\n", i, argv[i]);
}
str = strdup(use_dpy);
str += strlen("WAIT:");
q = strchr(str, ':');
str += strlen("WAIT");
/* get any leading geometry: */
if (q) *q = '\0';
if (sscanf(str, "%dx%d", &w0, &h0) == 2) {
w = w0;
h = h0;
q = strchr(str+1, ':');
if (q) {
*q = '\0';
if (sscanf(str+1, "%dx%d", &w0, &h0) == 2) {
w = w0;
h = h0;
rfbLog("wait_for_client set: w=%d h=%d\n", w, h);
}
*q = ':';
str = q;
}
if (q) *q = ':';
q = strchr(str, ':');
if (! q) {
if (strstr(str, "cmd=") != str) {
str = strdup(":0");
}
/* str currently begins with a ':' */
if (strstr(str, ":cmd=") == str) {
/* cmd=/path/to/mycommand */
str++;
} else if (strpbrk(str, "0123456789") == str+1) {
/* :0.0 */
;
} else {
str = q;
/* hostname:0.0 */
str++;
}
if (db) fprintf(stderr, "str: %s\n", str);
if (strstr(str, "cmd=") == str) {
cmd = str + strlen("cmd=");
if (db) fprintf(stderr, "cmd: %s\n", cmd);
/* WAIT */
if (no_external_cmds) {
rfbLog("wait_for_client external cmds not allowed:"
" %s\n", use_dpy);
clean_up_exit(1);
}
cmd = str + strlen("cmd=");
if (!strcmp(str, "FINDDISPLAY-print")) {
fprintf(stdout, "%s", find_display);
clean_up_exit(0);
}
if (db) fprintf(stderr, "cmd: %s\n", cmd);
}
if (fake_fb) {
free(fake_fb);
}
fake_fb = (char *) calloc(w*h*b/4, 1);
fake_fb = (char *) calloc(w*h*b/8, 1);
fb_image = &ximage_struct;
fb_image->data = fake_fb;
......@@ -1017,10 +1124,39 @@ int wait_for_client(int *argc, char** argv, int http) {
off_x = 0;
off_y = 0;
if (! dt) {
char *s;
argv[*argc] = strdup("-desktop");
(*argc)++;
if (cmd) {
char *q;
s = choose_title(":0");
q = strstr(s, ":0");
if (q) {
*q = '\0';
}
} else {
s = choose_title(str);
}
rfb_desktop_name = strdup(s);
argv[*argc] = s;
(*argc)++;
}
initialize_allowed_input();
initialize_cursors_mode();
initialize_screen(argc, argv, fb_image);
initialize_signals();
if (!strcmp(cmd, "HTTPONCE")) {
handle_one_http_request();
clean_up_exit(0);
}
if (http && check_httpdir()) {
http_connections(1);
}
......@@ -1081,11 +1217,28 @@ int wait_for_client(int *argc, char** argv, int http) {
memset(line1, 0, 1024);
memset(line2, 0, 16384);
if (!strcmp(cmd, "FINDDISPLAY")) {
tmp_fd = mkstemp(tmp);
if (tmp_fd < 0) {
rfbLog("wait_for_client: open failed: %s\n", tmp);
rfbLogPerror("mkstemp");
clean_up_exit(1);
}
write(tmp_fd, find_display, strlen(find_display));
close(tmp_fd);
chmod(tmp, 0644);
cmd = (char *) malloc(strlen(tmp) + strlen("/bin/sh ") + 1);
sprintf(cmd, "/bin/sh %s", tmp);
}
rfbLog("wait_for_client: running: %s\n", cmd);
if (unixpw) {
int res = 0, k, j, i;
char line[18000];
memset(line, 0, 18000);
if (0) unixpw_msg("Looking up DISPLAY", 0);
if (keep_unixpw_user && keep_unixpw_pass) {
n = 18000;
......@@ -1096,8 +1249,15 @@ int wait_for_client(int *argc, char** argv, int http) {
}
keep_unixpw = 0;
if (tmp_fd >= 0) {
unlink(tmp);
}
if (db) write(2, line, n); write(2, "\n", 1);
if (! res) {
rfbLog("wait_for_client: cmd failed: %s\n", cmd);
unixpw_msg("No DISPLAY found.", 3);
clean_up_exit(1);
}
......@@ -1135,19 +1295,31 @@ int wait_for_client(int *argc, char** argv, int http) {
if (! p) {
rfbLog("wait_for_client: cmd failed: %s\n", cmd);
rfbLogPerror("popen");
if (tmp_fd >= 0) {
unlink(tmp);
}
unixpw_msg("No DISPLAY found.", 3);
clean_up_exit(1);
}
if (fgets(line1, 1024, p) == NULL) {
rfbLog("wait_for_client: read failed: %s\n", cmd);
rfbLogPerror("fgets");
if (tmp_fd >= 0) {
unlink(tmp);
}
unixpw_msg("No DISPLAY found.", 3);
clean_up_exit(1);
}
n = fread(line2, 1, 16384, p);
pclose(p);
if (tmp_fd >= 0) {
unlink(tmp);
}
}
if (strstr(line1, "DISPLAY=") != line1) {
rfbLog("wait_for_client: bad reply %s\n", line1);
unixpw_msg("No DISPLAY found.", 3);
clean_up_exit(1);
}
......@@ -1158,7 +1330,6 @@ int wait_for_client(int *argc, char** argv, int http) {
q++;
}
if (db) fprintf(stderr, "use_dpy: %s n: %d\n", use_dpy, n);
if (0) write(2, line2, n);
if (line2[0] != '\0') {
if (strstr(line2, "XAUTHORITY=") == line2) {
q = line2;
......@@ -1176,12 +1347,13 @@ if (0) write(2, line2, n);
xauth_raw_len = n;
memcpy(xauth_raw_data, line2, n);
if (db) fprintf(stderr, "xauth_raw_len: %d\n", n);
if (0) {
write(2, xauth_raw_data, xauth_raw_len);
fprintf(stderr, "\n");
}
}
}
if (unixpw) {
char str[32];
snprintf(str, 30, "Using DISPLAY %s", use_dpy);
unixpw_msg(str, 2);
}
} else {
use_dpy = strdup(str);
}
......
......@@ -47,6 +47,8 @@ void rfbCFD(long usec);
double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1,
int X2, int Y2);
char *choose_title(char *display);
/*
* routine to keep 0 <= i < n, should use in more places...
......@@ -448,3 +450,32 @@ double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1,
return o;
}
/*
* choose a desktop name
*/
char *choose_title(char *display) {
static char title[(MAXN+10)];
strcpy(title, "x11vnc");
if (display == NULL) {
display = getenv("DISPLAY");
}
if (display == NULL) {
return title;
}
title[0] = '\0';
if (display[0] == ':') {
if (this_host() != NULL) {
strncpy(title, this_host(), MAXN - strlen(title));
}
}
strncat(title, display, MAXN - strlen(title));
if (subwin && valid_window(subwin, NULL, 0)) {
char *name;
if (dpy && XFetchName(dpy, subwin, &name)) {
strncat(title, " ", MAXN - strlen(title));
strncat(title, name, MAXN - strlen(title));
}
}
return title;
}
......@@ -35,6 +35,7 @@ extern void rfbPE(long usec);
extern void rfbCFD(long usec);
extern double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1,
int X2, int Y2);
extern char *choose_title(char *display);
#define NONUL(x) ((x) ? (x) : "")
......
......@@ -2,7 +2,7 @@
.TH X11VNC "1" "June 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.2, lastmod: 2006-06-08
version: 0.8.2, lastmod: 2006-06-12
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -380,7 +380,12 @@ Instead of using \fB-httpdir\fR (see below) to specify
where the Java vncviewer applet is, have x11vnc try
to *guess* where the directory is by looking relative
to the program location and in standard locations
(/usr/local/share/x11vnc/classes, etc).
(/usr/local/share/x11vnc/classes, etc). Under \fB-ssl\fR or
\fB-stunnel\fR the ssl classes subdirectory is sought.
.PP
\fB-http_ssl\fR
.IP
As \fB-http,\fR but force lookup for ssl classes subdir.
.PP
\fB-connect\fR \fIstring\fR
.IP
......@@ -718,9 +723,22 @@ switch to the user as well. Note: there will be a 2nd
SSL helper process that will not switch, but it is only
encoding and decoding the stream at that point.
.IP
As a special case, WAIT:cmd=FINDDISPLAY will run a
script that works on most Unixes to determine a user's
DISPLAY variable and xauthority data. this is TBD.
As a special case, WAIT:cmd=FINDDISPLAY will run
a script that works on most Unixes to determine a
user's DISPLAY variable and xauthority data. To have
this default script printed to stdout (e.g. for
customization) run with WAIT:cmd=FINDDISPLAY-print
.IP
As another special case, WAIT:cmd=HTTPONCE will allow
x11vnc to service one http request and then exit.
This is usually done in \fB-inetd\fR mode to run on, say,
port 5800 and allow the Java vncviewer to be downloaded
by client web browsers. For example:
.IP
5815 stream tcp nowait root /usr/sbin/tcpd .../x11vnc \\
\fB-inetd\fR \fB-q\fR \fB-http_ssl\fR \fB-display\fR WAIT:cmd=HTTPONCE
.IP
Is used in the Apache SSL-portal example (see FAQ).
.IP
Finally, one can insert a geometry between colons,
e.g. WAIT:1280x1024:... to set the size of the display
......@@ -1274,9 +1292,6 @@ use it with \fB-passwdfile;\fR otherwise, prompt the user
for a password to create ~/.vnc/passwd and use it with
the \fB-rfbauth\fR option. If none of these succeed x11vnc
exits immediately.
.IP
Note: \fB-unixpw\fR currently does not count as a password
method by this option.
.PP
\fB-storepasswd\fR \fIpass\fR \fIfile\fR
.IP
......
......@@ -148,13 +148,10 @@
* main routine for the x11vnc program
*/
static void check_cursor_changes(void);
static void record_last_fb_update(void);
static int choose_delay(double dt);
static void watch_loop(void);
static char *choose_title(char *display);
static int limit_shm(void);
static void check_rcfile(int argc, char **argv);
static void immediate_switch_user(int argc, char* argv[]);
......@@ -581,36 +578,6 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
}
}
/*
* choose a desktop name
*/
static char *choose_title(char *display) {
static char title[(MAXN+10)];
strcpy(title, "x11vnc");
if (display == NULL) {
display = getenv("DISPLAY");
}
if (display == NULL) {
return title;
}
title[0] = '\0';
if (display[0] == ':') {
if (this_host() != NULL) {
strncpy(title, this_host(), MAXN - strlen(title));
}
}
strncat(title, display, MAXN - strlen(title));
if (subwin && valid_window(subwin, NULL, 0)) {
char *name;
if (dpy && XFetchName(dpy, subwin, &name)) {
strncat(title, " ", MAXN - strlen(title));
strncat(title, name, MAXN - strlen(title));
}
}
return title;
}
/*
* check blacklist for OSs with tight shm limits.
*/
......@@ -1193,6 +1160,7 @@ static void print_settings(int try_http, int bg, char *gui_str) {
fprintf(stderr, " safer: %d\n", more_safe);
fprintf(stderr, " nocmds: %d\n", no_external_cmds);
fprintf(stderr, " deny_all: %d\n", deny_all);
fprintf(stderr, " pid: %d\n", getpid());
fprintf(stderr, "\n");
#endif
rfbLog("x11vnc version: %s\n", lastmod);
......@@ -1371,7 +1339,7 @@ static void store_homedir_passwd(char *file) {
#define SHOW_NO_PASSWORD_WARNING \
(!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) \
&& !query_cmd && !remote_cmd && !unixpw && !got_gui_pw \
&& ! ssl_verify)
&& ! ssl_verify && !inetd)
int main(int argc, char* argv[]) {
......@@ -1393,7 +1361,8 @@ int main(int argc, char* argv[]) {
XImage *fb0 = NULL;
/* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc = 1; char *argv_vnc[128];
int argc_vnc_max = 1024;
int argc_vnc = 1; char *argv_vnc[2048];
/* check for -loop mode: */
check_loop_mode(argc, argv);
......@@ -1472,6 +1441,13 @@ int main(int argc, char* argv[]) {
if (!strcmp(arg, "-display")) {
CHECK_ARGC
use_dpy = strdup(argv[++i]);
if (strstr(use_dpy, "WAIT")) {
extern find_display[];
if (strstr(use_dpy, "cmd=FINDDISPLAY-print")) {
fprintf(stdout, "%s", find_display);
exit(0);
}
}
} else if (!strcmp(arg, "-auth") || !strcmp(arg, "-xauth")) {
CHECK_ARGC
auth_file = strdup(argv[++i]);
......@@ -1568,6 +1544,9 @@ int main(int argc, char* argv[]) {
filexfer = 1;
} else if (!strcmp(arg, "-http")) {
try_http = 1;
} else if (!strcmp(arg, "-http_ssl")) {
try_http = 1;
http_ssl = 1;
} else if (!strcmp(arg, "-connect")) {
CHECK_ARGC
if (strchr(argv[++i], '/')) {
......@@ -2239,8 +2218,11 @@ int main(int argc, char* argv[]) {
listen_str = strdup(argv[i+1]);
}
/* otherwise copy it for libvncserver use below. */
if (argc_vnc < 100) {
if (argc_vnc < argc_vnc_max) {
argv_vnc[argc_vnc++] = strdup(arg);
} else {
rfbLog("too many arguments.\n");
exit(1);
}
}
}
......@@ -2340,7 +2322,7 @@ int main(int argc, char* argv[]) {
}
}
if (usepw && ! got_rfbauth && ! got_passwd && ! got_passwdfile) {
if (usepw && ! got_rfbauth && ! got_passwd && ! got_passwdfile && !unixpw) {
char *f, *h = getenv("HOME");
struct stat sbuf;
int found = 0, set_rfbauth = 0;
......@@ -2523,7 +2505,11 @@ int main(int argc, char* argv[]) {
" -unixpw\n");
rfbLog("mode, assuming your SSH encryption"
" is: %s\n", s);
rfbLog("Setting -localhost in SSH + -unixpw"
" mode.\n");
fprintf(stderr, "\n");
allow_list = strdup("127.0.0.1");
got_localhost = 1;
if (! nopw) {
usleep(2000*1000);
}
......@@ -2536,7 +2522,8 @@ int main(int argc, char* argv[]) {
rfbLog("set -ssl in -unixpw mode.\n");
use_openssl = 1;
} else if (inetd) {
rfbLog("could not set -ssl in -inetd + -unixpw mode.\n");
rfbLog("could not set -ssl in -inetd"
" + -unixpw mode.\n");
exit(1);
} else {
rfbLog("set -stunnel in -unixpw mode.\n");
......
......@@ -287,6 +287,7 @@ extern int h_errno;
__FreeBSD__
__NetBSD__
__linux__
(defined(__MACH__) && defined(__APPLE__))
_AIX
*/
......
......@@ -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.2 lastmod: 2006-06-08";
char lastmod[] = "0.8.2 lastmod: 2006-06-12";
/* X display info */
......@@ -150,4 +150,3 @@ char *program_cmdline = NULL;
struct utsname UT;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment