Commit a7726a6f authored by runge's avatar runge

x11vnc: more -unixpw work. add -license, etc. options

parent 99921601
2006-07-04 Karl Runge <runge@karlrunge.com>
* configure.ac: add getspnam.
2006-06-08 Karl Runge <runge@karlrunge.com>
* prepare_x11vnc_dist.sh: to 0.8.2
......
......@@ -445,7 +445,7 @@ AC_FUNC_VPRINTF
AC_FUNC_FORK
AC_CHECK_LIB(nsl,gethostbyname)
AC_CHECK_LIB(socket,socket)
AC_CHECK_FUNCS([ftime gethostbyname gethostname gettimeofday inet_ntoa memmove memset mmap mkfifo select socket strchr strcspn strdup strerror strstr setsid setpgrp getpwuid getpwnam getuid geteuid setuid setgid seteuid setegid waitpid setutxent grantpt])
AC_CHECK_FUNCS([ftime gethostbyname gethostname gettimeofday inet_ntoa memmove memset mmap mkfifo select socket strchr strcspn strdup strerror strstr setsid setpgrp getpwuid getpwnam getspnam getuid geteuid setuid setgid seteuid setegid waitpid setutxent grantpt])
# check, if shmget is in cygipc.a
AC_CHECK_LIB(cygipc,shmget)
......
2006-07-04 Karl Runge <runge@karlrunge.com>
* x11vnc: 2nd -accept popup with WAIT, and UNIX: info for unixpw
login. Use RFB_CLIENT_ON_HOLD for -unixpw. -unixpw white arrow
-license option. Use getspnam if getpwnam is short.
abbrevs sc=, cm, ck for user:opts.
2006-06-23 Karl Runge <runge@karlrunge.com>
* x11vnc: misc cleanup.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -48,6 +48,7 @@ void start_client_info_sock(char *host_port_cookie);
void send_client_info(char *str);
void adjust_grabs(int grab, int quiet);
void check_new_clients(void);
int accept_client(rfbClientPtr client);
static rfbClientPtr *client_match(char *str);
......@@ -58,7 +59,6 @@ static void ugly_geom(char *p, int *x, int *y);
static int ugly_window(char *addr, char *userhost, int X, int Y,
int timeout, char *mode, int accept);
static int action_match(char *action, int rc);
static int accept_client(rfbClientPtr client);
static void check_connect_file(char *file);
static void send_client_connect(void);
......@@ -133,7 +133,11 @@ char *list_clients(void) {
char *s = ident_username(cl);
if (s) free(s);
}
strcat(list, cd->username);
if (strstr(cd->username, "UNIX:") == cd->username) {
strcat(list, cd->username + strlen("UNIX:"));
} else {
strcat(list, cd->username);
}
strcat(list, ":");
if (cd->unixname[0] == '\0') {
strcat(list, "none");
......@@ -996,7 +1000,15 @@ static unsigned char t2x2_bits[] = {
XFlush_wr(dpy);
if (accept) {
snprintf(strh, 100, "x11vnc: accept connection from %s?", addr);
char *ip = addr;
char *type = "accept";
if (unixpw && strstr(userhost, "UNIX:") != userhost) {
type = "unixpw";
if (openssl_last_ip) {
ip = openssl_last_ip;
}
}
snprintf(strh, 100, "x11vnc: %s connection from %s?", type, ip);
} else {
snprintf(strh, 100, "x11vnc: client disconnected from %s", addr);
}
......@@ -1282,7 +1294,7 @@ static void ugly_geom(char *p, int *x, int *y) {
* popup: use internal X widgets for prompting.
*
*/
static int accept_client(rfbClientPtr client) {
int accept_client(rfbClientPtr client) {
char xmessage[200], *cmd = NULL;
char *addr = client->host;
......@@ -1327,6 +1339,14 @@ static int accept_client(rfbClientPtr client) {
mode = "both";
}
if (dpy == NULL && use_dpy && strstr(use_dpy, "WAIT:") ==
use_dpy) {
rfbLog("accept_client: warning allowing client under conditions:\n");
rfbLog(" -display WAIT:, dpy == NULL, -accept popup.\n");
rfbLog(" There will be another popup.\n");
return 1;
}
rfbLog("accept_client: using builtin popup for: %s\n", addr);
if ((ret = ugly_window(addr, userhost, x, y, timeout,
mode, 1))) {
......@@ -1526,6 +1546,7 @@ static int do_reverse_connect(char *str) {
rfbLog("reverse connections disabled in -ssl mode.\n");
return 0;
}
if (unixpw_in_progress) return 0;
/* copy in to host */
host = (char *) malloc(len+1);
......@@ -1579,11 +1600,15 @@ static int do_reverse_connect(char *str) {
* Break up comma separated list of hosts and call do_reverse_connect()
*/
void reverse_connect(char *str) {
char *p, *tmp = strdup(str);
char *p, *tmp;
int sleep_between_host = 300;
int sleep_min = 1500, sleep_max = 4500, n_max = 5;
int n, tot, t, dt = 100, cnt = 0;
if (unixpw_in_progress) return;
tmp = strdup(str);
p = strtok(tmp, ", \t\r\n");
while (p) {
if ((n = do_reverse_connect(p)) != 0) {
......@@ -1887,7 +1912,6 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
last_event = last_input = time(NULL);
if (inetd) {
/*
* Set this so we exit as soon as connection closes,
......@@ -2010,6 +2034,12 @@ if (0) fprintf(stderr, "SET ssl_helper_pid: %d\n", openssl_last_helper_pid);
unixpw_last_try_time = time(NULL);
unixpw_screen(1);
unixpw_keystroke(0, 0, 1);
if (!unixpw_in_rfbPE) {
rfbLog("new client: %s in non-unixpw_in_rfbPE.\n",
client->host);
}
/* always put client on hold even if unixpw_in_rfbPE is true */
return(RFB_CLIENT_ON_HOLD);
}
return(RFB_CLIENT_ACCEPT);
......
......@@ -31,5 +31,6 @@ extern void start_client_info_sock(char *host_port_cookie);
extern void send_client_info(char *str);
extern void adjust_grabs(int grab, int quiet);
extern void check_new_clients(void);
extern int accept_client(rfbClientPtr client);
#endif /* _X11VNC_CONNECTIONS_H */
......@@ -30,6 +30,7 @@ int cursor_shape_updates_clients(rfbScreenInfoPtr s);
int cursor_pos_updates_clients(rfbScreenInfoPtr s);
void cursor_position(int x, int y);
void set_no_cursor(void);
void set_warrow_cursor(void);
int set_cursor(int x, int y, int which);
int check_x11_pointer(void);
......@@ -490,6 +491,7 @@ enum cursor_names {
CURS_DOT,
CURS_ARROW,
CURS_WARROW,
CURS_ROOT,
CURS_WM,
CURS_TERM,
......@@ -657,6 +659,7 @@ static void setup_cursors(void) {
alt_arrow = 1;
curs_copy(cursors[CURS_ARROW], &cur_arrow); n++;
}
curs_copy(cursors[CURS_WARROW], &cur_arrow2); n++;
curs_copy(cursors[CURS_ROOT], &cur_root); n++;
curs_copy(cursors[CURS_WM], &cur_fleur); n++;
......@@ -1744,6 +1747,10 @@ void set_no_cursor(void) {
set_rfb_cursor(CURS_EMPTY);
}
void set_warrow_cursor(void) {
set_rfb_cursor(CURS_WARROW);
}
int set_cursor(int x, int y, int which) {
static int last = -1;
int changed_cursor = 0;
......
......@@ -27,6 +27,7 @@ extern int cursor_shape_updates_clients(rfbScreenInfoPtr s);
extern int cursor_pos_updates_clients(rfbScreenInfoPtr s);
extern void cursor_position(int x, int y);
extern void set_no_cursor(void);
extern void set_warrow_cursor(void);
extern int set_cursor(int x, int y, int which);
extern int check_x11_pointer(void);
......
This diff is collapsed.
......@@ -4,6 +4,7 @@
/* -- help.h -- */
extern void print_help(int mode);
extern void print_license(void);
extern void xopen_display_fail_message(char *disp);
extern void nopassword_warning_msg(int gotloc);
......
/* -- inet.c -- */
#include "x11vnc.h"
#include "unixpw.h"
#include "sslhelper.h"
/*
* Simple utility to map host name to dotted IP address. Ignores aliases.
......@@ -22,7 +24,6 @@ int have_ssh_env(void);
static int get_port(int sock, int remote);
static char *get_host(int sock, int remote);
char *host2ip(char *host) {
struct hostent *hp;
struct sockaddr_in addr;
......@@ -291,7 +292,11 @@ char *ident_username(rfbClientPtr client) {
if (!strcmp(user, "unknown-user") && cd && cd->unixname[0] != '\0') {
user = cd->unixname;
}
newhost = ip2host(client->host);
if (unixpw && openssl_last_ip && strstr("UNIX:", user) != user) {
newhost = ip2host(openssl_last_ip);
} else {
newhost = ip2host(client->host);
}
len = strlen(user) + 1 + strlen(newhost) + 1;
str = (char *) malloc(len);
sprintf(str, "%s@%s", user, newhost);
......
......@@ -617,7 +617,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
last_x = x;
last_y = y;
}
if (mask >= 0 && unixpw && unixpw_in_progress) {
if (unixpw && unixpw_in_progress) {
return;
}
......
......@@ -23,6 +23,7 @@
#include "userinput.h"
#include "keyboard.h"
#include "selection.h"
#include "unixpw.h"
int send_remote_cmd(char *cmd, int query, int wait);
int do_remote_query(char *remote_cmd, char *query_cmd, int remote_sync,
......@@ -633,6 +634,10 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("remote commands disabled: %s\n", cmd);
return NULL;
}
if (unixpw_in_progress) {
rfbLog("skip remote command: %s unixpw_in_progress.\n", cmd);
return NULL;
}
if (!query_default && priv_remote) {
if (! remote_control_access_ok()) {
......
......@@ -1294,6 +1294,8 @@ static int copy_tiles(int tx, int ty, int nt) {
char *src, *dst, *s_src, *s_dst, *m_src, *m_dst;
char *h_src, *h_dst;
if (unixpw_in_progress) return 0;
if (! first_line) {
/* allocate arrays first time in. */
int n = ntiles_x + 1;
......@@ -1626,6 +1628,8 @@ static int copy_all_tiles(void) {
int x, y, n, m;
int diffs = 0, ct;
if (unixpw_in_progress) return 0;
for (y=0; y < ntiles_y; y++) {
for (x=0; x < ntiles_x; x++) {
n = x + y * ntiles_x;
......@@ -1672,6 +1676,8 @@ static int copy_all_tile_runs(void) {
int in_run = 0, run = 0;
int ntave = 0, ntcnt = 0;
if (unixpw_in_progress) return 0;
for (y=0; y < ntiles_y; y++) {
for (x=0; x < ntiles_x + 1; x++) {
n = x + y * ntiles_x;
......@@ -1742,6 +1748,8 @@ static int copy_tiles_backward_pass(void) {
int x, y, n, m;
int diffs = 0, ct;
if (unixpw_in_progress) return 0;
for (y = ntiles_y - 1; y >= 0; y--) {
for (x = ntiles_x - 1; x >= 0; x--) {
n = x + y * ntiles_x; /* number of this tile */
......@@ -1783,6 +1791,8 @@ static int copy_tiles_additional_pass(void) {
int x, y, n;
int diffs = 0, ct;
if (unixpw_in_progress) return 0;
for (y=0; y < ntiles_y; y++) {
for (x=0; x < ntiles_x; x++) {
n = x + y * ntiles_x; /* number of this tile */
......@@ -1974,6 +1984,7 @@ int copy_screen(void) {
if (! fs_factor) {
return 0;
}
if (unixpw_in_progress) return 0;
block_size = (dpy_x * (dpy_y/fs_factor) * pixelsize);
......@@ -2686,6 +2697,9 @@ int scan_for_updates(int count_only) {
*/
old_copy_tile = 0;
}
if (unixpw_in_progress) return 0;
if (old_copy_tile) {
tile_diffs = copy_all_tiles();
} else {
......
......@@ -31,6 +31,7 @@ int openssl_sock = -1;
int openssl_port_num = 0;
int https_sock = -1;
pid_t openssl_last_helper_pid = 0;
char *openssl_last_ip = NULL;
void raw_xfer(int csock, int s_in, int s_out);
......@@ -1030,7 +1031,6 @@ if (db) fprintf(stderr, "waitpid(%d) 2\n", helpers[i]);
}
}
/* AUDIT */
static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
int mode) {
int nfd, db = 0;
......@@ -1063,7 +1063,7 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
*/
if (time(NULL) < last_https + 30) {
tv.tv_sec = 8;
if (strstr(last_get, "VncViewer")) {
if (last_get && strstr(last_get, "VncViewer")) {
tv.tv_sec = 4;
}
}
......@@ -1099,6 +1099,9 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
if (getenv("ACCEPT_OPENSSL_DEBUG")) {
db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
}
if (! buf_a || ! n_a) {
return 0;
}
buf = (char *) calloc((ABSIZE+1), 1);
*n_a = 0;
......@@ -1137,7 +1140,9 @@ static int watch_for_http_traffic(char *buf_a, int *n_a) {
if (n2 >= 0) {
n += n2;
}
*n_a = n;
if (db) fprintf(stderr, "watch_for_http_traffic readmore: %d\n", n2);
if (n > 0) {
......@@ -1180,6 +1185,7 @@ static int wait_conn(int sock) {
int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie,
int mode) {
int sock1, db = 0;
char reply[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: octet-stream\r\n"
"Pragma: no-cache\r\n\r\n";
......@@ -1187,7 +1193,6 @@ int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie,
"Content-Type: octet-stream\r\n"
"Content-Length: 9\r\n"
"Pragma: no-cache\r\n\r\nGO_AHEAD\n";
int sock1, db = 0;
rfbLog("SSL: accept_openssl: detected https proxied connection"
" request.\n");
......@@ -1208,20 +1213,24 @@ int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie,
} else if (mode == OPENSSL_HTTPS) {
listen = https_sock;
} else {
/* inetd */
return 0;
}
sock1 = wait_conn(listen);
if (csock_timeout_sock < 0 || sock1 < 0) {
close(sock1);
return 0;
}
if (db) fprintf(stderr, "got applet input sock1: %d\n", sock1);
if (! ssl_init(sock1, sock1)) {
if (db) fprintf(stderr, "ssl_init FAILED\n");
exit(1);
}
SSL_write(ssl, reply, strlen(reply));
{
......@@ -1241,21 +1250,23 @@ if (db) fprintf(stderr, "buf: '%s'\n", buf);
}
}
write(vncsock, cookie, strlen(cookie));
if (cookie) {
write(vncsock, cookie, strlen(cookie));
}
ssl_xfer(vncsock, sock1, sock1, 0);
return 1;
}
void accept_openssl(int mode) {
int sock = -1, cport, csock, vsock, listen = -1;
int sock = -1, listen = -1, cport, csock, vsock;
int status, n, i, db = 0;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
char cookie[128], rcookie[128], *name;
rfbClientPtr client;
pid_t pid;
char uniq[] = "__evilrats__";
char cookie[128], rcookie[128], *name = NULL;
static time_t last_https = 0;
static char last_get[128];
static int first = 1;
......@@ -1267,7 +1278,7 @@ void accept_openssl(int mode) {
if (first) {
last_get[i] = '\0';
}
cookie[i] = '\0';
cookie[i] = '\0';
rcookie[i] = '\0';
}
first = 0;
......@@ -1280,26 +1291,35 @@ void accept_openssl(int mode) {
if (mode == OPENSSL_INETD) {
ssl_initialized = 1;
} else if (mode == OPENSSL_VNC && openssl_sock >= 0) {
} else if (mode == OPENSSL_VNC) {
sock = accept(openssl_sock, (struct sockaddr *)&addr, &addrlen);
listen = openssl_sock;
if (sock < 0) {
rfbLog("SSL: accept_openssl: accept connection failed\n");
rfbLogPerror("accept");
return;
}
listen = openssl_sock;
} else if (mode == OPENSSL_HTTPS && https_sock >= 0) {
} else if (mode == OPENSSL_HTTPS) {
sock = accept(https_sock, (struct sockaddr *)&addr, &addrlen);
listen = https_sock;
if (sock < 0) {
rfbLog("SSL: accept_openssl: accept connection failed\n");
rfbLogPerror("accept");
return;
}
listen = https_sock;
}
if (db) fprintf(stderr, "SSL: accept_openssl: sock: %d\n", sock);
if (openssl_last_ip) {
free(openssl_last_ip);
openssl_last_ip = NULL;
}
if (mode == OPENSSL_INETD) {
openssl_last_ip = get_remote_host(fileno(stdin));
} else {
openssl_last_ip = get_remote_host(sock);
}
/* now make a listening socket for child to connect back to us by: */
......@@ -1339,11 +1359,23 @@ void accept_openssl(int mode) {
if (mode != OPENSSL_INETD) {
name = get_remote_host(sock);
} else {
name = strdup("inetd-connection");
openssl_last_ip = get_remote_host(fileno(stdin));
if (openssl_last_ip) {
name = strdup(openssl_last_ip);
} else {
name = strdup("unknown");
}
}
if (name) {
rfbLog("SSL: spawning helper process to handle: %s\n", name);
if (mode == OPENSSL_INETD) {
rfbLog("SSL: (inetd) spawning helper process "
"to handle: %s\n", name);
} else {
rfbLog("SSL: spawning helper process to handle: "
"%s\n", name);
}
free(name);
name = NULL;
}
/* now fork the child to handle the SSL: */
......@@ -1361,7 +1393,7 @@ void accept_openssl(int mode) {
} else if (pid == 0) {
int s_in, s_out, httpsock = -1;
int vncsock, sslsock = sock;
int vncsock;
int i, have_httpd = 0;
int f_in = fileno(stdin);
int f_out = fileno(stdout);
......@@ -1376,7 +1408,7 @@ void accept_openssl(int mode) {
continue;
}
}
if (i == sslsock) {
if (i == sock) {
continue;
}
if (i == 2) {
......@@ -1400,7 +1432,6 @@ void accept_openssl(int mode) {
if (vncsock < 0) {
rfbLog("SSL: ssl_helper[%d]: could not connect"
" back to: %d\n", getpid(), cport);
close(vncsock);
exit(1);
}
......@@ -1424,6 +1455,10 @@ void accept_openssl(int mode) {
* SSL socket.
*/
if (! screen) {
close(vncsock);
exit(1);
}
if (screen->httpListenSock >= 0 && screen->httpPort > 0) {
have_httpd = 1;
}
......@@ -1470,6 +1505,7 @@ void accept_openssl(int mode) {
*/
if (db) fprintf(stderr, "watch_for_http_traffic\n");
is_http = watch_for_http_traffic(buf, &n);
if (is_http < 0 || is_http == 0) {
......@@ -1484,7 +1520,9 @@ void accept_openssl(int mode) {
}
goto wrote_cookie;
}
if (db) fprintf(stderr, "is_http: %d n: %d\n", is_http, n);
if (db) fprintf(stderr, "is_http: %d n: %d\n",
is_http, n);
if (db) fprintf(stderr, "buf: '%s'\n", buf);
if (strstr(buf, "/request.https.vnc.connection")) {
......@@ -1497,6 +1535,8 @@ void accept_openssl(int mode) {
* instead of a direct SSL connection.
*/
rfbLog("Handling VNC request via https GET. [%d]\n", getpid());
/* AUDIT */
if (strstr(buf, "/reverse.proxy")) {
char *buf;
int n, ptr;
......@@ -1736,6 +1776,10 @@ if (db) fprintf(stderr, "iface: %s\n", iface);
inetd_client = client;
client->clientGoneHook = client_gone;
}
if (openssl_last_ip &&
strpbrk(openssl_last_ip, "0123456789") == openssl_last_ip) {
client->host = strdup(openssl_last_ip);
}
} else {
rfbLog("SSL: accept_openssl: rfbNewClient failed.\n");
close(vsock);
......
......@@ -12,6 +12,7 @@ extern int openssl_sock;
extern int openssl_port_num;
extern int https_sock;
extern pid_t openssl_last_helper_pid;
extern char *openssl_last_ip;
extern void raw_xfer(int csock, int s_in, int s_out);
......
......@@ -5,6 +5,7 @@
extern int grantpt(int);
extern int unlockpt(int);
extern char *ptsname(int);
/* XXX remove need for this */
extern char *crypt(const char*, const char *);
#endif
......@@ -14,6 +15,8 @@ extern char *crypt(const char*, const char *);
#include "xinerama.h"
#include "connections.h"
#include "user.h"
#include "connections.h"
#include "cursor.h"
#include <rfb/default8x16.h>
#if LIBVNCSERVER_HAVE_FORK
......@@ -25,6 +28,9 @@ extern char *crypt(const char*, const char *);
#if LIBVNCSERVER_HAVE_PWD_H && LIBVNCSERVER_HAVE_GETPWNAM
#if LIBVNCSERVER_HAVE_CRYPT || LIBVNCSERVER_HAVE_LIBCRYPT
#define UNIXPW_CRYPT
#if LIBVNCSERVER_HAVE_GETSPNAM
#include <shadow.h>
#endif
#endif
#endif
......@@ -65,6 +71,7 @@ static void set_db(void);
static void unixpw_verify(char *user, char *pass);
int unixpw_in_progress = 0;
int unixpw_in_rfbPE = 0;
int unixpw_login_viewonly = 0;
time_t unixpw_last_try_time = 0;
rfbClientPtr unixpw_client = NULL;
......@@ -143,6 +150,8 @@ void unixpw_screen(int init) {
char_y = y;
char_col = strlen(log);
char_row = 0;
set_warrow_cursor();
}
if (scaling) {
......@@ -347,11 +356,32 @@ int crypt_verify(char *user, char *pass) {
return 0;
}
if (db > 1) fprintf(stderr, "realpw='%s'\n", realpw);
if (strlen(realpw) < 10) {
/* e.g. "x", try getspnam(), sometimes root for inetd, etc */
#if LIBVNCSERVER_HAVE_GETSPNAM
struct spwd *sp = getspnam(user);
if (sp != NULL && sp->sp_pwdp != NULL) {
if (db) fprintf(stderr, "using getspnam()\n");
realpw = sp->sp_pwdp;
} else {
if (db) fprintf(stderr, "skipping getspnam()\n");
}
#endif
}
n = strlen(pass);
if (pass[n-1] == '\n') {
pass[n-1] = '\0';
}
/* XXX remove need for cast */
cr = (char *) crypt(pass, realpw);
if (db > 1) {
fprintf(stderr, "user='%s' pass='%s' realpw='%s' cr='%s'\n",
user, pass, realpw, cr ? cr : "(null)");
}
if (cr == NULL) {
return 0;
}
......@@ -793,6 +823,7 @@ static void unixpw_verify(char *user, char *pass) {
char li[] = "Login incorrect";
char log[] = "login: ";
char *colon = NULL;
ClientData *cd = NULL;
if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "********");
rfbLog("unixpw_verify: %s\n", user);
......@@ -802,10 +833,23 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
*colon = '\0';
rfbLog("unixpw_verify: colon: %s\n", user);
}
if (unixpw_client) {
cd = (ClientData *) unixpw_client->clientData;
if (cd) {
char *str = (char *)malloc(strlen("UNIX:") +
strlen(user) + 1);
sprintf(str, "UNIX:%s", user);
if (cd->username) {
free(cd->username);
}
cd->username = str;
}
}
if (unixpw_nis) {
if (crypt_verify(user, pass)) {
rfbLog("unixpw_verify: crypt_verify login for '%s'"
" succeeded.\n", user);
unixpw_accept(user);
if (keep_unixpw) {
keep_unixpw_user = strdup(user);
......@@ -818,12 +862,14 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
}
if (colon) *colon = ':';
return;
} else {
rfbLog("unixpw_verify: crypt_verify login for %s failed.\n", user);
usleep(3000*1000);
}
rfbLog("unixpw_verify: crypt_verify login for '%s' failed.\n",
user);
usleep(3000*1000);
} else {
if (su_verify(user, pass, NULL, NULL, NULL)) {
rfbLog("unixpw_verify: su_verify login for '%s'"
" succeeded.\n", user);
unixpw_accept(user);
if (keep_unixpw) {
keep_unixpw_user = strdup(user);
......@@ -837,7 +883,8 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
if (colon) *colon = ':';
return;
}
rfbLog("unixpw_verify: su_verify login for %s failed.\n", user);
rfbLog("unixpw_verify: su_verify login for '%s' failed.\n",
user);
}
if (colon) *colon = ':';
......@@ -1142,6 +1189,17 @@ static void apply_opts (char *user) {
void unixpw_accept(char *user) {
apply_opts(user);
if (accept_cmd && strstr(accept_cmd, "popup") == accept_cmd) {
if (use_dpy && strstr(use_dpy, "WAIT:") == use_dpy &&
dpy == NULL) {
/* handled in main() */
unixpw_client->onHold = TRUE;
} else if (! accept_client(unixpw_client)) {
unixpw_deny();
return;
}
}
if (started_as_root == 1 && users_list
&& strstr(users_list, "unixpw=") == users_list) {
if (getuid() && geteuid()) {
......
......@@ -12,6 +12,7 @@ extern int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_si
extern int crypt_verify(char *user, char *pass);
extern int unixpw_in_progress;
extern int unixpw_in_rfbPE;
extern int unixpw_login_viewonly;
extern time_t unixpw_last_try_time;
extern rfbClientPtr unixpw_client;
......
......@@ -1038,8 +1038,8 @@ void user_supplied_opts(char *opts) {
char *p, *str;
char *allow[] = {
"skip-display", "skip-auth", "skip-shared",
"scale", "scale_cursor", "solid", "id", "clear_mods",
"clear_keys", "repeat", "speeds",
"scale", "scale_cursor", "sc", "solid", "id",
"clear_mods", "cm", "clear_keys", "ck", "repeat", "speeds",
NULL
};
......@@ -1067,7 +1067,8 @@ void user_supplied_opts(char *opts) {
i++;
}
if (! ok && sscanf(p, "%d/%d", &n, &m) == 2) {
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) {
......@@ -1077,6 +1078,8 @@ void user_supplied_opts(char *opts) {
} else if (strstr(p, "auth=") == p) {
if (auth_file) free(auth_file);
auth_file = strdup(p + strlen("auth="));
} else if (!strcmp(p, "shared")) {
shared = 1;
} else if (strstr(p, "scale=") == p) {
if (scale_str) free(scale_str);
scale_str = strdup(p + strlen("scale="));
......@@ -1084,8 +1087,9 @@ void user_supplied_opts(char *opts) {
if (scale_cursor_str) free(scale_cursor_str);
scale_cursor_str = strdup(p +
strlen("scale_cursor="));
} else if (!strcmp(p, "shared")) {
shared = 1;
} else if (strstr(p, "sc=") == p) {
if (scale_cursor_str) free(scale_cursor_str);
scale_cursor_str = strdup(p + strlen("sc="));
} else if (!strcmp(p, "solid")) {
use_solid_bg = 1;
if (!solid_str) {
......@@ -1103,9 +1107,11 @@ void user_supplied_opts(char *opts) {
subwin = win;
}
}
} else if (!strcmp(p, "clear_mods")) {
} else if (!strcmp(p, "clear_mods") ||
!strcmp(p, "cm")) {
clear_mods = 1;
} else if (!strcmp(p, "clear_keys")) {
} else if (!strcmp(p, "clear_keys") ||
!strcmp(p, "ck")) {
clear_mods = 2;
} else if (!strcmp(p, "repeat")) {
no_autorepeat = 0;
......@@ -1296,12 +1302,18 @@ int wait_for_client(int *argc, char** argv, int http) {
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) {
usleep(20 * 1000);
......
......@@ -2145,6 +2145,8 @@ static int check_xrecord_keys(void) {
RAWFB_RET(0)
if (unixpw_in_progress) return 0;
set_repeat_in = set_repeat;
set_repeat = 0.0;
......@@ -3303,6 +3305,7 @@ int check_wireframe(void) {
RAWFB_RET(0)
if (unixpw_in_progress) return 0;
if (nofb) {
return 0;
}
......
......@@ -3,6 +3,7 @@
#include "x11vnc.h"
#include "cleanup.h"
#include "win_utils.h"
#include "unixpw.h"
struct timeval _mysleep;
......@@ -407,9 +408,14 @@ double rfac(void) {
*/
#define USEC_MAX 999999 /* libvncsever assumes < 1 second */
void rfbPE(long usec) {
int uip0 = unixpw_in_progress;
if (! screen) {
return;
}
if (unixpw && unixpw_in_progress && !unixpw_in_rfbPE) {
rfbLog("unixpw_in_rfbPE: skipping rfbPE\n");
return;
}
if (usec > USEC_MAX) {
usec = USEC_MAX;
......@@ -417,18 +423,38 @@ void rfbPE(long usec) {
if (! use_threads) {
rfbProcessEvents(screen, usec);
}
if (unixpw && unixpw_in_progress && !uip0) {
if (!unixpw_in_rfbPE) {
rfbLog("rfbPE: got new client in non-rfbPE\n");
; /* this is new unixpw client */
}
}
}
void rfbCFD(long usec) {
int uip0 = unixpw_in_progress;
if (! screen) {
return;
}
if (unixpw && unixpw_in_progress && !unixpw_in_rfbPE) {
rfbLog("unixpw_in_rfbPE: skipping rfbCFD\n");
return;
}
if (usec > USEC_MAX) {
usec = USEC_MAX;
}
if (! use_threads) {
rfbCheckFds(screen, usec);
}
if (unixpw && unixpw_in_progress && !uip0) {
if (!unixpw_in_rfbPE) {
rfbLog("rfbCFD: got new client in non-rfbPE\n");
; /* this is new unixpw client */
}
}
}
double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1,
......
.\" This file was automatically generated from x11vnc -help output.
.TH X11VNC "1" "June 2006" "x11vnc " "User Commands"
.TH X11VNC "1" "July 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.2, lastmod: 2006-06-23
version: 0.8.2, lastmod: 2006-07-04
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -37,7 +37,7 @@ In brief:
.PP
% vncviewer -encodings 'copyrect tight zrle hextile' localhost:0
.PP
Also, use of a VNC password (-rfbauth or \fB-passwdfile)\fR is strongly recommend.
Also, use of a VNC password (-rfbauth or \fB-passwdfile)\fR is strongly recommended.
.PP
For additional info see: http://www.karlrunge.com/x11vnc/
and http://www.karlrunge.com/x11vnc/#faq
......@@ -231,11 +231,11 @@ speedup may be achieved via the option "nogetimage".
This enables a scheme were XGetImage() is not used
to retrieve the 8bpp data. Instead, it assumes that
the 8bpp data is in bits 25-32 of the 32bit X pixels.
There is no reason the X server should put the data
there for our poll requests, but some do and so the
extra steps to retrieve it can be skipped. Tested with
mga driver with XFree86/Xorg. For the default depth
8 case this option is ignored.
There is no requirement that the X server should put
the data there for our poll requests, but some do and
so the extra steps to retrieve it can be skipped.
Tested with mga driver with XFree86/Xorg. For the
default depth 8 case this option is ignored.
.IP
To adjust how often XGetImage() is used to poll the
non-default visual regions for changes, use the option
......@@ -373,6 +373,11 @@ Also clients that log in viewonly cannot transfer files.
However, if the remote control mechanism is used to
change the global or per-client viewonly state the
filetransfer permissions will NOT change.
.IP
Note, to *enable* UltraVNC filetransfer (currently
disabled by default, this may change...) and to get it
to work you probably need to supply these libvncserver
options: "\fB-rfbversion\fR \fI3.6 \fB-permitfiletransfer\fR"\fR
.PP
\fB-http\fR
.IP
......@@ -437,7 +442,7 @@ out with the "#" character in the usual way.
.PP
\fB-localhost\fR
.IP
Same as "\fB-allow\fR \fI127.0.0.1\fR".
Basically the same as "\fB-allow\fR \fI127.0.0.1\fR".
.IP
Note: if you want to restrict which network interface
x11vnc listens on, see the \fB-listen\fR option below.
......@@ -445,11 +450,11 @@ E.g. "\fB-listen\fR \fIlocalhost\fR" or "\fB-listen\fR \fI192.168.3.21\fR".
As a special case, the option "\fB-localhost\fR" implies
"\fB-listen\fR \fIlocalhost\fR".
.IP
For non-localhost \fB-listen\fR usage, if you use the remote
control mechanism (-R) to change the \fB-listen\fR interface
you may need to manually adjust the \fB-allow\fR list (and
vice versa) to avoid situations where no connections
(or too many) are allowed.
A rare case, but for non-localhost \fB-listen\fR usage, if
you use the remote control mechanism (-R) to change
the \fB-listen\fR interface you may need to manually adjust
the \fB-allow\fR list (and vice versa) to avoid situations
where no connections (or too many) are allowed.
.PP
\fB-nolookup\fR
.IP
......@@ -519,7 +524,7 @@ removed after being read. Perhaps this is useful in
limiting the readability of the file. In general,
the password file should not be readable by untrusted
users (BTW: neither should the VNC \fB-rfbauth\fR file:
it is NOT encrypted).
it is NOT encrypted, only obscured).
.IP
If the filename is prefixed with "read:" it will
periodically be checked for changes and reread.
......@@ -661,7 +666,7 @@ The user names in the comma separated [list] can have
per-user options after a ":", e.g. "fred:opts"
where "opts" is a "+" separated list of
"viewonly", "fullaccess", "input=XXXX", or
"deny", e.g. "karl,fred:viewonly,boss:input=M".
"deny", e.g. "karl,wally:viewonly,boss:input=M".
For "input=" it is the K,M,B,C described under \fB-input.\fR
.IP
If a user in the list is "*" that means those
......@@ -696,8 +701,10 @@ mode to work (only that
.IR getpwnam (3)
return the encrypted
password is required), but it is unlikely it will work
for any other modern environment. All of the \fB-unixpw\fR
options and contraints apply.
for any other modern environment unless x11vnc is run
as root (which, btw, is often done when running x11vnc
from inetd and xdm/gdm/kdm). All of the \fB-unixpw\fR options
and contraints apply.
.PP
\fB-display\fR \fIWAIT:...\fR
.IP
......@@ -726,17 +733,17 @@ output is taken as XAUTHORITY data. It can be either
of the form XAUTHORITY=<file> or raw xauthority data for
the display (e.g. "xauth extract - $DISPLAY" output).
.IP
In the case of \fB-unixpw,\fR then the above command is run
as the user who just authenticated via the login and
password prompt.
In the case of \fB-unixpw\fR (but not \fB-unixpw_nis),\fR then the
above command is run as the user who just authenticated
via the login and password prompt.
.IP
Also in the case of \fB-unixpw,\fR the user logging in can
place a colon at the end of his username and supply
a few options: scale=, scale_cursor=, solid, id=,
clear_mods, clear_keys, repeat, or speeds= separated
by commas if there is more than one. After the user
logs in successfully, these options will be applied to
the VNC screen. For example,
a few options: scale=, scale_cursor= (or sc=), solid,
id=, clear_mods (or cm), clear_keys (or ck), repeat, or
speeds= separated by commas if there is more than one.
After the user logs in successfully, these options will
be applied to the VNC screen. For example,
.IP
login: fred:scale=3/4,repeat
Password: ...
......@@ -760,17 +767,19 @@ A nice way to use WAIT:cmd=... is out of
.IR inetd (8)
(it automatically forks a new x11vnc for each user).
You can have the x11vnc inetd spawned process run as,
say, root or nobody. When run as root (for either
inetd or display manager), you can also supply the
option "\fB-users\fR \fIunixpw=\fR" to have the x11vnc process
switch to the user as well. Note: there will be a 2nd
SSL helper process that will not switch, but it is only
encoding and decoding the stream at that point.
.IP
As a special case, WAIT:cmd=FINDDISPLAY will run
a script that works on most Unixes to determine a
user's DISPLAY variable and xauthority data. To have
this default script printed to stdout (e.g. for
say, root or nobody. When run as root (for either inetd
or display manager), you can also supply the option
"\fB-users\fR \fIunixpw=\fR" to have the x11vnc process switch to
the user as well. Note: there will be a 2nd SSL helper
process that will not switch, but it is only encoding
and decoding the encrypted stream at that point.
.IP
As a special case, WAIT:cmd=FINDDISPLAY will run a
script that works on most Unixes to determine a user's
DISPLAY variable and xauthority data (see
.IR who (1)
).
To have this default script printed to stdout (e.g. for
customization) run with WAIT:cmd=FINDDISPLAY-print
.IP
As another special case, WAIT:cmd=HTTPONCE will allow
......@@ -1399,6 +1408,15 @@ is used. The popup will time out after 120 seconds,
use "popup:N" to modify the timeout to N seconds
(use 0 for no timeout).
.IP
In the case of "popup" and when the \fB-unixpw\fR option
is specified, then a *second* window will be popped
up after the user successfully logs in via his UNIX
password. This time the user will be identified as
UNIX:username@hostname, the "UNIX:" prefix indicates
which user the viewer logged as via \fB-unixpw.\fR The first
popup is only for whether to allow him to even *try*
to login via unix password.
.IP
If \fIstring\fR is "xmessage" then an
.IR xmessage (1)
invocation is used for the command. xmessage must be
......@@ -1690,6 +1708,11 @@ Print this help text.
.IP
Print program version and last modification date.
.PP
\fB-license\fR
.IP
Print out license information. Same as \fB-copying\fR and
\fB-warranty.\fR
.PP
\fB-dbg\fR
.IP
Instead of exiting after cleaning up, run a simple
......
......@@ -407,6 +407,7 @@ static void watch_loop(void) {
}
while (1) {
char msg[] = "new client: %s taking unixpw client off hold.\n";
got_user_input = 0;
got_pointer_input = 0;
......@@ -418,10 +419,35 @@ static void watch_loop(void) {
if (! use_threads) {
dtime0(&tm);
if (! skip_pe) {
measure_send_rates(1);
if (unixpw && unixpw_in_progress) {
rfbClientPtr cl = unixpw_client;
if (cl && cl->onHold) {
rfbLog(msg, cl->host);
unixpw_client->onHold = FALSE;
}
} else {
measure_send_rates(1);
}
unixpw_in_rfbPE = 1;
rfbPE(-1);
measure_send_rates(0);
fb_update_sent(NULL);
unixpw_in_rfbPE = 0;
if (unixpw && unixpw_in_progress) {
/* rfbPE loop until logged in. */
skip_pe = 0;
continue;
} else {
measure_send_rates(0);
fb_update_sent(NULL);
}
} else {
if (unixpw && unixpw_in_progress) {
skip_pe = 0;
continue;
}
}
dtr = dtime(&tm);
......@@ -432,26 +458,27 @@ static void watch_loop(void) {
if (screen && screen->clientHead) {
int ret = check_user_input(dt, dtr,
tile_diffs, &cnt);
/* true means loop back for more input */
/* true: loop back for more input */
if (ret == 2) {
skip_pe = 1;
}
if (ret) {
if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
continue;
}
}
/* watch for viewonly input piling up: */
if ((got_pointer_calls > got_pointer_input)
|| (got_keyboard_calls > got_keyboard_input)) {
if ((got_pointer_calls > got_pointer_input) ||
(got_keyboard_calls > got_keyboard_input)) {
eat_viewonly_input(10, 3);
}
} else {
#if 0
if (0 && use_xrecord) {
/* XXX not working */
check_xrecord();
}
#endif
if (wireframe && button_mask) {
check_wireframe();
}
......@@ -462,6 +489,8 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
clean_up_exit(0);
}
if (unixpw_in_progress) continue;
if (! urgent_update) {
if (do_copy_screen) {
do_copy_screen = 0;
......@@ -540,6 +569,8 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
if (use_xdamage && last_dt > xdamage_thrash) {
clear_xdamage_mark_region(NULL, 0);
}
if (unixpw_in_progress) continue;
dtime0(&tm);
if (use_snapfb) {
int t, tries = 3;
......@@ -1823,6 +1854,9 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-V") || !strcmp(arg, "-version")) {
fprintf(stdout, "x11vnc: %s\n", lastmod);
exit(0);
} else if (!strcmp(arg, "-license") ||
!strcmp(arg, "-copying") || !strcmp(arg, "-warranty")) {
print_license();
} else if (!strcmp(arg, "-dbg")) {
crash_debug = 1;
} else if (!strcmp(arg, "-nodbg")) {
......@@ -2569,6 +2603,12 @@ int main(int argc, char* argv[]) {
}
}
}
if (use_threads) {
if (! quiet) {
rfbLog("disabling -threads under -unixpw\n");
}
use_threads = 0;
}
}
if (use_stunnel && ! got_localhost) {
if (! getenv("STUNNEL_DISABLE_LOCALHOST") &&
......@@ -3203,6 +3243,31 @@ int main(int argc, char* argv[]) {
if (use_solid_bg && client_count) {
solid_bg(0);
}
if (accept_cmd && strstr(accept_cmd, "popup") == accept_cmd) {
rfbClientIteratorPtr iter;
rfbClientPtr cl, cl0 = NULL;
int i = 0;
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
i++;
if (i != 1) {
rfbLog("WAIT popup: too many clients\n");
clean_up_exit(1);
}
cl0 = cl;
}
rfbReleaseClientIterator(iter);
if (i != 1 || cl0 == NULL) {
rfbLog("WAIT popup: no clients.\n");
clean_up_exit(1);
}
if (! accept_client(cl0)) {
rfbLog("WAIT popup: denied.\n");
clean_up_exit(1);
}
rfbLog("waited_for_client: popup accepted.\n");
cl0->onHold = FALSE;
}
}
if (! waited_for_client) {
......
......@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.8.2 lastmod: 2006-06-23";
char lastmod[] = "0.8.2 lastmod: 2006-07-04";
/* X display info */
......
......@@ -1089,7 +1089,10 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
RAWFB_RET_VOID
if (unixpw_in_progress) return;
if (unixpw_in_progress) {
rfbLog("xcut_receive: unixpw_in_progress, skipping.\n");
return;
}
if (!watch_selection) {
return;
......
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