summaryrefslogtreecommitdiffstats
path: root/x11vnc/sslhelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/sslhelper.c')
-rw-r--r--x11vnc/sslhelper.c261
1 files changed, 215 insertions, 46 deletions
diff --git a/x11vnc/sslhelper.c b/x11vnc/sslhelper.c
index ab2a43f..ae33520 100644
--- a/x11vnc/sslhelper.c
+++ b/x11vnc/sslhelper.c
@@ -42,10 +42,12 @@ so, delete this exception statement from your version.
#include "unixpw.h"
#include "user.h"
-#define OPENSSL_INETD 1
-#define OPENSSL_VNC 2
-#define OPENSSL_HTTPS 3
-#define OPENSSL_REVERSE 4
+#define OPENSSL_INETD 1
+#define OPENSSL_VNC 2
+#define OPENSSL_VNC6 3
+#define OPENSSL_HTTPS 4
+#define OPENSSL_HTTPS6 5
+#define OPENSSL_REVERSE 6
#define DO_DH 0
@@ -56,8 +58,10 @@ so, delete this exception statement from your version.
#endif
int openssl_sock = -1;
+int openssl_sock6 = -1;
int openssl_port_num = 0;
int https_sock = -1;
+int https_sock6 = -1;
pid_t openssl_last_helper_pid = 0;
char *openssl_last_ip = NULL;
@@ -658,8 +662,8 @@ char *get_ssl_verify_file(char *str_in) {
int openssl_present(void);
void openssl_init(int isclient);
-void openssl_port(void);
-void https_port(void);
+void openssl_port(int restart);
+void https_port(int restart);
void check_openssl(void);
void check_https(void);
void ssl_helper_pid(pid_t pid, int sock);
@@ -1989,6 +1993,10 @@ static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
name = get_remote_host(ssock);
peerport = get_remote_port(ssock);
+ if (!strcmp(name, "0.0.0.0") && openssl_last_ip != NULL) {
+ name = strdup(openssl_last_ip);
+ }
+
if (db > 1) fprintf(stderr, "ssl_init: 4\n");
while (1) {
@@ -2593,7 +2601,7 @@ static void init_prng(void) {
void check_openssl(void) {
fd_set fds;
struct timeval tv;
- int nfds;
+ int nfds, nmax = openssl_sock;
static time_t last_waitall = 0;
static double last_check = 0.0;
double now;
@@ -2607,7 +2615,7 @@ void check_openssl(void) {
ssl_helper_pid(0, -2); /* waitall */
}
- if (openssl_sock < 0) {
+ if (openssl_sock < 0 && openssl_sock6 < 0) {
return;
}
@@ -2618,29 +2626,43 @@ void check_openssl(void) {
last_check = now;
FD_ZERO(&fds);
- FD_SET(openssl_sock, &fds);
+ if (openssl_sock >= 0) {
+ FD_SET(openssl_sock, &fds);
+ }
+ if (openssl_sock6 >= 0) {
+ FD_SET(openssl_sock6, &fds);
+ if (openssl_sock6 > openssl_sock) {
+ nmax = openssl_sock6;
+ }
+ }
tv.tv_sec = 0;
tv.tv_usec = 0;
- nfds = select(openssl_sock+1, &fds, NULL, NULL, &tv);
+ nfds = select(nmax+1, &fds, NULL, NULL, &tv);
if (nfds <= 0) {
return;
}
-
- rfbLog("SSL: accept_openssl(OPENSSL_VNC)\n");
- accept_openssl(OPENSSL_VNC, -1);
+
+ if (openssl_sock >= 0 && FD_ISSET(openssl_sock, &fds)) {
+ rfbLog("SSL: accept_openssl(OPENSSL_VNC)\n");
+ accept_openssl(OPENSSL_VNC, -1);
+ }
+ if (openssl_sock6 >= 0 && FD_ISSET(openssl_sock6, &fds)) {
+ rfbLog("SSL: accept_openssl(OPENSSL_VNC6)\n");
+ accept_openssl(OPENSSL_VNC6, -1);
+ }
}
void check_https(void) {
fd_set fds;
struct timeval tv;
- int nfds;
+ int nfds, nmax = https_sock;
static double last_check = 0.0;
double now;
- if (! use_openssl || https_sock < 0) {
+ if (! use_openssl || (https_sock < 0 && https_sock6 < 0)) {
return;
}
@@ -2651,25 +2673,40 @@ void check_https(void) {
last_check = now;
FD_ZERO(&fds);
- FD_SET(https_sock, &fds);
+ if (https_sock >= 0) {
+ FD_SET(https_sock, &fds);
+ }
+ if (https_sock6 >= 0) {
+ FD_SET(https_sock6, &fds);
+ if (https_sock6 > https_sock) {
+ nmax = https_sock6;
+ }
+ }
tv.tv_sec = 0;
tv.tv_usec = 0;
- nfds = select(https_sock+1, &fds, NULL, NULL, &tv);
+ nfds = select(nmax+1, &fds, NULL, NULL, &tv);
if (nfds <= 0) {
return;
}
- rfbLog("SSL: accept_openssl(OPENSSL_HTTPS)\n");
- accept_openssl(OPENSSL_HTTPS, -1);
+
+ if (https_sock >= 0 && FD_ISSET(https_sock, &fds)) {
+ rfbLog("SSL: accept_openssl(OPENSSL_HTTPS)\n");
+ accept_openssl(OPENSSL_HTTPS, -1);
+ }
+ if (https_sock6 >= 0 && FD_ISSET(https_sock6, &fds)) {
+ rfbLog("SSL: accept_openssl(OPENSSL_HTTPS6)\n");
+ accept_openssl(OPENSSL_HTTPS6, -1);
+ }
}
-void openssl_port(void) {
+void openssl_port(int restart) {
int sock = -1, shutdown = 0;
static int port = -1;
static in_addr_t iface = INADDR_ANY;
- int db = 0;
+ int db = 0, fd6 = -1;
if (! screen) {
rfbLog("openssl_port: no screen!\n");
@@ -2680,15 +2717,18 @@ void openssl_port(void) {
return;
}
- if (screen->listenSock > -1 && screen->port > 0) {
+ if (restart) {
+ port = screen->port;
+ } else if (screen->listenSock > -1 && screen->port > 0) {
port = screen->port;
shutdown = 1;
+ } else if (ipv6_listen && screen->port > 0) {
+ port = screen->port;
} else if (screen->port == 0) {
port = screen->port;
}
- if (screen->listenInterface) {
- iface = screen->listenInterface;
- }
+
+ iface = screen->listenInterface;
if (shutdown) {
if (db) fprintf(stderr, "shutting down %d/%d\n",
@@ -2698,21 +2738,56 @@ void openssl_port(void) {
#endif
}
+ if (openssl_sock >= 0) {
+ close(openssl_sock);
+ openssl_sock = -1;
+ }
+ if (openssl_sock6 >= 0) {
+ close(openssl_sock6);
+ openssl_sock6 = -1;
+ }
+
if (port < 0) {
rfbLog("openssl_port: could not obtain listening port %d\n", port);
+ if (!got_rfbport && !ipv6_listen) {
+ rfbLog("openssl_port: if this system is IPv6-only, use the -6 option\n");
+ }
clean_up_exit(1);
} else if (port == 0) {
/* no listen case, i.e. -connect */
sock = -1;
} else {
- sock = rfbListenOnTCPPort(port, iface);
+ sock = listen_tcp(port, iface, 0);
+ if (ipv6_listen) {
+ fd6 = listen6(port);
+ } else if (!got_rfbport) {
+ rfbLog("openssl_port: if this system is IPv6-only, use the -6 option\n");
+ }
if (sock < 0) {
- rfbLog("openssl_port: could not reopen port %d\n", port);
- clean_up_exit(1);
+ if (fd6 < 0) {
+ rfbLog("openssl_port: could not reopen port %d\n", port);
+ if (!restart) {
+ clean_up_exit(1);
+ }
+ } else {
+ rfbLog("openssl_port: Info: only listening on IPv6\n");
+ }
}
}
rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock);
- if (!quiet) {
+ if (ipv6_listen && port > 0) {
+ if (fd6 < 0) {
+ fd6 = listen6(port);
+ }
+ if (fd6 < 0) {
+ ipv6_listen = 0;
+ } else {
+ rfbLog("openssl_port: listen on port/sock %d/%d (ipv6)\n",
+ port, fd6);
+ openssl_sock6 = fd6;
+ }
+ }
+ if (!quiet && sock >=0) {
announce(port, 1, NULL);
}
openssl_sock = sock;
@@ -2721,11 +2796,10 @@ void openssl_port(void) {
ssl_initialized = 1;
}
-void https_port(void) {
- int sock;
+void https_port(int restart) {
+ int sock, fd6 = -1;
static int port = 0;
static in_addr_t iface = INADDR_ANY;
- int db = 0;
/* as openssl_port above: open a listening socket for pure https: */
if (https_port_num < 0) {
@@ -2735,6 +2809,9 @@ void https_port(void) {
rfbLog("https_port: no screen!\n");
clean_up_exit(1);
}
+ if (! screen->httpDir) {
+ return;
+ }
if (screen->listenInterface) {
iface = screen->listenInterface;
}
@@ -2742,6 +2819,9 @@ void https_port(void) {
if (https_port_num == 0) {
https_port_num = find_free_port(5801, 5851);
}
+ if (ipv6_listen && https_port_num <= 0) {
+ https_port_num = find_free_port6(5801, 5851);
+ }
if (https_port_num <= 0) {
rfbLog("https_port: could not find port %d\n", https_port_num);
clean_up_exit(1);
@@ -2750,17 +2830,54 @@ void https_port(void) {
if (port <= 0) {
rfbLog("https_port: could not obtain listening port %d\n", port);
- clean_up_exit(1);
+ if (!restart) {
+ clean_up_exit(1);
+ } else {
+ return;
+ }
+ }
+ if (https_sock >= 0) {
+ close(https_sock);
+ https_sock = -1;
}
- sock = rfbListenOnTCPPort(port, iface);
+ if (https_sock6 >= 0) {
+ close(https_sock6);
+ https_sock6 = -1;
+ }
+ sock = listen_tcp(port, iface, 0);
if (sock < 0) {
rfbLog("https_port: could not open port %d\n", port);
- clean_up_exit(1);
+ if (ipv6_listen) {
+ fd6 = listen6(port);
+ }
+ if (fd6 < 0) {
+ if (!restart) {
+ clean_up_exit(1);
+ }
+ }
+ rfbLog("https_port: trying IPv6 only mode.\n");
}
- if (db) fprintf(stderr, "https_port: listen on port/sock %d/%d\n",
- port, sock);
-
+ rfbLog("https_port: listen on port/sock %d/%d\n", port, sock);
https_sock = sock;
+
+ if (ipv6_listen) {
+ if (fd6 < 0) {
+ fd6 = listen6(port);
+ }
+ if (fd6 < 0) {
+ ;
+ } else {
+ rfbLog("https_port: listen on port/sock %d/%d (ipv6)\n",
+ port, fd6);
+ https_sock6 = fd6;
+ }
+ if (fd6 < 0 && https_sock < 0) {
+ rfbLog("https_port: could not listen on either IPv4 or IPv6.\n");
+ if (!restart) {
+ clean_up_exit(1);
+ }
+ }
+ }
}
static void lose_ram(void) {
@@ -3095,6 +3212,7 @@ void accept_openssl(int mode, int presock) {
char cookie[256], rcookie[256], *name = NULL;
int vencrypt_sel = 0;
int anontls_sel = 0;
+ char *ipv6_name = NULL;
static double last_https = 0.0;
static char last_get[256];
static int first = 1;
@@ -3138,6 +3256,25 @@ void accept_openssl(int mode, int presock) {
}
listen = openssl_sock;
+ } else if (mode == OPENSSL_VNC6 || mode == OPENSSL_HTTPS6) {
+#if X11VNC_IPV6
+ struct sockaddr_in6 a6;
+ socklen_t a6len = sizeof(a6);
+ int fd = (mode == OPENSSL_VNC6 ? openssl_sock6 : https_sock6);
+
+ sock = accept(fd, (struct sockaddr *)&a6, &a6len);
+ if (sock < 0) {
+ rfbLog("SSL: accept_openssl: accept connection failed\n");
+ rfbLogPerror("accept");
+ if (ssl_no_fail) {
+ clean_up_exit(1);
+ }
+ return;
+ }
+ ipv6_name = ipv6_getipaddr((struct sockaddr *)&a6, a6len);
+ if (!ipv6_name) ipv6_name = strdup("unknown");
+ listen = fd;
+#endif
} else if (mode == OPENSSL_REVERSE) {
sock = presock;
if (sock < 0) {
@@ -3147,6 +3284,10 @@ void accept_openssl(int mode, int presock) {
}
return;
}
+ if (getenv("OPENSSL_REVERSE_DEBUG")) fprintf(stderr, "OPENSSL_REVERSE: ipv6_client_ip_str: %s\n", ipv6_client_ip_str);
+ if (ipv6_client_ip_str != NULL) {
+ ipv6_name = strdup(ipv6_client_ip_str);
+ }
listen = -1;
} else if (mode == OPENSSL_HTTPS) {
@@ -3169,13 +3310,17 @@ void accept_openssl(int mode, int presock) {
}
if (mode == OPENSSL_INETD) {
openssl_last_ip = get_remote_host(fileno(stdin));
+ } else if (mode == OPENSSL_VNC6 || mode == OPENSSL_HTTPS6) {
+ openssl_last_ip = ipv6_name;
+ } else if (mode == OPENSSL_REVERSE && ipv6_name != NULL) {
+ openssl_last_ip = ipv6_name;
} else {
openssl_last_ip = get_remote_host(sock);
}
if (!check_ssl_access(openssl_last_ip)) {
rfbLog("SSL: accept_openssl: denying client %s\n", openssl_last_ip);
- rfbLog("SSL: accept_openssl: does not match -allow (or other reason).\n");
+ rfbLog("SSL: accept_openssl: does not match -allow or other reason.\n");
close(sock);
sock = -1;
if (ssl_no_fail) {
@@ -3186,7 +3331,12 @@ void accept_openssl(int mode, int presock) {
/* now make a listening socket for child to connect back to us by: */
- cport = find_free_port(20000, 0);
+ cport = find_free_port(20000, 22000);
+ if (! cport && ipv6_listen) {
+ rfbLog("SSL: accept_openssl: seeking IPv6 port.\n");
+ cport = find_free_port6(20000, 22000);
+ rfbLog("SSL: accept_openssl: IPv6 port: %d\n", cport);
+ }
if (! cport) {
rfbLog("SSL: accept_openssl: could not find open port.\n");
close(sock);
@@ -3197,7 +3347,7 @@ void accept_openssl(int mode, int presock) {
}
if (db) fprintf(stderr, "accept_openssl: cport: %d\n", cport);
- csock = rfbListenOnTCPPort(cport, htonl(INADDR_LOOPBACK));
+ csock = listen_tcp(cport, htonl(INADDR_LOOPBACK), 1);
if (csock < 0) {
rfbLog("SSL: accept_openssl: could not listen on port %d.\n",
@@ -3225,7 +3375,13 @@ void accept_openssl(int mode, int presock) {
rb[0], rb[1], rb[2], rb[3], rb[4], rb[5],
dnow() - x11vnc_start, x11vnc_start, (void *)rb);
- if (mode != OPENSSL_INETD) {
+ if (mode == OPENSSL_VNC6) {
+ name = strdup(ipv6_name);
+ peerport = get_remote_port(sock);
+ } else if (mode == OPENSSL_REVERSE && ipv6_name != NULL) {
+ name = strdup(ipv6_name);
+ peerport = get_remote_port(sock);
+ } else if (mode != OPENSSL_INETD) {
name = get_remote_host(sock);
peerport = get_remote_port(sock);
} else {
@@ -3338,7 +3494,7 @@ void accept_openssl(int mode, int presock) {
lose_ram();
/* now connect back to parent socket: */
- vncsock = rfbConnectToTcpAddr("127.0.0.1", cport);
+ vncsock = connect_tcp("127.0.0.1", cport);
if (vncsock < 0) {
rfbLog("SSL: ssl_helper[%d]: could not connect"
" back to: %d\n", getpid(), cport);
@@ -3388,8 +3544,9 @@ void accept_openssl(int mode, int presock) {
}
if (screen->httpListenSock >= 0 && screen->httpPort > 0) {
have_httpd = 1;
- }
- if (screen->httpListenSock == -2) {
+ } else if (ipv6_http_fd >= 0) {
+ have_httpd = 1;
+ } else if (screen->httpListenSock == -2) {
have_httpd = 1;
}
if (mode == OPENSSL_HTTPS && ! have_httpd) {
@@ -3614,7 +3771,7 @@ void accept_openssl(int mode, int presock) {
if (db) fprintf(stderr, "iface: %s:%d\n", iface, hport);
usleep(150*1000);
- httpsock = rfbConnectToTcpAddr(iface, hport);
+ httpsock = connect_tcp(iface, hport);
if (httpsock < 0) {
/* UGH, after all of that! */
@@ -3962,6 +4119,18 @@ void accept_openssl(int mode, int presock) {
openssl_last_helper_pid = 0;
if (client) {
+ int swt = 0;
+ if (mode == OPENSSL_VNC6 && openssl_last_ip != NULL) {
+ swt = 1;
+ } else if (mode == OPENSSL_REVERSE && ipv6_name != NULL && openssl_last_ip != NULL) {
+ swt = 1;
+ }
+ if (swt) {
+ if (client->host) {
+ free(client->host);
+ }
+ client->host = strdup(openssl_last_ip);
+ }
if (db) fprintf(stderr, "accept_openssl: client %p\n", (void *) client);
if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) screen->newClientHook);
if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) new_client);
OpenPOWER on IntegriCloud