diff options
Diffstat (limited to 'x11vnc/user.c')
-rw-r--r-- | x11vnc/user.c | 3155 |
1 files changed, 0 insertions, 3155 deletions
diff --git a/x11vnc/user.c b/x11vnc/user.c deleted file mode 100644 index f09fbb9..0000000 --- a/x11vnc/user.c +++ /dev/null @@ -1,3155 +0,0 @@ -/* - Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com> - All rights reserved. - -This file is part of x11vnc. - -x11vnc 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; either version 2 of the License, or (at -your option) any later version. - -x11vnc 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 x11vnc; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA -or see <http://www.gnu.org/licenses/>. - -In addition, as a special exception, Karl J. Runge -gives permission to link the code of its release of x11vnc with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. -*/ - -/* -- user.c -- */ - -#include "x11vnc.h" -#include "solid.h" -#include "cleanup.h" -#include "scan.h" -#include "screen.h" -#include "unixpw.h" -#include "sslhelper.h" -#include "xwrappers.h" -#include "connections.h" -#include "inet.h" -#include "keyboard.h" -#include "cursor.h" -#include "remote.h" -#include "sslhelper.h" -#include "avahi.h" - -void check_switched_user(void); -void lurk_loop(char *str); -int switch_user(char *user, int fb_mode); -int read_passwds(char *passfile); -void install_passwds(void); -void check_new_passwds(int force); -void progress_client(void); -int wait_for_client(int *argc, char** argv, int http); -rfbBool custom_passwd_check(rfbClientPtr cl, const char *response, int len); -char *xdmcp_insert = NULL; - -static void switch_user_task_dummy(void); -static void switch_user_task_solid_bg(void); -static char *get_login_list(int with_display); -static char **user_list(char *user_str); -static void user2uid(char *user, uid_t *uid, gid_t *gid, char **name, char **home); -static int lurk(char **users); -static int guess_user_and_switch(char *str, int fb_mode); -static int try_user_and_display(uid_t uid, gid_t gid, char *dpystr); -static int switch_user_env(uid_t uid, gid_t gid, char *name, char *home, int fb_mode); -static void try_to_switch_users(void); - - -/* tasks for after we switch */ -static void switch_user_task_dummy(void) { - ; /* dummy does nothing */ -} -static void switch_user_task_solid_bg(void) { - /* we have switched users, some things to do. */ - if (use_solid_bg && client_count) { - solid_bg(0); - } -} - -void check_switched_user(void) { - static time_t sched_switched_user = 0; - static int did_solid = 0; - static int did_dummy = 0; - int delay = 15; - time_t now = time(NULL); - - if (unixpw_in_progress) return; - - if (started_as_root == 1 && users_list) { - try_to_switch_users(); - if (started_as_root == 2) { - /* - * schedule the switch_user_tasks() call - * 15 secs is for piggy desktops to start up. - * might not be enough for slow machines... - */ - sched_switched_user = now; - did_dummy = 0; - did_solid = 0; - /* add other activities */ - } - } - if (! sched_switched_user) { - return; - } - - if (! did_dummy) { - switch_user_task_dummy(); - did_dummy = 1; - } - if (! did_solid) { - int doit = 0; - char *ss = solid_str; - if (now >= sched_switched_user + delay) { - doit = 1; - } else if (ss && strstr(ss, "root:") == ss) { - if (now >= sched_switched_user + 3) { - doit = 1; - } - } else if (strcmp("root", guess_desktop())) { - usleep(1000 * 1000); - doit = 1; - } - if (doit) { - switch_user_task_solid_bg(); - did_solid = 1; - } - } - - if (did_dummy && did_solid) { - sched_switched_user = 0; - } -} - -/* utilities for switching users */ -static char *get_login_list(int with_display) { - char *out; -#if LIBVNCSERVER_HAVE_UTMPX_H - int i, cnt, max = 200, ut_namesize = 32; - int dpymax = 1000, sawdpy[1000]; - struct utmpx *utx; - - /* size based on "username:999," * max */ - out = (char *) malloc(max * (ut_namesize+1+3+1) + 1); - out[0] = '\0'; - - for (i=0; i<dpymax; i++) { - sawdpy[i] = 0; - } - - setutxent(); - cnt = 0; - while (1) { - char *user, *line, *host, *id; - char tmp[10]; - int d = -1; - utx = getutxent(); - if (! utx) { - break; - } - if (utx->ut_type != USER_PROCESS) { - continue; - } - user = lblanks(utx->ut_user); - if (*user == '\0') { - continue; - } - if (strchr(user, ',')) { - continue; /* unlikely, but comma is our sep. */ - } - - line = lblanks(utx->ut_line); - host = lblanks(utx->ut_host); - id = lblanks(utx->ut_id); - - if (with_display) { - if (0 && line[0] != ':' && strcmp(line, "dtlocal")) { - /* XXX useful? */ - continue; - } - - if (line[0] == ':') { - if (sscanf(line, ":%d", &d) != 1) { - d = -1; - } - } - if (d < 0 && host[0] == ':') { - if (sscanf(host, ":%d", &d) != 1) { - d = -1; - } - } - if (d < 0 && id[0] == ':') { - if (sscanf(id, ":%d", &d) != 1) { - d = -1; - } - } - - if (d < 0 || d >= dpymax || sawdpy[d]) { - continue; - } - sawdpy[d] = 1; - sprintf(tmp, ":%d", d); - } else { - /* try to eliminate repeats */ - int repeat = 0; - char *q; - - q = out; - while ((q = strstr(q, user)) != NULL) { - char *p = q + strlen(user) + strlen(":DPY"); - if (q == out || *(q-1) == ',') { - /* bounded on left. */ - if (*p == ',' || *p == '\0') { - /* bounded on right. */ - repeat = 1; - break; - } - } - q = p; - } - if (repeat) { - continue; - } - sprintf(tmp, ":DPY"); - } - - if (*out) { - strcat(out, ","); - } - strcat(out, user); - strcat(out, tmp); - - cnt++; - if (cnt >= max) { - break; - } - } - endutxent(); -#else - out = strdup(""); -#endif - return out; -} - -static char **user_list(char *user_str) { - int n, i; - char *p, **list; - - p = user_str; - n = 1; - while (*p++) { - if (*p == ',') { - n++; - } - } - list = (char **) calloc((n+1)*sizeof(char *), 1); - - p = strtok(user_str, ","); - i = 0; - while (p) { - list[i++] = strdup(p); - p = strtok(NULL, ","); - } - list[i] = NULL; - return list; -} - -static void user2uid(char *user, uid_t *uid, gid_t *gid, char **name, char **home) { - int numerical = 1, gotgroup = 0; - char *q; - - *uid = (uid_t) -1; - *name = NULL; - *home = NULL; - - q = user; - while (*q) { - if (! isdigit((unsigned char) (*q++))) { - numerical = 0; - break; - } - } - - if (user2group != NULL) { - static int *did = NULL; - int i; - - if (did == NULL) { - int n = 0; - i = 0; - while (user2group[i] != NULL) { - n++; - i++; - } - did = (int *) malloc((n+1) * sizeof(int)); - i = 0; - for (i=0; i<n; i++) { - did[i] = 0; - } - } - i = 0; - while (user2group[i] != NULL) { - if (strstr(user2group[i], user) == user2group[i]) { - char *w = user2group[i] + strlen(user); - if (*w == '.') { -#if (SMALL_FOOTPRINT > 2) - gotgroup = 0; -#else - struct group* gr = getgrnam(++w); - if (! gr) { - rfbLog("Invalid group: %s\n", w); - clean_up_exit(1); - } - *gid = gr->gr_gid; - if (! did[i]) { - rfbLog("user2uid: using group %s (%d) for %s\n", - w, (int) *gid, user); - did[i] = 1; - } - gotgroup = 1; -#endif - } - } - i++; - } - } - - if (numerical) { - int u = atoi(user); - - if (u < 0) { - return; - } - *uid = (uid_t) u; - } - -#if LIBVNCSERVER_HAVE_PWD_H - if (1) { - struct passwd *pw; - if (numerical) { - pw = getpwuid(*uid); - } else { - pw = getpwnam(user); - } - if (pw) { - *uid = pw->pw_uid; - if (! gotgroup) { - *gid = pw->pw_gid; - } - *name = pw->pw_name; /* n.b. use immediately */ - *home = pw->pw_dir; - } - } -#endif -} - - -static int lurk(char **users) { - uid_t uid; - gid_t gid; - int success = 0, dmin = -1, dmax = -1; - char *p, *logins, **u; - char **list; - int lind; - - if ((u = users) != NULL && *u != NULL && *(*u) == ':') { - int len; - char *tmp; - - /* extract min and max display numbers */ - tmp = *u; - if (strchr(tmp, '-')) { - if (sscanf(tmp, ":%d-%d", &dmin, &dmax) != 2) { - dmin = -1; - dmax = -1; - } - } - if (dmin < 0) { - if (sscanf(tmp, ":%d", &dmin) != 1) { - dmin = -1; - dmax = -1; - } else { - dmax = dmin; - } - } - if ((dmin < 0 || dmax < 0) || dmin > dmax || dmax > 10000) { - dmin = -1; - dmax = -1; - } - - /* get user logins regardless of having a display: */ - logins = get_login_list(0); - - /* - * now we append the list in users (might as well try - * them) this will probably allow weird ways of starting - * xservers to work. - */ - len = strlen(logins); - u++; - while (*u != NULL) { - len += strlen(*u) + strlen(":DPY,"); - u++; - } - tmp = (char *) malloc(len+1); - strcpy(tmp, logins); - - /* now concatenate them: */ - u = users+1; - while (*u != NULL) { - char *q, chk[100]; - snprintf(chk, 100, "%s:DPY", *u); - q = strstr(tmp, chk); - if (q) { - char *p = q + strlen(chk); - - if (q == tmp || *(q-1) == ',') { - /* bounded on left. */ - if (*p == ',' || *p == '\0') { - /* bounded on right. */ - u++; - continue; - } - } - } - - if (*tmp) { - strcat(tmp, ","); - } - strcat(tmp, *u); - strcat(tmp, ":DPY"); - u++; - } - free(logins); - logins = tmp; - - } else { - logins = get_login_list(1); - } - - list = (char **) calloc((strlen(logins)+2)*sizeof(char *), 1); - lind = 0; - p = strtok(logins, ","); - while (p) { - list[lind++] = strdup(p); - p = strtok(NULL, ","); - } - free(logins); - - lind = 0; - while (list[lind] != NULL) { - char *user, *name, *home, dpystr[10]; - char *q, *t; - int ok = 1, dn; - - p = list[lind++]; - - t = strdup(p); /* bob:0 */ - q = strchr(t, ':'); - if (! q) { - free(t); - break; - } - *q = '\0'; - user = t; - snprintf(dpystr, 10, ":%s", q+1); - - if (users) { - u = users; - ok = 0; - while (*u != NULL) { - if (*(*u) == ':') { - u++; - continue; - } - if (!strcmp(user, *u++)) { - ok = 1; - break; - } - } - } - - user2uid(user, &uid, &gid, &name, &home); - free(t); - - if (! uid || ! gid) { - ok = 0; - } - - if (! ok) { - continue; - } - - for (dn = dmin; dn <= dmax; dn++) { - if (dn >= 0) { - sprintf(dpystr, ":%d", dn); - } - if (try_user_and_display(uid, gid, dpystr)) { - if (switch_user_env(uid, gid, name, home, 0)) { - rfbLog("lurk: now user: %s @ %s\n", - name, dpystr); - started_as_root = 2; - success = 1; - } - set_env("DISPLAY", dpystr); - break; - } - } - if (success) { - break; - } - } - - lind = 0; - while (list[lind] != NULL) { - free(list[lind]); - lind++; - } - - return success; -} - -void lurk_loop(char *str) { - char *tstr = NULL, **users = NULL; - - if (strstr(str, "lurk=") != str) { - exit(1); - } - rfbLog("lurking for logins using: '%s'\n", str); - if (strlen(str) > strlen("lurk=")) { - char *q = strchr(str, '='); - tstr = strdup(q+1); - users = user_list(tstr); - } - - while (1) { - if (lurk(users)) { - break; - } - sleep(3); - } - if (tstr) { - free(tstr); - } - if (users) { - free(users); - } -} - -static int guess_user_and_switch(char *str, int fb_mode) { - char *dstr, *d; - char *p, *tstr = NULL, *allowed = NULL, *logins, **users = NULL; - int dpy1, ret = 0; - char **list; - int lind; - - RAWFB_RET(0) - - d = DisplayString(dpy); - /* pick out ":N" */ - dstr = strchr(d, ':'); - if (! dstr) { - return 0; - } - if (sscanf(dstr, ":%d", &dpy1) != 1) { - return 0; - } - if (dpy1 < 0) { - return 0; - } - - if (strstr(str, "guess=") == str && strlen(str) > strlen("guess=")) { - allowed = strchr(str, '='); - allowed++; - - tstr = strdup(allowed); - users = user_list(tstr); - } - - /* loop over the utmpx entries looking for this display */ - logins = get_login_list(1); - - list = (char **) calloc((strlen(logins)+2)*sizeof(char *), 1); - lind = 0; - p = strtok(logins, ","); - while (p) { - list[lind++] = strdup(p); - p = strtok(NULL, ","); - } - - lind = 0; - while (list[lind] != NULL) { - char *user, *q, *t; - int dpy2, ok = 1; - - p = list[lind++]; - - t = strdup(p); - q = strchr(t, ':'); - if (! q) { - free(t); - break; - } - *q = '\0'; - user = t; - dpy2 = atoi(q+1); - - if (users) { - char **u = users; - ok = 0; - while (*u != NULL) { - if (!strcmp(user, *u++)) { - ok = 1; - break; - } - } - } - if (dpy1 != dpy2) { - ok = 0; - } - - if (! ok) { - free(t); - continue; - } - - if (switch_user(user, fb_mode)) { - rfbLog("switched to guessed user: %s\n", user); - free(t); - ret = 1; - break; - } - } - if (tstr) { - free(tstr); - } - if (users) { - free(users); - } - if (logins) { - free(logins); - } - return ret; -} - -static int try_user_and_display(uid_t uid, gid_t gid, char *dpystr) { - /* NO strtoks */ -#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_PWD_H - pid_t pid, pidw; - char *home, *name; - int st; - struct passwd *pw; - - pw = getpwuid(uid); - if (pw) { - name = pw->pw_name; - home = pw->pw_dir; - } else { - return 0; - } - - /* - * We fork here and try to open the display again as the - * new user. Unreadable XAUTHORITY could be a problem... - * This is not really needed since we have DISPLAY open but: - * 1) is a good indicator this user owns the session and 2) - * some activities do spawn new X apps, e.g. xmessage(1), etc. - */ - if ((pid = fork()) > 0) { - ; - } else if (pid == -1) { - fprintf(stderr, "could not fork\n"); - rfbLogPerror("fork"); - return 0; - } else { - /* child */ - Display *dpy2 = NULL; - int rc; - - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - - rc = switch_user_env(uid, gid, name, home, 0); - if (! rc) { - exit(1); - } - - fclose(stderr); - dpy2 = XOpenDisplay_wr(dpystr); - if (dpy2) { - XCloseDisplay_wr(dpy2); - exit(0); /* success */ - } else { - exit(2); /* fail */ - } - } - - /* see what the child says: */ - pidw = waitpid(pid, &st, 0); - if (pidw == pid && WIFEXITED(st) && WEXITSTATUS(st) == 0) { - return 1; - } -#endif /* LIBVNCSERVER_HAVE_FORK ... */ - return 0; -} - -int switch_user(char *user, int fb_mode) { - /* NO strtoks */ - int doit = 0; - uid_t uid = 0; - gid_t gid = 0; - char *name, *home; - - if (*user == '+') { - doit = 1; - user++; - } - - ssl_helper_pid(0, -2); /* waitall */ - - if (strstr(user, "guess=") == user) { - return guess_user_and_switch(user, fb_mode); - } - - user2uid(user, &uid, &gid, &name, &home); - - if (uid == (uid_t) -1 || uid == 0) { - return 0; - } - if (gid == 0) { - return 0; - } - - if (! doit && dpy) { - /* see if this display works: */ - char *dstr = DisplayString(dpy); - doit = try_user_and_display(uid, gid, dstr); - } - - if (doit) { - int rc = switch_user_env(uid, gid, name, home, fb_mode); - if (rc) { - started_as_root = 2; - } - return rc; - } else { - return 0; - } -} - -static int switch_user_env(uid_t uid, gid_t gid, char *name, char *home, int fb_mode) { - /* NO strtoks */ - char *xauth; - int reset_fb = 0; - int grp_ok = 0; - -#if !LIBVNCSERVER_HAVE_SETUID - return 0; -#else - /* - * OK, tricky here, we need to free the shm... otherwise - * we won't be able to delete it as the other user... - */ - if (fb_mode == 1 && (using_shm && ! xform24to32)) { - reset_fb = 1; - clean_shm(0); - free_tiles(); - } -#if LIBVNCSERVER_HAVE_INITGROUPS -#if LIBVNCSERVER_HAVE_PWD_H - if (getpwuid(uid) != NULL && getenv("X11VNC_SINGLE_GROUP") == NULL) { - struct passwd *p = getpwuid(uid); - /* another possibility is p->pw_gid instead of gid */ - if (setgid(gid) == 0 && initgroups(p->pw_name, gid) == 0) { - grp_ok = 1; - } else { - rfbLogPerror("initgroups"); - } - endgrent(); - } -#endif -#endif - if (! grp_ok) { - if (setgid(gid) == 0) { - grp_ok = 1; - } - } - if (! grp_ok) { - if (reset_fb) { - /* 2 means we did clean_shm and free_tiles */ - do_new_fb(2); - } - return 0; - } - - if (setuid(uid) != 0) { - if (reset_fb) { - /* 2 means we did clean_shm and free_tiles */ - do_new_fb(2); - } - return 0; - } -#endif - if (reset_fb) { - do_new_fb(2); - } - - xauth = getenv("XAUTHORITY"); - if (xauth && access(xauth, R_OK) != 0) { - *(xauth-2) = '_'; /* yow */ - } - - set_env("USER", name); - set_env("LOGNAME", name); - set_env("HOME", home); - return 1; -} - -static void try_to_switch_users(void) { - static time_t last_try = 0; - time_t now = time(NULL); - char *users, *p; - - if (getuid() && geteuid()) { - rfbLog("try_to_switch_users: not root\n"); - started_as_root = 2; - return; - } - if (!last_try) { - last_try = now; - } else if (now <= last_try + 2) { - /* try every 3 secs or so */ - return; - } - last_try = now; - - users = strdup(users_list); - - if (strstr(users, "guess=") == users) { - if (switch_user(users, 1)) { - started_as_root = 2; - } - free(users); - return; - } - - p = strtok(users, ","); - while (p) { - if (switch_user(p, 1)) { - started_as_root = 2; - rfbLog("try_to_switch_users: now %s\n", p); - break; - } - p = strtok(NULL, ","); - } - free(users); -} - -int read_passwds(char *passfile) { - char line[1024]; - char *filename; - char **old_passwd_list = passwd_list; - int linecount = 0, i, remove = 0, read_mode = 0, begin_vo = -1; - struct stat sbuf; - static int max = -1; - FILE *in = NULL; - static time_t last_read = 0; - static int read_cnt = 0; - int db_passwd = 0; - - if (max < 0) { - max = 1000; - if (getenv("X11VNC_MAX_PASSWDS")) { - max = atoi(getenv("X11VNC_MAX_PASSWDS")); - } - } - - filename = passfile; - if (strstr(filename, "rm:") == filename) { - filename += strlen("rm:"); - remove = 1; - } else if (strstr(filename, "read:") == filename) { - filename += strlen("read:"); - read_mode = 1; - if (stat(filename, &sbuf) == 0) { - if (sbuf.st_mtime <= last_read) { - return 1; - } - last_read = sbuf.st_mtime; - } - } else if (strstr(filename, "cmd:") == filename) { - int rc; - - filename += strlen("cmd:"); - read_mode = 1; - in = tmpfile(); - if (in == NULL) { - rfbLog("run_user_command tmpfile() failed: %s\n", - filename); - clean_up_exit(1); - } - rc = run_user_command(filename, latest_client, "read_passwds", - NULL, 0, in); - if (rc != 0) { - rfbLog("run_user_command command failed: %s\n", - filename); - clean_up_exit(1); - } - rewind(in); - } else if (strstr(filename, "custom:") == filename) { - return 1; - } - - if (in == NULL && stat(filename, &sbuf) == 0) { - /* (poor...) upper bound to number of lines */ - max = (int) sbuf.st_size; - last_read = sbuf.st_mtime; - } - - /* create 1 more than max to have it be the ending NULL */ - passwd_list = (char **) malloc( (max+1) * (sizeof(char *)) ); - for (i=0; i<max+1; i++) { - passwd_list[i] = NULL; - } - - if (in == NULL) { - in = fopen(filename, "r"); - } - if (in == NULL) { - rfbLog("cannot open passwdfile: %s\n", passfile); - rfbLogPerror("fopen"); - if (remove) { - unlink(filename); - } - clean_up_exit(1); - } - - if (getenv("DEBUG_PASSWDFILE") != NULL) { - db_passwd = 1; - } - - while (fgets(line, 1024, in) != NULL) { - char *p; - int blank = 1; - int len = strlen(line); - - if (db_passwd) { - fprintf(stderr, "read_passwds: raw line: %s\n", line); - } - - if (len == 0) { - continue; - } else if (line[len-1] == '\n') { - line[len-1] = '\0'; - } - if (line[0] == '\0') { - continue; - } - if (strstr(line, "__SKIP__") != NULL) { - continue; - } - if (strstr(line, "__COMM__") == line) { - continue; - } - if (!strcmp(line, "__BEGIN_VIEWONLY__")) { - if (begin_vo < 0) { - begin_vo = linecount; - } - continue; - } - if (line[0] == '#') { - /* commented out, cannot have password beginning with # */ - continue; - } - p = line; - while (*p != '\0') { - if (! isspace((unsigned char) (*p))) { - blank = 0; - break; - } - p++; - } - if (blank) { - continue; - } - - passwd_list[linecount++] = strdup(line); - if (db_passwd) { - fprintf(stderr, "read_passwds: keepline: %s\n", line); - fprintf(stderr, "read_passwds: begin_vo: %d\n", begin_vo); - } - - if (linecount >= max) { - rfbLog("read_passwds: hit max passwd: %d\n", max); - break; - } - } - fclose(in); - - for (i=0; i<1024; i++) { - line[i] = '\0'; - } - - if (remove) { - unlink(filename); - } - - if (! linecount) { - rfbLog("cannot read a valid line from passwdfile: %s\n", - passfile); - if (read_cnt == 0) { - clean_up_exit(1); - } else { - return 0; - } - } - read_cnt++; - - for (i=0; i<linecount; i++) { - char *q, *p = passwd_list[i]; - if (!strcmp(p, "__EMPTY__")) { - *p = '\0'; - } else if ((q = strstr(p, "__COMM__")) != NULL) { - *q = '\0'; - } - passwd_list[i] = strdup(p); - if (db_passwd) { - fprintf(stderr, "read_passwds: trimline: %s\n", p); - } - strzero(p); - } - - begin_viewonly = begin_vo; - if (read_mode && read_cnt > 1) { - if (viewonly_passwd) { - free(viewonly_passwd); - viewonly_passwd = NULL; - } - } - - if (begin_viewonly < 0 && linecount == 2) { - /* for compatibility with previous 2-line usage: */ - viewonly_passwd = strdup(passwd_list[1]); - if (db_passwd) { - fprintf(stderr, "read_passwds: linecount is 2.\n"); - } - if (screen) { - char **apd = (char **) screen->authPasswdData; - if (apd) { - if (apd[0] != NULL) { - strzero(apd[0]); - } - apd[0] = strdup(passwd_list[0]); - } - } - begin_viewonly = 1; - } - - if (old_passwd_list != NULL) { - char *p; - i = 0; - while (old_passwd_list[i] != NULL) { - p = old_passwd_list[i]; - strzero(p); - free(old_passwd_list[i]); - i++; - } - free(old_passwd_list); - } - return 1; -} - -void install_passwds(void) { - if (viewonly_passwd) { - /* append the view only passwd after the normal passwd */ - char **passwds_new = (char **) malloc(3*sizeof(char *)); - char **passwds_old = (char **) screen->authPasswdData; - passwds_new[0] = passwds_old[0]; - passwds_new[1] = viewonly_passwd; - passwds_new[2] = NULL; - /* mutex */ - screen->authPasswdData = (void*) passwds_new; - } else if (passwd_list) { - int i = 0; - while(passwd_list[i] != NULL) { - i++; - } - if (begin_viewonly < 0) { - begin_viewonly = i+1; - } - /* mutex */ - screen->authPasswdData = (void*) passwd_list; - screen->authPasswdFirstViewOnly = begin_viewonly; - } -} - -void check_new_passwds(int force) { - static time_t last_check = 0; - time_t now; - - if (! passwdfile) { - return; - } - if (strstr(passwdfile, "read:") != passwdfile) { - return; - } - if (unixpw_in_progress) return; - - if (force) { - last_check = 0; - } - - now = time(NULL); - if (now > last_check + 1) { - if (read_passwds(passwdfile)) { - install_passwds(); - } - last_check = now; - } -} - -rfbBool custom_passwd_check(rfbClientPtr cl, const char *response, int len) { - char *input, *cmd; - char num[16]; - int j, i, n, rc; - - rfbLog("custom_passwd_check: len=%d\n", len); - - if (!passwdfile || strstr(passwdfile, "custom:") != passwdfile) { - return FALSE; - } - cmd = passwdfile + strlen("custom:"); - - sprintf(num, "%d\n", len); - - input = (char *) malloc(2 * len + 16 + 1); - - input[0] = '\0'; - strcat(input, num); - n = strlen(num); - - j = n; - for (i=0; i < len; i++) { - input[j] = cl->authChallenge[i]; - j++; - } - for (i=0; i < len; i++) { - input[j] = response[i]; - j++; - } - rc = run_user_command(cmd, cl, "custom_passwd", input, n+2*len, NULL); - free(input); - if (rc == 0) { - return TRUE; - } else { - return FALSE; - } -} - -static void handle_one_http_request(void) { - rfbLog("handle_one_http_request: begin.\n"); - if (inetd || screen->httpPort == 0) { - int port = find_free_port(5800, 5860); - if (port) { - /* mutex */ - 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) { - /* XXX ipv6 */ - 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 { - /* inetd case: */ -#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 = connect_tcp("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 - } -} - -void user_supplied_opts(char *opts) { - char *p, *str; - char *allow[] = { - "skip-display", "skip-auth", "skip-shared", - "scale", "scale_cursor", "sc", "solid", "so", "id", - "clear_mods", "cm", "clear_keys", "ck", "repeat", - "clear_all", "ca", - "speeds", "sp", "readtimeout", "rd", - "rotate", "ro", - "geometry", "geom", "ge", - "noncache", "nc", - "nodisplay", "nd", - "viewonly", "vo", - "tag", - NULL - }; - - if (getenv("X11VNC_NO_UNIXPW_OPTS")) { - return; - } - - str = strdup(opts); - - p = strtok(str, ","); - while (p) { - char *q; - int i, n, m, ok = 0; - - i = 0; - while (allow[i] != NULL) { - if (strstr(allow[i], "skip-")) { - i++; - continue; - } - if (strstr(p, allow[i]) == p) { - ok = 1; - break; - } - i++; - } - - if (! ok && strpbrk(p, "0123456789") == p && - sscanf(p, "%d/%d", &n, &m) == 2) { - if (scale_str) free(scale_str); - scale_str = strdup(p); - } else if (ok) { - if (0 && strstr(p, "display=") == p) { - if (use_dpy) free(use_dpy); - use_dpy = strdup(p + strlen("display=")); - } else if (0 && strstr(p, "auth=") == p) { - if (auth_file) free(auth_file); - auth_file = strdup(p + strlen("auth=")); - } else if (0 && !strcmp(p, "shared")) { - shared = 1; - } else if (strstr(p, "scale=") == p) { - if (scale_str) free(scale_str); - scale_str = strdup(p + strlen("scale=")); - } else if (strstr(p, "scale_cursor=") == p || - strstr(p, "sc=") == p) { - if (scale_cursor_str) free(scale_cursor_str); - q = strchr(p, '=') + 1; - scale_cursor_str = strdup(q); - } else if (strstr(p, "rotate=") == p || - strstr(p, "ro=") == p) { - if (rotating_str) free(rotating_str); - q = strchr(p, '=') + 1; - rotating_str = strdup(q); - } else if (!strcmp(p, "solid") || !strcmp(p, "so")) { - use_solid_bg = 1; - if (!solid_str) { - solid_str = strdup(solid_default); - } - } else if (!strcmp(p, "viewonly") || !strcmp(p, "vo")) { - view_only = 1; - } else if (strstr(p, "solid=") == p || - strstr(p, "so=") == p) { - use_solid_bg = 1; - if (solid_str) free(solid_str); - q = strchr(p, '=') + 1; - if (!strcmp(q, "R")) { - solid_str = strdup("root:"); - } else { - solid_str = strdup(q); - } - } else if (strstr(p, "id=") == p) { - unsigned long win; - q = p + strlen("id="); - if (strcmp(q, "pick")) { - if (scan_hexdec(q, &win)) { - subwin = win; - } - } - } else if (!strcmp(p, "clear_mods") || - !strcmp(p, "cm")) { - clear_mods = 1; - } else if (!strcmp(p, "clear_keys") || - !strcmp(p, "ck")) { - clear_mods = 2; - } else if (!strcmp(p, "clear_all") || - !strcmp(p, "ca")) { - clear_mods = 3; - } else if (!strcmp(p, "noncache") || - !strcmp(p, "nc")) { - ncache = 0; - ncache0 = 0; - } else if (strstr(p, "nc=") == p) { - int n2 = atoi(p + strlen("nc=")); - if (nabs(n2) < nabs(ncache)) { - if (ncache < 0) { - ncache = -nabs(n2); - } else { - ncache = nabs(n2); - } - } - } else if (!strcmp(p, "repeat")) { - no_autorepeat = 0; - } else if (strstr(p, "speeds=") == p || - strstr(p, "sp=") == p) { - if (speeds_str) free(speeds_str); - q = strchr(p, '=') + 1; - speeds_str = strdup(q); - q = speeds_str; - while (*q != '\0') { - if (*q == '-') { - *q = ','; - } - q++; - } - } else if (strstr(p, "readtimeout=") == p || - strstr(p, "rd=") == p) { - q = strchr(p, '=') + 1; - rfbMaxClientWait = atoi(q) * 1000; - } - } else { - rfbLog("skipping option: %s\n", p); - } - p = strtok(NULL, ","); - } - free(str); -} - -static void vnc_redirect_timeout (int sig) { - write(2, "timeout: no clients connected.\n", 31); - if (sig) {}; - exit(0); -} - -static void do_chvt(int vt) { - char chvt[100]; - sprintf(chvt, "chvt %d >/dev/null 2>/dev/null &", vt); - rfbLog("running: %s\n", chvt); - system(chvt); - sleep(2); -} - -static void setup_fake_fb(XImage* fb_image, int w, int h, int b) { - if (fake_fb) { - free(fake_fb); - } - fake_fb = (char *) calloc(w*h*b/8, 1); - - fb_image->data = fake_fb; - fb_image->format = ZPixmap; - fb_image->width = w; - fb_image->height = h; - fb_image->bits_per_pixel = b; - fb_image->bytes_per_line = w*b/8; - fb_image->bitmap_unit = -1; - if (b >= 24) { - fb_image->depth = 24; - fb_image->red_mask = 0xff0000; - fb_image->green_mask = 0x00ff00; - fb_image->blue_mask = 0x0000ff; - } else if (b >= 16) { - fb_image->depth = 16; - fb_image->red_mask = 0x003f; - fb_image->green_mask = 0x07c0; - fb_image->blue_mask = 0xf800; - } else if (b >= 2) { - fb_image->depth = 8; - fb_image->red_mask = 0x07; - fb_image->green_mask = 0x38; - fb_image->blue_mask = 0xc0; - } else { - fb_image->depth = 1; - fb_image->red_mask = 0x1; - fb_image->green_mask = 0x1; - fb_image->blue_mask = 0x1; - } - - depth = fb_image->depth; - - dpy_x = wdpy_x = w; - dpy_y = wdpy_y = h; - off_x = 0; - off_y = 0; -} - -void do_announce_http(void); -void do_mention_java_urls(void); - -static void setup_service(void) { - if (remote_direct) { - return; - } - if (!inetd) { - do_mention_java_urls(); - do_announce_http(); - if (!use_openssl) { - announce(screen->port, use_openssl, NULL); - fprintf(stdout, "PORT=%d\n", screen->port); - } else { - 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); - } else if (!use_openssl && avahi) { - char *name = rfb_desktop_name; - if (!name) { - name = use_dpy; - } - avahi_initialise(); - avahi_advertise(name, this_host(), screen->port); - } -} - -static void check_waitbg(void) { - if (getenv("WAITBG")) { -#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID - int p, n; - if ((p = fork()) > 0) { - exit(0); - } else if (p == -1) { - rfbLogEnable(1); - fprintf(stderr, "could not fork\n"); - perror("fork"); - clean_up_exit(1); - } - if (setsid() == -1) { - rfbLogEnable(1); - fprintf(stderr, "setsid failed\n"); - perror("setsid"); - clean_up_exit(1); - } - /* adjust our stdio */ - n = open("/dev/null", O_RDONLY); - dup2(n, 0); - dup2(n, 1); - if (! logfile) { - dup2(n, 2); - } - if (n > 2) { - close(n); - } -#else - clean_up_exit(1); -#endif - } -} - -static void setup_client_connect(int *did_client_connect) { - if (client_connect != NULL) { - char *remainder = NULL; - if (inetd) { - rfbLog("wait_for_client: -connect disallowed in inetd mode: %s\n", - client_connect); - } else if (screen && screen->clientHead) { - rfbLog("wait_for_client: -connect disallowed: client exists: %s\n", - client_connect); - } else if (strchr(client_connect, '=')) { - rfbLog("wait_for_client: invalid -connect string: %s\n", - client_connect); - } else { - char *q = strchr(client_connect, ','); - if (q) { - rfbLog("wait_for_client: only using first" - " connect host in: %s\n", client_connect); - remainder = strdup(q+1); - *q = '\0'; - } - rfbLog("wait_for_client: reverse_connect(%s)\n", - client_connect); - reverse_connect(client_connect); - *did_client_connect = 1; - } - free(client_connect); - if (remainder != NULL) { - /* reset to host2,host3,... */ - client_connect = remainder; - } else { - client_connect = NULL; - } - } -} - -static void loop_for_connect(int did_client_connect) { - int loop = 0; - time_t start = time(NULL); - - if (first_conn_timeout < 0) { - first_conn_timeout = -first_conn_timeout; - } - - while (1) { - loop++; - if (first_conn_timeout && time(NULL) > start + first_conn_timeout) { - rfbLog("no client connect after %d seconds.\n", first_conn_timeout); - shut_down = 1; - } - if (shut_down) { - clean_up_exit(0); - } - if (loop < 2) { - if (did_client_connect) { - goto screen_check; - } - if (inetd) { - goto screen_check; - } - if (screen && screen->clientHead) { - goto screen_check; - } - } - if ((use_openssl || use_stunnel) && !inetd) { - int enc_none = (enc_str && !strcmp(enc_str, "none")); - if (!use_stunnel || enc_none) { - check_openssl(); - check_https(); - } - /* - * This is to handle an initial verify cert from viewer, - * they disconnect right after fetching the cert. - */ - if (use_threads) { - usleep(10 * 1000); - } else { - rfbPE(-1); - } - if (screen && screen->clientHead) { - int i; - if (unixpw) { - if (! unixpw_in_progress && !vencrypt_enable_plain_login) { - rfbLog("unixpw but no unixpw_in_progress\n"); - clean_up_exit(1); - } - if (unixpw_client && unixpw_client->onHold) { - rfbLog("taking unixpw_client off hold\n"); - unixpw_client->onHold = FALSE; - } - } - for (i=0; i<10; i++) { - if (shut_down) { - clean_up_exit(0); - } - usleep(20 * 1000); - if (0) rfbLog("wait_for_client: %d\n", i); - - if (! use_threads) { - if (unixpw) { - unixpw_in_rfbPE = 1; - } - rfbPE(-1); - if (unixpw) { - unixpw_in_rfbPE = 0; - } - } - - if (unixpw && !unixpw_in_progress) { - /* XXX too soon. */ - goto screen_check; - } - if (!screen->clientHead) { - break; - } - } - } - } else if (use_openssl) { - check_openssl(); - } - - if (use_threads) { - usleep(10 * 1000); - } else { - rfbPE(-1); - } - - screen_check: - if (! screen || ! screen->clientHead) { - usleep(100 * 1000); - continue; - } - - rfbLog("wait_for_client: got client\n"); - break; - } -} - -static void do_unixpw_loop(void) { - if (unixpw) { - if (! unixpw_in_progress && !vencrypt_enable_plain_login) { - rfbLog("unixpw but no unixpw_in_progress\n"); - clean_up_exit(1); - } - if (unixpw_client && unixpw_client->onHold) { - rfbLog("taking unixpw_client off hold.\n"); - unixpw_client->onHold = FALSE; - } - while (1) { - if (shut_down) { - clean_up_exit(0); - } - if (! use_threads) { - unixpw_in_rfbPE = 1; - rfbPE(-1); - unixpw_in_rfbPE = 0; - } - if (unixpw_in_progress) { - static double lping = 0.0; - if (lping < dnow() + 5) { - mark_rect_as_modified(0, 0, 1, 1, 1); - lping = dnow(); - } - if (time(NULL) > unixpw_last_try_time + 45) { - rfbLog("unixpw_deny: timed out waiting for reply.\n"); - unixpw_deny(); - } - usleep(20 * 1000); - continue; - } - rfbLog("wait_for_client: unixpw finished.\n"); - break; - } - } -} - -static void vnc_redirect_loop(char *vnc_redirect_test, int *vnc_redirect_cnt) { - if (unixpw) { - rfbLog("wait_for_client: -unixpw and Xvnc.redirect not allowed\n"); - clean_up_exit(1); - } - if (client_connect) { - rfbLog("wait_for_client: -connect and Xvnc.redirect not allowed\n"); - clean_up_exit(1); - } - if (inetd) { - if (use_openssl) { - accept_openssl(OPENSSL_INETD, -1); - } - } else { - pid_t pid = 0; - /* XXX ipv6 */ - if (screen->httpListenSock >= 0) { -#if LIBVNCSERVER_HAVE_FORK - if ((pid = fork()) > 0) { - close(screen->httpListenSock); - /* mutex */ - screen->httpListenSock = -2; - usleep(500 * 1000); - } else { - close(screen->listenSock); - screen->listenSock = -1; - while (1) { - usleep(10 * 1000); - rfbHttpCheckFds(screen); - } - exit(1); - } -#else - clean_up_exit(1); -#endif - } - if (first_conn_timeout) { - if (first_conn_timeout < 0) { - first_conn_timeout = -first_conn_timeout; - } - signal(SIGALRM, vnc_redirect_timeout); - alarm(first_conn_timeout); - } - if (use_openssl) { - int i; - if (pid == 0) { - accept_openssl(OPENSSL_VNC, -1); - } else { - for (i=0; i < 16; i++) { - accept_openssl(OPENSSL_VNC, -1); - rfbLog("iter %d: vnc_redirect_sock: %d\n", i, vnc_redirect_sock); - if (vnc_redirect_sock >= 0) { - break; - } - } - } - } else { - struct sockaddr_in addr; -#ifdef __hpux - int addrlen = sizeof(addr); -#else - socklen_t addrlen = sizeof(addr); -#endif - if (screen->listenSock < 0) { - rfbLog("wait_for_client: Xvnc.redirect not listening... sock=%d port=%d\n", screen->listenSock, screen->port); - clean_up_exit(1); - } - vnc_redirect_sock = accept(screen->listenSock, (struct sockaddr *)&addr, &addrlen); - } - if (first_conn_timeout) { - alarm(0); - } - if (pid > 0) { -#if LIBVNCSERVER_HAVE_FORK - int rc; - pid_t pidw; - rfbLog("wait_for_client: kill TERM: %d\n", (int) pid); - kill(pid, SIGTERM); - usleep(1000 * 1000); /* 1.0 sec */ - pidw = waitpid(pid, &rc, WNOHANG); - if (pidw <= 0) { - usleep(1000 * 1000); /* 1.0 sec */ - pidw = waitpid(pid, &rc, WNOHANG); - } -#else - clean_up_exit(1); -#endif - } - } - if (vnc_redirect_sock < 0) { - rfbLog("wait_for_client: vnc_redirect failed.\n"); - clean_up_exit(1); - } - if (!inetd && use_openssl) { - /* check for Fetch Cert closing */ - fd_set rfds; - struct timeval tv; - int nfds; - - usleep(300*1000); - - FD_ZERO(&rfds); - FD_SET(vnc_redirect_sock, &rfds); - - tv.tv_sec = 0; - tv.tv_usec = 200000; - nfds = select(vnc_redirect_sock+1, &rfds, NULL, NULL, &tv); - - rfbLog("wait_for_client: vnc_redirect nfds: %d\n", nfds); - if (nfds > 0) { - int n; - n = read(vnc_redirect_sock, vnc_redirect_test, 1); - if (n <= 0) { - close(vnc_redirect_sock); - vnc_redirect_sock = -1; - rfbLog("wait_for_client: waiting for 2nd connection (Fetch Cert?)\n"); - accept_openssl(OPENSSL_VNC, -1); - if (vnc_redirect_sock < 0) { - rfbLog("wait_for_client: vnc_redirect failed.\n"); - clean_up_exit(1); - } - } else { - *vnc_redirect_cnt = n; - } - } - } -} - -static void do_vnc_redirect(int created_disp, char *vnc_redirect_host, int vnc_redirect_port, - int vnc_redirect_cnt, char *vnc_redirect_test) { - char *q = strrchr(use_dpy, ':'); - int vdpy = -1, sock = -1; - int s_in, s_out, i; - if (vnc_redirect == 2) { - char num[32]; - sprintf(num, ":%d", vnc_redirect_port); - q = num; - } - if (!q) { - rfbLog("wait_for_client: can't find number in X display: %s\n", use_dpy); - clean_up_exit(1); - } - if (sscanf(q+1, "%d", &vdpy) != 1) { - rfbLog("wait_for_client: can't find number in X display: %s\n", q); - clean_up_exit(1); - } - if (vdpy == -1 && vnc_redirect != 2) { - rfbLog("wait_for_client: can't find number in X display: %s\n", q); - clean_up_exit(1); - } - if (vnc_redirect == 2) { - if (vdpy < 0) { - vdpy = -vdpy; - } else if (vdpy < 200) { - vdpy += 5900; - } - } else { - vdpy += 5900; - } - if (created_disp) { - usleep(1000*1000); - } - for (i=0; i < 20; i++) { - sock = connect_tcp(vnc_redirect_host, vdpy); - if (sock >= 0) { - break; - } - rfbLog("wait_for_client: ...\n"); - usleep(500*1000); - } - if (sock < 0) { - rfbLog("wait_for_client: could not connect to a VNC Server at %s:%d\n", vnc_redirect_host, vdpy); - clean_up_exit(1); - } - if (inetd) { - s_in = fileno(stdin); - s_out = fileno(stdout); - } else { - s_in = s_out = vnc_redirect_sock; - } - if (vnc_redirect_cnt > 0) { - write(vnc_redirect_sock, vnc_redirect_test, vnc_redirect_cnt); - } - rfbLog("wait_for_client: switching control to VNC Server at %s:%d\n", vnc_redirect_host, vdpy); - raw_xfer(sock, s_in, s_out); -} - -extern char find_display[]; -extern char create_display[]; - -char *setup_cmd(char *str, int *vnc_redirect, char **vnc_redirect_host, int *vnc_redirect_port, int db) { - char *cmd = NULL; - - if (no_external_cmds || !cmd_ok("WAIT")) { - rfbLog("wait_for_client external cmds not allowed:" - " %s\n", use_dpy); - clean_up_exit(1); - } - - cmd = str + strlen("cmd="); - if (!strcmp(cmd, "FINDDISPLAY-print")) { - fprintf(stdout, "%s", find_display); - clean_up_exit(0); - } - if (!strcmp(cmd, "FINDDISPLAY-run")) { - char tmp[] = "/tmp/fd.XXXXXX"; - char com[100]; - int fd = mkstemp(tmp); - if (fd >= 0) { - int ret; - write(fd, find_display, strlen(find_display)); - close(fd); - set_env("FINDDISPLAY_run", "1"); - sprintf(com, "/bin/sh %s -n", tmp); - ret = system(com); - if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { - if (got_findauth && !getenv("FD_XDM")) { - if (getuid() == 0 || geteuid() == 0) { - set_env("FD_XDM", "1"); - system(com); - } - } - } - } - unlink(tmp); - exit(0); - } - if (!strcmp(str, "FINDCREATEDISPLAY-print")) { - fprintf(stdout, "%s", create_display); - clean_up_exit(0); - } - if (db) fprintf(stderr, "cmd: %s\n", cmd); - if (strstr(str, "FINDCREATEDISPLAY") || strstr(str, "FINDDISPLAY")) { - if (strstr(str, "Xvnc.redirect") || strstr(str, "X.redirect")) { - *vnc_redirect = 1; - } - } - if (strstr(cmd, "FINDDISPLAY-vnc_redirect") == cmd) { - int p; - char h[256]; - if (strlen(cmd) >= 256) { - rfbLog("wait_for_client string too long: %s\n", str); - clean_up_exit(1); - } - h[0] = '\0'; - if (sscanf(cmd, "FINDDISPLAY-vnc_redirect=%d", &p) == 1) { - ; - } else if (sscanf(cmd, "FINDDISPLAY-vnc_redirect=%s %d", h, &p) == 2) { - ; - } else { - rfbLog("wait_for_client bad string: %s\n", cmd); - clean_up_exit(1); - } - *vnc_redirect_port = p; - if (strcmp(h, "")) { - *vnc_redirect_host = strdup(h); - } - *vnc_redirect = 2; - rfbLog("wait_for_client: vnc_redirect: %s:%d\n", *vnc_redirect_host, *vnc_redirect_port); - } - return cmd; -} - -static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *tmp) { - char *create_cmd = NULL; - char *opts = strchr(cmd, '-'); - char st[] = ""; - char fdgeom[128], fdsess[128], fdopts[128], fdextra[256], fdprog[128]; - char fdxsrv[128], fdxdum[128], fdcups[128], fdesd[128]; - char fdnas[128], fdsmb[128], fdtag[128], fdxdmcpif[128]; - char cdout[128]; - - if (opts) { - opts++; - if (strstr(opts, "xdmcp")) { - *saw_xdmcp = 1; - } - } else { - opts = st; - } - sprintf(fdgeom, "NONE"); - fdsess[0] = '\0'; - fdgeom[0] = '\0'; - fdopts[0] = '\0'; - fdextra[0] = '\0'; - fdprog[0] = '\0'; - fdxsrv[0] = '\0'; - fdxdum[0] = '\0'; - fdcups[0] = '\0'; - fdesd[0] = '\0'; - fdnas[0] = '\0'; - fdsmb[0] = '\0'; - fdtag[0] = '\0'; - fdxdmcpif[0] = '\0'; - cdout[0] = '\0'; - - if (unixpw && keep_unixpw_opts && !getenv("X11VNC_NO_UNIXPW_OPTS")) { - char *q, *p, *t = strdup(keep_unixpw_opts); - - if (strstr(t, "gnome")) { - sprintf(fdsess, "gnome"); - } else if (strstr(t, "kde")) { - sprintf(fdsess, "kde"); - } else if (strstr(t, "lxde")) { - sprintf(fdsess, "lxde"); - } else if (strstr(t, "twm")) { - sprintf(fdsess, "twm"); - } else if (strstr(t, "fvwm")) { - sprintf(fdsess, "fvwm"); - } else if (strstr(t, "mwm")) { - sprintf(fdsess, "mwm"); - } else if (strstr(t, "cde")) { - sprintf(fdsess, "cde"); - } else if (strstr(t, "dtwm")) { - sprintf(fdsess, "dtwm"); - } else if (strstr(t, "xterm")) { - sprintf(fdsess, "xterm"); - } else if (strstr(t, "wmaker")) { - sprintf(fdsess, "wmaker"); - } else if (strstr(t, "xfce")) { - sprintf(fdsess, "xfce"); - } else if (strstr(t, "enlightenment")) { - sprintf(fdsess, "enlightenment"); - } else if (strstr(t, "Xsession")) { - sprintf(fdsess, "Xsession"); - } else if (strstr(t, "failsafe")) { - sprintf(fdsess, "failsafe"); - } - - q = strstr(t, "ge="); - if (! q) q = strstr(t, "geom="); - if (! q) q = strstr(t, "geometry="); - if (q) { - int ok = 1; - q = strstr(q, "="); - q++; - p = strstr(q, ","); - if (p) *p = '\0'; - p = q; - while (*p) { - if (*p == 'x') { - ; - } else if (isdigit((int) *p)) { - ; - } else { - ok = 0; - break; - } - p++; - } - if (ok && strlen(q) < 32) { - sprintf(fdgeom, "%s", q); - if (!quiet) { - rfbLog("set create display geom: %s\n", fdgeom); - } - } - } - q = strstr(t, "cups="); - if (q) { - int p; - if (sscanf(q, "cups=%d", &p) == 1) { - sprintf(fdcups, "%d", p); - } - } - q = strstr(t, "esd="); - if (q) { - int p; - if (sscanf(q, "esd=%d", &p) == 1) { - sprintf(fdesd, "%d", p); - } - } - if (!getenv("FD_TAG")) { - char *s = NULL; - - q = strstr(t, "tag="); - if (q) s = strchr(q, ','); - if (s) *s = '\0'; - - if (q && strlen(q) < 120) { - char *p; - int ok = 1; - q = strchr(q, '=') + 1; - p = q; - while (*p != '\0') { - char c = *p; - if (*p == '_' || *p == '-') { - ; - } else if (!isalnum((int) c)) { - ok = 0; - rfbLog("bad tag char: '%c' in '%s'\n", c, q); - break; - } - p++; - } - if (ok) { - sprintf(fdtag, "%s", q); - } - } - if (s) *s = ','; - } - free(t); - } - if (fdgeom[0] == '\0' && getenv("FD_GEOM")) { - snprintf(fdgeom, 120, "%s", getenv("FD_GEOM")); - } - if (fdsess[0] == '\0' && getenv("FD_SESS")) { - snprintf(fdsess, 120, "%s", getenv("FD_SESS")); - } - if (fdopts[0] == '\0' && getenv("FD_OPTS")) { - snprintf(fdopts, 120, "%s", getenv("FD_OPTS")); - } - if (fdextra[0] == '\0' && getenv("FD_EXTRA")) { - if (!strchr(getenv("FD_EXTRA"), '\'')) { - snprintf(fdextra, 250, "%s", getenv("FD_EXTRA")); - } - } - if (fdprog[0] == '\0' && getenv("FD_PROG")) { - snprintf(fdprog, 120, "%s", getenv("FD_PROG")); - } - if (fdxsrv[0] == '\0' && getenv("FD_XSRV")) { - snprintf(fdxsrv, 120, "%s", getenv("FD_XSRV")); - } - if (fdcups[0] == '\0' && getenv("FD_CUPS")) { - snprintf(fdcups, 120, "%s", getenv("FD_CUPS")); - } - if (fdesd[0] == '\0' && getenv("FD_ESD")) { - snprintf(fdesd, 120, "%s", getenv("FD_ESD")); - } - if (fdnas[0] == '\0' && getenv("FD_NAS")) { - snprintf(fdnas, 120, "%s", getenv("FD_NAS")); - } - if (fdsmb[0] == '\0' && getenv("FD_SMB")) { - snprintf(fdsmb, 120, "%s", getenv("FD_SMB")); - } - if (fdtag[0] == '\0' && getenv("FD_TAG")) { - snprintf(fdtag, 120, "%s", getenv("FD_TAG")); - } - if (fdxdmcpif[0] == '\0' && getenv("FD_XDMCP_IF")) { - snprintf(fdxdmcpif, 120, "%s", getenv("FD_XDMCP_IF")); - } - if (fdxdum[0] == '\0' && getenv("FD_XDUMMY_RUN_AS_ROOT")) { - snprintf(fdxdum, 120, "%s", getenv("FD_XDUMMY_RUN_AS_ROOT")); - } - if (getenv("CREATE_DISPLAY_OUTPUT")) { - snprintf(cdout, 120, "CREATE_DISPLAY_OUTPUT='%s'", getenv("CREATE_DISPLAY_OUTPUT")); - } - - if (strchr(fdgeom, '\'')) fdgeom[0] = '\0'; - if (strchr(fdopts, '\'')) fdopts[0] = '\0'; - if (strchr(fdextra, '\'')) fdextra[0] = '\0'; - if (strchr(fdprog, '\'')) fdprog[0] = '\0'; - if (strchr(fdxsrv, '\'')) fdxsrv[0] = '\0'; - if (strchr(fdcups, '\'')) fdcups[0] = '\0'; - if (strchr(fdesd, '\'')) fdesd[0] = '\0'; - if (strchr(fdnas, '\'')) fdnas[0] = '\0'; - if (strchr(fdsmb, '\'')) fdsmb[0] = '\0'; - if (strchr(fdtag, '\'')) fdtag[0] = '\0'; - if (strchr(fdxdmcpif, '\'')) fdxdmcpif[0] = '\0'; - if (strchr(fdxdum, '\'')) fdxdum[0] = '\0'; - if (strchr(fdsess, '\'')) fdsess[0] = '\0'; - if (strchr(cdout, '\'')) cdout[0] = '\0'; - - set_env("FD_GEOM", fdgeom); - set_env("FD_OPTS", fdopts); - set_env("FD_EXTRA", fdextra); - set_env("FD_PROG", fdprog); - set_env("FD_XSRV", fdxsrv); - set_env("FD_CUPS", fdcups); - set_env("FD_ESD", fdesd); - set_env("FD_NAS", fdnas); - set_env("FD_SMB", fdsmb); - set_env("FD_TAG", fdtag); - set_env("FD_XDMCP_IF", fdxdmcpif); - set_env("FD_XDUMMY_RUN_AS_ROOT", fdxdum); - set_env("FD_SESS", fdsess); - - if (usslpeer || (unixpw && keep_unixpw_user)) { - char *uu = usslpeer; - if (!uu) { - uu = keep_unixpw_user; - } - if (strchr(uu, '\'')) { - uu = ""; - } - create_cmd = (char *) malloc(strlen(tmp)+1 - + strlen("env USER='' ") - + strlen("FD_GEOM='' ") - + strlen("FD_OPTS='' ") - + strlen("FD_EXTRA='' ") - + strlen("FD_PROG='' ") - + strlen("FD_XSRV='' ") - + strlen("FD_CUPS='' ") - + strlen("FD_ESD='' ") - + strlen("FD_NAS='' ") - + strlen("FD_SMB='' ") - + strlen("FD_TAG='' ") - + strlen("FD_XDMCP_IF='' ") - + strlen("FD_XDUMMY_RUN_AS_ROOT='' ") - + strlen("FD_SESS='' /bin/sh ") - + strlen(uu) + 1 - + strlen(fdgeom) + 1 - + strlen(fdopts) + 1 - + strlen(fdextra) + 1 - + strlen(fdprog) + 1 - + strlen(fdxsrv) + 1 - + strlen(fdcups) + 1 - + strlen(fdesd) + 1 - + strlen(fdnas) + 1 - + strlen(fdsmb) + 1 - + strlen(fdtag) + 1 - + strlen(fdxdmcpif) + 1 - + strlen(fdxdum) + 1 - + strlen(fdsess) + 1 - + strlen(cdout) + 1 - + strlen(opts) + 1); - sprintf(create_cmd, "env USER='%s' FD_GEOM='%s' FD_SESS='%s' " - "FD_OPTS='%s' FD_EXTRA='%s' FD_PROG='%s' FD_XSRV='%s' FD_CUPS='%s' " - "FD_ESD='%s' FD_NAS='%s' FD_SMB='%s' FD_TAG='%s' FD_XDMCP_IF='%s' " - "FD_XDUMMY_RUN_AS_ROOT='%s' %s /bin/sh %s %s", - uu, fdgeom, fdsess, fdopts, fdextra, fdprog, fdxsrv, - fdcups, fdesd, fdnas, fdsmb, fdtag, fdxdmcpif, fdxdum, cdout, tmp, opts); - } else { - create_cmd = (char *) malloc(strlen(tmp) - + strlen("/bin/sh ") + 1 + strlen(opts) + 1); - sprintf(create_cmd, "/bin/sh %s %s", tmp, opts); - } - return create_cmd; -} - -static char *certret_extract() { - char *q, *p, *str = strdup(certret_str); - char *upeer = NULL; - int ok = 0; - - q = strstr(str, "Subject: "); - if (! q) return NULL; - - p = strstr(q, "\n"); - if (p) *p = '\0'; - - q = strstr(q, "CN="); - if (! q) return NULL; - - if (! getenv("X11VNC_SSLPEER_CN")) { - p = q; - q = strstr(q, "/emailAddress="); - if (! q) q = strstr(p, "/Email="); - if (! q) return NULL; - } - - q = strstr(q, "="); - if (! q) return NULL; - - q++; - p = strstr(q, " "); - if (p) *p = '\0'; - p = strstr(q, "@"); - if (p) *p = '\0'; - p = strstr(q, "/"); - if (p) *p = '\0'; - - upeer = strdup(q); - - if (strcmp(upeer, "")) { - p = upeer; - while (*p != '\0') { - char c = *p; - if (!isalnum((int) c)) { - *p = '\0'; - break; - } - p++; - } - if (strcmp(upeer, "")) { - ok = 1; - } - } - if (! ok) { - upeer = NULL; - } - return upeer; -} - -static void check_nodisplay(char **nd, char **tag) { - if (unixpw && !getenv("X11VNC_NO_UNIXPW_OPTS") && keep_unixpw_opts && keep_unixpw_opts[0] != '\0') { - char *q, *t2, *t = keep_unixpw_opts; - q = strstr(t, "nd="); - if (! q) q = strstr(t, "nodisplay="); - if (q) { - q = strchr(q, '=') + 1; - t = strdup(q); - q = t; - t2 = strchr(t, ','); - if (t2) *t2 = '\0'; - - while (*t != '\0') { - if (*t == '+') { - *t = ','; - } - t++; - } - if (!strchr(q, '\'') && !strpbrk(q, "[](){}`'\"$&*|<>")) { - if (! quiet) rfbLog("set X11VNC_SKIP_DISPLAY: %s\n", q); - *nd = q; - } - } - - q = strstr(keep_unixpw_opts, "tag="); - if (getenv("FD_TAG")) { - *tag = strdup(getenv("FD_TAG")); - } else if (q) { - q = strchr(q, '=') + 1; - t = strdup(q); - q = t; - t2 = strchr(t, ','); - if (t2) *t2 = '\0'; - - if (strlen(q) < 120) { - int ok = 1; - while (*t != '\0') { - char c = *t; - if (*t == '_' || *t == '-') { - ; - } else if (!isalnum((int) c)) { - ok = 0; - rfbLog("bad tag char: '%c' in '%s'\n", c, q); - break; - } - t++; - } - if (ok) { - if (! quiet) rfbLog("set FD_TAG: %s\n", q); - *tag = q; - } - } - } - } - if (unixpw_system_greeter_active == 2) { - if (!keep_unixpw_user) { - clean_up_exit(1); - } - *nd = strdup("all"); - } -} - -static char *get_usslpeer() { - char *u = NULL, *upeer = NULL; - - if (certret_str) { - upeer = certret_extract(); - } - if (!upeer) { - return NULL; - } - rfbLog("sslpeer unix username extracted from x509 cert: %s\n", upeer); - - u = (char *) malloc(strlen(upeer+2)); - u[0] = '\0'; - if (!strcmp(users_list, "sslpeer=")) { - sprintf(u, "+%s", upeer); - } else { - char *p, *str = strdup(users_list); - p = strtok(str + strlen("sslpeer="), ","); - while (p) { - if (!strcmp(p, upeer)) { - sprintf(u, "+%s", upeer); - break; - } - p = strtok(NULL, ","); - } - free(str); - } - if (u[0] == '\0') { - rfbLog("sslpeer cannot determine user: %s\n", upeer); - free(u); - return NULL; - } - free(u); - return upeer; -} - -static void do_try_switch(char *usslpeer, char *users_list_save) { - if (unixpw_system_greeter_active == 2) { - rfbLog("unixpw_system_greeter: not trying switch to user '%s'\n", usslpeer ? usslpeer : ""); - return; - } - if (usslpeer) { - char *u = (char *) malloc(strlen(usslpeer+2)); - sprintf(u, "+%s", usslpeer); - if (switch_user(u, 0)) { - rfbLog("sslpeer switched to user: %s\n", usslpeer); - } else { - rfbLog("sslpeer failed to switch to user: %s\n", usslpeer); - } - free(u); - - } else if (users_list_save && keep_unixpw_user) { - char *user = keep_unixpw_user; - char *u = (char *)malloc(strlen(user)+1); - - users_list = users_list_save; - - u[0] = '\0'; - if (!strcmp(users_list, "unixpw=")) { - sprintf(u, "+%s", user); - } else { - char *p, *str = strdup(users_list); - p = strtok(str + strlen("unixpw="), ","); - while (p) { - if (!strcmp(p, user)) { - sprintf(u, "+%s", user); - break; - } - p = strtok(NULL, ","); - } - free(str); - } - - if (u[0] == '\0') { - rfbLog("unixpw_accept skipping switch to user: %s (drc)\n", user); - } else if (switch_user(u, 0)) { - rfbLog("unixpw_accept switched to user: %s (drc)\n", user); - } else { - rfbLog("unixpw_accept failed to switch to user: %s (drc)\n", user); - } - free(u); - } -} - -static void path_lookup(char *prog) { - /* see create_display script */ - char *create_display_extra = "/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/dt/bin:/opt/kde4/bin:/opt/kde3/bin:/opt/gnome/bin:/usr/bin:/bin:/usr/sfw/bin:/usr/local/bin"; - char *path, *try, *p; - int found = 0, len = strlen(create_display_extra); - - if (getenv("PATH")) { - len += strlen(getenv("PATH")) + 1; - path = (char *) malloc((len+1) * sizeof(char)); - sprintf(path, "%s:%s", getenv("PATH"), create_display_extra); - } else { - path = (char *) malloc((len+1) * sizeof(char)); - sprintf(path, "%s", create_display_extra); - } - try = (char *) malloc((len+2+strlen(prog)) * sizeof(char)); - - p = strtok(path, ":"); - while (p) { - struct stat sbuf; - - sprintf(try, "%s/%s", p, prog); - if (stat(try, &sbuf) == 0) { - found = 1; - break; - } - p = strtok(NULL, ":"); - } - - free(path); - free(try); - - if (!found) { - fprintf(stderr, "\n"); - fprintf(stderr, "The program \"%s\" could not be found in PATH and standard locations.\n", prog); - fprintf(stderr, "You probably need to install a package that provides the \"%s\" program.\n", prog); - fprintf(stderr, "Without it FINDCREATEDISPLAY mode may not be able to create an X display.\n"); - fprintf(stderr, "\n"); - } -} - -static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int created_disp, int db) { - char tmp[] = "/tmp/x11vnc-find_display.XXXXXX"; - char line1[1024], line2[16384]; - char *q, *usslpeer = NULL; - int n, nodisp = 0, saw_xdmcp = 0; - int tmp_fd = -1; - int internal_cmd = 0; - int tried_switch = 0; - - memset(line1, 0, sizeof(line1)); - memset(line2, 0, sizeof(line2)); - - if (users_list && strstr(users_list, "sslpeer=") == users_list) { - usslpeer = get_usslpeer(); - if (! usslpeer) { - return 0; - } - } - if (getenv("DEBUG_RUN_CMD")) db = 1; - - /* only sets environment variables: */ - run_user_command("", latest_client, "env", NULL, 0, NULL); - - if (program_name) { - set_env("X11VNC_PROG", program_name); - } else { - set_env("X11VNC_PROG", "x11vnc"); - } - - if (!strcmp(cmd, "FINDDISPLAY") || - strstr(cmd, "FINDCREATEDISPLAY") == cmd) { - char *nd = ""; - char *tag = ""; - char fdout[128]; - - internal_cmd = 1; - - tmp_fd = mkstemp(tmp); - - if (tmp_fd < 0) { - rfbLog("wait_for_client: open failed: %s\n", tmp); - rfbLogPerror("mkstemp"); - clean_up_exit(1); - } - chmod(tmp, 0644); - if (getenv("X11VNC_FINDDISPLAY_ALWAYS_FAILS")) { - char *s = "#!/bin/sh\necho _FAIL_\nexit 1\n"; - write(tmp_fd, s, strlen(s)); - } else { - write(tmp_fd, find_display, strlen(find_display)); - } - close(tmp_fd); - nodisp = 1; - - if (strstr(cmd, "FINDCREATEDISPLAY") == cmd) { - create_cmd = build_create_cmd(cmd, &saw_xdmcp, usslpeer, tmp); - if (db) fprintf(stderr, "create_cmd: %s\n", create_cmd); - } - if (getenv("X11VNC_SKIP_DISPLAY")) { - nd = strdup(getenv("X11VNC_SKIP_DISPLAY")); - } - check_nodisplay(&nd, &tag); - - fdout[0] = '\0'; - if (getenv("FIND_DISPLAY_OUTPUT")) { - snprintf(fdout, 120, " FIND_DISPLAY_OUTPUT='%s' ", getenv("FIND_DISPLAY_OUTPUT")); - } - - cmd = (char *) malloc(strlen("env X11VNC_SKIP_DISPLAY='' ") - + strlen(nd) + strlen(" FD_TAG='' ") + strlen(tag) + strlen(tmp) + strlen("/bin/sh ") + strlen(fdout) + 1); - - if (strcmp(tag, "")) { - sprintf(cmd, "env X11VNC_SKIP_DISPLAY='%s' FD_TAG='%s' %s /bin/sh %s", nd, tag, fdout, tmp); - } else { - sprintf(cmd, "env X11VNC_SKIP_DISPLAY='%s' %s /bin/sh %s", nd, fdout, tmp); - } - } - - rfbLog("wait_for_client: running: %s\n", cmd); - - if (create_cmd != NULL) { - if (strstr(create_cmd, "Xvfb")) { - path_lookup("Xvfb"); - } - if (strstr(create_cmd, "Xvnc")) { - path_lookup("Xvnc"); - } - if (strstr(create_cmd, "Xdummy")) { - path_lookup("Xdummy"); - } - } - - if (unixpw && !unixpw_nis) { - int res = 0, k, j, i; - char line[18000]; - - memset(line, 0, sizeof(line)); - - if (unixpw_system_greeter_active == 2) { - rfbLog("unixpw_system_greeter: forcing find display failure.\n"); - res = 0; - } else if (keep_unixpw_user && keep_unixpw_pass) { - n = sizeof(line); - if (unixpw_cmd != NULL) { - res = unixpw_cmd_run(keep_unixpw_user, - keep_unixpw_pass, cmd, line, &n); - } else { - res = su_verify(keep_unixpw_user, - keep_unixpw_pass, cmd, line, &n, nodisp); - } - } - -if (db) {fprintf(stderr, "line: "); write(2, line, n); write(2, "\n", 1); fprintf(stderr, "res=%d n=%d\n", res, n);} - if (! res) { - rfbLog("wait_for_client: find display cmd failed.\n"); - } - - if (! res && create_cmd) { - FILE *mt = fopen(tmp, "w"); - if (! mt) { - rfbLog("wait_for_client: open failed: %s\n", tmp); - rfbLogPerror("fopen"); - clean_up_exit(1); - } - fprintf(mt, "%s", create_display); - fclose(mt); - - findcreatedisplay = 1; - - if (unixpw_cmd != NULL) { - /* let the external unixpw command do it: */ - n = sizeof(line); - close_exec_fds(); - res = unixpw_cmd_run(keep_unixpw_user, - keep_unixpw_pass, create_cmd, line, &n); - } else if (getuid() != 0 && unixpw_system_greeter_active != 2) { - /* if not root, run as the other user... */ - n = sizeof(line); - close_exec_fds(); - res = su_verify(keep_unixpw_user, - keep_unixpw_pass, create_cmd, line, &n, nodisp); -if (db) fprintf(stderr, "c-res=%d n=%d line: '%s'\n", res, n, line); - - } else { - FILE *p; - close_exec_fds(); - if (unixpw_system_greeter_active == 2) { - rfbLog("unixpw_system_greeter: not trying su_verify() to run\n"); - rfbLog("unixpw_system_greeter: create display command.\n"); - } - rfbLog("wait_for_client: running: %s\n", create_cmd); - p = popen(create_cmd, "r"); - if (! p) { - rfbLog("wait_for_client: popen failed: %s\n", create_cmd); - res = 0; - } else if (fgets(line1, 1024, p) == NULL) { - rfbLog("wait_for_client: read failed: %s\n", create_cmd); - res = 0; - } else { - n = fread(line2, 1, 16384, p); - if (pclose(p) != 0) { - res = 0; - } else { - strncpy(line, line1, 100); - memcpy(line + strlen(line1), line2, n); -if (db) fprintf(stderr, "line1: '%s'\n", line1); - n += strlen(line1); - created_disp = 1; - res = 1; - } - } - } - if (res && saw_xdmcp && unixpw_system_greeter_active != 2) { - xdmcp_insert = strdup(keep_unixpw_user); - } - } - - if (tmp_fd >= 0) { - unlink(tmp); - } - - if (! res) { - rfbLog("wait_for_client: cmd failed: %s\n", cmd); - unixpw_msg("No DISPLAY found.", 3); - clean_up_exit(1); - } - - /* - * we need to hunt for DISPLAY= since there may be - * a login banner or something at the beginning. - */ - q = strstr(line, "DISPLAY="); - if (! q) { - q = line; - } - n -= (q - line); - - for (k = 0; k < 1024; k++) { - line1[k] = q[k]; - if (q[k] == '\n') { - k++; - break; - } - } - n -= k; - i = 0; - for (j = 0; j < 16384; j++) { - if (j < 16384 - 1) { - /* xauth data, assume pty added CR */ - if (q[k+j] == '\r' && q[k+j+1] == '\n') { - continue; - } - } - - line2[i] = q[k+j]; - i++; - } -if (db) write(2, line, 100); -if (db) fprintf(stderr, "\n"); - - } else { - FILE *p; - int rc; - close_exec_fds(); - - if (usslpeer) { - char *c; - if (getuid() == 0) { - c = (char *) malloc(strlen("su - '' -c \"") - + strlen(usslpeer) + strlen(cmd) + 1 + 1); - sprintf(c, "su - '%s' -c \"%s\"", usslpeer, cmd); - } else { - c = strdup(cmd); - } - p = popen(c, "r"); - free(c); - - } else if (unixpw_nis && keep_unixpw_user) { - char *c; - if (getuid() == 0) { - c = (char *) malloc(strlen("su - '' -c \"") - + strlen(keep_unixpw_user) + strlen(cmd) + 1 + 1); - sprintf(c, "su - '%s' -c \"%s\"", keep_unixpw_user, cmd); - } else { - c = strdup(cmd); - } - p = popen(c, "r"); - free(c); - - } else { - p = popen(cmd, "r"); - } - - if (! p) { - rfbLog("wait_for_client: cmd failed: %s\n", cmd); - rfbLogPerror("popen"); - if (tmp_fd >= 0) { - unlink(tmp); - } - 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); - } - clean_up_exit(1); - } - n = fread(line2, 1, 16384, p); - rc = pclose(p); - - if (rc != 0) { - rfbLog("wait_for_client: find display cmd failed.\n"); - } - - if (create_cmd && rc != 0) { - FILE *mt = fopen(tmp, "w"); - if (! mt) { - rfbLog("wait_for_client: open failed: %s\n", tmp); - rfbLogPerror("fopen"); - if (tmp_fd >= 0) { - unlink(tmp); - } - clean_up_exit(1); - } - fprintf(mt, "%s", create_display); - fclose(mt); - - findcreatedisplay = 1; - - rfbLog("wait_for_client: FINDCREATEDISPLAY cmd: %s\n", create_cmd); - - p = popen(create_cmd, "r"); - if (! p) { - rfbLog("wait_for_client: cmd failed: %s\n", create_cmd); - rfbLogPerror("popen"); - if (tmp_fd >= 0) { - unlink(tmp); - } - clean_up_exit(1); - } - if (fgets(line1, 1024, p) == NULL) { - rfbLog("wait_for_client: read failed: %s\n", create_cmd); - rfbLogPerror("fgets"); - if (tmp_fd >= 0) { - unlink(tmp); - } - clean_up_exit(1); - } - n = fread(line2, 1, 16384, p); - pclose(p); - } - if (tmp_fd >= 0) { - unlink(tmp); - } - } - -if (db) fprintf(stderr, "line1=%s\n", line1); - - if (strstr(line1, "DISPLAY=") != line1) { - rfbLog("wait_for_client: bad reply '%s'\n", line1); - if (unixpw) { - unixpw_msg("No DISPLAY found.", 3); - } - clean_up_exit(1); - } - - - if (strstr(line1, ",VT=")) { - int vt; - char *t = strstr(line1, ",VT="); - vt = atoi(t + strlen(",VT=")); - *t = '\0'; - if (7 <= vt && vt <= 15) { - do_chvt(vt); - } - } else if (strstr(line1, ",XPID=")) { - int i, pvt, vt = -1; - char *t = strstr(line1, ",XPID="); - pvt = atoi(t + strlen(",XPID=")); - *t = '\0'; - if (pvt > 0) { - for (i=3; i <= 10; i++) { - int k; - char proc[100]; - char buf[100]; - sprintf(proc, "/proc/%d/fd/%d", pvt, i); -if (db) fprintf(stderr, "%d -- %s\n", i, proc); - for (k=0; k < 100; k++) { - buf[k] = '\0'; - } - - if (readlink(proc, buf, 100) != -1) { - buf[100-1] = '\0'; -if (db) fprintf(stderr, "%d -- %s -- %s\n", i, proc, buf); - if (strstr(buf, "/dev/tty") == buf) { - vt = atoi(buf + strlen("/dev/tty")); - if (vt > 0) { - break; - } - } - } - } - } - if (7 <= vt && vt <= 12) { - do_chvt(vt); - } - } - - use_dpy = strdup(line1 + strlen("DISPLAY=")); - q = use_dpy; - while (*q != '\0') { - if (*q == '\n' || *q == '\r') *q = '\0'; - q++; - } - if (line2[0] != '\0') { - if (strstr(line2, "XAUTHORITY=") == line2) { - q = line2; - while (*q != '\0') { - if (*q == '\n' || *q == '\r') *q = '\0'; - q++; - } - if (auth_file) { - free(auth_file); - } - auth_file = strdup(line2 + strlen("XAUTHORITY=")); - - } else { - xauth_raw_data = (char *)malloc(n); - xauth_raw_len = n; - memcpy(xauth_raw_data, line2, n); -if (db) {fprintf(stderr, "xauth_raw_len: %d\n", n); -write(2, xauth_raw_data, n); -fprintf(stderr, "\n");} - } - } - - if (!tried_switch) { - do_try_switch(usslpeer, users_list_save); - tried_switch = 1; - } - - if (unixpw) { - /* Some cleanup and messaging for -unixpw case: */ - char str[32]; - - if (keep_unixpw_user && keep_unixpw_pass) { - strzero(keep_unixpw_user); - strzero(keep_unixpw_pass); - keep_unixpw = 0; - } - - if (created_disp) { - snprintf(str, 30, "Created DISPLAY %s", use_dpy); - } else { - snprintf(str, 30, "Using DISPLAY %s", use_dpy); - } - unixpw_msg(str, 2); - } - return 1; -} - -void ssh_remote_tunnel(char *, int); - -static XImage ximage_struct; - -void progress_client(void) { - int i, j = 0, progressed = 0, db = 0; - double start = dnow(); - if (getenv("PROGRESS_CLIENT_DBG")) { - rfbLog("progress_client: begin\n"); - db = 1; - } - for (i = 0; i < 15; i++) { - if (latest_client) { - for (j = 0; j < 10; j++) { - if (latest_client->state != RFB_PROTOCOL_VERSION) { - progressed = 1; - break; - } - if (db) rfbLog("progress_client: calling-1 rfbCFD(1) %.6f\n", dnow()-start); - rfbCFD(1); - } - } - if (progressed) { - break; - } - if (db) rfbLog("progress_client: calling-2 rfbCFD(1) %.6f\n", dnow()-start); - rfbCFD(1); - } - if (!quiet) { - rfbLog("client progressed=%d in %d/%d %.6f s\n", - progressed, i, j, dnow() - start); - } -} - -int wait_for_client(int *argc, char** argv, int http) { - /* ugh, here we go... */ - XImage* fb_image; - int w = 640, h = 480, b = 32; - int w0 = -1, h0 = -1, i, chg_raw_fb = 0; - char *str, *q, *cmd = NULL; - int db = 0, dt = 0; - char *create_cmd = NULL; - char *users_list_save = NULL; - int created_disp = 0, ncache_save; - int did_client_connect = 0; - char *vnc_redirect_host = "localhost"; - int vnc_redirect_port = -1, vnc_redirect_cnt = 0; - char vnc_redirect_test[10]; - - if (getenv("WAIT_FOR_CLIENT_DB")) { - db = 1; - } - - vnc_redirect = 0; - - if (! use_dpy || strstr(use_dpy, "WAIT:") != use_dpy) { - return 0; - } - - for (i=0; i < *argc; i++) { - if (!strcmp(argv[i], "-desktop")) { - dt = 1; - } - if (db) fprintf(stderr, "args %d %s\n", i, argv[i]); - } - if (!quiet && !strstr(use_dpy, "FINDDISPLAY-run")) { - rfbLog("\n"); - rfbLog("wait_for_client: %s\n", use_dpy); - rfbLog("\n"); - } - - str = strdup(use_dpy); - str += strlen("WAIT"); - - xdmcp_insert = NULL; - - /* get any leading geometry: */ - 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); - } else { - w0 = -1; - h0 = -1; - } - *q = ':'; - str = q; - } - if ((w0 == -1 || h0 == -1) && pad_geometry != NULL) { - int b0, del = 0; - char *s = pad_geometry; - if (strstr(s, "once:") == s) { - del = 1; - s += strlen("once:"); - } - if (sscanf(s, "%dx%dx%d", &w0, &h0, &b0) == 3) { - w = nabs(w0); - h = nabs(h0); - b = nabs(b0); - } else if (sscanf(s, "%dx%d", &w0, &h0) == 2) { - w = nabs(w0); - h = nabs(h0); - } - if (del) { - pad_geometry = NULL; - } - } - - /* 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 { - /* hostname:0.0 */ - str++; - } - - if (db) fprintf(stderr, "str: %s\n", str); - - if (strstr(str, "cmd=") == str) { - cmd = setup_cmd(str, &vnc_redirect, &vnc_redirect_host, &vnc_redirect_port, db); - } - - fb_image = &ximage_struct; - setup_fake_fb(fb_image, w, h, b); - - if (! dt) { - char *s; - argv[*argc] = strdup("-desktop"); - *argc = (*argc) + 1; - - 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 = (*argc) + 1; - } - - ncache_save = ncache; - ncache = 0; - - initialize_allowed_input(); - - if (! multiple_cursors_mode) { - multiple_cursors_mode = strdup("default"); - } - initialize_cursors_mode(); - - initialize_screen(argc, argv, fb_image); - - if (! inetd && ! use_openssl) { - if (! screen->port || screen->listenSock < 0) { - if (got_rfbport && got_rfbport_val == 0) { - ; - } else if (ipv6_listen && ipv6_listen_fd >= 0) { - rfbLog("Info: listening on IPv6 interface only. (wait for client)\n"); - } else { - rfbLogEnable(1); - rfbLog("Error: could not obtain listening port. (wait for client)\n"); - if (!got_rfbport && !got_ipv6_listen) { - rfbLog("If this system is IPv6-only, use the -6 option.\n"); - } - clean_up_exit(1); - } - } - } - - initialize_signals(); - - if (ssh_str != NULL) { - ssh_remote_tunnel(ssh_str, screen->port); - } - - if (! raw_fb) { - chg_raw_fb = 1; - /* kludge to get RAWFB_RET with dpy == NULL guards */ - raw_fb = (char *) 0x1; - } - - if (cmd && !strcmp(cmd, "HTTPONCE")) { - handle_one_http_request(); - clean_up_exit(0); - } - - if (http && check_httpdir()) { - http_connections(1); - } - - if (cmd && unixpw) { - keep_unixpw = 1; - } - - setup_service(); - - check_waitbg(); - - if (vnc_redirect) { - vnc_redirect_loop(vnc_redirect_test, &vnc_redirect_cnt); - } else { - - if (use_threads && !started_rfbRunEventLoop) { - started_rfbRunEventLoop = 1; - rfbRunEventLoop(screen, -1, TRUE); - } - - if (inetd && use_openssl) { - accept_openssl(OPENSSL_INETD, -1); - } - - setup_client_connect(&did_client_connect); - - loop_for_connect(did_client_connect); - - if (unixpw) { - if (cmd && strstr(cmd, "FINDCREATEDISPLAY") == cmd) { - if (users_list && strstr(users_list, "unixpw=") == users_list) { - users_list_save = users_list; - users_list = NULL; - } - } - do_unixpw_loop(); - } else if (cmd && !use_threads) { - /* try to get RFB proto done now. */ - progress_client(); - } - } - - if (vnc_redirect == 2) { - ; - } else if (cmd) { - if (!do_run_cmd(cmd, create_cmd, users_list_save, created_disp, db)) { - return 0; - } - } else { - use_dpy = strdup(str); - } - if (chg_raw_fb) { - raw_fb = NULL; - } - - ncache = ncache_save; - - if (unixpw && keep_unixpw_opts && keep_unixpw_opts[0] != '\0') { - user_supplied_opts(keep_unixpw_opts); - } - if (create_cmd) { - free(create_cmd); - } - - if (vnc_redirect) { - do_vnc_redirect(created_disp, vnc_redirect_host, vnc_redirect_port, - vnc_redirect_cnt, vnc_redirect_test); - clean_up_exit(0); - } - - return 1; -} - |