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 source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -574,18 +574,57 @@ int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input,
close_exec_fds();
if (output != NULL) {
FILE *ph = popen(cmd, "r");
FILE *ph;
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) {
rfbLog("popen(%s) failed", cmd);
rfbLogPerror("popen");
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);
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);
if (cmd2 != NULL) {
free(cmd2);
}
if (deltmp) {
unlink(tmp);
}
goto got_rc;
} else if (input != NULL) {
FILE *ph = popen(cmd, "w");
......@@ -789,7 +828,7 @@ void client_gone(rfbClientPtr client) {
free(userhost);
} else {
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.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* 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
* In addition, as a special exception, Karl J. Runge gives permission
* to link the code of its release of ultravnc_dsm_helper 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
......
......@@ -335,8 +335,8 @@ void print_help(int mode) {
" is needed for the latter, feel free to ask).\n"
"\n"
"-scale fraction Scale the framebuffer by factor \"fraction\". Values\n"
" less than 1 shrink the fb, larger ones expand it. Note:\n"
" image may not be sharp and response may be slower.\n"
" less than 1 shrink the fb, larger ones expand it. Note:\n"
" the image may not be sharp and response may be slower.\n"
" If \"fraction\" contains a decimal point \".\" it\n"
" is taken as a floating point number, alternatively\n"
" the notation \"m/n\" may be used to denote fractions\n"
......@@ -507,7 +507,7 @@ void print_help(int mode) {
" Repeater mode: Some services provide an intermediate\n"
" \"vnc repeater\": http://www.uvnc.com/addons/repeater.html\n"
" (and also http://koti.mbnet.fi/jtko/ for linux port)\n"
" that acts as a proxy / gateway. Modes like these require\n"
" that acts as a proxy/gateway. Modes like these require\n"
" an initial string to be sent for the reverse connection\n"
" before the VNC protocol is started. Here are the ways\n"
" to do this:\n"
......@@ -782,12 +782,12 @@ void print_help(int mode) {
" full-access passwords)\n"
"\n"
"-unixpw [list] Use Unix username and password authentication. x11vnc\n"
" uses the su(1) program to verify the user's password.\n"
" [list] is an optional comma separated list of allowed\n"
" Unix usernames. If the [list] string begins with the\n"
" character \"!\" then the entire list is taken as an\n"
" exclude list. See below for per-user options that can\n"
" be applied.\n"
" will use the su(1) program to verify the user's\n"
" password. [list] is an optional comma separated list\n"
" of allowed Unix usernames. If the [list] string begins\n"
" with the character \"!\" then the entire list is taken\n"
" as an exclude list. See below for per-user options\n"
" that can be applied.\n"
"\n"
" A familiar \"login:\" and \"Password:\" dialog is\n"
" presented to the user on a black screen inside the\n"
......@@ -803,8 +803,9 @@ void print_help(int mode) {
"\n"
" Since the detailed behavior of su(1) can vary from\n"
" OS to OS and for local configurations, test the mode\n"
" carefully. x11vnc will attempt to be conservative and\n"
" reject a login if anything abnormal occurs.\n"
" before deployment to make sure it is working properly.\n"
" x11vnc will attempt to be conservative and reject a\n"
" login if anything abnormal occurs.\n"
"\n"
" One case to note: FreeBSD and the other BSD's by\n"
" default it is impossible for the user running x11vnc to\n"
......@@ -837,7 +838,7 @@ void print_help(int mode) {
" to come from the same machine x11vnc is running on\n"
" (e.g. from a ssh -L port redirection). And that the\n"
" -stunnel SSL mode be used for encryption over the\n"
" network.(see the description of -stunnel below).\n"
" network. (see the description of -stunnel below).\n"
"\n"
" Note: as a convenience, if you ssh(1) in and start\n"
" x11vnc it will check if the environment variable\n"
......@@ -865,7 +866,7 @@ void print_help(int mode) {
" Set UNIXPW_DISABLE_LOCALHOST=1 to disable the -localhost\n"
" requirement in Method 2). One should never do this\n"
" (i.e. allow the Unix passwords to be sniffed on the\n"
" network).\n"
" network.)\n"
"\n"
" Regarding reverse connections (e.g. -R connect:host\n"
" and -connect host), when the -localhost constraint is\n"
......@@ -883,7 +884,7 @@ void print_help(int mode) {
" in -inetd mode (thereby bypassing inetd). See the FAQ\n"
" for details.\n"
"\n"
" The user names in the comma separated [list] can have\n"
" The user names in the comma separated [list] may have\n"
" per-user options after a \":\", e.g. \"fred:opts\"\n"
" where \"opts\" is a \"+\" separated list of\n"
" \"viewonly\", \"fullaccess\", \"input=XXXX\", or\n"
......@@ -891,13 +892,13 @@ void print_help(int mode) {
" For \"input=\" it is the K,M,B,C described under -input.\n"
"\n"
" If an item in the list is \"*\" that means those\n"
" options apply to all users. It also means all users\n"
" options apply to all users. It ALSO implies all users\n"
" are allowed to log in after supplying a valid password.\n"
" Use \"deny\" to explicitly deny some users if you use\n"
" \"*\" to set a global option. If [list] begins with\n"
" the \"!\" character then \"*\" is ignored for checking\n"
" if the user is allowed, but the any value of options\n"
" associated with it does apply as normal.\n"
" \"*\" to set a global option. If [list] begins with the\n"
" \"!\" character then \"*\" is ignored for checking if\n"
" the user is allowed, but the option values associated\n"
" with it do apply as normal.\n"
"\n"
" There are also some utilities for testing password\n"
" if [list] starts with the \"%%\" character. See the\n"
......@@ -922,32 +923,89 @@ void print_help(int mode) {
"\n"
" NIS is not required for this mode to work (only that\n"
" getpwnam(3) return the encrypted password is required),\n"
" but it is unlikely it will work for any most modern\n"
" environments unless x11vnc is run as root to be able\n"
" to access /etc/shadow (note running as root is often\n"
" done when running x11vnc from inetd and xdm/gdm/kdm).\n"
" but it is unlikely it will work (as an ordinary user)\n"
" for most modern environments unless NIS is available.\n"
" On the other hand, when x11vnc is run as root it will\n"
" be able to to access /etc/shadow even if NIS is not\n"
" available (note running as root is often done when\n"
" running x11vnc from inetd and xdm/gdm/kdm).\n"
"\n"
" Looked at another way, if you do not want to use the\n"
" su(1) method provided by -unixpw, you can run x11vnc\n"
" as root and use -unixpw_nis. Any users with passwords\n"
" in /etc/shadow can then be authenticated. You may want\n"
" to use -users unixpw= to switch the process user after\n"
" the user logs in.\n"
" su(1) method provided by -unixpw (i.e. su_verify()), you\n"
" can run x11vnc as root and use -unixpw_nis. Any users\n"
" with passwords in /etc/shadow can then be authenticated.\n"
"\n"
" In -unixpw_nis mode, under no circumstances is x11vnc's\n"
" user password verifying function based on su called\n"
" (i.e. the function su_verify() that runs /bin/su\n"
" in a pseudoterminal to verify passwords.) However,\n"
" if -unixpw_nis is used in conjunction with the -find\n"
" and -create -display WAIT:... modes then, if x11vnc is\n"
" running as root, /bin/su may be called externally to\n"
" run the find or create commands.\n"
"\n"
"-unixpw_cmd cmd As -unixpw above, however do not use su(1) but rather\n"
" run the externally supplied command \"cmd\". The first\n"
" line of its stdin will the username and the second line\n"
" the received password. If the command exits with status\n"
" 0 (success) the VNC client will be accepted. It will be\n"
" rejected for any other return status.\n"
"\n"
" Dynamic passwords and non-unix passwords can be\n"
" implemented this way by providing your own custom helper\n"
" program. Note that under unixpw mode the remote viewer\n"
" is given 3 tries to enter the correct password.\n"
"\n"
" If a list of allowed users is needed use -unixpw [list]\n"
" in addition to this option.\n"
" line of its stdin will be the username and the second\n"
" line the received password. If the command exits\n"
" with status 0 (success) the VNC user will be accepted.\n"
" It will be rejected for any other return status.\n"
"\n"
" Dynamic passwords and non-unix passwords, e.g. LDAP,\n"
" can be implemented this way by providing your own custom\n"
" helper program. Note that the remote viewer is given 3\n"
" tries to enter the correct password, and so the program\n"
" may be called in a row that many (or more) times.\n"
"\n"
" If a list of allowed users is needed to limit who can\n"
" log in, use -unixpw [list] in addition to this option.\n"
"\n"
" In FINDDISPLAY and FINDCREATEDISPLAY modes the \"cmd\"\n"
" will also be run with the RFB_UNIXPW_CMD_RUN env. var.\n"
" non-empty and set to the corresponding display\n"
" find/create command. The first two lines of input are\n"
" the username and passwd as in the normal case described\n"
" above. To support FINDDISPLAY and FINDCREATEDISPLAY,\n"
" \"cmd\" should run the requested command as the user\n"
" (and most likely refusing to run it if the password is\n"
" not correct.) Here is an example script (note it has\n"
" a hardwired bogus password \"abc\"!)\n"
"\n"
" #!/bin/sh\n"
" # Example x11vnc -unixpw_cmd script.\n"
" # Read the first two lines of stdin (user and passwd)\n"
" read user\n"
" read pass\n"
" \n"
" debug=0\n"
" if [ $debug = 1 ]; then\n"
" echo \"user: $user\" 1>&2\n"
" echo \"pass: $pass\" 1>&2\n"
" env | egrep -i 'rfb|vnc' 1>&2\n"
" fi\n"
" \n"
" # Check if the password is valid.\n"
" # (A real example would use ldap lookup, etc!)\n"
" if [ \"X$pass\" != \"Xabc\" ]; then\n"
" exit 1 # incorrect password\n"
" fi\n"
" \n"
" if [ \"X$RFB_UNIXPW_CMD_RUN\" = \"X\" ]; then\n"
" exit 0 # correct password\n"
" else\n"
" # Run the requested command (finddisplay)\n"
" if [ $debug = 1 ]; then\n"
" echo \"run: $RFB_UNIXPW_CMD_RUN\" 1>&2\n"
" fi\n"
" exec /bin/su - \"$user\" -c \"$RFB_UNIXPW_CMD_RUN\"\n"
" fi\n"
"\n"
" In -unixpw_cmd mode, under no circumstances is x11vnc's\n"
" user password verifying function based on su called\n"
" (i.e. the function su_verify() that runs /bin/su in a\n"
" pseudoterminal to verify passwords.) It is up to the\n"
" supplied unixpw_cmd to do user switching if desired\n"
" and if it has the permissions to do so.\n"
"\n"
"-find Find the user's display using FINDDISPLAY. This is an\n"
" alias for \"-display WAIT:cmd=FINDDISPLAY\".\n"
......@@ -1064,9 +1122,15 @@ void print_help(int mode) {
"\n"
" xauth extract - $DISPLAY\"\n"
"\n"
" In the case of -unixpw (but not -unixpw_nis), then the\n"
" cmd= command is run as the user who just authenticated\n"
" via the login and password prompt.\n"
" In the case of -unixpw (and -unixpw_nis only if x11vnc\n"
" is running as root), then the cmd= command is run\n"
" as the user who just authenticated via the login and\n"
" password prompt.\n"
"\n"
" In the case of -unixpw_cmd, the commands will also be\n"
" run as the logged-in user, as long as the user-supplied\n"
" helper program supports RFB_UNIXPW_CMD_RUN (see the\n"
" -unixpw_cmd option.)\n"
"\n"
" Also in the case of -unixpw, the user logging in can\n"
" place a colon at the end of her username and supply\n"
......
......@@ -343,11 +343,22 @@ void update_x11_pointer_position(int x, int y) {
return;
#else
int rc;
static int watch_dx_dy = -1;
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;
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
* window is used:
......
......@@ -96,6 +96,7 @@ void unixpw_accept(char *user);
void unixpw_deny(void);
void unixpw_msg(char *msg, int delay);
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 cmd_verify(char *user, char *pass);
void unixpw_verify_screen(char *user, char *pass);
......@@ -530,6 +531,82 @@ int crypt_verify(char *user, char *pass) {
#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 i, len, rc;
char *str;
......@@ -602,6 +679,7 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size, int
set_db();
first = 0;
}
rfbLog("su_verify: '%s' for %s.\n", user, cmd ? "command" : "login");
if (! scheck(user, 100, "username")) {
return 0;
......@@ -1043,7 +1121,7 @@ int unixpw_verify(char *user, char *pass) {
" succeeded.\n", user);
ok = 1;
} else {
rfbLog("unixpw_verify: crypt_verify login for '%s'"
rfbLog("unixpw_verify: cmd_verify login for '%s'"
" failed.\n", user);
usleep(3000*1000);
ok = 0;
......
......@@ -42,6 +42,7 @@ extern void unixpw_accept(char *user);
extern void unixpw_deny(void);
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 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 cmd_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
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);
......@@ -320,6 +323,7 @@ static void user2uid(char *user, uid_t *uid, gid_t *gid, char **name, char **hom
did[i] = 1;
}
gotgroup = 1;
#endif
}
}
i++;
......@@ -761,7 +765,7 @@ static int switch_user_env(uid_t uid, gid_t gid, char *name, char *home, int fb_
return 0;
#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...
*/
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_
#if LIBVNCSERVER_HAVE_PWD_H
if (getpwuid(uid) != NULL && getenv("X11VNC_SINGLE_GROUP") == NULL) {
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;
} else {
rfbLogPerror("initgroups");
}
endgrent();
}
#endif
#endif
......@@ -2235,12 +2241,58 @@ static char *get_usslpeer() {
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) {
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, 1024);
memset(line2, 0, 16384);
......@@ -2251,6 +2303,7 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
return 0;
}
}
if (getenv("DEBUG_RUN_CMD")) db = 1;
/* only sets environment variables: */
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
strstr(cmd, "FINDCREATEDISPLAY") == cmd) {
char *nd = "";
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");
......@@ -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);
if (unixpw) {
if (unixpw && !unixpw_nis) {
int res = 0, k, j, i;
char line[18000];
......@@ -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) {
n = 18000;
res = su_verify(keep_unixpw_user,
keep_unixpw_pass, cmd, line, &n, nodisp);
if (unixpw_cmd != NULL) {
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);}
......@@ -2331,7 +2393,13 @@ if (db) {fprintf(stderr, "line: "); write(2, line, n); write(2, "\n", 1); fprint
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... */
n = 18000;
close_exec_fds();
......@@ -2411,6 +2479,7 @@ if (db) fprintf(stderr, "line1: '%s'\n", line1);
}
if (db) write(2, line, 100);
if (db) fprintf(stderr, "\n");
} else {
FILE *p;
int rc;
......@@ -2428,9 +2497,22 @@ if (db) fprintf(stderr, "\n");
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");
......@@ -2575,49 +2657,13 @@ fprintf(stderr, "\n");}
}
}
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\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 (!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) {
......
.\" This file was automatically generated from x11vnc -help output.
.TH X11VNC "1" "July 2009" "x11vnc " "User Commands"
.TH X11VNC "1" "August 2009" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.9.9, lastmod: 2009-07-11
version: 0.9.9, lastmod: 2009-08-10
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -347,8 +347,8 @@ is needed for the latter, feel free to ask).
\fB-scale\fR \fIfraction\fR
.IP
Scale the framebuffer by factor \fIfraction\fR. Values
less than 1 shrink the fb, larger ones expand it. Note:
image may not be sharp and response may be slower.
less than 1 shrink the fb, larger ones expand it. Note:
the image may not be sharp and response may be slower.
If \fIfraction\fR contains a decimal point "." it
is taken as a floating point number, alternatively
the notation "m/n" may be used to denote fractions
......@@ -568,7 +568,7 @@ is running as root (e.g. via
Repeater mode: Some services provide an intermediate
"vnc repeater": http://www.uvnc.com/addons/repeater.html
(and also http://koti.mbnet.fi/jtko/ for linux port)
that acts as a proxy / gateway. Modes like these require
that acts as a proxy/gateway. Modes like these require
an initial string to be sent for the reverse connection
before the VNC protocol is started. Here are the ways
to do this:
......@@ -871,14 +871,14 @@ full-access passwords)
\fB-unixpw\fR \fI[list]\fR
.IP
Use Unix username and password authentication. x11vnc
uses the
will use the
.IR su (1)
program to verify the user's password.
[list] is an optional comma separated list of allowed
Unix usernames. If the [list] string begins with the
character "!" then the entire list is taken as an
exclude list. See below for per-user options that can
be applied.
program to verify the user's
password. [list] is an optional comma separated list
of allowed Unix usernames. If the [list] string begins
with the character "!" then the entire list is taken
as an exclude list. See below for per-user options
that can be applied.
.IP
A familiar "login:" and "Password:" dialog is
presented to the user on a black screen inside the
......@@ -896,8 +896,9 @@ Since the detailed behavior of
.IR su (1)
can vary from
OS to OS and for local configurations, test the mode
carefully. x11vnc will attempt to be conservative and
reject a login if anything abnormal occurs.
before deployment to make sure it is working properly.
x11vnc will attempt to be conservative and reject a
login if anything abnormal occurs.
.IP
One case to note: FreeBSD and the other BSD's by
default it is impossible for the user running x11vnc to
......@@ -932,7 +933,7 @@ Method 2) requires the viewer connection to appear
to come from the same machine x11vnc is running on
(e.g. from a ssh \fB-L\fR port redirection). And that the
\fB-stunnel\fR SSL mode be used for encryption over the
network.(see the description of \fB-stunnel\fR below).
network. (see the description of \fB-stunnel\fR below).
.IP
Note: as a convenience, if you
.IR ssh (1)
......@@ -966,7 +967,7 @@ local connections from that machine are accepted).
Set UNIXPW_DISABLE_LOCALHOST=1 to disable the \fB-localhost\fR
requirement in Method 2). One should never do this
(i.e. allow the Unix passwords to be sniffed on the
network).
network.)
.IP
Regarding reverse connections (e.g. \fB-R\fR connect:host
and \fB-connect\fR host), when the \fB-localhost\fR constraint is
......@@ -984,7 +985,7 @@ Tip: you can also have your own stunnel spawn x11vnc
in \fB-inetd\fR mode (thereby bypassing inetd). See the FAQ
for details.
.IP
The user names in the comma separated [list] can have
The user names in the comma separated [list] may have
per-user options after a ":", e.g. "fred:opts"
where "opts" is a "+" separated list of
"viewonly", "fullaccess", "input=XXXX", or
......@@ -992,13 +993,13 @@ where "opts" is a "+" separated list of
For "input=" it is the K,M,B,C described under \fB-input.\fR
.IP
If an item in the list is "*" that means those
options apply to all users. It also means all users
options apply to all users. It ALSO implies all users
are allowed to log in after supplying a valid password.
Use "deny" to explicitly deny some users if you use
"*" to set a global option. If [list] begins with
the "!" character then "*" is ignored for checking
if the user is allowed, but the any value of options
associated with it does apply as normal.
"*" to set a global option. If [list] begins with the
"!" character then "*" is ignored for checking if
the user is allowed, but the option values associated
with it do apply as normal.
.IP
There are also some utilities for testing password
if [list] starts with the "%" character. See the
......@@ -1032,18 +1033,27 @@ user can authenticate ANY user.
NIS is not required for this mode to work (only that
.IR getpwnam (3)
return the encrypted password is required),
but it is unlikely it will work for any most modern
environments unless x11vnc is run as root to be able
to access /etc/shadow (note running as root is often
done when running x11vnc from inetd and xdm/gdm/kdm).
but it is unlikely it will work (as an ordinary user)
for most modern environments unless NIS is available.
On the other hand, when x11vnc is run as root it will
be able to to access /etc/shadow even if NIS is not
available (note running as root is often done when
running x11vnc from inetd and xdm/gdm/kdm).
.IP
Looked at another way, if you do not want to use the
.IR su (1)
method provided by \fB-unixpw,\fR you can run x11vnc
as root and use \fB-unixpw_nis.\fR Any users with passwords
in /etc/shadow can then be authenticated. You may want
to use \fB-users\fR unixpw= to switch the process user after
the user logs in.
method provided by \fB-unixpw\fR (i.e. su_verify()), you
can run x11vnc as root and use \fB-unixpw_nis.\fR Any users
with passwords in /etc/shadow can then be authenticated.
.IP
In \fB-unixpw_nis\fR mode, under no circumstances is x11vnc's
user password verifying function based on su called
(i.e. the function su_verify() that runs /bin/su
in a pseudoterminal to verify passwords.) However,
if \fB-unixpw_nis\fR is used in conjunction with the \fB-find\fR
and \fB-create\fR \fB-display\fR WAIT:... modes then, if x11vnc is
running as root, /bin/su may be called externally to
run the find or create commands.
.PP
\fB-unixpw_cmd\fR \fIcmd\fR
.IP
......@@ -1051,18 +1061,66 @@ As \fB-unixpw\fR above, however do not use
.IR su (1)
but rather
run the externally supplied command \fIcmd\fR. The first
line of its stdin will the username and the second line
the received password. If the command exits with status
0 (success) the VNC client will be accepted. It will be
rejected for any other return status.
.IP
Dynamic passwords and non-unix passwords can be
implemented this way by providing your own custom helper
program. Note that under unixpw mode the remote viewer
is given 3 tries to enter the correct password.
.IP
If a list of allowed users is needed use \fB-unixpw\fR [list]
in addition to this option.
line of its stdin will be the username and the second
line the received password. If the command exits
with status 0 (success) the VNC user will be accepted.
It will be rejected for any other return status.
.IP
Dynamic passwords and non-unix passwords, e.g. LDAP,
can be implemented this way by providing your own custom
helper program. Note that the remote viewer is given 3
tries to enter the correct password, and so the program
may be called in a row that many (or more) times.
.IP
If a list of allowed users is needed to limit who can
log in, use \fB-unixpw\fR [list] in addition to this option.
.IP
In FINDDISPLAY and FINDCREATEDISPLAY modes the \fIcmd\fR
will also be run with the RFB_UNIXPW_CMD_RUN env. var.
non-empty and set to the corresponding display
find/create command. The first two lines of input are
the username and passwd as in the normal case described
above. To support FINDDISPLAY and FINDCREATEDISPLAY,
\fIcmd\fR should run the requested command as the user
(and most likely refusing to run it if the password is
not correct.) Here is an example script (note it has
a hardwired bogus password "abc"!)
.IP
#!/bin/sh
# Example x11vnc \fB-unixpw_cmd\fR script.
# Read the first two lines of stdin (user and passwd)
read user
read pass
.IP
debug=0
if [ $debug = 1 ]; then
echo "user: $user" 1>&2
echo "pass: $pass" 1>&2
env | egrep \fB-i\fR 'rfb|vnc' 1>&2
fi
.IP
# Check if the password is valid.
# (A real example would use ldap lookup, etc!)
if [ "X$pass" != "Xabc" ]; then
exit 1 # incorrect password
fi
.IP
if [ "X$RFB_UNIXPW_CMD_RUN" = "X" ]; then
exit 0 # correct password
else
# Run the requested command (finddisplay)
if [ $debug = 1 ]; then
echo "run: $RFB_UNIXPW_CMD_RUN" 1>&2
fi
exec /bin/su - "$user" \fB-c\fR "$RFB_UNIXPW_CMD_RUN"
fi
.IP
In \fB-unixpw_cmd\fR mode, under no circumstances is x11vnc's
user password verifying function based on su called
(i.e. the function su_verify() that runs /bin/su in a
pseudoterminal to verify passwords.) It is up to the
supplied unixpw_cmd to do user switching if desired
and if it has the permissions to do so.
.PP
\fB-find\fR
.IP
......@@ -1214,9 +1272,15 @@ xauthority data for the display. For example;
.IP
xauth extract - $DISPLAY"
.IP
In the case of \fB-unixpw\fR (but not \fB-unixpw_nis),\fR then the
cmd= command is run as the user who just authenticated
via the login and password prompt.
In the case of \fB-unixpw\fR (and \fB-unixpw_nis\fR only if x11vnc
is running as root), then the cmd= command is run
as the user who just authenticated via the login and
password prompt.
.IP
In the case of \fB-unixpw_cmd,\fR the commands will also be
run as the logged-in user, as long as the user-supplied
helper program supports RFB_UNIXPW_CMD_RUN (see the
\fB-unixpw_cmd\fR option.)
.IP
Also in the case of \fB-unixpw,\fR the user logging in can
place a colon at the end of her username and supply
......@@ -5827,7 +5891,7 @@ max time in ms to wait for RFB client
\fB-rfbauth\fR \fIpasswd-file\fR
.IP
use authentication on RFB protocol
(use 'storepasswd' to create a password file)
(use 'x11vnc \fB-storepasswd\fR pass file' to create a password file)
.PP
\fB-rfbversion\fR \fI3.x\fR
.IP
......
......@@ -2482,6 +2482,9 @@ int main(int argc, char* argv[]) {
if (unixpw_list) {
unixpw_list = NULL;
}
if (unixpw_cmd) {
unixpw_cmd = NULL;
}
continue;
}
if (!strcmp(arg, "-vencrypt")) {
......
......@@ -47,7 +47,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* 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 */
......
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