x11vnc: improve SSL Java viewer, cleanup -unixpw code.

pull/1/head
runge 18 years ago
parent b9688bb38d
commit 6f47809af2

Binary file not shown.

Binary file not shown.

@ -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-06-12 00:00:28.000000000 -0400
@@ -0,0 +1,1276 @@
+++ vnc_javasrc/SSLSocketToMe.java 2006-09-23 18:35:25.000000000 -0400
@@ -0,0 +1,1301 @@
+/*
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
+ *
@ -408,8 +408,14 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ public void check_for_proxy() {
+
+ boolean result = false;
+ String ustr = "https://" + host + ":" + port;
+ String ustr = "https://" + host + ":";
+ if (viewer.httpsPort != null) {
+ ustr += viewer.httpsPort;
+ } else {
+ ustr += port; // hmmm
+ }
+ ustr += viewer.urlPrefix + "/check.https.proxy.connection";
+ dbg("ustr is: " + ustr);
+
+ trusturlCerts = null;
+ proxy_in_use = false;
@ -429,6 +435,11 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ https.connect();
+
+ trusturlCerts = https.getServerCertificates();
+ if (trusturlCerts == null) {
+ dbg("set trusturlCerts to null...");
+ } else {
+ dbg("set trusturlCerts to non-null");
+ }
+
+ if (https.usingProxy()) {
+ proxy_in_use = true;
@ -485,9 +496,14 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ */
+ check_for_proxy();
+
+ if (use_url_cert_for_auth && trusturlCerts != null) {
+ if (viewer.trustAllVncCerts) {
+ dbg("viewer.trustAllVncCerts-0 using trustall_ctx");
+ factory = trustall_ctx.getSocketFactory();
+ } else if (use_url_cert_for_auth && trusturlCerts != null) {
+ dbg("using trusturl_ctx");
+ factory = trusturl_ctx.getSocketFactory();
+ } else {
+ dbg("using trustloc_ctx");
+ factory = trustloc_ctx.getSocketFactory();
+ }
+
@ -528,7 +544,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ SSLSession sess = socket.getSession();
+ currentTrustedCerts = sess.getPeerCertificates();
+
+ if (currentTrustedCerts == null || currentTrustedCerts.length < 1) {
+ if (viewer.trustAllVncCerts) {
+ dbg("viewer.trustAllVncCerts-1");
+ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) {
+ socket.close();
+ socket = null;
+ throw new SSLHandshakeException("no current certs");
@ -542,16 +560,21 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ ;
+ }
+
+ bcd = new BrowserCertsDialog(serv, host + ":" + port);
+ bcd.queryUser();
+ if (bcd.showCertDialog) {
+ String msg = "user wants to see cert";
+ dbg(msg);
+ user_wants_to_see_cert = true;
+ throw new SSLHandshakeException(msg);
+ } else {
+ if (viewer.trustAllVncCerts) {
+ dbg("viewer.trustAllVncCerts-2");
+ user_wants_to_see_cert = false;
+ dbg("bcd: user said yes, accept it");
+ } else {
+ bcd = new BrowserCertsDialog(serv, host + ":" + port);
+ bcd.queryUser();
+ if (bcd.showCertDialog) {
+ String msg = "user wants to see cert";
+ dbg(msg);
+ user_wants_to_see_cert = true;
+ throw new SSLHandshakeException(msg);
+ } else {
+ user_wants_to_see_cert = false;
+ dbg("bcd: user said yes, accept it");
+ }
+ }
+
+ } catch (SSLHandshakeException eh) {
@ -586,7 +609,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ "Peer Certificate");
+ }
+
+ if (! browser_cert_match()) {
+ if (viewer.trustAllVncCerts) {
+ dbg("viewer.trustAllVncCerts-3");
+ } else if (! browser_cert_match()) {
+ /*
+ * close socket now, we will reopen after
+ * dialog if user agrees to use the cert.
@ -636,7 +661,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ }
+ }
+
+ if (socket != null && viewer.GET != null) {
+ if (socket != null && viewer.GET) {
+ String str = "GET ";
+ str += viewer.urlPrefix;
+ str += "/request.https.vnc.connection";
@ -1353,21 +1378,23 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+}
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-04-16 11:21:13.000000000 -0400
@@ -88,6 +88,12 @@
+++ vnc_javasrc/VncViewer.java 2006-09-23 18:36:42.000000000 -0400
@@ -88,6 +88,14 @@
int deferCursorUpdates;
int deferUpdateRequests;
+ boolean disableSSL;
+ String GET;
+ boolean GET;
+ String CONNECT;
+ String urlPrefix;
+ String httpsPort;
+ boolean forceProxy;
+ boolean trustAllVncCerts;
+
// Reference to this applet for inter-applet communication.
public static java.applet.Applet refApplet;
@@ -626,6 +632,39 @@
@@ -626,6 +634,51 @@
// SocketFactory.
socketFactory = readParameter("SocketFactory", false);
@ -1378,31 +1405,43 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView
+ if (str != null && str.equalsIgnoreCase("Yes"))
+ disableSSL = true;
+
+ httpsPort = readParameter("httpsPort", false);
+
+ // Extra GET, CONNECT string:
+ CONNECT = readParameter("CONNECT", false);
+ if (CONNECT != null) {
+ CONNECT = CONNECT.replaceAll(" ", ":");
+ }
+ GET = readParameter("GET", false);
+ urlPrefix = "";
+ if (GET != null) {
+ GET = GET.replaceAll("%2F", "/");
+ GET = GET.replaceAll("%2f", "/");
+ GET = GET.replaceAll("_2F_", "/");
+ if (! GET.equals("1")) {
+ if (GET.indexOf("/") != 0) {
+ urlPrefix += "/";
+ }
+ urlPrefix += GET;
+
+ GET = false;
+ str = readParameter("GET", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ GET = true;
+ }
+ if (str != null && str.equalsIgnoreCase("1")) {
+ GET = true;
+ }
+
+ urlPrefix = readParameter("urlPrefix", false);
+ if (urlPrefix != null) {
+ urlPrefix = urlPrefix.replaceAll("%2F", "/");
+ urlPrefix = urlPrefix.replaceAll("%2f", "/");
+ urlPrefix = urlPrefix.replaceAll("_2F_", "/");
+ if (urlPrefix.indexOf("/") != 0) {
+ urlPrefix = "/" + urlPrefix;
+ }
+ }
+ urlPrefix = urlPrefix.replaceAll("%2f", "/");
+ System.out.println("urlPrefix: " + urlPrefix);
+
+ forceProxy = false;
+ str = readParameter("forceProxy", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ forceProxy = true;
+ }
+ trustAllVncCerts = false;
+ str = readParameter("trustAllVncCerts", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ trustAllVncCerts = true;
+ }
}

@ -1,3 +1,8 @@
2006-09-23 Karl Runge <runge@karlrunge.com>
* Java viewer: improvements to connection response, faster
connections.
* x11vnc: some cleanup for -unixpw login process.
2006-09-20 Karl Runge <runge@karlrunge.com>
* x11vnc: -unixpw_cmd, -passwfile cmd:/custom:, -sslnofail,
-ultrafilexfer

File diff suppressed because it is too large Load Diff

@ -1048,7 +1048,7 @@ static unsigned char t2x2_bits[] = {
char *ip = addr;
char *type = "accept";
if (unixpw && strstr(userhost, "UNIX:") != userhost) {
type = "unixpw";
type = "UNIXPW";
if (openssl_last_ip) {
ip = openssl_last_ip;
}
@ -2007,7 +2007,6 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
}
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) {
@ -2016,7 +2015,7 @@ if (getenv("NEW_CLIENT")) fprintf(stderr, "new_client: %s %d\n", client->host, c
return(RFB_CLIENT_REFUSE);
}
}
if (unixpw && unixpw_in_progress) {
if (unixpw_in_progress) {
rfbLog("denying additional client: %s during -unixpw login.\n",
client->host);
return(RFB_CLIENT_REFUSE);
@ -2052,7 +2051,6 @@ if (getenv("NEW_CLIENT")) fprintf(stderr, "new_client: %s %d\n", client->host, c
cd->ssl_helper_pid = 0;
if (use_openssl && 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;
}
@ -2086,7 +2084,6 @@ if (0) fprintf(stderr, "SET ssl_helper_pid: %d\n", openssl_last_helper_pid);
cd->uid = clients_served;
client->clientGoneHook = client_gone;
if (client_count) {
@ -2131,8 +2128,10 @@ if (0) fprintf(stderr, "SET ssl_helper_pid: %d\n", openssl_last_helper_pid);
client->viewOnly = FALSE;
}
unixpw_last_try_time = time(NULL);
unixpw_screen(1);
unixpw_keystroke(0, 0, 1);
if (!unixpw_in_rfbPE) {
rfbLog("new client: %s in non-unixpw_in_rfbPE.\n",
client->host);

@ -513,8 +513,10 @@ void print_help(int mode) {
"-unixpw [list] Use Unix username and password authentication. x11vnc\n"
" uses the su(1) program to verify the user's password.\n"
" [list] is an optional comma separated list of allowed\n"
" Unix usernames. See below for per-user options that\n"
" can be applied.\n"
" Unix usernames. If the [list] string begins with the\n"
" character \"!\" then the entire list is taken as an\n"
" exclude list. See below for per-user options that can\n"
" be applied.\n"
"\n"
" A familiar \"login:\" and \"Password:\" dialog is\n"
" presented to the user on a black screen inside the\n"
@ -613,11 +615,14 @@ void print_help(int mode) {
" \"deny\", e.g. \"karl,wally:viewonly,boss:input=M\".\n"
" For \"input=\" it is the K,M,B,C described under -input.\n"
"\n"
" If a user in the list is \"*\" that means those\n"
" If an item in the list is \"*\" that means those\n"
" options apply to all users. It also means all users\n"
" are allowed to log in after supplying a valid password.\n"
" Use \"deny\" to explicitly deny some users if you use\n"
" \"*\" to set a global option.\n"
" \"*\" to set a global option. If [list] begins with\n"
" the \"!\" character then \"*\" is ignored for checking\n"
" if the user is allowed, but the any value of options\n"
" associated with it does apply as normal.\n"
"\n"
" There are also some utilities for testing password\n"
" if [list] starts with the \"%\" character. See the\n"
@ -656,11 +661,15 @@ void print_help(int mode) {
" line of its stdin will the username and the second line\n"
" the received password. If the command exits with status\n"
" 0 (success) the VNC client will be accepted. It will be\n"
" rejected for any other return status. Dynamic passwords\n"
" and non-unix passwords can be implemented this way by\n"
" providing your own custom helper program. Note that\n"
" under unixpw mode the remote viewer is given 3 tries\n"
" to enter the correct password.\n"
" rejected for any other return status.\n"
"\n"
" Dynamic passwords and non-unix passwords can be\n"
" implemented this way by providing your own custom helper\n"
" program. Note that under unixpw mode the remote viewer\n"
" is given 3 tries to enter the correct password.\n"
"\n"
" If a list of allowed users is needed use -unixpw [list]\n"
" in addition to this option.\n"
"\n"
#endif
"-display WAIT:... A special usage mode for the normal -display option.\n"
@ -2707,7 +2716,7 @@ void print_help(int mode) {
" @WxHxB at the end of the string.\n"
"\n"
" Examples:\n"
" -rawfb console (same as -rawfb console)\n"
" -rawfb console\n"
" -rawfb /dev/fb0 (same)\n"
" -rawfb console3 (force /dev/tty3)\n"
" -rawfb consolex (no keystrokes or mouse)\n"

@ -2680,20 +2680,19 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
if (debug_keyboard) {
char *str;
X_LOCK;
str = XKeysymToString(keysym);
str = XKeysymToString((KeySym) keysym);
X_UNLOCK;
rfbLog("# keyboard(%s, 0x%x \"%s\") uip=%d %.4f\n",
down ? "down":"up", (int) keysym, str ? str : "null",
unixpw_in_progress, tnow - x11vnc_start);
}
if (keysym <= 0) {
rfbLog("keyboard: skipping 0x0 keysym\n");
return;
}
if (unixpw && unixpw_in_progress) {
if (unixpw_in_progress) {
if (unixpw_denied) {
rfbLog("keyboard: ignoring keystroke 0x%x in "
"unixpw_denied=1 state\n", (int) keysym);
@ -2703,7 +2702,9 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
rfbLog("keyboard: skipping other client in unixpw\n");
return;
}
unixpw_keystroke(down, keysym, 0);
return;
}

@ -617,7 +617,6 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
if (mask >= 0) {
got_pointer_calls++;
}
get_allowed_input(client, &input);
if (debug_pointer && mask >= 0) {
static int show_motion = -1;
@ -643,10 +642,13 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
last_x = x;
last_y = y;
}
if (unixpw && unixpw_in_progress) {
if (unixpw_in_progress) {
return;
}
get_allowed_input(client, &input);
if (rotating) {
rotate_coords_inverse(x, y, &x, &y, -1, -1);
}

@ -1574,6 +1574,7 @@ void accept_openssl(int mode) {
* instead of a direct SSL connection.
*/
rfbLog("Handling VNC request via https GET. [%d]\n", getpid());
rfbLog("-- %s\n", buf);
if (strstr(buf, "/reverse.proxy")) {
char *buf2;
@ -1604,6 +1605,9 @@ void accept_openssl(int mode) {
"Content-Type: octet-stream\r\n"
"Pragma: no-cache\r\n\r\n";
rfbLog("Handling Check HTTPS request via https GET. [%d]\n", getpid());
rfbLog("-- %s\n", buf);
SSL_write(ssl, reply, strlen(reply));
SSL_shutdown(ssl);

@ -122,7 +122,9 @@ static rfbScreenInfo fscreen;
static rfbScreenInfoPtr pscreen;
void unixpw_screen(int init) {
if (unixpw_nis) {
if (unixpw_cmd) {
; /* OK */
} else if (unixpw_nis) {
#ifndef UNIXPW_CRYPT
rfbLog("-unixpw_nis is not supported on this OS/machine\n");
clean_up_exit(1);
@ -355,6 +357,79 @@ static void kill_child (pid_t pid, int fd) {
waitpid(pid, &status, WNOHANG);
}
static int scheck(char *str, int n, char *name) {
int j, i;
if (! str) {
return 0;
}
j = 0;
for (i=0; i<n; i++) {
if (str[i] == '\0') {
j = 1;
break;
}
if (!strcmp(name, "password")) {
if (str[i] == '\n') {
continue;
}
}
if (str[i] < ' ' || str[i] >= 0x7f) {
rfbLog("scheck: invalid character in %s.\n", name);
return 0;
}
}
if (j == 0) {
rfbLog("scheck: unterminated string in %s.\n", name);
return 0;
}
return 1;
}
int unixpw_list_match(char *user) {
if (! unixpw_list || unixpw_list[0] == '\0') {
return 1;
} else {
char *p, *q, *str = strdup(unixpw_list);
int ok = 0;
int notmode = 0;
if (str[0] == '!') {
notmode = 1;
ok = 1;
p = strtok(str+1, ",");
} else {
p = strtok(str, ",");
}
while (p) {
if ( (q = strchr(p, ':')) != NULL ) {
*q = '\0'; /* get rid of options. */
}
if (!strcmp(user, p)) {
if (notmode) {
ok = 0;
} else {
ok = 1;
}
break;
}
if (!notmode && !strcmp("*", p)) {
ok = 1;
break;
}
p = strtok(NULL, ",");
}
free(str);
if (! ok) {
rfbLog("unixpw_list_match: fail for '%s'\n", user);
return 0;
} else {
rfbLog("unixpw_list_match: OK for '%s'\n", user);
return 1;
}
}
}
int crypt_verify(char *user, char *pass) {
#ifndef UNIXPW_CRYPT
return 0;
@ -362,6 +437,17 @@ int crypt_verify(char *user, char *pass) {
struct passwd *pwd;
char *realpw, *cr;
int n;
if (! scheck(user, 100, "username")) {
return 0;
}
if (! scheck(pass, 100, "password")) {
return 0;
}
if (! unixpw_list_match(user)) {
return 0;
}
pwd = getpwnam(user);
if (! pwd) {
return 0;
@ -419,6 +505,17 @@ int cmd_verify(char *user, char *pass) {
if (! unixpw_cmd || *unixpw_cmd == '\0') {
return 0;
}
if (! scheck(user, 100, "username")) {
return 0;
}
if (! scheck(pass, 100, "password")) {
return 0;
}
if (! unixpw_list_match(user)) {
return 0;
}
if (unixpw_client) {
ClientData *cd = (ClientData *) unixpw_client->clientData;
if (cd) {
@ -464,33 +561,23 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size) {
pid_t pid, pidw;
struct stat sbuf;
static int first = 1;
char instr[32], buf[10];
char instr[32], cbuf[10];
if (first) {
set_db();
first = 0;
}
if (unixpw_list) {
char *p, *q, *str = strdup(unixpw_list);
int ok = 0;
p = strtok(str, ",");
while (p) {
if ( (q = strchr(p, ':')) != NULL ) {
*q = '\0'; /* get rid of options. */
}
if (!strcmp(user, p) || !strcmp("*", p)) {
ok = 1;
break;
}
p = strtok(NULL, ",");
}
free(str);
if (! ok) {
return 0;
}
if (! scheck(user, 100, "username")) {
return 0;
}
if (! scheck(pass, 100, "password")) {
return 0;
}
if (! unixpw_list_match(user)) {
return 0;
}
/* unixpw */
if (no_external_cmds || !cmd_ok("unixpw")) {
rfbLog("su_verify: cannot run external commands.\n");
@ -521,7 +608,7 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size) {
bin_true = "/usr/bin/true";
}
if (cmd != NULL && cmd[0] != '\0') {
/* this is for ext. cmd su -c "my cmd" */
/* this is for ext. cmd su -c "my cmd" after login */
bin_true = cmd;
}
if (bin_true == NULL) {
@ -536,7 +623,7 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size) {
return 0;
}
if (db) fprintf(stderr, "slave is: %s fd=%d\n", slave, fd);
if (db) fprintf(stderr, "slave is: %s fd=%d\n", slave, fd);
if (fd < 0) {
rfbLogPerror("get_pty fd < 0");
@ -618,7 +705,8 @@ if (db) fprintf(stderr, "slave is: %s fd=%d\n", slave, fd);
tfd = open("/tmp/isatty", O_CREAT|O_WRONLY, 0600);
if (isatty(sfd)) {
close(tfd);
sprintf(nam, "stty -a < %s > /tmp/isatty 2>&1", slave);
sprintf(nam, "stty -a < %s > /tmp/isatty 2>&1",
slave);
system(nam);
} else {
write(tfd, "NOTTTY\n", 7);
@ -630,11 +718,6 @@ if (db) fprintf(stderr, "slave is: %s fd=%d\n", slave, fd);
try_to_be_nobody();
#if LIBVNCSERVER_HAVE_GETUID
if (0 && db > 1) {
/* does not work, writes to pty... */
fprintf(stderr, "getuid=%d geteuid=%d\n",
getuid(), geteuid());
}
if (getuid() == 0 || geteuid() == 0) {
exit(1);
}
@ -648,7 +731,7 @@ if (db) fprintf(stderr, "slave is: %s fd=%d\n", slave, fd);
if (!cmd && getenv("DISPLAY")) {
/* this will cause timeout problems with pam_xauth */
char *s = getenv("DISPLAY");
if (s) *(s-2) = '_';
if (s) *(s-2) = '_'; /* quite... */
}
/* synchronize with parent: */
@ -677,11 +760,13 @@ if (db) fprintf(stderr, "slave is: %s fd=%d\n", slave, fd);
alarm(10);
/* synchronize with child: */
cbuf[0] = '\0';
cbuf[1] = '\0';
for (i=0; i<10; i++) {
int n;
buf[0] = '\0';
buf[1] = '\0';
n = read(fd, buf, 1);
cbuf[0] = '\0';
cbuf[1] = '\0';
n = read(fd, cbuf, 1);
if (n < 0 && errno == EINTR) {
continue;
} else {
@ -690,7 +775,7 @@ if (db) fprintf(stderr, "slave is: %s fd=%d\n", slave, fd);
}
if (db) {
fprintf(stderr, "read from child: '%s'\n", buf);
fprintf(stderr, "read from child: '%s'\n", cbuf);
}
alarm(0);
@ -728,42 +813,52 @@ if (db) fprintf(stderr, "slave is: %s fd=%d\n", slave, fd);
char pstr[] = "password:";
int n;
buf[0] = '\0';
buf[1] = '\0';
cbuf[0] = '\0';
cbuf[1] = '\0';
n = read(fd, buf, 1);
n = read(fd, cbuf, 1);
if (n < 0 && errno == EINTR) {
i--;
if (i < 0) i = 0;
continue;
}
if (db) fprintf(stderr, "%s", buf);
if (db > 3 && n == 1 && buf[0] == ':') {
char cmd0[32];
usleep( 100 * 1000 );
fprintf(stderr, "\n\n");
sprintf(cmd0, "ps wu %d", pid);
system(cmd0);
sprintf(cmd0, "stty -a < %s", slave);
system(cmd0);
fprintf(stderr, "\n\n");
if (db) {
fprintf(stderr, "%s", cbuf);
if (db > 3 && n == 1 && cbuf[0] == ':') {
char cmd0[32];
usleep( 100 * 1000 );
fprintf(stderr, "\n\n");
sprintf(cmd0, "ps wu %d", pid);
system(cmd0);
sprintf(cmd0, "stty -a < %s", slave);
system(cmd0);
fprintf(stderr, "\n\n");
}
}
if (n == 1) {
if (isspace((unsigned char) buf[0])) {
if (isspace((unsigned char) cbuf[0])) {
i--;
if (i < 0) i = 0;
continue;
}
instr[j++] = tolower((unsigned char)buf[0]);
if (j >= 32-1) {
rfbLog("su_verify: problem finding Password:\n");
return 0;
}
instr[j++] = tolower((unsigned char)cbuf[0]);
}
if (n <= 0 || strstr(pstr, instr) != pstr) {
if (db) {
fprintf(stderr, "\"Password:\" did not appear: '%s'" " n=%d\n", instr, n);
if (db > 3 && n == 1 && j < 32) {
continue;
}
}
if (db) {
fprintf(stderr, "\"Password:\" did not "
"appear: '%s'" " n=%d\n", instr, n);
if (db > 3 && n == 1 && j < 32) {
continue;
}
}
alarm(0);
signal(SIGALRM, SIG_DFL);
kill_child(pid, fd);
@ -806,26 +901,27 @@ if (db) {
for (i = 0; i< drain_size; i++) {
int n;
buf[0] = '\0';
buf[1] = '\0';
cbuf[0] = '\0';
cbuf[1] = '\0';
n = read(fd, buf, 1);
n = read(fd, cbuf, 1);
if (n < 0 && errno == EINTR) {
i--;
if (i < 0) i = 0;
continue;
}
if (db) fprintf(stderr, "%s", buf);
if (db) fprintf(stderr, "%s", cbuf);
if (n <= 0) {
break;
}
if (rbuf) {
rbuf[i] = buf[0];
rsize++;
if (rbuf && *rbuf_size > 0) {
rbuf[rsize++] = cbuf[0];
}
}
if (rbuf) {
if (rbuf && *rbuf_size > 0) {
char *s = rbuf;
char *p = strdup(pass);
int n, o = 0;
@ -861,9 +957,10 @@ if (db) fprintf(stderr, "%s", buf);
}
*rbuf_size = rsize;
strzero(p);
free(p);
}
if (db) fprintf(stderr, "\n");
if (db) fprintf(stderr, "\n");
alarm(0);
signal(SIGALRM, SIG_DFL);
@ -898,12 +995,14 @@ static void unixpw_verify(char *user, char *pass) {
int ok;
if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "********");
rfbLog("unixpw_verify: %s\n", user);
rfbLog("unixpw_verify: '%s'\n", user ? user : "(null)");
colon = strchr(user, ':');
if (user) {
colon = strchr(user, ':');
}
if (colon) {
*colon = '\0';
rfbLog("unixpw_verify: colon: %s\n", user);
rfbLog("unixpw_verify: colon: '%s'\n", user);
}
if (unixpw_client) {
cd = (ClientData *) unixpw_client->clientData;
@ -1007,7 +1106,7 @@ static void set_db(void) {
}
void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
int x, y, i, nmax = 100;
int x, y, i, rc, nmax = 100;
static char user_r[100], user[100], pass[100];
static int u_cnt = 0, p_cnt = 0, first = 1;
char keystr[100];
@ -1018,6 +1117,8 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
first = 0;
for (i=0; i < nmax; i++) {
user_r[i] = '\0';
user[i] = '\0';
pass[i] = '\0';
}
}
@ -1040,13 +1141,16 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
keep_unixpw_user = NULL;
}
if (keep_unixpw_pass) {
strzero(keep_unixpw_pass);
free(keep_unixpw_pass);
keep_unixpw_pass = NULL;
}
if (keep_unixpw_opts) {
strzero(keep_unixpw_opts);
free(keep_unixpw_opts);
keep_unixpw_opts = NULL;
}
return;
}
@ -1058,14 +1162,22 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
rfbLog("unixpw_keystroke: bad keysym1: 0x%x\n", (int) keysym);
return;
}
/* rfbKeySym = uint32_t */
/* KeySym = XID = CARD32 = (unsigned long or unsigned int on LONG64) */
X_LOCK;
str = XKeysymToString(keysym);
X_UNLOCK;
if (! str) {
if (str == NULL) {
rfbLog("unixpw_keystroke: bad keysym2: 0x%x\n", (int) keysym);
return;
}
snprintf(keystr, 100, "%s", str);
rc = snprintf(keystr, 100, "%s", str);
if (rc < 1 || rc > 90) {
rfbLog("unixpw_keystroke: bad keysym3: 0x%x\n", (int) keysym);
return;
}
if (db > 2) {
fprintf(stderr, "%s / %s 0x%x %s\n", in_login ? "login":"pass ",
@ -1073,7 +1185,10 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
}
if (keysym == XK_Return || keysym == XK_Linefeed) {
; /* let "up" pass down below for Return case */
/* let "up" pass down below for Return case */
if (down) {
return;
}
} else if (! down) {
return;
}
@ -1082,6 +1197,8 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
if (keysym == XK_BackSpace || keysym == XK_Delete) {
if (u_cnt > 0) {
user[u_cnt-1] = '\0';
u_cnt--;
x = text_x();
y = text_y();
if (scaling) {
@ -1102,10 +1219,11 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
y - char_h, x, y, 0);
}
char_col--;
u_cnt--;
}
return;
}
if (keysym == XK_Return || keysym == XK_Linefeed) {
char pw[] = "Password: ";
@ -1113,6 +1231,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
/*
* require Up so the Return Up is not processed
* by the normal session after login.
* (actually we already returned above)
*/
return;
}
@ -1135,8 +1254,10 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
} else {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
}
return;
}
if (u_cnt == 0 && keysym == XK_Up) {
/*
* Allow user to hit Up arrow at beginning to
@ -1144,28 +1265,39 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
*/
int i;
for (i=0; i < nmax; i++) {
user[i] = '\0';
}
for (i=0; i < nmax; i++) {
char str[10];
user[u_cnt++] = user_r[i];
if (user_r[i] == '\0') {
break;
}
keystr[0] = (char) user_r[i];
keystr[1] = '\0';
str[0] = (char) user_r[i];
str[1] = '\0';
x = text_x();
y = text_y();
rfbDrawString(pscreen, &default8x16Font, x, y,
keystr, white());
str, white());
mark_rect_as_modified(x, y-char_h, x+char_w,
y, scaling);
char_col++;
usleep(10*1000);
}
return;
}
if (keysym <= ' ' || keysym >= 0x7f) {
if (keysym < ' ' || keysym >= 0x7f) {
/* require normal keyboard characters for username */
rfbLog("unixpw_keystroke: bad keysym4: 0x%x\n", (int) keysym);
return;
}
if (u_cnt >= nmax - 1) {
rfbLog("unixpw_deny: username too long\n");
/* user[u_cnt=99] will be '\0' */
rfbLog("unixpw_deny: username too long: %d\n", u_cnt);
for (i=0; i<nmax; i++) {
user[i] = '\0';
pass[i] = '\0';
@ -1179,22 +1311,25 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
#else
user[u_cnt++] = (char) keysym;
for (i=0; i < nmax; i++) {
/* keep a full copy of username */
user_r[i] = user[i];
}
keystr[0] = (char) keysym;
#endif
keystr[1] = '\0';
x = text_x();
y = text_y();
if (db && db <= 2) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x %s\n", u_cnt, x, y, keysym, keystr);
if (db && db <= 2) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x '%s'\n", u_cnt, x, y, keysym, keystr);
keystr[1] = '\0';
rfbDrawString(pscreen, &default8x16Font, x, y, keystr, white());
mark_rect_as_modified(x, y-char_h, x+char_w, y, scaling);
char_col++;
return;
} else if (in_passwd) {
if (keysym == XK_BackSpace || keysym == XK_Delete) {
if (p_cnt > 0) {
@ -1208,11 +1343,14 @@ if (db && db <= 2) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x %s\n", u_cnt, x, y
/*
* require Up so the Return Up is not processed
* by the normal session after login.
* (actually we already returned above)
*/
return;
}
in_login = 0;
in_passwd = 0;
pass[p_cnt++] = '\n';
unixpw_verify(user, pass);
for (i=0; i<nmax; i++) {
@ -1221,11 +1359,16 @@ if (db && db <= 2) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x %s\n", u_cnt, x, y
}
return;
}
if (keysym <= ' ' || keysym >= 0x7f) {
if (keysym < ' ' || keysym >= 0x7f) {
/* require normal keyboard characters for password */
return;
}
if (p_cnt >= nmax - 2) {
rfbLog("unixpw_deny: password too long\n");
/* pass[u_cnt=98] will be '\n' */
/* pass[u_cnt=99] will be '\0' */
rfbLog("unixpw_deny: password too long: %d\n", p_cnt);
for (i=0; i<nmax; i++) {
user[i] = '\0';
pass[i] = '\0';
@ -1233,42 +1376,61 @@ if (db && db <= 2) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x %s\n", u_cnt, x, y
unixpw_deny();
return;
}
pass[p_cnt++] = (char) keysym;
return;
} else {
/* should not happen... clean up a bit. */
/* should not happen... anyway clean up a bit. */
u_cnt = 0;
p_cnt = 0;
for (i=0; i<nmax; i++) {
user_r[i] = '\0';
user[i] = '\0';
pass[i] = '\0';
}
return;
}
}
static void apply_opts (char *user) {
char *p, *q, *str, *opts = NULL, *opts_star = NULL;
ClientData *cd = (ClientData *) unixpw_client->clientData;
rfbClientPtr cl = unixpw_client;
int i;
rfbClientPtr cl;
ClientData *cd;
int i, notmode = 0;
if (! cd) {
if (! unixpw_list) {
return;
}
if (! unixpw_client) {
rfbLog("apply_opts: unixpw_client is NULL\n");
clean_up_exit(1);
}
cd = (ClientData *) unixpw_client->clientData;
cl = unixpw_client;
if (! cd) {
rfbLog("apply_opts: no ClientData\n");
}
if (user) {
if (user && cd) {
if (cd->unixname) {
free(cd->unixname);
}
cd->unixname = strdup(user);
}
if (! unixpw_list) {
return;
}
str = strdup(unixpw_list);
/* apply any per-user options. */
p = strtok(str, ",");
if (str[0] == '!') {
p = strtok(str+1, ",");
notmode = 1;
} else {
p = strtok(str, ",");
}
while (p) {
if ( (q = strchr(p, ':')) != NULL ) {
*q = '\0'; /* get rid of options. */
@ -1277,6 +1439,7 @@ static void apply_opts (char *user) {
continue;
}
if (user && !strcmp(user, p)) {
/* will not happen in notmode */
opts = strdup(q+1);
}
if (!strcmp("*", p)) {
@ -1295,13 +1458,19 @@ static void apply_opts (char *user) {
while (p) {
if (!strcmp(p, "viewonly")) {
cl->viewOnly = TRUE;
strncpy(cd->input, "-", CILEN);
if (cd) {
strncpy(cd->input, "-", CILEN);
}
} else if (!strcmp(p, "fullaccess")) {
cl->viewOnly = FALSE;
strncpy(cd->input, "-", CILEN);
if (cd) {
strncpy(cd->input, "-", CILEN);
}
} else if ((q = strstr(p, "input=")) == p) {
q += strlen("input=");
strncpy(cd->input, q, CILEN);
if (cd) {
strncpy(cd->input, q, CILEN);
}
} else if (!strcmp(p, "deny")) {
cl->viewOnly = TRUE;
unixpw_deny();

@ -2,7 +2,7 @@
.TH X11VNC "1" "September 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.3, lastmod: 2006-09-20
version: 0.8.3, lastmod: 2006-09-23
.SH SYNOPSIS
.B x11vnc
[OPTION]...
@ -617,8 +617,10 @@ uses the
.IR su (1)
program to verify the user's password.
[list] is an optional comma separated list of allowed
Unix usernames. See below for per-user options that
can be applied.
Unix usernames. If the [list] string begins with the
character "!" then the entire list is taken as an
exclude list. See below for per-user options that can
be applied.
.IP
A familiar "login:" and "Password:" dialog is
presented to the user on a black screen inside the
@ -727,11 +729,14 @@ where "opts" is a "+" separated list of
"deny", e.g. "karl,wally:viewonly,boss:input=M".
For "input=" it is the K,M,B,C described under \fB-input.\fR
.IP
If a user in the list is "*" that means those
If an item in the list is "*" that means those
options apply to all users. It also means all users
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.
"*" to set a global option. If [list] begins with
the "!" character then "*" is ignored for checking
if the user is allowed, but the any value of options
associated with it does apply as normal.
.IP
There are also some utilities for testing password
if [list] starts with the "%" character. See the
@ -784,11 +789,15 @@ run the externally supplied command \fIstr\fR. The first
line of its stdin will the username and the second line
the received password. If the command exits with status
0 (success) the VNC client will be accepted. It will be
rejected for any other return status. Dynamic passwords
and non-unix passwords can be implemented this way by
providing your own custom helper program. Note that
under unixpw mode the remote viewer is given 3 tries
to enter the correct password.
rejected for any other return status.
.IP
Dynamic passwords and non-unix passwords can be
implemented this way by providing your own custom helper
program. Note that under unixpw mode the remote viewer
is given 3 tries to enter the correct password.
.IP
If a list of allowed users is needed use \fB-unixpw\fR [list]
in addition to this option.
.PP
\fB-display\fR \fIWAIT:...\fR
.IP
@ -3182,7 +3191,7 @@ gives inaccurate information), specify them with a
@WxHxB at the end of the string.
.IP
Examples:
\fB-rawfb\fR console (same as \fB-rawfb\fR console)
\fB-rawfb\fR console
\fB-rawfb\fR /dev/fb0 (same)
\fB-rawfb\fR console3 (force /dev/tty3)
\fB-rawfb\fR consolex (no keystrokes or mouse)

@ -460,7 +460,7 @@ static void watch_loop(void) {
if (! use_threads) {
dtime0(&tm);
if (! skip_pe) {
if (unixpw && unixpw_in_progress) {
if (unixpw_in_progress) {
rfbClientPtr cl = unixpw_client;
if (cl && cl->onHold) {
rfbLog(msg, cl->host);
@ -490,17 +490,19 @@ static void watch_loop(void) {
unixpw_in_rfbPE = 0;
if (unixpw && unixpw_in_progress) {
if (unixpw_in_progress) {
/* rfbPE loop until logged in. */
skip_pe = 0;
check_new_clients();
continue;
} else {
measure_send_rates(0);
fb_update_sent(NULL);
}
} else {
if (unixpw && unixpw_in_progress) {
if (unixpw_in_progress) {
skip_pe = 0;
check_new_clients();
continue;
}
}
@ -528,12 +530,6 @@ static void watch_loop(void) {
eat_viewonly_input(10, 3);
}
} else {
#if 0
if (0 && use_xrecord) {
/* XXX not working */
check_xrecord();
}
#endif
if (wireframe && button_mask) {
check_wireframe();
}
@ -544,7 +540,10 @@ static void watch_loop(void) {
clean_up_exit(0);
}
if (unixpw_in_progress) continue;
if (unixpw_in_progress) {
check_new_clients();
continue;
}
if (! urgent_update) {
if (do_copy_screen) {

@ -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.3 lastmod: 2006-09-20";
char lastmod[] = "0.8.3 lastmod: 2006-09-23";
/* X display info */

Loading…
Cancel
Save