summaryrefslogtreecommitdiffstats
path: root/x11vnc/user.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/user.c')
-rw-r--r--x11vnc/user.c203
1 files changed, 191 insertions, 12 deletions
diff --git a/x11vnc/user.c b/x11vnc/user.c
index 09da679..7349c8b 100644
--- a/x11vnc/user.c
+++ b/x11vnc/user.c
@@ -1221,6 +1221,7 @@ void user_supplied_opts(char *opts) {
}
extern char find_display[];
+extern char create_display[];
static XImage ximage_struct;
int wait_for_client(int *argc, char** argv, int http) {
@@ -1231,6 +1232,9 @@ int wait_for_client(int *argc, char** argv, int http) {
int db = 0;
char tmp[] = "/tmp/x11vnc-find_display.XXXXXX";
int tmp_fd = -1, dt = 0;
+ char *create_cmd = NULL;
+ char *users_list_save = NULL;
+ int created_disp = 0;
if (! use_dpy || strstr(use_dpy, "WAIT:") != use_dpy) {
return 0;
@@ -1285,6 +1289,10 @@ int wait_for_client(int *argc, char** argv, int http) {
fprintf(stdout, "%s", find_display);
clean_up_exit(0);
}
+ if (!strcmp(str, "FINDCREATEDISPLAY-print")) {
+ fprintf(stdout, "%s", create_display);
+ clean_up_exit(0);
+ }
if (db) fprintf(stderr, "cmd: %s\n", cmd);
}
@@ -1394,6 +1402,12 @@ int wait_for_client(int *argc, char** argv, int http) {
rfbLog("taking unixpw_client off hold.\n");
unixpw_client->onHold = FALSE;
}
+ if (cmd && strstr(cmd, "FINDCREATEDISPLAY") == cmd) {
+ if (users_list && strstr(users_list, "unixpw=") == users_list) {
+ users_list_save = users_list;
+ users_list = NULL;
+ }
+ }
while (1) {
if (shut_down) {
clean_up_exit(0);
@@ -1421,7 +1435,8 @@ int wait_for_client(int *argc, char** argv, int http) {
memset(line1, 0, 1024);
memset(line2, 0, 16384);
- if (!strcmp(cmd, "FINDDISPLAY")) {
+ if (!strcmp(cmd, "FINDDISPLAY") ||
+ strstr(cmd, "FINDCREATEDISPLAY") == cmd) {
tmp_fd = mkstemp(tmp);
if (tmp_fd < 0) {
rfbLog("wait_for_client: open failed: %s\n", tmp);
@@ -1431,6 +1446,28 @@ int wait_for_client(int *argc, char** argv, int http) {
write(tmp_fd, find_display, strlen(find_display));
close(tmp_fd);
chmod(tmp, 0644);
+
+ if (strstr(cmd, "FINDCREATEDISPLAY") == cmd) {
+ char *opts = strchr(cmd, '-');
+ char st[] = "";
+ if (opts) {
+ opts++;
+ } else {
+ opts = st;
+ }
+ if (unixpw && keep_unixpw_user) {
+ create_cmd = (char *) malloc(strlen(tmp)
+ + strlen("env USER='' /bin/sh ")
+ + strlen(keep_unixpw_user) + 1 + strlen(opts) + 1);
+ sprintf(create_cmd, "env USER='%s' /bin/sh %s %s",
+ keep_unixpw_user, 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);
+ }
+if (db) fprintf(stderr, "create_cmd: %s\n", create_cmd);
+ }
cmd = (char *) malloc(strlen(tmp) + strlen("/bin/sh ") + 1);
sprintf(cmd, "/bin/sh %s", tmp);
}
@@ -1447,17 +1484,58 @@ int wait_for_client(int *argc, char** argv, int http) {
n = 18000;
res = su_verify(keep_unixpw_user,
keep_unixpw_pass, cmd, line, &n);
- strzero(keep_unixpw_user);
- strzero(keep_unixpw_pass);
}
- keep_unixpw = 0;
+
+if (db) write(2, line, n); write(2, "\n", 1);
+
+ 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);
+
+ if (getuid() != 0) {
+ /* if not root, run as the other user... */
+ n = 18000;
+ res = su_verify(keep_unixpw_user,
+ keep_unixpw_pass, create_cmd, line, &n);
+/*if (1) fprintf(stderr, "line: '%s'\n", line); */
+
+ } else {
+ FILE *p;
+ close_exec_fds();
+ 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 (tmp_fd >= 0) {
unlink(tmp);
}
-if (db) write(2, line, n); write(2, "\n", 1);
-
if (! res) {
rfbLog("wait_for_client: cmd failed: %s\n", cmd);
unixpw_msg("No DISPLAY found.", 3);
@@ -1490,18 +1568,23 @@ if (db) write(2, line, n); write(2, "\n", 1);
continue;
}
}
+
line2[i] = q[k+j];
i++;
}
+write(2, line, 100);
+fprintf(stderr, "\n");
} else {
- FILE *p = popen(cmd, "r");
+ FILE *p;
+ int rc;
+ close_exec_fds();
+ p = popen(cmd, "r");
if (! p) {
rfbLog("wait_for_client: cmd failed: %s\n", cmd);
rfbLogPerror("popen");
if (tmp_fd >= 0) {
unlink(tmp);
}
- unixpw_msg("No DISPLAY found.", 3);
clean_up_exit(1);
}
if (fgets(line1, 1024, p) == NULL) {
@@ -1510,22 +1593,71 @@ if (db) write(2, line, n); write(2, "\n", 1);
if (tmp_fd >= 0) {
unlink(tmp);
}
- unixpw_msg("No DISPLAY found.", 3);
clean_up_exit(1);
}
n = fread(line2, 1, 16384, p);
- pclose(p);
+ rc = pclose(p);
+
+ 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);
+
+ 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);
+ }
if (tmp_fd >= 0) {
unlink(tmp);
}
}
+
if (strstr(line1, "DISPLAY=") != line1) {
- rfbLog("wait_for_client: bad reply %s\n", line1);
+ rfbLog("wait_for_client: bad reply '%s'\n", line1);
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 <= 128) {
+ char chvt[100];
+ sprintf(chvt, "chvt %d >/dev/null 2>/dev/null &", vt);
+ rfbLog("running: %s\n", chvt);
+ system(chvt);
+ sleep(2);
+ }
+ }
+
use_dpy = strdup(line1 + strlen("DISPLAY="));
q = use_dpy;
while (*q != '\0') {
@@ -1551,9 +1683,53 @@ if (db) write(2, line, n); write(2, "\n", 1);
if (db) fprintf(stderr, "xauth_raw_len: %d\n", n);
}
}
+
+ 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\n", user);
+ } else if (switch_user(u, 0)) {
+ rfbLog("unixpw_accept switched to user: %s\n", user);
+ } else {
+ rfbLog("unixpw_accept failed to switched to user: %s\n", user);
+ }
+ free(u);
+ }
+
if (unixpw) {
char str[32];
- snprintf(str, 30, "Using DISPLAY %s", use_dpy);
+
+ 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);
}
} else {
@@ -1565,6 +1741,9 @@ if (db) fprintf(stderr, "xauth_raw_len: %d\n", n);
if (unixpw && keep_unixpw_opts && keep_unixpw_opts[0] != '\0') {
user_supplied_opts(keep_unixpw_opts);
}
+ if (create_cmd) {
+ free(create_cmd);
+ }
return 1;
}