diff options
author | runge <runge> | 2006-09-24 00:08:42 +0000 |
---|---|---|
committer | runge <runge> | 2006-09-24 00:08:42 +0000 |
commit | 6f47809af2e44e28d9f97c11b26726e62ee2654f (patch) | |
tree | d2b3913ee11b81f7cf65cbe0b1bf31182e5c0e72 /x11vnc/unixpw.c | |
parent | b9688bb38d00bbc77a54464dabc7aa6313404f0c (diff) | |
download | libtdevnc-6f47809af2e44e28d9f97c11b26726e62ee2654f.tar.gz libtdevnc-6f47809af2e44e28d9f97c11b26726e62ee2654f.zip |
x11vnc: improve SSL Java viewer, cleanup -unixpw code.
Diffstat (limited to 'x11vnc/unixpw.c')
-rw-r--r-- | x11vnc/unixpw.c | 361 |
1 files changed, 265 insertions, 96 deletions
diff --git a/x11vnc/unixpw.c b/x11vnc/unixpw.c index c40d5d6..a14b831 100644 --- a/x11vnc/unixpw.c +++ b/x11vnc/unixpw.c @@ -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(); |