summaryrefslogtreecommitdiffstats
path: root/x11vnc/connections.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/connections.c')
-rw-r--r--x11vnc/connections.c239
1 files changed, 210 insertions, 29 deletions
diff --git a/x11vnc/connections.c b/x11vnc/connections.c
index 25eb86a..f465325 100644
--- a/x11vnc/connections.c
+++ b/x11vnc/connections.c
@@ -92,6 +92,7 @@ void send_client_info(char *str);
void adjust_grabs(int grab, int quiet);
void check_new_clients(void);
int accept_client(rfbClientPtr client);
+void check_ipv6_listen(long usec);
int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input,
int len, FILE *output);
int check_access(char *addr);
@@ -168,6 +169,7 @@ char *list_clients(void) {
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
ClientData *cd = (ClientData *) cl->clientData;
+ char *tmp_host, *p;
if (! cd) {
continue;
@@ -177,7 +179,13 @@ char *list_clients(void) {
}
sprintf(tmp, "0x%x:", cd->uid);
strcat(list, tmp);
- strcat(list, cl->host);
+ p = tmp_host = strdup(cl->host);
+ while (*p) {
+ if (*p == ':') *p = '#';
+ p++;
+ }
+ strcat(list, tmp_host);
+ free(tmp_host);
strcat(list, ":");
sprintf(tmp, "%d:", cd->client_port);
strcat(list, tmp);
@@ -197,7 +205,13 @@ char *list_clients(void) {
strcat(list, cd->unixname);
}
strcat(list, ":");
- strcat(list, cd->hostname);
+ p = tmp_host = strdup(cd->hostname);
+ while (*p) {
+ if (*p == ':') *p = '#';
+ p++;
+ }
+ strcat(list, tmp_host);
+ free(tmp_host);
strcat(list, ":");
strcat(list, cd->input);
strcat(list, ":");
@@ -292,7 +306,9 @@ static rfbClientPtr *client_match(char *str) {
port = 5500 + port;
}
}
- if (! dotted_ip(str)) {
+ if (ipv6_ip(str)) {
+ ;
+ } else if (! dotted_ip(str)) {
char *orig = rstr;
rstr = host2ip(rstr);
free(orig);
@@ -891,13 +907,16 @@ void client_gone(rfbClientPtr client) {
client->state == RFB_AUTHENTICATION ||
client->state == RFB_INITIALISATION) && accepted_client) {
rfbLog("connect_once: invalid password or early "
- "disconnect.\n");
+ "disconnect. %d\n", client->state);
rfbLog("connect_once: waiting for next connection.\n");
accepted_client--;
if (accepted_client < 0) {
accepted_client = 0;
}
CLIENT_UNLOCK;
+ if (connect_or_exit) {
+ clean_up_exit(1);
+ }
return;
}
if (shared && client_count > 0) {
@@ -913,7 +932,11 @@ void client_gone(rfbClientPtr client) {
kill(gui_pid, SIGTERM);
}
CLIENT_UNLOCK;
- clean_up_exit(0);
+ if (connect_or_exit) {
+ clean_up_exit(1);
+ } else {
+ clean_up_exit(0);
+ }
}
#ifdef MACOSX
if (macosx_console && client_count == 0) {
@@ -1042,7 +1065,9 @@ int check_access(char *addr) {
p = strtok(NULL, ", \t\n\r");
continue;
}
- if (! dotted_ip(p)) {
+ if (ipv6_ip(p)) {
+ chk = p;
+ } else if (! dotted_ip(p)) {
r = host2ip(p);
if (r == NULL || *r == '\0') {
rfbLog("check_access: bad lookup \"%s\"\n", p);
@@ -1054,26 +1079,37 @@ int check_access(char *addr) {
} else {
chk = p;
}
+ if (getenv("X11VNC_DEBUG_ACCESS")) fprintf(stderr, "chk: %s part: %s addr: %s\n", chk, p, addr);
q = strstr(addr, chk);
- if (chk[strlen(chk)-1] != '.') {
+ if (ipv6_ip(addr)) {
+ if (!strcmp(chk, "localhost") && !strcmp(addr, "::1")) {
+ rfbLog("check_access: client addr %s is local.\n", addr);
+ allowed = 1;
+ } else if (!strcmp(chk, "::1") && !strcmp(addr, "::1")) {
+ rfbLog("check_access: client addr %s is local.\n", addr);
+ allowed = 1;
+ } else if (!strcmp(chk, "127.0.0.1") && !strcmp(addr, "::1")) {
+ /* this if for host2ip("localhost") */
+ rfbLog("check_access: client addr %s is local.\n", addr);
+ allowed = 1;
+ } else if (q == addr) {
+ rfbLog("check_access: client %s matches pattern %s\n", addr, chk);
+ allowed = 1;
+ }
+ } else if (chk[strlen(chk)-1] != '.') {
if (!strcmp(addr, chk)) {
if (chk != p) {
- rfbLog("check_access: client %s "
- "matches host %s=%s\n", addr,
- chk, p);
+ rfbLog("check_access: client %s " "matches host %s=%s\n", addr, chk, p);
} else {
- rfbLog("check_access: client %s "
- "matches host %s\n", addr, chk);
+ rfbLog("check_access: client %s " "matches host %s\n", addr, chk);
}
allowed = 1;
- } else if(!strcmp(chk, "localhost") &&
- !strcmp(addr, "127.0.0.1")) {
+ } else if(!strcmp(chk, "localhost") && !strcmp(addr, "127.0.0.1")) {
allowed = 1;
}
} else if (q == addr) {
- rfbLog("check_access: client %s matches pattern %s\n",
- addr, chk);
+ rfbLog("check_access: client %s matches pattern %s\n", addr, chk);
allowed = 1;
}
p = strtok(NULL, ", \t\n\r");
@@ -1691,6 +1727,121 @@ int accept_client(rfbClientPtr client) {
/* return 0; NOTREACHED */
}
+void check_ipv6_listen(long usec) {
+#if X11VNC_IPV6
+ fd_set fds;
+ struct timeval tv;
+ int nfds, csock = -1, one = 1;
+ struct sockaddr_in6 addr;
+ socklen_t addrlen = sizeof(addr);
+ rfbClientPtr cl;
+ int nmax = 0;
+ char *name;
+
+ if (!ipv6_listen || noipv6) {
+ return;
+ }
+ if (ipv6_listen_fd < 0 && ipv6_http_fd < 0) {
+ return;
+ }
+
+ FD_ZERO(&fds);
+ if (ipv6_listen_fd >= 0) {
+ FD_SET(ipv6_listen_fd, &fds);
+ nmax = ipv6_listen_fd;
+ }
+ if (ipv6_http_fd >= 0 && screen->httpSock < 0) {
+ FD_SET(ipv6_http_fd, &fds);
+ if (ipv6_http_fd > nmax) {
+ nmax = ipv6_http_fd;
+ }
+ }
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ nfds = select(nmax+1, &fds, NULL, NULL, &tv);
+
+ if (nfds <= 0) {
+ return;
+ }
+
+ if (ipv6_listen_fd >= 0 && FD_ISSET(ipv6_listen_fd, &fds)) {
+
+ csock = accept(ipv6_listen_fd, (struct sockaddr *)&addr, &addrlen);
+ if (csock < 0) {
+ rfbLogPerror("check_ipv6_listen: accept");
+ goto err1;
+ }
+ if (fcntl(csock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("check_ipv6_listen: fcntl");
+ close(csock);
+ goto err1;
+ }
+ if (setsockopt(csock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("check_ipv6_listen: setsockopt");
+ close(csock);
+ goto err1;
+ }
+
+ name = ipv6_getipaddr((struct sockaddr *) &addr, addrlen);
+
+ ipv6_client_ip_str = name;
+ cl = rfbNewClient(screen, csock);
+ ipv6_client_ip_str = NULL;
+ if (cl == NULL) {
+ close(csock);
+ goto err1;
+ }
+
+ if (name) {
+ if (cl->host) {
+ free(cl->host);
+ }
+ cl->host = name;
+ rfbLog("ipv6 client: %s\n", name);
+ }
+ }
+
+ err1:
+
+ if (ipv6_http_fd >= 0 && FD_ISSET(ipv6_http_fd, &fds)) {
+
+ csock = accept(ipv6_http_fd, (struct sockaddr *)&addr, &addrlen);
+ if (csock < 0) {
+ rfbLogPerror("check_ipv6_listen: accept");
+ return;
+ }
+ if (fcntl(csock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("check_ipv6_listen: fcntl");
+ close(csock);
+ return;
+ }
+ if (setsockopt(csock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("check_ipv6_listen: setsockopt");
+ close(csock);
+ return;
+ }
+
+ rfbLog("check_ipv6_listen: setting httpSock to %d\n", csock);
+ screen->httpSock = csock;
+
+ if (screen->httpListenSock < 0) {
+ /* this may not always work... */
+ int save = screen->httpListenSock;
+ screen->httpListenSock = ipv6_http_fd;
+ rfbLog("check_ipv6_listen: no httpListenSock, calling rfbHttpCheckFds()\n");
+ rfbHttpCheckFds(screen);
+ screen->httpListenSock = save;
+ }
+ }
+#else
+ if (usec) {}
+#endif
+}
+
/*
* For the -connect <file> option: periodically read the file looking for
* a connect string. If one is found set client_connect to it.
@@ -2093,7 +2244,7 @@ static int pconnect(int psock, char *host, int port, int type, char *http_path,
}
if (newhost && newport > 0) {
rfbLog("proxy GET reconnect to: %s:%d\n", newhost, newport);
- pxy_get_sock = rfbConnectToTcpAddr(newhost, newport);
+ pxy_get_sock = connect_tcp(newhost, newport);
}
}
free(req);
@@ -2263,10 +2414,10 @@ static int proxy_connect(char *host, int port) {
psock = -1;
goto pxy_clean;
}
- psock = rfbConnectToTcpAddr("localhost", sport);
+ psock = connect_tcp("localhost", sport);
} else {
- psock = rfbConnectToTcpAddr(pxy_h[0], pxy_p[0]);
+ psock = connect_tcp(pxy_h[0], pxy_p[0]);
}
if (psock < 0) {
@@ -2462,7 +2613,7 @@ static int do_reverse_connect(char *str_in) {
host[len] = '\0';
/* extract port, if any */
- if ((p = strchr(host, ':')) != NULL) {
+ if ((p = strrchr(host, ':')) != NULL) {
rport = atoi(p+1);
if (rport < 0) {
rport = -rport;
@@ -2472,12 +2623,17 @@ static int do_reverse_connect(char *str_in) {
*p = '\0';
}
+ if (ipv6_client_ip_str) {
+ free(ipv6_client_ip_str);
+ ipv6_client_ip_str = NULL;
+ }
+
if (use_openssl) {
int vncsock;
if (connect_proxy) {
vncsock = proxy_connect(host, rport);
} else {
- vncsock = rfbConnectToTcpAddr(host, rport);
+ vncsock = connect_tcp(host, rport);
}
if (vncsock < 0) {
rfbLog("reverse_connect: failed to connect to: %s\n", str);
@@ -2488,7 +2644,7 @@ static int do_reverse_connect(char *str_in) {
free(prestring);
}
/* XXX use header */
-#define OPENSSL_REVERSE 4
+#define OPENSSL_REVERSE 6
openssl_init(1);
if (first_conn_timeout > 0) {
@@ -2560,7 +2716,7 @@ static int do_reverse_connect(char *str_in) {
return 0;
}
} else if (prestring != NULL) {
- int sock = rfbConnectToTcpAddr(host, rport);
+ int sock = connect_tcp(host, rport);
if (set_alarm) {alarm(0); signal(SIGALRM, SIG_DFL);}
if (sock >= 0) {
write(sock, prestring, prestring_len);
@@ -2571,6 +2727,12 @@ static int do_reverse_connect(char *str_in) {
}
} else {
cl = rfbReverseConnection(screen, host, rport);
+ if (cl == NULL) {
+ int sock = connect_tcp(host, rport);
+ if (sock >= 0) {
+ cl = create_new_client(sock, 1);
+ }
+ }
if (set_alarm) {alarm(0); signal(SIGALRM, SIG_DFL);}
if (cl != NULL && use_threads) {
cl->onHold = FALSE;
@@ -2580,6 +2742,12 @@ static int do_reverse_connect(char *str_in) {
free(host);
+ if (ipv6_client_ip_str) {
+ free(ipv6_client_ip_str);
+ ipv6_client_ip_str = NULL;
+ }
+
+
if (cl == NULL) {
if (quiet && connect_or_exit) {
rfbLogEnable(1);
@@ -2699,7 +2867,7 @@ void reverse_connect(char *str) {
rfbLog("killing gui_pid %d\n", gui_pid);
kill(gui_pid, SIGTERM);
}
- clean_up_exit(0);
+ clean_up_exit(1);
}
if (xrandr || xrandr_maybe) {
check_xrandr_event("reverse_connect1");
@@ -2768,7 +2936,7 @@ void reverse_connect(char *str) {
rfbLog("killing gui_pid %d\n", gui_pid);
kill(gui_pid, SIGTERM);
}
- clean_up_exit(0);
+ clean_up_exit(1);
}
}
if (xrandr || xrandr_maybe) {
@@ -2924,6 +3092,8 @@ void read_x11vnc_remote_prop(int nomsg) {
#endif /* NO_X11 */
}
+extern int rc_npieces;
+
void grab_state(int *ptr_grabbed, int *kbd_grabbed) {
int rcp, rck;
double t0, t1;
@@ -2965,8 +3135,10 @@ void grab_state(int *ptr_grabbed, int *kbd_grabbed) {
if (rck == AlreadyGrabbed || rck == GrabFrozen) {
*kbd_grabbed = 1;
}
- rfbLog("grab_state: checked %d,%d in %.6f sec (%.6f %.6f)\n",
- *ptr_grabbed, *kbd_grabbed, t1-t0, tb-ta, tc-tb);
+ if (rc_npieces < 10) {
+ rfbLog("grab_state: checked %d,%d in %.6f sec (%.6f %.6f)\n",
+ *ptr_grabbed, *kbd_grabbed, t1-t0, tb-ta, tc-tb);
+ }
#endif
}
@@ -3715,6 +3887,15 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
}
}
+ if (ipv6_client_ip_str != NULL) {
+ rfbLog("renaming client->host from '%s' to '%s'\n",
+ client->host ? client->host : "", ipv6_client_ip_str);
+ if (client->host) {
+ free(client->host);
+ }
+ client->host = strdup(ipv6_client_ip_str);
+ }
+
if (! check_access(client->host)) {
rfbLog("denying client: %s does not match %s\n", client->host,
allow_list ? allow_list : "(null)" );
@@ -3945,10 +4126,10 @@ void start_client_info_sock(char *host_port_cookie) {
free(host);
host = strdup("localhost");
}
- sock = rfbConnectToTcpAddr(host, port);
+ sock = connect_tcp(host, port);
if (sock < 0) {
usleep(200 * 1000);
- sock = rfbConnectToTcpAddr(host, port);
+ sock = connect_tcp(host, port);
}
if (sock >= 0) {
char *lst = list_clients();