diff options
Diffstat (limited to 'x11vnc/sslhelper.c')
-rw-r--r-- | x11vnc/sslhelper.c | 140 |
1 files changed, 89 insertions, 51 deletions
diff --git a/x11vnc/sslhelper.c b/x11vnc/sslhelper.c index 13e60a3..b121f91 100644 --- a/x11vnc/sslhelper.c +++ b/x11vnc/sslhelper.c @@ -91,7 +91,7 @@ static void init_prng(void); static void sslerrexit(void); static char *get_input(char *tag, char **in); static char *create_tmp_pem(char *path, int prompt); -static int ssl_init(int s_in, int s_out); +static int ssl_init(int s_in, int s_out, int skip_vnc_tls); static void ssl_xfer(int csock, int s_in, int s_out, int is_https); #ifndef FORK_OK @@ -142,6 +142,7 @@ char *get_saved_pem(char *save, int create) { clean_up_exit(1); } + cdir = get_Cert_dir(NULL, &tmp); if (! cdir || ! tmp) { rfbLog("get_saved_pem: could not find Cert dir.\n"); @@ -156,8 +157,11 @@ char *get_saved_pem(char *save, int create) { if (stat(path, &sbuf) != 0) { char *new = NULL; if (create) { + if (inetd || opts_bg) { + set_env("GENCERT_NOPROMPT", "1"); + } new = create_tmp_pem(path, prompt); - if (! getenv("X11VNC_SSL_NO_PASSPHRASE") && ! inetd) { + if (!getenv("X11VNC_SSL_NO_PASSPHRASE") && !inetd && !opts_bg) { sslEncKey(new, 0); } } @@ -842,7 +846,7 @@ static int verify_callback(int ok, X509_STORE_CTX *callback_ctx) { return 1; } -#define rfbSecTypeTlsVnc 18 +#define rfbSecTypeAnonTls 18 #define rfbSecTypeVencrypt 19 #define rfbVencryptPlain 256 @@ -854,7 +858,7 @@ static int verify_callback(int ok, X509_STORE_CTX *callback_ctx) { #define rfbVencryptX509Plain 262 static int vencrypt_selected = 0; -static int tlsvnc_selected = 0; +static int anontls_selected = 0; static int ssl_client_mode = 0; @@ -946,8 +950,14 @@ void openssl_init(int isclient) { mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; SSL_CTX_set_mode(ctx, mode); +#define ssl_cache 0 +#if ssl_cache SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); SSL_CTX_set_timeout(ctx, 300); +#else + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); + SSL_CTX_set_timeout(ctx, 1); +#endif ds = dnow(); if (! openssl_pem) { @@ -1255,16 +1265,31 @@ void ssl_helper_pid(pid_t pid, int sock) { continue; } if (kill(helpers[i], 0) == 0) { + int kret = -2; + pid_t wret; if (sock != -2) { if (sockets[i] >= 0) { close(sockets[i]); } - kill(helpers[i], SIGTERM); + kret = kill(helpers[i], SIGTERM); + if (kret == 0) { + usleep(20 * 1000); + } } #if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID if (db) fprintf(stderr, "waitpid(%d)\n", helpers[i]); - waitpid(helpers[i], &status, WNOHANG); + wret = waitpid(helpers[i], &status, WNOHANG); + if (kret == 0 && wret != helpers[i]) { + int k; + for (k=0; k < 10; k++) { + usleep(100 * 1000); + wret = waitpid(helpers[i], &status, WNOHANG); + if (wret == helpers[i]) { + break; + } + } + } #endif if (sock == -2) { continue; @@ -1350,7 +1375,7 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get, * for each socket (and some clients send requests * rapid fire). */ - tv.tv_sec = 6; + tv.tv_sec = 6; } /* @@ -1358,9 +1383,9 @@ static int is_ssl_readable(int s_in, time_t last_https, char *last_get, * recently: */ if (time(NULL) < last_https + 30) { - tv.tv_sec = 8; + tv.tv_sec = 10; if (last_get && strstr(last_get, "VncViewer")) { - tv.tv_sec = 4; + tv.tv_sec = 5; } } if (getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT")) { @@ -1543,7 +1568,7 @@ int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie, if (db) fprintf(stderr, "got applet input sock1: %d\n", sock1); - if (! ssl_init(sock1, sock1)) { + if (! ssl_init(sock1, sock1, 0)) { if (db) fprintf(stderr, "ssl_init FAILED\n"); exit(1); } @@ -1715,7 +1740,7 @@ void accept_openssl(int mode, int presock) { char uniq[] = "_evilrats_"; char cookie[256], rcookie[256], *name = NULL; int vencrypt_sel = 0; - int tlsvnc_sel = 0; + int anontls_sel = 0; static time_t last_https = 0; static char last_get[256]; static int first = 1; @@ -1832,7 +1857,7 @@ void accept_openssl(int mode, int presock) { * but hard to guess exactly (just worrying about local lusers * here, since we use INADDR_LOOPBACK). */ - rb = (unsigned char *) malloc(6); + rb = (unsigned char *) calloc(6, 1); RAND_bytes((char *)rb, 6); sprintf(cookie, "RB=%d%d%d%d%d%d/%f%f/0x%x", rb[0], rb[1], rb[2], rb[3], rb[4], rb[5], @@ -1915,6 +1940,7 @@ void accept_openssl(int mode, int presock) { int i, have_httpd = 0; int f_in = fileno(stdin); int f_out = fileno(stdout); + int skip_vnc_tls = mode == OPENSSL_HTTPS ? 1 : 0; if (db) fprintf(stderr, "helper pid in: %d %d %d %d\n", f_in, f_out, sock, listen); @@ -1962,7 +1988,7 @@ void accept_openssl(int mode, int presock) { s_in = s_out = sock; } - if (! ssl_init(s_in, s_out)) { + if (! ssl_init(s_in, s_out, skip_vnc_tls)) { close(vncsock); exit(1); } @@ -1973,10 +1999,10 @@ void accept_openssl(int mode, int presock) { sprintf(tbuf, "%s,VENCRYPT=%d,%s", uniq, vencrypt_selected, cookie); write(vncsock, tbuf, strlen(cookie)); goto wrote_cookie; - } else if (tlsvnc_selected != 0) { + } else if (anontls_selected != 0) { char *tbuf; tbuf = (char *) malloc(strlen(cookie) + 100); - sprintf(tbuf, "%s,TLSVNC=%d,%s", uniq, tlsvnc_selected, cookie); + sprintf(tbuf, "%s,ANONTLS=%d,%s", uniq, anontls_selected, cookie); write(vncsock, tbuf, strlen(cookie)); goto wrote_cookie; } @@ -2005,7 +2031,7 @@ void accept_openssl(int mode, int presock) { } if (have_httpd) { - int n = 0, is_http; + int n = 0, is_http = 0; int hport = screen->httpPort; char *iface = NULL; char *buf, *tbuf; @@ -2348,7 +2374,7 @@ void accept_openssl(int mode, int presock) { char *q = strstr(rcookie, "RB="); if (q && strstr(cookie, q) == cookie) { vencrypt_sel = 0; - tlsvnc_sel = 0; + anontls_sel = 0; q = strstr(rcookie, "VENCRYPT="); if (q && sscanf(q, "VENCRYPT=%d,", &vencrypt_sel) == 1) { if (vencrypt_sel != 0) { @@ -2356,10 +2382,10 @@ void accept_openssl(int mode, int presock) { goto accept_client; } } - q = strstr(rcookie, "TLSVNC="); - if (q && sscanf(q, "TLSVNC=%d,", &tlsvnc_sel) == 1) { - if (tlsvnc_sel != 0) { - rfbLog("SSL: TLSVNC mode=%d accepted.\n", tlsvnc_sel); + q = strstr(rcookie, "ANONTLS="); + if (q && sscanf(q, "ANONTLS=%d,", &anontls_sel) == 1) { + if (anontls_sel != 0) { + rfbLog("SSL: ANONTLS mode=%d accepted.\n", anontls_sel); goto accept_client; } } @@ -2508,7 +2534,7 @@ void accept_openssl(int mode, int presock) { if (!finish_vencrypt_auth(client, vencrypt_sel)) { rfbCloseClient(client); } - } else if (tlsvnc_sel != 0) { + } else if (anontls_sel != 0) { client->protocolMajorVersion = 3; client->protocolMinorVersion = 8; rfbAuthNewClient(client); @@ -2744,12 +2770,12 @@ static int switch_to_anon_dh(void) { return 1; } -static int tlsvnc_dialog(int s_in, int s_out) { +static int anontls_dialog(int s_in, int s_out) { - tlsvnc_selected = 1; + anontls_selected = 1; if (!switch_to_anon_dh()) { - rfbLog("tlsvnc: Anonymous Diffie-Hellman failed.\n"); + rfbLog("anontls: Anonymous Diffie-Hellman failed.\n"); return 0; } @@ -2924,27 +2950,27 @@ static int check_vnc_tls_mode(int s_in, int s_out) { char buf[256]; vencrypt_selected = 0; - tlsvnc_selected = 0; + anontls_selected = 0; - if (vencrypt_mode == VENCRYPT_NONE && tlsvnc_mode == TLSVNC_NONE) { + if (vencrypt_mode == VENCRYPT_NONE && anontls_mode == ANONTLS_NONE) { /* only normal SSL */ return 1; } if (ssl_client_mode) { /* XXX check if this can be done in SSL client mode. */ - if (vencrypt_mode == VENCRYPT_FORCE || tlsvnc_mode == TLSVNC_FORCE) { - rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/TLSVNC_FORCE prevents normal SSL\n"); + if (vencrypt_mode == VENCRYPT_FORCE || anontls_mode == ANONTLS_FORCE) { + rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/ANONTLS_FORCE prevents normal SSL\n"); return 0; } return 1; } - if (ssl_verify && vencrypt_mode != VENCRYPT_FORCE && tlsvnc_mode == TLSVNC_FORCE) { - rfbLog("check_vnc_tls_mode: Cannot use TLSVNC_FORCE with -sslverify (Anon DH only)\n"); + if (ssl_verify && vencrypt_mode != VENCRYPT_FORCE && anontls_mode == ANONTLS_FORCE) { + rfbLog("check_vnc_tls_mode: Cannot use ANONTLS_FORCE with -sslverify (Anon DH only)\n"); /* fallback to normal SSL */ return 1; } - while (waited < 0.7) { + while (waited < 1.1) { fd_set rfds; FD_ZERO(&rfds); FD_SET(s_in, &rfds); @@ -2962,8 +2988,8 @@ static int check_vnc_tls_mode(int s_in, int s_out) { if (input) { /* got SSL client hello, can only assume normal SSL */ - if (vencrypt_mode == VENCRYPT_FORCE || tlsvnc_mode == TLSVNC_FORCE) { - rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/TLSVNC_FORCE prevents normal SSL\n"); + if (vencrypt_mode == VENCRYPT_FORCE || anontls_mode == ANONTLS_FORCE) { + rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/ANONTLS_FORCE prevents normal SSL\n"); return 0; } return 1; @@ -2982,7 +3008,12 @@ static int check_vnc_tls_mode(int s_in, int s_out) { } if (sscanf(buf, "RFB %03d.%03d\n", &major, &minor) != 2) { - rfbLog("check_vnc_tls_mode: abnormal handshake: '%s'\n", buf); + int i; + rfbLog("check_vnc_tls_mode: abnormal handshake: '%s'\nbytes: ", buf); + for (i=0; i < 12; i++) { + fprintf(stderr, "%x.", (int) buf[i]); + } + fprintf(stderr, "\n"); close(s_in); close(s_out); return 0; } @@ -2996,18 +3027,18 @@ static int check_vnc_tls_mode(int s_in, int s_out) { n = 1; if (vencrypt_mode == VENCRYPT_FORCE) { buf[n++] = rfbSecTypeVencrypt; - } else if (tlsvnc_mode == TLSVNC_FORCE && !ssl_verify) { - buf[n++] = rfbSecTypeTlsVnc; + } else if (anontls_mode == ANONTLS_FORCE && !ssl_verify) { + buf[n++] = rfbSecTypeAnonTls; } else if (vencrypt_mode == VENCRYPT_SOLE) { buf[n++] = rfbSecTypeVencrypt; - } else if (tlsvnc_mode == TLSVNC_SOLE && !ssl_verify) { - buf[n++] = rfbSecTypeTlsVnc; + } else if (anontls_mode == ANONTLS_SOLE && !ssl_verify) { + buf[n++] = rfbSecTypeAnonTls; } else { if (vencrypt_mode == VENCRYPT_SUPPORT) { buf[n++] = rfbSecTypeVencrypt; } - if (tlsvnc_mode == TLSVNC_SUPPORT && !ssl_verify) { - buf[n++] = rfbSecTypeTlsVnc; + if (anontls_mode == ANONTLS_SUPPORT && !ssl_verify) { + buf[n++] = rfbSecTypeAnonTls; } } @@ -3026,7 +3057,7 @@ static int check_vnc_tls_mode(int s_in, int s_out) { } if (buf[0] == rfbSecTypeVencrypt) stype = "VeNCrypt"; - if (buf[0] == rfbSecTypeTlsVnc) stype = "TLSVNC"; + if (buf[0] == rfbSecTypeAnonTls) stype = "ANONTLS"; rfbLog("check_vnc_tls_mode: reply: %d (%s)\n", (int) buf[0], stype); @@ -3051,8 +3082,8 @@ static int check_vnc_tls_mode(int s_in, int s_out) { if (sectype == rfbSecTypeVencrypt) { return vencrypt_dialog(s_in, s_out); - } else if (sectype == rfbSecTypeTlsVnc) { - return tlsvnc_dialog(s_in, s_out); + } else if (sectype == rfbSecTypeAnonTls) { + return anontls_dialog(s_in, s_out); } else { return 0; } @@ -3088,11 +3119,15 @@ static void pr_ssl_info(int verb) { } static void ssl_timeout (int sig) { - rfbLog("sig: %d, ssl_init timed out.\n", sig); + int i; + rfbLog("sig: %d, ssl_init[%d] timed out.\n", sig, getpid()); + for (i=0; i < 256; i) { + close(i); + } exit(1); } -static int ssl_init(int s_in, int s_out) { +static int ssl_init(int s_in, int s_out, int skip_vnc_tls) { unsigned char *sid = (unsigned char *) "x11vnc SID"; char *name; int peerport = 0; @@ -3112,7 +3147,10 @@ static int ssl_init(int s_in, int s_out) { } if (db) fprintf(stderr, "ssl_init: %d/%d\n", s_in, s_out); - if (!check_vnc_tls_mode(s_in, s_out)) { + if (skip_vnc_tls) { + rfbLog("SSL: ssl_helper[%d]: HTTPS mode, skipping check_vnc_tls_mode()\n", + getpid(), name, peerport); + } else if (!check_vnc_tls_mode(s_in, s_out)) { return 0; } @@ -3305,7 +3343,7 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { time_t start; int tv_https_early = 60; int tv_https_later = 20; - int tv_vnc_early = 25; + int tv_vnc_early = 40; int tv_vnc_later = 43200; /* was 300, stunnel: 43200 */ int tv_cutover = 70; int tv_closing = 60; @@ -3374,7 +3412,7 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { cptr = 0; /* offsets into ABSIZE buffers */ sptr = 0; - if (vencrypt_selected > 0 || tlsvnc_selected > 0) { + if (vencrypt_selected > 0 || anontls_selected > 0) { char tmp[16]; /* read and discard the extra RFB version */ memset(tmp, 0, sizeof(tmp)); @@ -3501,8 +3539,8 @@ static void ssl_xfer(int csock, int s_in, int s_out, int is_https) { } continue; } - rfbLog("SSL: ssl_xfer[%d]: connection timedout. %d\n", - getpid(), ndata); + rfbLog("SSL: ssl_xfer[%d]: connection timedout. %d tv_use: %d\n", + getpid(), ndata, tv_use); /* connection finished */ return; } |