summaryrefslogtreecommitdiffstats
path: root/x11vnc/user.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/user.c')
-rw-r--r--x11vnc/user.c3155
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;
-}
-