Commit fd084b5d authored by runge's avatar runge

Improvements to -unixpw_cmd and -unixpw_nis.

Experimental X11VNC_WATCH_DX_DY=1 for buggy theme menus,
see: http://ubuntuforums.org/showthread.php?t=1223490
parent 2c6bf923
This diff is collapsed.
...@@ -574,18 +574,57 @@ int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, ...@@ -574,18 +574,57 @@ int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input,
close_exec_fds(); close_exec_fds();
if (output != NULL) { if (output != NULL) {
FILE *ph = popen(cmd, "r"); FILE *ph;
char line[1024]; char line[1024];
char *cmd2 = NULL;
char tmp[] = "/tmp/x11vnc-tmp.XXXXXX";
int deltmp = 0;
if (input != NULL) {
int tmp_fd = mkstemp(tmp);
if (tmp_fd < 0) {
rfbLog("mkstemp failed on: %s\n", tmp);
clean_up_exit(1);
}
write(tmp_fd, input, len);
close(tmp_fd);
deltmp = 1;
cmd2 = (char *) malloc(100 + strlen(tmp) + strlen(cmd));
sprintf(cmd2, "/bin/cat %s | %s", tmp, cmd);
ph = popen(cmd2, "r");
} else {
ph = popen(cmd, "r");
}
if (ph == NULL) { if (ph == NULL) {
rfbLog("popen(%s) failed", cmd); rfbLog("popen(%s) failed", cmd);
rfbLogPerror("popen"); rfbLogPerror("popen");
clean_up_exit(1); clean_up_exit(1);
} }
while (fgets(line, 1024, ph) != NULL) { memset(line, 0, sizeof(line));
while (fgets(line, sizeof(line), ph) != NULL) {
int j, k = -1;
if (0) fprintf(stderr, "line: %s", line); if (0) fprintf(stderr, "line: %s", line);
fprintf(output, "%s", line); /* take care to handle embedded nulls */
for (j=0; j < sizeof(line); j++) {
if (line[j] != '\0') {
k = j;
}
}
if (k >= 0) {
write(fileno(output), line, k+1);
}
memset(line, 0, sizeof(line));
} }
rc = pclose(ph); rc = pclose(ph);
if (cmd2 != NULL) {
free(cmd2);
}
if (deltmp) {
unlink(tmp);
}
goto got_rc; goto got_rc;
} else if (input != NULL) { } else if (input != NULL) {
FILE *ph = popen(cmd, "w"); FILE *ph = popen(cmd, "w");
...@@ -789,7 +828,7 @@ void client_gone(rfbClientPtr client) { ...@@ -789,7 +828,7 @@ void client_gone(rfbClientPtr client) {
free(userhost); free(userhost);
} else { } else {
rfbLog("client_gone: using cmd: %s\n", client->host); rfbLog("client_gone: using cmd: %s\n", client->host);
run_user_command(gone_cmd, client, "gone", NULL,0,NULL); run_user_command(gone_cmd, client, "gone", NULL, 0, NULL);
} }
} }
......
...@@ -83,8 +83,8 @@ so, delete this exception statement from your version. ...@@ -83,8 +83,8 @@ so, delete this exception statement from your version.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA or see <http://www.gnu.org/licenses/>. * USA or see <http://www.gnu.org/licenses/>.
* *
* In addition, as a special exception, Karl J. Runge * In addition, as a special exception, Karl J. Runge gives permission
* gives permission to link the code of its release of x11vnc with the * to link the code of its release of ultravnc_dsm_helper with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it * OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute * that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License * the linked executables. You must obey the GNU General Public License
......
This diff is collapsed.
...@@ -343,11 +343,22 @@ void update_x11_pointer_position(int x, int y) { ...@@ -343,11 +343,22 @@ void update_x11_pointer_position(int x, int y) {
return; return;
#else #else
int rc; int rc;
static int watch_dx_dy = -1;
RAWFB_RET_VOID RAWFB_RET_VOID
if (watch_dx_dy == -1) {
if (getenv("X11VNC_WATCH_DX_DY")) {
watch_dx_dy = 1;
} else {
watch_dx_dy = 0;
}
}
X_LOCK; X_LOCK;
if (use_xwarppointer) { if (watch_dx_dy && cursor_x == x && cursor_y == y) {
;
} else if (use_xwarppointer) {
/* /*
* off_x and off_y not needed with XWarpPointer since * off_x and off_y not needed with XWarpPointer since
* window is used: * window is used:
......
...@@ -96,6 +96,7 @@ void unixpw_accept(char *user); ...@@ -96,6 +96,7 @@ void unixpw_accept(char *user);
void unixpw_deny(void); void unixpw_deny(void);
void unixpw_msg(char *msg, int delay); void unixpw_msg(char *msg, int delay);
int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int nodisp); int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int nodisp);
int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n, int nodisp);
int crypt_verify(char *user, char *pass); int crypt_verify(char *user, char *pass);
int cmd_verify(char *user, char *pass); int cmd_verify(char *user, char *pass);
void unixpw_verify_screen(char *user, char *pass); void unixpw_verify_screen(char *user, char *pass);
...@@ -530,6 +531,82 @@ int crypt_verify(char *user, char *pass) { ...@@ -530,6 +531,82 @@ int crypt_verify(char *user, char *pass) {
#endif /* UNIXPW_CRYPT */ #endif /* UNIXPW_CRYPT */
} }
int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n, int nodisp) {
int i, len, rc;
char *str;
FILE *out;
if (! user || ! pass) {
return 0;
}
if (! unixpw_cmd || *unixpw_cmd == '\0') {
return 0;
}
if (! scheck(user, 100, "username")) {
return 0;
}
if (! scheck(pass, 100, "password")) {
return 0;
}
if (! unixpw_list_match(user)) {
return 0;
}
if (cmd == NULL) {
cmd = "";
}
len = strlen(user) + 1 + strlen(pass) + 1 + 1;
str = (char *) malloc(len);
if (! str) {
return 0;
}
str[0] = '\0';
strcat(str, user);
strcat(str, "\n");
strcat(str, pass);
if (!strchr(pass, '\n')) {
strcat(str, "\n");
}
out = tmpfile();
if (out == NULL) {
rfbLog("unixpw_cmd_run tmpfile() failed.\n");
clean_up_exit(1);
}
set_env("RFB_UNIXPW_CMD_RUN", cmd);
rc = run_user_command(unixpw_cmd, unixpw_client, "cmd_verify",
str, strlen(str), out);
set_env("RFB_UNIXPW_CMD_RUN", "");
for (i=0; i < len; i++) {
str[i] = '\0';
}
free(str);
fflush(out);
rewind(out);
for (i=0; i < (*n) - 1; i++) {
int c = fgetc(out);
if (c == EOF) {
break;
}
line[i] = (char) c;
}
fclose(out);
*n = i;
if (rc == 0) {
return 1;
} else {
return 0;
}
}
int cmd_verify(char *user, char *pass) { int cmd_verify(char *user, char *pass) {
int i, len, rc; int i, len, rc;
char *str; char *str;
...@@ -602,6 +679,7 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int ...@@ -602,6 +679,7 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int
set_db(); set_db();
first = 0; first = 0;
} }
rfbLog("su_verify: '%s' for %s.\n", user, cmd ? "command" : "login");
if (! scheck(user, 100, "username")) { if (! scheck(user, 100, "username")) {
return 0; return 0;
...@@ -1043,7 +1121,7 @@ int unixpw_verify(char *user, char *pass) { ...@@ -1043,7 +1121,7 @@ int unixpw_verify(char *user, char *pass) {
" succeeded.\n", user); " succeeded.\n", user);
ok = 1; ok = 1;
} else { } else {
rfbLog("unixpw_verify: crypt_verify login for '%s'" rfbLog("unixpw_verify: cmd_verify login for '%s'"
" failed.\n", user); " failed.\n", user);
usleep(3000*1000); usleep(3000*1000);
ok = 0; ok = 0;
......
...@@ -42,6 +42,7 @@ extern void unixpw_accept(char *user); ...@@ -42,6 +42,7 @@ extern void unixpw_accept(char *user);
extern void unixpw_deny(void); extern void unixpw_deny(void);
extern void unixpw_msg(char *msg, int delay); extern void unixpw_msg(char *msg, int delay);
extern int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int nodisp); extern int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int nodisp);
extern int unixpw_cmd_run(char *user, char *pass, char *cmd, char *line, int *n, int nodisp);
extern int crypt_verify(char *user, char *pass); extern int crypt_verify(char *user, char *pass);
extern int cmd_verify(char *user, char *pass); extern int cmd_verify(char *user, char *pass);
extern int unixpw_verify(char *user, char *pass); extern int unixpw_verify(char *user, char *pass);
......
...@@ -308,6 +308,9 @@ static void user2uid(char *user, uid_t *uid, gid_t *gid, char **name, char **hom ...@@ -308,6 +308,9 @@ static void user2uid(char *user, uid_t *uid, gid_t *gid, char **name, char **hom
if (strstr(user2group[i], user) == user2group[i]) { if (strstr(user2group[i], user) == user2group[i]) {
char *w = user2group[i] + strlen(user); char *w = user2group[i] + strlen(user);
if (*w == '.') { if (*w == '.') {
#if (SMALL_FOOTPRINT > 2)
gotgroup = 0;
#else
struct group* gr = getgrnam(++w); struct group* gr = getgrnam(++w);
if (! gr) { if (! gr) {
rfbLog("Invalid group: %s\n", w); rfbLog("Invalid group: %s\n", w);
...@@ -320,6 +323,7 @@ static void user2uid(char *user, uid_t *uid, gid_t *gid, char **name, char **hom ...@@ -320,6 +323,7 @@ static void user2uid(char *user, uid_t *uid, gid_t *gid, char **name, char **hom
did[i] = 1; did[i] = 1;
} }
gotgroup = 1; gotgroup = 1;
#endif
} }
} }
i++; i++;
...@@ -761,7 +765,7 @@ static int switch_user_env(uid_t uid, gid_t gid, char *name, char *home, int fb_ ...@@ -761,7 +765,7 @@ static int switch_user_env(uid_t uid, gid_t gid, char *name, char *home, int fb_
return 0; return 0;
#else #else
/* /*
* OK tricky here, we need to free the shm... otherwise * OK, tricky here, we need to free the shm... otherwise
* we won't be able to delete it as the other user... * we won't be able to delete it as the other user...
*/ */
if (fb_mode == 1 && (using_shm && ! xform24to32)) { if (fb_mode == 1 && (using_shm && ! xform24to32)) {
...@@ -773,11 +777,13 @@ static int switch_user_env(uid_t uid, gid_t gid, char *name, char *home, int fb_ ...@@ -773,11 +777,13 @@ static int switch_user_env(uid_t uid, gid_t gid, char *name, char *home, int fb_
#if LIBVNCSERVER_HAVE_PWD_H #if LIBVNCSERVER_HAVE_PWD_H
if (getpwuid(uid) != NULL && getenv("X11VNC_SINGLE_GROUP") == NULL) { if (getpwuid(uid) != NULL && getenv("X11VNC_SINGLE_GROUP") == NULL) {
struct passwd *p = getpwuid(uid); struct passwd *p = getpwuid(uid);
if (initgroups(p->pw_name, gid) == 0) { /* another possibility is p->pw_gid instead of gid */
if (setgid(gid) == 0 && initgroups(p->pw_name, gid) == 0) {
grp_ok = 1; grp_ok = 1;
} else { } else {
rfbLogPerror("initgroups"); rfbLogPerror("initgroups");
} }
endgrent();
} }
#endif #endif
#endif #endif
...@@ -2235,12 +2241,58 @@ static char *get_usslpeer() { ...@@ -2235,12 +2241,58 @@ static char *get_usslpeer() {
return upeer; return upeer;
} }
static void do_try_switch(char *usslpeer, char *users_list_save) {
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 int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int created_disp, int db) { 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 tmp[] = "/tmp/x11vnc-find_display.XXXXXX";
char line1[1024], line2[16384]; char line1[1024], line2[16384];
char *q, *usslpeer = NULL; char *q, *usslpeer = NULL;
int n, nodisp = 0, saw_xdmcp = 0; int n, nodisp = 0, saw_xdmcp = 0;
int tmp_fd = -1; int tmp_fd = -1;
int internal_cmd = 0;
int tried_switch = 0;
memset(line1, 0, 1024); memset(line1, 0, 1024);
memset(line2, 0, 16384); memset(line2, 0, 16384);
...@@ -2251,6 +2303,7 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr ...@@ -2251,6 +2303,7 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
return 0; return 0;
} }
} }
if (getenv("DEBUG_RUN_CMD")) db = 1;
/* only sets environment variables: */ /* only sets environment variables: */
run_user_command("", latest_client, "env", NULL, 0, NULL); run_user_command("", latest_client, "env", NULL, 0, NULL);
...@@ -2265,7 +2318,11 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr ...@@ -2265,7 +2318,11 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
strstr(cmd, "FINDCREATEDISPLAY") == cmd) { strstr(cmd, "FINDCREATEDISPLAY") == cmd) {
char *nd = ""; char *nd = "";
char fdout[128]; char fdout[128];
internal_cmd = 1;
tmp_fd = mkstemp(tmp); tmp_fd = mkstemp(tmp);
if (tmp_fd < 0) { if (tmp_fd < 0) {
rfbLog("wait_for_client: open failed: %s\n", tmp); rfbLog("wait_for_client: open failed: %s\n", tmp);
rfbLogPerror("mkstemp"); rfbLogPerror("mkstemp");
...@@ -2302,7 +2359,7 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr ...@@ -2302,7 +2359,7 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
rfbLog("wait_for_client: running: %s\n", cmd); rfbLog("wait_for_client: running: %s\n", cmd);
if (unixpw) { if (unixpw && !unixpw_nis) {
int res = 0, k, j, i; int res = 0, k, j, i;
char line[18000]; char line[18000];
...@@ -2310,8 +2367,13 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr ...@@ -2310,8 +2367,13 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
if (keep_unixpw_user && keep_unixpw_pass) { if (keep_unixpw_user && keep_unixpw_pass) {
n = 18000; n = 18000;
res = su_verify(keep_unixpw_user, if (unixpw_cmd != NULL) {
keep_unixpw_pass, cmd, line, &n, nodisp); res = unixpw_cmd_run(keep_unixpw_user,
keep_unixpw_pass, cmd, line, &n, nodisp);
} 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 (db) {fprintf(stderr, "line: "); write(2, line, n); write(2, "\n", 1); fprintf(stderr, "res=%d n=%d\n", res, n);}
...@@ -2331,7 +2393,13 @@ if (db) {fprintf(stderr, "line: "); write(2, line, n); write(2, "\n", 1); fprint ...@@ -2331,7 +2393,13 @@ if (db) {fprintf(stderr, "line: "); write(2, line, n); write(2, "\n", 1); fprint
findcreatedisplay = 1; findcreatedisplay = 1;
if (getuid() != 0) { if (unixpw_cmd != NULL) {
/* let the external unixpw command do it: */
n = 18000;
close_exec_fds();
res = unixpw_cmd_run(keep_unixpw_user,
keep_unixpw_pass, create_cmd, line, &n, nodisp);
} else if (getuid() != 0) {
/* if not root, run as the other user... */ /* if not root, run as the other user... */
n = 18000; n = 18000;
close_exec_fds(); close_exec_fds();
...@@ -2411,6 +2479,7 @@ if (db) fprintf(stderr, "line1: '%s'\n", line1); ...@@ -2411,6 +2479,7 @@ if (db) fprintf(stderr, "line1: '%s'\n", line1);
} }
if (db) write(2, line, 100); if (db) write(2, line, 100);
if (db) fprintf(stderr, "\n"); if (db) fprintf(stderr, "\n");
} else { } else {
FILE *p; FILE *p;
int rc; int rc;
...@@ -2428,9 +2497,22 @@ if (db) fprintf(stderr, "\n"); ...@@ -2428,9 +2497,22 @@ if (db) fprintf(stderr, "\n");
p = popen(c, "r"); p = popen(c, "r");
free(c); 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 { } else {
p = popen(cmd, "r"); p = popen(cmd, "r");
} }
if (! p) { if (! p) {
rfbLog("wait_for_client: cmd failed: %s\n", cmd); rfbLog("wait_for_client: cmd failed: %s\n", cmd);
rfbLogPerror("popen"); rfbLogPerror("popen");
...@@ -2575,49 +2657,13 @@ fprintf(stderr, "\n");} ...@@ -2575,49 +2657,13 @@ fprintf(stderr, "\n");}
} }
} }
if (usslpeer) { if (!tried_switch) {
char *u = (char *) malloc(strlen(usslpeer+2)); do_try_switch(usslpeer, users_list_save);
sprintf(u, "+%s", usslpeer); tried_switch = 1;
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\n", user);
} else if (switch_user(u, 0)) {
rfbLog("unixpw_accept switched to user: %s\n", user);
} else {
rfbLog("unixpw_accept failed to switch to user: %s\n", user);
}
free(u);
} }
if (unixpw) { if (unixpw) {
/* Some cleanup and messaging for -unixpw case: */
char str[32]; char str[32];
if (keep_unixpw_user && keep_unixpw_pass) { if (keep_unixpw_user && keep_unixpw_pass) {
......
This diff is collapsed.
...@@ -2482,6 +2482,9 @@ int main(int argc, char* argv[]) { ...@@ -2482,6 +2482,9 @@ int main(int argc, char* argv[]) {
if (unixpw_list) { if (unixpw_list) {
unixpw_list = NULL; unixpw_list = NULL;
} }
if (unixpw_cmd) {
unixpw_cmd = NULL;
}
continue; continue;
} }
if (!strcmp(arg, "-vencrypt")) { if (!strcmp(arg, "-vencrypt")) {
......
...@@ -47,7 +47,7 @@ int xtrap_base_event_type = 0; ...@@ -47,7 +47,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0; int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */ /* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.9.9 lastmod: 2009-07-11"; char lastmod[] = "0.9.9 lastmod: 2009-08-10";
/* X display info */ /* X display info */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment