Home | History | Annotate | Download | only in x11vnc
      1 /*
      2    Copyright (C) 2002-2010 Karl J. Runge <runge (at) karlrunge.com>
      3    All rights reserved.
      4 
      5 This file is part of x11vnc.
      6 
      7 x11vnc is free software; you can redistribute it and/or modify
      8 it under the terms of the GNU General Public License as published by
      9 the Free Software Foundation; either version 2 of the License, or (at
     10 your option) any later version.
     11 
     12 x11vnc is distributed in the hope that it will be useful,
     13 but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with x11vnc; if not, write to the Free Software
     19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
     20 or see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, as a special exception, Karl J. Runge
     23 gives permission to link the code of its release of x11vnc with the
     24 OpenSSL project's "OpenSSL" library (or with modified versions of it
     25 that use the same license as the "OpenSSL" library), and distribute
     26 the linked executables.  You must obey the GNU General Public License
     27 in all respects for all of the code used other than "OpenSSL".  If you
     28 modify this file, you may extend this exception to your version of the
     29 file, but you are not obligated to do so.  If you do not wish to do
     30 so, delete this exception statement from your version.
     31 */
     32 
     33 /* -- sslhelper.c -- */
     34 
     35 #include "x11vnc.h"
     36 #include "inet.h"
     37 #include "cleanup.h"
     38 #include "screen.h"
     39 #include "scan.h"
     40 #include "connections.h"
     41 #include "sslcmds.h"
     42 #include "unixpw.h"
     43 #include "user.h"
     44 
     45 #define OPENSSL_INETD   1
     46 #define OPENSSL_VNC     2
     47 #define OPENSSL_VNC6    3
     48 #define OPENSSL_HTTPS   4
     49 #define OPENSSL_HTTPS6  5
     50 #define OPENSSL_REVERSE 6
     51 
     52 #define DO_DH 0
     53 
     54 #if LIBVNCSERVER_HAVE_FORK
     55 #if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID
     56 #define FORK_OK
     57 #endif
     58 #endif
     59 
     60 int openssl_sock = -1;
     61 int openssl_sock6 = -1;
     62 int openssl_port_num = 0;
     63 int https_sock = -1;
     64 int https_sock6 = -1;
     65 pid_t openssl_last_helper_pid = 0;
     66 char *openssl_last_ip = NULL;
     67 
     68 static char *certret = NULL;
     69 static int certret_fd = -1;
     70 static mode_t omode;
     71 char *certret_str = NULL;
     72 
     73 static char *dhret = NULL;
     74 static int dhret_fd = -1;
     75 char *dhret_str = NULL;
     76 char *new_dh_params = NULL;
     77 
     78 void raw_xfer(int csock, int s_in, int s_out);
     79 
     80 /* openssl(1) pem related functions: */
     81 char *get_saved_pem(char *string, int create);
     82 char *find_openssl_bin(void);
     83 char *get_ssl_verify_file(char *str_in);
     84 char *create_tmp_pem(char *path, int prompt);
     85 
     86 static char *get_input(char *tag, char **in);
     87 
     88 char *get_saved_pem(char *save, int create) {
     89 	char *s = NULL, *path, *cdir, *tmp;
     90 	int prompt = 0, len;
     91 	struct stat sbuf;
     92 
     93 	if (! save) {
     94 		rfbLog("get_saved_pem: save string is null.\n");
     95 		clean_up_exit(1);
     96 	}
     97 
     98 	if (strstr(save, "SAVE_PROMPT") == save) {
     99 		prompt = 1;
    100 		s = save + strlen("SAVE_PROMPT");
    101 	} else if (strstr(save, "SAVE_NOPROMPT") == save) {
    102 		set_env("GENCERT_NOPROMPT", "1");
    103 		s = save + strlen("SAVE_NOPROMPT");
    104 	} else if (strstr(save, "SAVE") == save) {
    105 		s = save + strlen("SAVE");
    106 	} else {
    107 		rfbLog("get_saved_pem: invalid save string: %s\n", save);
    108 		clean_up_exit(1);
    109 	}
    110 	if (strchr(s, '/')) {
    111 		rfbLog("get_saved_pem: invalid save string: %s\n", s);
    112 		clean_up_exit(1);
    113 	}
    114 
    115 
    116 	cdir = get_Cert_dir(NULL, &tmp);
    117 	if (! cdir || ! tmp) {
    118 		rfbLog("get_saved_pem: could not find Cert dir.\n");
    119 		clean_up_exit(1);
    120 	}
    121 
    122 	len = strlen(cdir) + strlen("/server.pem") + strlen(s) + 1;
    123 
    124 	path = (char *) malloc(len);
    125 	sprintf(path, "%s/server%s.pem", cdir, s);
    126 
    127 	if (stat(path, &sbuf) != 0) {
    128 		char *new_name = NULL;
    129 		if (create) {
    130 			if (inetd || opts_bg) {
    131 				set_env("GENCERT_NOPROMPT", "1");
    132 			}
    133 			new_name = create_tmp_pem(path, prompt);
    134 			if (!getenv("X11VNC_SSL_NO_PASSPHRASE") && !inetd && !opts_bg) {
    135 				sslEncKey(new_name, 0);
    136 			}
    137 		}
    138 		return new_name;
    139 	}
    140 
    141 	if (! quiet) {
    142 		char line[1024];
    143 		int on = 0;
    144 		FILE *in = fopen(path, "r");
    145 		if (in != NULL) {
    146 			rfbLog("\n");
    147 			rfbLog("Using SSL Certificate:\n");
    148 			fprintf(stderr, "\n");
    149 			while (fgets(line, 1024, in) != NULL) {
    150 				if (strstr(line, "BEGIN CERTIFICATE")) {
    151 					on = 1;
    152 				}
    153 				if (on) {
    154 					fprintf(stderr, "%s", line);
    155 				}
    156 				if (strstr(line, "END CERTIFICATE")) {
    157 					on = 0;
    158 				}
    159 				if (strstr(line, "PRIVATE KEY")) {
    160 					on = 0;
    161 				}
    162 			}
    163 			fprintf(stderr, "\n");
    164 			fclose(in);
    165 		}
    166 	}
    167 	return strdup(path);
    168 }
    169 
    170 static char *get_input(char *tag, char **in) {
    171 	char line[1024], *str;
    172 
    173 	if (! tag || ! in || ! *in) {
    174 		return NULL;
    175 	}
    176 
    177 	fprintf(stderr, "%s:\n     [%s] ", tag, *in);
    178 	if (fgets(line, 1024, stdin) == NULL) {
    179 		rfbLog("could not read stdin!\n");
    180 		rfbLogPerror("fgets");
    181 		clean_up_exit(1);
    182 	}
    183 	if ((str = strrchr(line, '\n')) != NULL) {
    184 		*str = '\0';
    185 	}
    186 	str = lblanks(line);
    187 	if (!strcmp(str, "")) {
    188 		return *in;
    189 	} else {
    190 		return strdup(line);
    191 	}
    192 }
    193 
    194 char *find_openssl_bin(void) {
    195 	char *path, *exe, *p, *gp;
    196 	struct stat sbuf;
    197 	int found_openssl = 0;
    198 	char extra[] = ":/usr/bin:/bin:/usr/sbin:/usr/local/bin"
    199 	    ":/usr/local/sbin:/usr/sfw/bin";
    200 
    201 	gp = getenv("PATH");
    202 	if (! gp) {
    203 		fprintf(stderr, "could not find openssl(1) program in PATH. (null)\n");
    204 		return NULL;
    205 	}
    206 
    207 	path = (char *) malloc(strlen(gp) + strlen(extra) + 1);
    208 	strcpy(path, gp);
    209 	strcat(path, extra);
    210 
    211 	/* find openssl binary: */
    212 	exe = (char *) malloc(strlen(path) + strlen("/openssl") + 1);
    213 	p = strtok(path, ":");
    214 
    215 	while (p) {
    216 		sprintf(exe, "%s/openssl", p);
    217 		if (stat(exe, &sbuf) == 0) {
    218 			if (! S_ISDIR(sbuf.st_mode)) {
    219 				found_openssl = 1;
    220 				break;
    221 			}
    222 		}
    223 		p = strtok(NULL, ":");
    224 	}
    225 	free(path);
    226 
    227 	if (! found_openssl) {
    228 		fprintf(stderr, "could not find openssl(1) program in PATH.\n");
    229 		fprintf(stderr, "PATH=%s\n", gp);
    230 		fprintf(stderr, "(also checked: %s)\n", extra);
    231 		return NULL;
    232 	}
    233 	return exe;
    234 }
    235 
    236 /* uses /usr/bin/openssl to create a tmp cert */
    237 
    238 char *create_tmp_pem(char *pathin, int prompt) {
    239 	pid_t pid, pidw;
    240 	FILE *in, *out;
    241 	char cnf[] = "/tmp/x11vnc-cnf.XXXXXX";
    242 	char pem[] = "/tmp/x11vnc-pem.XXXXXX";
    243 	char str[8*1024], line[1024], *exe;
    244 	int cnf_fd, pem_fd, status, show_cert = 1;
    245 	char *days;
    246 	char *C, *L, *OU, *O, *CN, *EM;
    247 	char tmpl[] =
    248 "[ req ]\n"
    249 "prompt = no\n"
    250 "default_bits = 2048\n"
    251 "encrypt_key = yes\n"
    252 "distinguished_name = req_dn\n"
    253 "x509_extensions = cert_type\n"
    254 "\n"
    255 "[ req_dn ]\n"
    256 "countryName=%s\n"
    257 "localityName=%s\n"
    258 "organizationalUnitName=%s\n"
    259 "organizationName=%s\n"
    260 "commonName=%s\n"
    261 "emailAddress=%s\n"
    262 "\n"
    263 "[ cert_type ]\n"
    264 "nsCertType = server\n"
    265 ;
    266 
    267 	C = strdup("AU");
    268 	L = strdup(UT.sysname ? UT.sysname : "unknown-os");
    269 	snprintf(line, 1024, "%s-%f", UT.nodename ? UT.nodename :
    270 	    "unknown-node", dnow());
    271 	line[1024-1] = '\0';
    272 
    273 	OU = strdup(line);
    274 	O = strdup("x11vnc");
    275 	if (pathin) {
    276 		snprintf(line, 1024, "x11vnc-SELF-SIGNED-CERT-%d", getpid());
    277 	} else {
    278 		snprintf(line, 1024, "x11vnc-SELF-SIGNED-TEMPORARY-CERT-%d",
    279 		    getpid());
    280 	}
    281 	line[1024-1] = '\0';
    282 	CN = strdup(line);
    283 	EM = strdup("x11vnc (at) server.nowhere");
    284 
    285 	/* ssl */
    286 	if (no_external_cmds || !cmd_ok("ssl")) {
    287 		rfbLog("create_tmp_pem: cannot run external commands.\n");
    288 		return NULL;
    289 	}
    290 
    291 	rfbLog("\n");
    292 	if (pathin) {
    293 		rfbLog("Creating a self-signed PEM certificate...\n");
    294 	} else {
    295 		rfbLog("Creating a temporary, self-signed PEM certificate...\n");
    296 	}
    297 
    298 	rfbLog("\n");
    299 	rfbLog("This will NOT prevent Man-In-The-Middle attacks UNLESS you\n");
    300 	rfbLog("get the certificate information to the VNC viewers SSL\n");
    301 	rfbLog("tunnel configuration or you take the extra steps to sign it\n");
    302 	rfbLog("with a CA key. However, it will prevent passive network\n");
    303 	rfbLog("sniffing.\n");
    304 	rfbLog("\n");
    305 	rfbLog("The cert inside -----BEGIN CERTIFICATE-----\n");
    306 	rfbLog("                           ....\n");
    307 	rfbLog("                -----END CERTIFICATE-----\n");
    308 	rfbLog("printed below may be used on the VNC viewer-side to\n");
    309 	rfbLog("authenticate this server for this session.  See the -ssl\n");
    310 	rfbLog("help output and the FAQ for how to create a permanent\n");
    311 	rfbLog("server certificate.\n");
    312 	rfbLog("\n");
    313 
    314 	exe = find_openssl_bin();
    315 	if (! exe) {
    316 		return NULL;
    317 	}
    318 
    319 	/* create template file with our made up stuff: */
    320 	if (prompt) {
    321 		fprintf(stderr, "\nReply to the following prompts to set"
    322 		    " your Certificate parameters.\n");
    323 		fprintf(stderr, "(press Enter to accept the default in [...], "
    324 		    "or type in the value you want)\n\n");
    325 		C = get_input("CountryName", &C);
    326 		L = get_input("LocalityName", &L);
    327 		OU = get_input("OrganizationalUnitName", &OU);
    328 		O = get_input("OrganizationalName", &O);
    329 		CN = get_input("CommonName", &CN);
    330 		EM = get_input("EmailAddress", &EM);
    331 	}
    332 	sprintf(str, tmpl, C, L, OU, O, CN, EM);
    333 
    334 	cnf_fd = mkstemp(cnf);
    335 	if (cnf_fd < 0) {
    336 		return NULL;
    337 	}
    338 	pem_fd = mkstemp(pem);
    339 	if (pem_fd < 0) {
    340 		close(cnf_fd);
    341 		return NULL;
    342 	}
    343 
    344 	close(pem_fd);
    345 
    346 	write(cnf_fd, str, strlen(str));
    347 	close(cnf_fd);
    348 
    349 	if (pathin) {
    350 		days = "365";
    351 	} else {
    352 		days = "30";
    353 	}
    354 
    355 #ifndef FORK_OK
    356 	rfbLog("not compiled with fork(2)\n");
    357 	clean_up_exit(1);
    358 #else
    359 	/* make RSA key */
    360 	pid = fork();
    361 	if (pid < 0) {
    362 		return NULL;
    363 	} else if (pid == 0) {
    364 		int i;
    365 		for (i=0; i<256; i++) {
    366 			close(i);
    367 		}
    368 		execlp(exe, exe, "req", "-new", "-x509", "-nodes",
    369 		    "-days", days, "-config", cnf, "-out", pem,
    370 		    "-keyout", pem, (char *)0);
    371 		exit(1);
    372 	}
    373 	pidw = waitpid(pid, &status, 0);
    374 	if (pidw != pid) {
    375 		return NULL;
    376 	}
    377 	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
    378 		;
    379 	} else {
    380 		return NULL;
    381 	}
    382 
    383 #if DO_DH
    384 	/* make DH parameters */
    385 	pid = fork();
    386 	if (pid < 0) {
    387 		return NULL;
    388 	} else if (pid == 0) {
    389 		int i;
    390 		for (i=0; i<256; i++) {
    391 			close(i);
    392 		}
    393 		/* rather slow at 1024 */
    394 		execlp(exe, exe, "dhparam", "-out", cnf, "512", (char *)0);
    395 		exit(1);
    396 	}
    397 	pidw = waitpid(pid, &status, 0);
    398 	if (pidw != pid) {
    399 		return NULL;
    400 	}
    401 	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
    402 		;
    403 	} else {
    404 		return NULL;
    405 	}
    406 
    407 	/* append result: */
    408 	in = fopen(cnf, "r");
    409 	if (in == NULL) {
    410 		return NULL;
    411 	}
    412 	out = fopen(pem, "a");
    413 	if (out == NULL) {
    414 		fclose(in);
    415 		return NULL;
    416 	}
    417 	while (fgets(line, 1024, in) != NULL) {
    418 		fprintf(out, "%s", line);
    419 	}
    420 	fclose(in);
    421 	fclose(out);
    422 #endif
    423 
    424 #endif	/* FORK_OK */
    425 
    426 	unlink(cnf);
    427 	free(exe);
    428 
    429 	if (pathin != NULL) {
    430 		char *q, *pathcrt = strdup(pathin);
    431 		FILE *crt = NULL;
    432 		int on = 0;
    433 
    434 		q = strrchr(pathcrt, '/');
    435 		if (q) {
    436 			q = strstr(q, ".pem");
    437 			if (q) {
    438 				*(q+1) = 'c';
    439 				*(q+2) = 'r';
    440 				*(q+3) = 't';
    441 				crt = fopen(pathcrt, "w");
    442 			}
    443 		}
    444 		if (crt == NULL) {
    445 			rfbLog("could not open: %s\n", pathcrt);
    446 			rfbLogPerror("fopen");
    447 			return NULL;
    448 		}
    449 
    450 		out = fopen(pathin, "w");
    451 		chmod(pathin,  0600);
    452 		if (out == NULL) {
    453 			rfbLog("could not open: %s\n", pathin);
    454 			rfbLogPerror("fopen");
    455 			fclose(crt);
    456 			return NULL;
    457 		}
    458 
    459 		in = fopen(pem, "r");
    460 		if (in == NULL) {
    461 			rfbLog("could not open: %s\n", pem);
    462 			rfbLogPerror("fopen");
    463 			fclose(out);
    464 			fclose(crt);
    465 			unlink(pathin);
    466 			unlink(pathcrt);
    467 			return NULL;
    468 		}
    469 		while (fgets(line, 1024, in) != NULL) {
    470 			if (strstr(line, "BEGIN CERTIFICATE")) {
    471 				on = 1;
    472 			}
    473 			fprintf(out, "%s", line);
    474 			if (on) {
    475 				fprintf(crt, "%s", line);
    476 				if (!quiet) {
    477 					fprintf(stderr, "%s", line);
    478 				}
    479 			}
    480 			if (strstr(line, "END CERTIFICATE")) {
    481 				on = 0;
    482 			}
    483 			if (strstr(line, "PRIVATE KEY")) {
    484 				on = 0;
    485 			}
    486 		}
    487 		fclose(in);
    488 		fclose(out);
    489 		fclose(crt);
    490 	}
    491 
    492 	if (show_cert) {
    493 		exe = find_openssl_bin();
    494 		if (!exe) {
    495 			exe = strdup("openssl");
    496 		}
    497 		if (strlen(pem) + strlen(exe) < 4000) {
    498 			char cmd[5000];
    499 			if (inetd) {
    500 				sprintf(cmd, "%s x509 -text -in '%s' 1>&2", exe, pem);
    501 			} else {
    502 				sprintf(cmd, "%s x509 -text -in '%s'", exe, pem);
    503 			}
    504 			fprintf(stderr, "\n");
    505 			system(cmd);
    506 			fprintf(stderr, "\n");
    507 		}
    508 		free(exe);
    509 	}
    510 
    511 	if (pathin) {
    512 		unlink(pem);
    513 		return strdup(pathin);
    514 	} else {
    515 		return strdup(pem);
    516 	}
    517 }
    518 
    519 static int appendfile(FILE *out, char *infile) {
    520 	char line[1024];
    521 	FILE *in;
    522 
    523 	if (! infile) {
    524 		rfbLog("appendfile: null infile.\n");
    525 		return 0;
    526 	}
    527 	if (! out) {
    528 		rfbLog("appendfile: null out handle.\n");
    529 		return 0;
    530 	}
    531 
    532 	in = fopen(infile, "r");
    533 
    534 	if (in == NULL) {
    535 		rfbLog("appendfile: %s\n", infile);
    536 		rfbLogPerror("fopen");
    537 		return 0;
    538 	}
    539 
    540 	while (fgets(line, 1024, in) != NULL) {
    541 		fprintf(out, "%s", line);
    542 	}
    543 	fclose(in);
    544 	return 1;
    545 }
    546 
    547 char *get_ssl_verify_file(char *str_in) {
    548 	char *p, *str, *cdir, *tmp;
    549 	char *tfile, *tfile2;
    550 	FILE *file;
    551 	struct stat sbuf;
    552 	int count = 0, fd;
    553 
    554 	if (! str_in) {
    555 		rfbLog("get_ssl_verify_file: no filename\n");
    556 		exit(1);
    557 	}
    558 
    559 	if (stat(str_in, &sbuf) == 0) {
    560 		/* assume he knows what he is doing. */
    561 		return str_in;
    562 	}
    563 
    564 	cdir = get_Cert_dir(NULL, &tmp);
    565 	if (! cdir || ! tmp) {
    566 		rfbLog("get_ssl_verify_file: invalid cert-dir.\n");
    567 		exit(1);
    568 	}
    569 
    570 	tfile  = (char *) malloc(strlen(tmp) + 1024);
    571 	tfile2 = (char *) malloc(strlen(tmp) + 1024);
    572 
    573 	sprintf(tfile, "%s/sslverify-tmp-load-%d.crts.XXXXXX", tmp, getpid());
    574 
    575 	fd = mkstemp(tfile);
    576 	if (fd < 0) {
    577 		rfbLog("get_ssl_verify_file: %s\n", tfile);
    578 		rfbLogPerror("mkstemp");
    579 		exit(1);
    580 	}
    581 	close(fd);
    582 
    583 	file = fopen(tfile, "w");
    584 	chmod(tfile, 0600);
    585 	if (file == NULL) {
    586 		rfbLog("get_ssl_verify_file: %s\n", tfile);
    587 		rfbLogPerror("fopen");
    588 		exit(1);
    589 	}
    590 
    591 	str = strdup(str_in);
    592 	p = strtok(str, ",");
    593 
    594 	while (p) {
    595 		if (!strcmp(p, "CA")) {
    596 			sprintf(tfile2, "%s/CA/cacert.pem", cdir);
    597 			if (! appendfile(file, tfile2)) {
    598 				unlink(tfile);
    599 				exit(1);
    600 			}
    601 			rfbLog("sslverify: loaded %s\n", tfile2);
    602 			count++;
    603 
    604 		} else if (!strcmp(p, "clients")) {
    605 			DIR *dir;
    606 			struct dirent *dp;
    607 
    608 			sprintf(tfile2, "%s/clients", cdir);
    609 			dir = opendir(tfile2);
    610 			if (! dir) {
    611 				rfbLog("get_ssl_verify_file: %s\n", tfile2);
    612 				rfbLogPerror("opendir");
    613 				unlink(tfile);
    614 				exit(1);
    615 			}
    616 			while ( (dp = readdir(dir)) != NULL) {
    617 				char *n = dp->d_name;
    618 				char *q = strstr(n, ".crt");
    619 
    620 				if (! q || strlen(q) != strlen(".crt")) {
    621 					continue;
    622 				}
    623 				if (strlen(n) > 512) {
    624 					continue;
    625 				}
    626 
    627 				sprintf(tfile2, "%s/clients/%s", cdir, n);
    628 				if (! appendfile(file, tfile2)) {
    629 					unlink(tfile);
    630 					exit(1);
    631 				}
    632 				rfbLog("sslverify: loaded %s\n",
    633 				    tfile2);
    634 				count++;
    635 			}
    636 			closedir(dir);
    637 
    638 		} else {
    639 			if (strlen(p) > 512) {
    640 				unlink(tfile);
    641 				exit(1);
    642 			}
    643 			sprintf(tfile2, "%s/clients/%s.crt", cdir, p);
    644 			if (stat(tfile2, &sbuf) != 0) {
    645 				sprintf(tfile2, "%s/clients/%s", cdir, p);
    646 			}
    647 			if (! appendfile(file, tfile2)) {
    648 				unlink(tfile);
    649 				exit(1);
    650 			}
    651 			rfbLog("sslverify: loaded %s\n", tfile2);
    652 			count++;
    653 		}
    654 		p = strtok(NULL, ",");
    655 	}
    656 	fclose(file);
    657 	free(tfile2);
    658 	free(str);
    659 
    660 	rfbLog("sslverify: using %d client certs in\n", count);
    661 	rfbLog("sslverify: %s\n", tfile);
    662 
    663 	return tfile;
    664 }
    665 
    666 int openssl_present(void);
    667 void openssl_init(int isclient);
    668 void openssl_port(int restart);
    669 void https_port(int restart);
    670 void check_openssl(void);
    671 void check_https(void);
    672 void ssl_helper_pid(pid_t pid, int sock);
    673 void accept_openssl(int mode, int presock);
    674 
    675 static void lose_ram(void);
    676 #define ABSIZE 16384
    677 
    678 static int vencrypt_selected = 0;
    679 static int anontls_selected = 0;
    680 
    681 /* to test no openssl libssl */
    682 #if 0
    683 #undef LIBVNCSERVER_HAVE_LIBSSL
    684 #define LIBVNCSERVER_HAVE_LIBSSL 0
    685 #endif
    686 
    687 #if !LIBVNCSERVER_HAVE_LIBSSL
    688 
    689 static void badnews(char *name) {
    690 	use_openssl = 0;
    691 	use_stunnel = 0;
    692 	rfbLog("** %s: not compiled with libssl OpenSSL support **\n", name ? name : "???");
    693 	clean_up_exit(1);
    694 }
    695 
    696 int openssl_present(void) {return 0;}
    697 void openssl_init(int isclient) {badnews("openssl_init");}
    698 
    699 #define SSL_ERROR_NONE 0
    700 
    701 static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
    702 	if (enc_str != NULL) {
    703 		return 1;
    704 	}
    705 	badnews("ssl_init");
    706 	return 0;
    707 }
    708 
    709 static void ssl_xfer(int csock, int s_in, int s_out, int is_https) {
    710 	if (enc_str != NULL && !strcmp(enc_str, "none")) {
    711 		usleep(250*1000);
    712 		rfbLog("doing '-enc none' raw transfer (no encryption)\n");
    713 		raw_xfer(csock, s_in, s_out);
    714 	} else {
    715 		badnews("ssl_xfer");
    716 	}
    717 }
    718 
    719 #else 	/* LIBVNCSERVER_HAVE_LIBSSL */
    720 
    721 /*
    722  * This is because on older systems both zlib.h and ssl.h define
    723  * 'free_func' nothing we do below (currently) induces an external
    724  * dependency on 'free_func'.
    725  */
    726 #define free_func my_jolly_little_free_func
    727 
    728 #include <openssl/ssl.h>
    729 #include <openssl/err.h>
    730 #include <openssl/rand.h>
    731 
    732 static SSL_CTX *ctx = NULL;
    733 static RSA *rsa_512 = NULL;
    734 static RSA *rsa_1024 = NULL;
    735 static SSL *ssl = NULL;
    736 static X509_STORE *revocation_store = NULL;
    737 
    738 
    739 static void init_prng(void);
    740 static void sslerrexit(void);
    741 static int  ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https);
    742 static void ssl_xfer(int csock, int s_in, int s_out, int is_https);
    743 
    744 #ifndef FORK_OK
    745 void openssl_init(int isclient) {
    746 	rfbLog("openssl_init: fork is not supported. cannot create"
    747 	    " ssl helper process.\n");
    748 	clean_up_exit(1);
    749 }
    750 int openssl_present(void) {return 0;}
    751 
    752 #else
    753 
    754 int openssl_present(void) {return 1;}
    755 
    756 static void sslerrexit(void) {
    757 	unsigned long err = ERR_get_error();
    758 
    759 	if (err) {
    760 		char str[256];
    761 		ERR_error_string(err, str);
    762 		fprintf(stderr, "ssl error: %s\n", str);
    763 	}
    764 	clean_up_exit(1);
    765 }
    766 
    767 static int pem_passwd_callback(char *buf, int size, int rwflag,
    768     void *userdata) {
    769 	char *q, line[1024];
    770 
    771 	if (! buf) {
    772 		exit(1);
    773 	}
    774 
    775 	fprintf(stderr, "\nA passphrase is needed to unlock an OpenSSL "
    776 	    "private key (PEM file).\n");
    777 	fprintf(stderr, "Enter passphrase> ");
    778 	system("stty -echo");
    779 	if(fgets(line, 1024, stdin) == NULL) {
    780 		fprintf(stdout, "\n");
    781 		system("stty echo");
    782 		exit(1);
    783 	}
    784 	system("stty echo");
    785 	fprintf(stdout, "\n\n");
    786 	q = strrchr(line, '\n');
    787 	if (q) {
    788 		*q = '\0';
    789 	}
    790 	line[1024 - 1] = '\0';
    791 	strncpy(buf, line, size);
    792 	buf[size - 1] = '\0';
    793 
    794 	if (0) rwflag = 0;	/* compiler warning. */
    795 	if (0) userdata = 0;	/* compiler warning. */
    796 
    797 	return strlen(buf);
    798 }
    799 
    800 /* based on mod_ssl */
    801 static int crl_callback(X509_STORE_CTX *callback_ctx) {
    802 	X509_STORE_CTX store_ctx;
    803 	X509_OBJECT obj;
    804 	X509_NAME *subject;
    805 	X509_NAME *issuer;
    806 	X509 *xs;
    807 	X509_CRL *crl;
    808 	X509_REVOKED *revoked;
    809 	EVP_PKEY *pubkey;
    810 	long serial;
    811 	BIO *bio;
    812 	int i, n, rc;
    813 	char *cp, *cp2;
    814 	ASN1_TIME *t;
    815 
    816 	/* Determine certificate ingredients in advance */
    817 	xs      = X509_STORE_CTX_get_current_cert(callback_ctx);
    818 	subject = X509_get_subject_name(xs);
    819 	issuer  = X509_get_issuer_name(xs);
    820 
    821 	/* Try to retrieve a CRL corresponding to the _subject_ of
    822 	* the current certificate in order to verify it's integrity. */
    823 	memset((char *)&obj, 0, sizeof(obj));
    824 	X509_STORE_CTX_init(&store_ctx, revocation_store, NULL, NULL);
    825 	rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, subject, &obj);
    826 	X509_STORE_CTX_cleanup(&store_ctx);
    827 	crl=obj.data.crl;
    828 
    829 	if(rc>0 && crl) {
    830 		/* Log information about CRL
    831 		 * (A little bit complicated because of ASN.1 and BIOs...) */
    832 		bio=BIO_new(BIO_s_mem());
    833 		BIO_printf(bio, "lastUpdate: ");
    834 		ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(crl));
    835 		BIO_printf(bio, ", nextUpdate: ");
    836 		ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(crl));
    837 		n=BIO_pending(bio);
    838 		cp=malloc(n+1);
    839 		n=BIO_read(bio, cp, n);
    840 		cp[n]='\0';
    841 		BIO_free(bio);
    842 		cp2=X509_NAME_oneline(subject, NULL, 0);
    843 		rfbLog("CA CRL: Issuer: %s, %s\n", cp2, cp);
    844 		OPENSSL_free(cp2);
    845 		free(cp);
    846 
    847 		/* Verify the signature on this CRL */
    848 		pubkey=X509_get_pubkey(xs);
    849 		if(X509_CRL_verify(crl, pubkey)<=0) {
    850 			rfbLog("Invalid signature on CRL\n");
    851 			X509_STORE_CTX_set_error(callback_ctx,
    852 				X509_V_ERR_CRL_SIGNATURE_FAILURE);
    853 			X509_OBJECT_free_contents(&obj);
    854 			if(pubkey)
    855 				EVP_PKEY_free(pubkey);
    856 			return 0; /* Reject connection */
    857 		}
    858 		if(pubkey)
    859 			EVP_PKEY_free(pubkey);
    860 
    861 		/* Check date of CRL to make sure it's not expired */
    862 		t=X509_CRL_get_nextUpdate(crl);
    863 		if(!t) {
    864 			rfbLog("Found CRL has invalid nextUpdate field\n");
    865 			X509_STORE_CTX_set_error(callback_ctx,
    866 				X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
    867 			X509_OBJECT_free_contents(&obj);
    868 			return 0; /* Reject connection */
    869 		}
    870 		if(X509_cmp_current_time(t)<0) {
    871 			rfbLog("Found CRL is expired - "
    872 				"revoking all certificates until you get updated CRL\n");
    873 			X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CRL_HAS_EXPIRED);
    874 			X509_OBJECT_free_contents(&obj);
    875 			return 0; /* Reject connection */
    876 		}
    877 		X509_OBJECT_free_contents(&obj);
    878 	}
    879 
    880 	/* Try to retrieve a CRL corresponding to the _issuer_ of
    881 	 * the current certificate in order to check for revocation. */
    882 	memset((char *)&obj, 0, sizeof(obj));
    883 	X509_STORE_CTX_init(&store_ctx, revocation_store, NULL, NULL);
    884 	rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, issuer, &obj);
    885 	X509_STORE_CTX_cleanup(&store_ctx);
    886 	crl=obj.data.crl;
    887 
    888 	if(rc>0 && crl) {
    889 		/* Check if the current certificate is revoked by this CRL */
    890 		n=sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
    891 		for(i=0; i<n; i++) {
    892 			revoked=sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
    893 			if(ASN1_INTEGER_cmp(revoked->serialNumber,
    894 					X509_get_serialNumber(xs)) == 0) {
    895 				serial=ASN1_INTEGER_get(revoked->serialNumber);
    896 				cp=X509_NAME_oneline(issuer, NULL, 0);
    897 				rfbLog("Certificate with serial %ld (0x%lX) "
    898 					"revoked per CRL from issuer %s\n", serial, serial, cp);
    899 				OPENSSL_free(cp);
    900 				X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CERT_REVOKED);
    901 				X509_OBJECT_free_contents(&obj);
    902 				return 0; /* Reject connection */
    903 			}
    904 		}
    905 		X509_OBJECT_free_contents(&obj);
    906 	}
    907 
    908 	return 1; /* Accept connection */
    909 }
    910 
    911 static int verify_callback(int ok, X509_STORE_CTX *callback_ctx) {
    912 	if (!ssl_verify) {
    913 		rfbLog("CRL_check: skipped.\n");
    914 		return ok;
    915 	}
    916 	if (!ssl_crl) {
    917 		rfbLog("CRL_check: skipped.\n");
    918 		return ok;
    919 	}
    920 	if (!ok) {
    921 		rfbLog("CRL_check: client cert is already rejected.\n");
    922 		return ok;
    923 	}
    924 	if (revocation_store) {
    925 		if (crl_callback(callback_ctx)) {
    926 			rfbLog("CRL_check: succeeded.\n");
    927 			return 1;
    928 		} else {
    929 			rfbLog("CRL_check: did not pass.\n");
    930 			return 0;
    931 		}
    932 	}
    933 	/* NOTREACHED */
    934 	return 1;
    935 }
    936 
    937 #define rfbSecTypeAnonTls  18
    938 #define rfbSecTypeVencrypt 19
    939 
    940 #define rfbVencryptPlain	256
    941 #define rfbVencryptTlsNone	257
    942 #define rfbVencryptTlsVnc	258
    943 #define rfbVencryptTlsPlain	259
    944 #define rfbVencryptX509None	260
    945 #define rfbVencryptX509Vnc	261
    946 #define rfbVencryptX509Plain	262
    947 
    948 static int ssl_client_mode = 0;
    949 
    950 static int switch_to_anon_dh(void);
    951 
    952 void openssl_init(int isclient) {
    953 	int db = 0, tmp_pem = 0, do_dh;
    954 	FILE *in;
    955 	double ds;
    956 	long mode;
    957 	static int first = 1;
    958 
    959 	do_dh = DO_DH;
    960 
    961 	if (enc_str != NULL) {
    962 		if (first) {
    963 			init_prng();
    964 		}
    965 		first = 0;
    966 		return;
    967 	}
    968 
    969 	if (! quiet) {
    970 		rfbLog("\n");
    971 		rfbLog("Initializing SSL (%s connect mode).\n", isclient ? "client":"server");
    972 	}
    973 	if (first) {
    974 		if (db) fprintf(stderr, "\nSSL_load_error_strings()\n");
    975 
    976 		SSL_load_error_strings();
    977 
    978 		if (db) fprintf(stderr, "SSL_library_init()\n");
    979 
    980 		SSL_library_init();
    981 
    982 		if (db) fprintf(stderr, "init_prng()\n");
    983 
    984 		init_prng();
    985 
    986 		first = 0;
    987 	}
    988 
    989 	if (isclient) {
    990 		ssl_client_mode = 1;
    991 	} else {
    992 		ssl_client_mode = 0;
    993 	}
    994 
    995 	if (ssl_client_mode) {
    996 		if (db) fprintf(stderr, "SSLv23_client_method()\n");
    997 		ctx = SSL_CTX_new( SSLv23_client_method() );
    998 	} else {
    999 		if (db) fprintf(stderr, "SSLv23_server_method()\n");
   1000 		ctx = SSL_CTX_new( SSLv23_server_method() );
   1001 	}
   1002 
   1003 	if (ctx == NULL) {
   1004 		rfbLog("openssl_init: SSL_CTX_new failed.\n");
   1005 		sslerrexit();
   1006 	}
   1007 
   1008 	ds = dnow();
   1009 	rsa_512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
   1010 	if (rsa_512 == NULL) {
   1011 		rfbLog("openssl_init: RSA_generate_key(512) failed.\n");
   1012 		sslerrexit();
   1013 	}
   1014 
   1015 	rfbLog("created  512 bit temporary RSA key: %.3fs\n", dnow() - ds);
   1016 
   1017 	ds = dnow();
   1018 	rsa_1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
   1019 	if (rsa_1024 == NULL) {
   1020 		rfbLog("openssl_init: RSA_generate_key(1024) failed.\n");
   1021 		sslerrexit();
   1022 	}
   1023 
   1024 	rfbLog("created 1024 bit temporary RSA key: %.3fs\n", dnow() - ds);
   1025 
   1026 	if (db) fprintf(stderr, "SSL_CTX_set_tmp_rsa()\n");
   1027 
   1028 	if (! SSL_CTX_set_tmp_rsa(ctx, rsa_1024)) {
   1029 		rfbLog("openssl_init: SSL_CTX_set_tmp_rsa(1024) failed.\n");
   1030 		sslerrexit();
   1031 	}
   1032 
   1033 	mode = 0;
   1034 	mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
   1035 	mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
   1036 	SSL_CTX_set_mode(ctx, mode);
   1037 
   1038 #define ssl_cache 0
   1039 #if ssl_cache
   1040 	SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
   1041 	SSL_CTX_set_timeout(ctx, 300);
   1042 #else
   1043 	SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
   1044 	SSL_CTX_set_timeout(ctx, 1);
   1045 #endif
   1046 
   1047 	ds = dnow();
   1048 	if (! openssl_pem) {
   1049 		openssl_pem = create_tmp_pem(NULL, 0);
   1050 		if (! openssl_pem) {
   1051 			rfbLog("openssl_init: could not create temporary,"
   1052 			    " self-signed PEM.\n");
   1053 			clean_up_exit(1);
   1054 		}
   1055 		tmp_pem = 1;
   1056 
   1057 	} else if (!strcmp(openssl_pem, "ANON")) {
   1058 		if (ssl_verify) {
   1059 			rfbLog("openssl_init: Anonymous Diffie-Hellman cannot"
   1060 			    " be used in -sslverify mode.\n");
   1061 			clean_up_exit(1);
   1062 		}
   1063 		if (ssl_crl) {
   1064 			rfbLog("openssl_init: Anonymous Diffie-Hellman cannot"
   1065 			    " be used in -sslCRL mode.\n");
   1066 			clean_up_exit(1);
   1067 		}
   1068 		/* n.b. new ctx */
   1069 		if (!switch_to_anon_dh()) {
   1070 			rfbLog("openssl_init: Anonymous Diffie-Hellman setup"
   1071 			    " failed.\n");
   1072 			clean_up_exit(1);
   1073 		}
   1074 	} else if (strstr(openssl_pem, "SAVE") == openssl_pem) {
   1075 		openssl_pem = get_saved_pem(openssl_pem, 1);
   1076 		if (! openssl_pem) {
   1077 			rfbLog("openssl_init: could not create or open"
   1078 			    " saved PEM: %s\n", openssl_pem);
   1079 			clean_up_exit(1);
   1080 		}
   1081 		tmp_pem = 0;
   1082 	}
   1083 
   1084 	rfbLog("using PEM %s  %.3fs\n", openssl_pem, dnow() - ds);
   1085 
   1086 	SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_callback);
   1087 
   1088 	if (do_dh) {
   1089 		DH *dh;
   1090 		BIO *bio;
   1091 
   1092 		ds = dnow();
   1093 		in = fopen(openssl_pem, "r");
   1094 		if (in == NULL) {
   1095 			rfbLogPerror("fopen");
   1096 			clean_up_exit(1);
   1097 		}
   1098 		bio = BIO_new_fp(in, BIO_CLOSE|BIO_FP_TEXT);
   1099 		if (! bio) {
   1100 			rfbLog("openssl_init: BIO_new_fp() failed.\n");
   1101 			sslerrexit();
   1102 		}
   1103 		dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
   1104 		if (dh == NULL) {
   1105 			rfbLog("openssl_init: PEM_read_bio_DHparams() failed.\n");
   1106 			BIO_free(bio);
   1107 			sslerrexit();
   1108 		}
   1109 		BIO_free(bio);
   1110 		SSL_CTX_set_tmp_dh(ctx, dh);
   1111 		rfbLog("loaded Diffie Hellman %d bits, %.3fs\n",
   1112 		    8*DH_size(dh), dnow()-ds);
   1113 		DH_free(dh);
   1114 	}
   1115 
   1116 	if (strcmp(openssl_pem, "ANON")) {
   1117 		if (! SSL_CTX_use_certificate_chain_file(ctx, openssl_pem)) {
   1118 			rfbLog("openssl_init: SSL_CTX_use_certificate_chain_file() failed.\n");
   1119 			sslerrexit();
   1120 		}
   1121 		if (! SSL_CTX_use_RSAPrivateKey_file(ctx, openssl_pem,
   1122 		    SSL_FILETYPE_PEM)) {
   1123 			rfbLog("openssl_init: SSL_CTX_set_tmp_rsa(1024) failed.\n");
   1124 			sslerrexit();
   1125 		}
   1126 		if (! SSL_CTX_check_private_key(ctx)) {
   1127 			rfbLog("openssl_init: SSL_CTX_set_tmp_rsa(1024) failed.\n");
   1128 			sslerrexit();
   1129 		}
   1130 	}
   1131 
   1132 	if (tmp_pem && ! getenv("X11VNC_KEEP_TMP_PEM")) {
   1133 		if (getenv("X11VNC_SHOW_TMP_PEM")) {
   1134 			FILE *in = fopen(openssl_pem, "r");
   1135 			if (in != NULL) {
   1136 				char line[128];
   1137 				fprintf(stderr, "\n");
   1138 				while (fgets(line, 128, in) != NULL) {
   1139 					fprintf(stderr, "%s", line);
   1140 				}
   1141 				fprintf(stderr, "\n");
   1142 				fclose(in);
   1143 			}
   1144 		}
   1145 		unlink(openssl_pem);
   1146 		free(openssl_pem);
   1147 		openssl_pem = NULL;
   1148 	}
   1149 
   1150 	if (ssl_crl) {
   1151 		struct stat sbuf;
   1152 		X509_LOOKUP *lookup;
   1153 
   1154 		if (stat(ssl_crl, &sbuf) != 0) {
   1155 			rfbLog("openssl_init: -sslCRL does not exist %s.\n",
   1156 			    ssl_crl ? ssl_crl : "null");
   1157 			rfbLogPerror("stat");
   1158 			clean_up_exit(1);
   1159 		}
   1160 
   1161 		revocation_store = X509_STORE_new();
   1162 		if (!revocation_store) {
   1163 			rfbLog("openssl_init: X509_STORE_new failed.\n");
   1164 			sslerrexit();
   1165 		}
   1166 		if (! S_ISDIR(sbuf.st_mode)) {
   1167 			lookup = X509_STORE_add_lookup(revocation_store, X509_LOOKUP_file());
   1168 			if (!lookup) {
   1169 				rfbLog("openssl_init: X509_STORE_add_lookup failed.\n");
   1170 				sslerrexit();
   1171 			}
   1172 			if (!X509_LOOKUP_load_file(lookup, ssl_crl, X509_FILETYPE_PEM))  {
   1173 				rfbLog("openssl_init: X509_LOOKUP_load_file failed.\n");
   1174 				sslerrexit();
   1175 			}
   1176 		} else {
   1177 			lookup = X509_STORE_add_lookup(revocation_store, X509_LOOKUP_hash_dir());
   1178 			if (!lookup) {
   1179 				rfbLog("openssl_init: X509_STORE_add_lookup failed.\n");
   1180 				sslerrexit();
   1181 			}
   1182 			if (!X509_LOOKUP_add_dir(lookup, ssl_crl, X509_FILETYPE_PEM))  {
   1183 				rfbLog("openssl_init: X509_LOOKUP_add_dir failed.\n");
   1184 				sslerrexit();
   1185 			}
   1186 		}
   1187 		rfbLog("loaded CRL file: %s\n", ssl_crl);
   1188 	}
   1189 
   1190 	if (ssl_verify) {
   1191 		struct stat sbuf;
   1192 		char *file;
   1193 		int lvl;
   1194 
   1195 		file = get_ssl_verify_file(ssl_verify);
   1196 
   1197 		if (!file || stat(file, &sbuf) != 0) {
   1198 			rfbLog("openssl_init: -sslverify does not exist %s.\n",
   1199 			    file ? file : "null");
   1200 			rfbLogPerror("stat");
   1201 			clean_up_exit(1);
   1202 		}
   1203 		if (! S_ISDIR(sbuf.st_mode)) {
   1204 			if (! SSL_CTX_load_verify_locations(ctx, file, NULL)) {
   1205 				rfbLog("openssl_init: SSL_CTX_load_verify_"
   1206 				    "locations() failed.\n");
   1207 				sslerrexit();
   1208 			}
   1209 		} else {
   1210 			if (! SSL_CTX_load_verify_locations(ctx, NULL, file)) {
   1211 				rfbLog("openssl_init: SSL_CTX_load_verify_"
   1212 				    "locations() failed.\n");
   1213 				sslerrexit();
   1214 			}
   1215 		}
   1216 
   1217 		lvl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER;
   1218 		if (ssl_crl == NULL) {
   1219 			SSL_CTX_set_verify(ctx, lvl, NULL);
   1220 		} else {
   1221 			SSL_CTX_set_verify(ctx, lvl, verify_callback);
   1222 		}
   1223 		if (strstr(file, "/sslverify-tmp-load-")) {
   1224 			/* temporary file */
   1225 			unlink(file);
   1226 		}
   1227 	} else {
   1228 		SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
   1229 	}
   1230 
   1231 	rfbLog("\n");
   1232 }
   1233 
   1234 static int read_exact(int sock, char *buf, int len) {
   1235 	int n, fail = 0;
   1236 	if (sock < 0) {
   1237 		return 0;
   1238 	}
   1239 	while (len > 0) {
   1240 		n = read(sock, buf, len);
   1241 		if (n > 0) {
   1242 			buf += n;
   1243 			len -= n;
   1244 		} else if (n == 0) {
   1245 			fail = 1;
   1246 			break;
   1247 		} else if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
   1248 			usleep(10*1000);
   1249 		} else if (n < 0 && errno != EINTR) {
   1250 			fail = 1;
   1251 			break;
   1252 		}
   1253 	}
   1254 	if (fail) {
   1255 		return 0;
   1256 	} else {
   1257 		return 1;
   1258 	}
   1259 }
   1260 
   1261 static int write_exact(int sock, char *buf, int len) {
   1262 	int n, fail = 0;
   1263 	if (sock < 0) {
   1264 		return 0;
   1265 	}
   1266 	while (len > 0) {
   1267 		n = write(sock, buf, len);
   1268 		if (n > 0) {
   1269 			buf += n;
   1270 			len -= n;
   1271 		} else if (n == 0) {
   1272 			fail = 1;
   1273 			break;
   1274 		} else if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
   1275 			usleep(10*1000);
   1276 		} else if (n < 0 && errno != EINTR) {
   1277 			fail = 1;
   1278 			break;
   1279 		}
   1280 	}
   1281 	if (fail) {
   1282 		return 0;
   1283 	} else {
   1284 		return 1;
   1285 	}
   1286 }
   1287 
   1288 /* XXX not in rfb.h: */
   1289 void rfbClientSendString(rfbClientPtr cl, char *reason);
   1290 
   1291 static int finish_auth(rfbClientPtr client, char *type) {
   1292 	int security_result, ret;
   1293 
   1294 	ret = 0;
   1295 
   1296 if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "finish_auth type=%s\n", type);
   1297 
   1298 	if (!strcmp(type, "None")) {
   1299 		security_result = 0;	/* success */
   1300 		if (write_exact(client->sock, (char *) &security_result, 4)) {
   1301 			ret = 1;
   1302 		}
   1303 		rfbLog("finish_auth: using auth 'None'\n");
   1304 		client->state = RFB_INITIALISATION;
   1305 
   1306 	} else if (!strcmp(type, "Vnc")) {
   1307 		RAND_bytes(client->authChallenge, CHALLENGESIZE);
   1308 		if (write_exact(client->sock, (char *) &client->authChallenge, CHALLENGESIZE)) {
   1309 			ret = 1;
   1310 		}
   1311 		rfbLog("finish_auth: using auth 'Vnc', sent challenge.\n");
   1312 		client->state = RFB_AUTHENTICATION;
   1313 
   1314 	} else if (!strcmp(type, "Plain")) {
   1315 		if (!unixpw) {
   1316 			rfbLog("finish_auth: *Plain not allowed outside unixpw mode.\n");
   1317 			ret = 0;
   1318 		} else {
   1319 			char *un, *pw;
   1320 			int unlen, pwlen;
   1321 
   1322 if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "*Plain begin: onHold=%d client=%p unixpw_client=%p\n", client->onHold, (void *) client, (void *) unixpw_client);
   1323 
   1324 			if (!read_exact(client->sock, (char *)&unlen, 4)) goto fail;
   1325 			unlen = Swap32IfLE(unlen);
   1326 
   1327 if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "unlen: %d\n", unlen);
   1328 
   1329 			if (!read_exact(client->sock, (char *)&pwlen, 4)) goto fail;
   1330 			pwlen = Swap32IfLE(pwlen);
   1331 
   1332 if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "pwlen: %d\n", pwlen);
   1333 
   1334 			un = (char *) malloc(unlen+1);
   1335 			memset(un, 0, unlen+1);
   1336 
   1337 			pw = (char *) malloc(pwlen+2);
   1338 			memset(pw, 0, pwlen+2);
   1339 
   1340 			if (!read_exact(client->sock, un, unlen)) goto fail;
   1341 			if (!read_exact(client->sock, pw, pwlen)) goto fail;
   1342 
   1343 if (getenv("X11VNC_DEBUG_TLSPLAIN")) fprintf(stderr, "*Plain: %d %d '%s' ... \n", unlen, pwlen, un);
   1344 			strcat(pw, "\n");
   1345 
   1346 			if (unixpw_verify(un, pw)) {
   1347 				security_result = 0;	/* success */
   1348 				if (write_exact(client->sock, (char *) &security_result, 4)) {
   1349 					ret = 1;
   1350 					unixpw_verify_screen(un, pw);
   1351 				}
   1352 				client->onHold = FALSE;
   1353 				client->state = RFB_INITIALISATION;
   1354 			}
   1355 			if (ret == 0) {
   1356 				rfbClientSendString(client, "unixpw failed");
   1357 			}
   1358 
   1359 			memset(un, 0, unlen+1);
   1360 			memset(pw, 0, pwlen+2);
   1361 			free(un);
   1362 			free(pw);
   1363 		}
   1364 	} else {
   1365 		rfbLog("finish_auth: unknown sub-type: %s\n", type);
   1366 		ret = 0;
   1367 	}
   1368 
   1369 	fail:
   1370 	return ret;
   1371 }
   1372 
   1373 static int finish_vencrypt_auth(rfbClientPtr client, int subtype) {
   1374 
   1375 	if (subtype == rfbVencryptTlsNone || subtype == rfbVencryptX509None) {
   1376 		return finish_auth(client, "None");
   1377 	} else if (subtype == rfbVencryptTlsVnc || subtype == rfbVencryptX509Vnc) {
   1378 		return finish_auth(client, "Vnc");
   1379 	} else if (subtype == rfbVencryptTlsPlain || subtype == rfbVencryptX509Plain) {
   1380 		return finish_auth(client, "Plain");
   1381 	} else {
   1382 		rfbLog("finish_vencrypt_auth: unknown sub-type: %d\n", subtype);
   1383 		return 0;
   1384 	}
   1385 }
   1386 
   1387 
   1388 static int add_anon_dh(void) {
   1389 	pid_t pid, pidw;
   1390 	char cnf[] = "/tmp/x11vnc-dh.XXXXXX";
   1391 	char *infile = NULL;
   1392 	int status, cnf_fd;
   1393 	DH *dh;
   1394 	BIO *bio;
   1395 	FILE *in;
   1396 	double ds;
   1397 	/*
   1398 	 * These are dh parameters (prime, generator), not dh keys.
   1399 	 * Evidently it is ok for them to be publicly known.
   1400 	 * openssl dhparam -out dh.out 1024
   1401 	 */
   1402 	char *fixed_dh_params =
   1403 "-----BEGIN DH PARAMETERS-----\n"
   1404 "MIGHAoGBAL28w69ZnLYBvp8R2OeqtAIms+oatY19iBL4WhGI/7H1OMmkJjIe+OHs\n"
   1405 "PXoJfe5ucrnvno7Xm+HJZYa1jnPGQuWoa/VJKXdVjYdJVNzazJKM2daKKcQA4GDc\n"
   1406 "msFS5DxLbzUR5jy1n12K3EcbvpyFqDYVTJJXm7NuNuiWRfz3wTozAgEC\n"
   1407 "-----END DH PARAMETERS-----\n";
   1408 
   1409 	if (dhparams_file != NULL) {
   1410 		infile = dhparams_file;
   1411 		rfbLog("add_anon_dh: using %s\n", dhparams_file);
   1412 		goto readin;
   1413 	}
   1414 
   1415 	cnf_fd = mkstemp(cnf);
   1416 	if (cnf_fd < 0) {
   1417 		return 0;
   1418 	}
   1419 	infile = cnf;
   1420 
   1421 	if (create_fresh_dhparams) {
   1422 
   1423 		if (new_dh_params != NULL) {
   1424 			write(cnf_fd, new_dh_params, strlen(new_dh_params));
   1425 			close(cnf_fd);
   1426 		} else {
   1427 			char *exe = find_openssl_bin();
   1428 			struct stat sbuf;
   1429 
   1430 			if (no_external_cmds || !cmd_ok("ssl")) {
   1431 				rfbLog("add_anon_dh: cannot run external commands.\n");
   1432 				return 0;
   1433 			}
   1434 
   1435 			close(cnf_fd);
   1436 			if (exe == NULL) {
   1437 				return 0;
   1438 			}
   1439 			ds = dnow();
   1440 			pid = fork();
   1441 			if (pid < 0) {
   1442 				return 0;
   1443 			} else if (pid == 0) {
   1444 				int i;
   1445 				for (i=0; i<256; i++) {
   1446 					if (i == 2) continue;
   1447 					close(i);
   1448 				}
   1449 				/* rather slow at 1024 */
   1450 				execlp(exe, exe, "dhparam", "-out", cnf, "1024", (char *)0);
   1451 				exit(1);
   1452 			}
   1453 			pidw = waitpid(pid, &status, 0);
   1454 			if (pidw != pid) {
   1455 				return 0;
   1456 			}
   1457 			if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
   1458 				;
   1459 			} else {
   1460 				return 0;
   1461 			}
   1462 			rfbLog("add_anon_dh: created new DH params in %.3f secs\n", dnow() - ds);
   1463 
   1464 			if (stat(cnf, &sbuf) == 0 && sbuf.st_size > 0) {
   1465 				/* save it to reuse during our process's lifetime: */
   1466 				int d = open(cnf, O_RDONLY);
   1467 				if (d >= 0) {
   1468 					int n, len = sbuf.st_size;
   1469 					new_dh_params = (char *) calloc(len+1, 1);
   1470 					n = read(d, new_dh_params, len);
   1471 					close(d);
   1472 					if (n != len) {
   1473 						free(new_dh_params);
   1474 						new_dh_params = NULL;
   1475 					} else if (dhret != NULL) {
   1476 						d = open(dhret, O_WRONLY);
   1477 						if (d >= 0) {
   1478 							write(d, new_dh_params, strlen(new_dh_params));
   1479 							close(d);
   1480 						}
   1481 					}
   1482 				}
   1483 			}
   1484 		}
   1485 	} else {
   1486 		write(cnf_fd, fixed_dh_params, strlen(fixed_dh_params));
   1487 		close(cnf_fd);
   1488 	}
   1489 
   1490 	readin:
   1491 
   1492 	ds = dnow();
   1493 	in = fopen(infile, "r");
   1494 
   1495 	if (in == NULL) {
   1496 		rfbLogPerror("fopen");
   1497 		unlink(cnf);
   1498 		return 0;
   1499 	}
   1500 	bio = BIO_new_fp(in, BIO_CLOSE|BIO_FP_TEXT);
   1501 	if (! bio) {
   1502 		rfbLog("openssl_init: BIO_new_fp() failed.\n");
   1503 		unlink(cnf);
   1504 		return 0;
   1505 	}
   1506 	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
   1507 	if (dh == NULL) {
   1508 		rfbLog("openssl_init: PEM_read_bio_DHparams() failed.\n");
   1509 		unlink(cnf);
   1510 		BIO_free(bio);
   1511 		return 0;
   1512 	}
   1513 	BIO_free(bio);
   1514 	SSL_CTX_set_tmp_dh(ctx, dh);
   1515 	rfbLog("loaded Diffie Hellman %d bits, %.3fs\n", 8*DH_size(dh), dnow()-ds);
   1516 	DH_free(dh);
   1517 
   1518 	unlink(cnf);
   1519 	return 1;
   1520 }
   1521 
   1522 static int switch_to_anon_dh(void) {
   1523 	long mode;
   1524 
   1525 	rfbLog("Using Anonymous Diffie-Hellman mode.\n");
   1526 	rfbLog("WARNING: Anonymous Diffie-Hellman uses encryption but is\n");
   1527 	rfbLog("WARNING: susceptible to a Man-In-The-Middle attack.\n");
   1528 	if (ssl_client_mode) {
   1529 		ctx = SSL_CTX_new( SSLv23_client_method() );
   1530 	} else {
   1531 		ctx = SSL_CTX_new( SSLv23_server_method() );
   1532 	}
   1533 	if (ctx == NULL) {
   1534 		return 0;
   1535 	}
   1536 	if (ssl_client_mode) {
   1537 		return 1;
   1538 	}
   1539 	if (!SSL_CTX_set_cipher_list(ctx, "ADH:@STRENGTH")) {
   1540 		return 0;
   1541 	}
   1542 	if (!add_anon_dh()) {
   1543 		return 0;
   1544 	}
   1545 
   1546 	mode = 0;
   1547 	mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
   1548 	mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
   1549 	SSL_CTX_set_mode(ctx, mode);
   1550 
   1551 	SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
   1552 	SSL_CTX_set_timeout(ctx, 300);
   1553 	SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_callback);
   1554 	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
   1555 
   1556 	return 1;
   1557 }
   1558 
   1559 static int anontls_dialog(int s_in, int s_out) {
   1560 
   1561 	if (s_in || s_out) {}
   1562 	anontls_selected = 1;
   1563 
   1564 	if (!switch_to_anon_dh()) {
   1565 		rfbLog("anontls: Anonymous Diffie-Hellman failed.\n");
   1566 		return 0;
   1567 	}
   1568 
   1569 	/* continue with SSL/TLS */
   1570 	return 1;
   1571 }
   1572 
   1573 /*
   1574  * Using spec:
   1575  * http://www.mail-archive.com/qemu-devel@nongnu.org/msg08681.html
   1576  */
   1577 static int vencrypt_dialog(int s_in, int s_out) {
   1578 	char buf[256], buf2[256];
   1579 	int subtypes[16];
   1580 	int n, i, ival, ok, nsubtypes = 0;
   1581 
   1582 	vencrypt_selected = 0;
   1583 
   1584 	/* send version 0.2 */
   1585 	buf[0] = 0;
   1586 	buf[1] = 2;
   1587 
   1588 	if (!write_exact(s_out, buf, 2)) {
   1589 		close(s_in); close(s_out);
   1590 		return 0;
   1591 	}
   1592 
   1593 	/* read client version 0.2 */
   1594 	memset(buf, 0, sizeof(buf));
   1595 	if (!read_exact(s_in, buf, 2)) {
   1596 		close(s_in); close(s_out);
   1597 		return 0;
   1598 	}
   1599 	rfbLog("vencrypt: received %d.%d client version.\n", (int) buf[0], (int) buf[1]);
   1600 
   1601 	/* close 0.0 */
   1602 	if (buf[0] == 0 && buf[1] == 0) {
   1603 		rfbLog("vencrypt: received 0.0 version, closing connection.\n");
   1604 		close(s_in); close(s_out);
   1605 		return 0;
   1606 	}
   1607 
   1608 	/* accept only 0.2 */
   1609 	if (buf[0] != 0 || buf[1] != 2) {
   1610 		rfbLog("vencrypt: unsupported VeNCrypt version, closing connection.\n");
   1611 		buf[0] = (char) 255;
   1612 		write_exact(s_out, buf, 1);
   1613 		close(s_in); close(s_out);
   1614 		return 0;
   1615 	}
   1616 
   1617 	/* tell them OK */
   1618 	buf[0] = 0;
   1619 	if (!write_exact(s_out, buf, 1)) {
   1620 		close(s_in); close(s_out);
   1621 		return 0;
   1622 	}
   1623 
   1624 	if (getenv("X11VNC_ENABLE_VENCRYPT_PLAIN_LOGIN")) {
   1625 		vencrypt_enable_plain_login = atoi(getenv("X11VNC_ENABLE_VENCRYPT_PLAIN_LOGIN"));
   1626 	}
   1627 
   1628 	/* load our list of sub-types: */
   1629 	n = 0;
   1630 	if (!ssl_verify && vencrypt_kx != VENCRYPT_NODH) {
   1631 		if (screen->authPasswdData != NULL) {
   1632 			subtypes[n++] = rfbVencryptTlsVnc;
   1633 		} else {
   1634 			if (vencrypt_enable_plain_login && unixpw) {
   1635 				subtypes[n++] = rfbVencryptTlsPlain;
   1636 			} else {
   1637 				subtypes[n++] = rfbVencryptTlsNone;
   1638 			}
   1639 		}
   1640 	}
   1641 	if (vencrypt_kx != VENCRYPT_NOX509) {
   1642 		if (screen->authPasswdData != NULL) {
   1643 			subtypes[n++] = rfbVencryptX509Vnc;
   1644 		} else {
   1645 			if (vencrypt_enable_plain_login && unixpw) {
   1646 				subtypes[n++] = rfbVencryptX509Plain;
   1647 			} else {
   1648 				subtypes[n++] = rfbVencryptX509None;
   1649 			}
   1650 		}
   1651 	}
   1652 
   1653 	nsubtypes = n;
   1654 	for (i = 0; i < nsubtypes; i++) {
   1655 		((uint32_t *)buf)[i] = Swap32IfLE(subtypes[i]);
   1656 	}
   1657 
   1658 	/* send number first: */
   1659 	buf2[0] = (char) nsubtypes;
   1660 	if (!write_exact(s_out, buf2, 1)) {
   1661 		close(s_in); close(s_out);
   1662 		return 0;
   1663 	}
   1664 	/* and now the list: */
   1665 	if (!write_exact(s_out, buf, 4*n)) {
   1666 		close(s_in); close(s_out);
   1667 		return 0;
   1668 	}
   1669 
   1670 	/* read client's selection: */
   1671 	if (!read_exact(s_in, (char *)&ival, 4)) {
   1672 		close(s_in); close(s_out);
   1673 		return 0;
   1674 	}
   1675 	ival = Swap32IfLE(ival);
   1676 
   1677 	/* zero means no dice: */
   1678 	if (ival == 0) {
   1679 		rfbLog("vencrypt: client selected no sub-type, closing connection.\n");
   1680 		close(s_in); close(s_out);
   1681 		return 0;
   1682 	}
   1683 
   1684 	/* check if he selected a valid one: */
   1685 	ok = 0;
   1686 	for (i = 0; i < nsubtypes; i++) {
   1687 		if (ival == subtypes[i]) {
   1688 			ok = 1;
   1689 		}
   1690 	}
   1691 
   1692 	if (!ok) {
   1693 		rfbLog("vencrypt: client selected invalid sub-type: %d\n", ival);
   1694 		close(s_in); close(s_out);
   1695 		return 0;
   1696 	} else {
   1697 		char *st = "unknown!!";
   1698 		if (ival == rfbVencryptTlsNone)	  st = "rfbVencryptTlsNone";
   1699 		if (ival == rfbVencryptTlsVnc)    st = "rfbVencryptTlsVnc";
   1700 		if (ival == rfbVencryptTlsPlain)  st = "rfbVencryptTlsPlain";
   1701 		if (ival == rfbVencryptX509None)  st = "rfbVencryptX509None";
   1702 		if (ival == rfbVencryptX509Vnc)   st = "rfbVencryptX509Vnc";
   1703 		if (ival == rfbVencryptX509Plain) st = "rfbVencryptX509Plain";
   1704 		rfbLog("vencrypt: client selected sub-type: %d (%s)\n", ival, st);
   1705 	}
   1706 
   1707 	vencrypt_selected = ival;
   1708 
   1709 	/* not documented in spec, send OK: */
   1710 	buf[0] = 1;
   1711 	if (!write_exact(s_out, buf, 1)) {
   1712 		close(s_in); close(s_out);
   1713 		return 0;
   1714 	}
   1715 
   1716 	if (vencrypt_selected == rfbVencryptTlsNone ||
   1717 	    vencrypt_selected == rfbVencryptTlsVnc  ||
   1718 	    vencrypt_selected == rfbVencryptTlsPlain) {
   1719 		/* these modes are Anonymous Diffie-Hellman */
   1720 		if (!switch_to_anon_dh()) {
   1721 			rfbLog("vencrypt: Anonymous Diffie-Hellman failed.\n");
   1722 			return 0;
   1723 		}
   1724 	}
   1725 
   1726 	/* continue with SSL/TLS */
   1727 	return 1;
   1728 }
   1729 
   1730 static int check_vnc_tls_mode(int s_in, int s_out, double last_https) {
   1731 	double waited = 0.0, waitmax = 1.4, dt = 0.01, start = dnow();
   1732 	struct timeval tv;
   1733 	int input = 0, i, n, ok;
   1734 	int major, minor, sectype = -1;
   1735 	char *proto = "RFB 003.008\n";
   1736 	char *stype = "unknown";
   1737 	char buf[256];
   1738 
   1739 	vencrypt_selected = 0;
   1740 	anontls_selected = 0;
   1741 
   1742 	if (vencrypt_mode == VENCRYPT_NONE && anontls_mode == ANONTLS_NONE) {
   1743 		/* only normal SSL */
   1744 		return 1;
   1745 	}
   1746 	if (ssl_client_mode) {
   1747 		if (vencrypt_mode == VENCRYPT_FORCE || anontls_mode == ANONTLS_FORCE) {
   1748 			rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/ANONTLS_FORCE in client\n");
   1749 			rfbLog("check_vnc_tls_mode: connect mode.\n");
   1750 			/* this is OK, continue on below for dialog. */
   1751 		} else {
   1752 			/* otherwise we must assume normal SSL (we send client hello) */
   1753 			return 1;
   1754 		}
   1755 	}
   1756 	if (ssl_verify && vencrypt_mode != VENCRYPT_FORCE && anontls_mode == ANONTLS_FORCE) {
   1757 		rfbLog("check_vnc_tls_mode: Cannot use ANONTLS_FORCE with -sslverify (Anon DH only)\n");
   1758 		/* fallback to normal SSL */
   1759 		return 1;
   1760 	}
   1761 
   1762 	if (last_https > 0.0) {
   1763 		double now = dnow();
   1764 		if (now < last_https + 5.0) {
   1765 			waitmax = 20.0;
   1766 		} else if (now < last_https + 15.0) {
   1767 			waitmax = 10.0;
   1768 		} else if (now < last_https + 30.0) {
   1769 			waitmax = 5.0;
   1770 		} else if (now < last_https + 60.0) {
   1771 			waitmax = 2.5;
   1772 		}
   1773 	}
   1774 
   1775 	while (waited < waitmax) {
   1776 		fd_set rfds;
   1777 		FD_ZERO(&rfds);
   1778 		FD_SET(s_in, &rfds);
   1779 		tv.tv_sec = 0;
   1780 		tv.tv_usec = 0;
   1781 		select(s_in+1, &rfds, NULL, NULL, &tv);
   1782 		if (FD_ISSET(s_in, &rfds)) {
   1783 			input = 1;
   1784 			break;
   1785 		}
   1786 		usleep((int) (1000 * 1000 * dt));
   1787 		waited += dt;
   1788 	}
   1789 	rfbLog("check_vnc_tls_mode: waited: %f / %.2f input: %s\n",
   1790 	    dnow() - start, waitmax, input ? "SSL Handshake" : "(future) RFB Handshake");
   1791 
   1792 	if (input) {
   1793 		/* got SSL client hello, can only assume normal SSL */
   1794 		if (vencrypt_mode == VENCRYPT_FORCE || anontls_mode == ANONTLS_FORCE) {
   1795 			rfbLog("check_vnc_tls_mode: VENCRYPT_FORCE/ANONTLS_FORCE prevents normal SSL\n");
   1796 			return 0;
   1797 		}
   1798 		return 1;
   1799 	}
   1800 
   1801 	/* send RFB 003.008 -- there is no turning back from this point... */
   1802 	if (!write_exact(s_out, proto, strlen(proto))) {
   1803 		close(s_in); close(s_out);
   1804 		return 0;
   1805 	}
   1806 
   1807 	memset(buf, 0, sizeof(buf));
   1808 	if (!read_exact(s_in, buf, 12)) {
   1809 		close(s_in); close(s_out);
   1810 		return 0;
   1811 	}
   1812 
   1813 	if (sscanf(buf, "RFB %03d.%03d\n", &major, &minor) != 2) {
   1814 		int i;
   1815 		rfbLog("check_vnc_tls_mode: abnormal handshake: '%s'\nbytes: ", buf);
   1816 		for (i=0; i < 12; i++) {
   1817 			fprintf(stderr, "%d.", (unsigned char) buf[i]);
   1818 		}
   1819 		fprintf(stderr, "\n");
   1820 		close(s_in); close(s_out);
   1821 		return 0;
   1822 	}
   1823 	rfbLog("check_vnc_tls_mode: version: %d.%d\n", major, minor);
   1824 	if (major != 3 || minor < 8) {
   1825 		rfbLog("check_vnc_tls_mode: invalid version: '%s'\n", buf);
   1826 		close(s_in); close(s_out);
   1827 		return 0;
   1828 	}
   1829 
   1830 	n = 1;
   1831 	if (vencrypt_mode == VENCRYPT_FORCE) {
   1832 		buf[n++] = rfbSecTypeVencrypt;
   1833 	} else if (anontls_mode == ANONTLS_FORCE && !ssl_verify) {
   1834 		buf[n++] = rfbSecTypeAnonTls;
   1835 	} else if (vencrypt_mode == VENCRYPT_SOLE) {
   1836 		buf[n++] = rfbSecTypeVencrypt;
   1837 	} else if (anontls_mode == ANONTLS_SOLE && !ssl_verify) {
   1838 		buf[n++] = rfbSecTypeAnonTls;
   1839 	} else {
   1840 		if (vencrypt_mode == VENCRYPT_SUPPORT) {
   1841 			buf[n++] = rfbSecTypeVencrypt;
   1842 		}
   1843 		if (anontls_mode == ANONTLS_SUPPORT && !ssl_verify) {
   1844 			buf[n++] = rfbSecTypeAnonTls;
   1845 		}
   1846 	}
   1847 
   1848 	n--;
   1849 	buf[0] = (char) n;
   1850 	if (!write_exact(s_out, buf, n+1)) {
   1851 		close(s_in); close(s_out);
   1852 		return 0;
   1853 	}
   1854 	if (0) fprintf(stderr, "wrote[%d] %d %d %d\n", n, buf[0], buf[1], buf[2]);
   1855 
   1856 	buf[0] = 0;
   1857 	if (!read_exact(s_in, buf, 1)) {
   1858 		close(s_in); close(s_out);
   1859 		return 0;
   1860 	}
   1861 
   1862 	if (buf[0] == rfbSecTypeVencrypt) stype = "VeNCrypt";
   1863 	if (buf[0] == rfbSecTypeAnonTls)  stype = "ANONTLS";
   1864 
   1865 	rfbLog("check_vnc_tls_mode: reply: %d (%s)\n", (int) buf[0], stype);
   1866 
   1867 	ok = 0;
   1868 	for (i=1; i < n+1; i++) {
   1869 		if (buf[0] == buf[i]) {
   1870 			ok = 1;
   1871 		}
   1872 	}
   1873 	if (!ok) {
   1874 		char *msg = "check_vnc_tls_mode: invalid security-type";
   1875 		int len = strlen(msg);
   1876 		rfbLog("%s: %d\n", msg, (int) buf[0]);
   1877 		((uint32_t *)buf)[0] = Swap32IfLE(len);
   1878 		write_exact(s_out, buf, 4);
   1879 		write_exact(s_out, msg, strlen(msg));
   1880 		close(s_in); close(s_out);
   1881 		return 0;
   1882 	}
   1883 
   1884 	sectype = (int) buf[0];
   1885 
   1886 	if (sectype == rfbSecTypeVencrypt) {
   1887 		return vencrypt_dialog(s_in, s_out);
   1888 	} else if (sectype == rfbSecTypeAnonTls) {
   1889 		return anontls_dialog(s_in, s_out);
   1890 	} else {
   1891 		return 0;
   1892 	}
   1893 }
   1894 
   1895 static void pr_ssl_info(int verb) {
   1896 	SSL_CIPHER *c;
   1897 	SSL_SESSION *s;
   1898 	char *proto = "unknown";
   1899 
   1900 	if (verb) {}
   1901 
   1902 	if (ssl == NULL) {
   1903 		return;
   1904 	}
   1905 	c = SSL_get_current_cipher(ssl);
   1906 	s = SSL_get_session(ssl);
   1907 
   1908 	if (s == NULL) {
   1909 		proto = "nosession";
   1910 	} else if (s->ssl_version == SSL2_VERSION) {
   1911 		proto = "SSLv2";
   1912 	} else if (s->ssl_version == SSL3_VERSION) {
   1913 		proto = "SSLv3";
   1914 	} else if (s->ssl_version == TLS1_VERSION) {
   1915 		proto = "TLSv1";
   1916 	}
   1917 	if (c != NULL) {
   1918 		rfbLog("SSL: ssl_helper[%d]: Cipher: %s %s Proto: %s\n", getpid(),
   1919 		    SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c), proto);
   1920 	} else {
   1921 		rfbLog("SSL: ssl_helper[%d]: Proto: %s\n", getpid(),
   1922 		    proto);
   1923 	}
   1924 }
   1925 
   1926 static void ssl_timeout (int sig) {
   1927 	int i;
   1928 	rfbLog("sig: %d, ssl_init[%d] timed out.\n", sig, getpid());
   1929 	rfbLog("To increase the SSL initialization timeout use, e.g.:\n");
   1930 	rfbLog("   -env SSL_INIT_TIMEOUT=120        (for 120 seconds)\n");
   1931 	for (i=0; i < 256; i++) {
   1932 		close(i);
   1933 	}
   1934 	exit(1);
   1935 }
   1936 
   1937 static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
   1938 	unsigned char *sid = (unsigned char *) "x11vnc SID";
   1939 	char *name = NULL;
   1940 	int peerport = 0;
   1941 	int db = 0, rc, err;
   1942 	int ssock = s_in;
   1943 	double start = dnow();
   1944 	int timeout = 20;
   1945 
   1946 	if (enc_str != NULL) {
   1947 		return 1;
   1948 	}
   1949 	if (getenv("SSL_DEBUG")) {
   1950 		db = atoi(getenv("SSL_DEBUG"));
   1951 	}
   1952 	usleep(100 * 1000);
   1953 	if (getenv("SSL_INIT_TIMEOUT")) {
   1954 		timeout = atoi(getenv("SSL_INIT_TIMEOUT"));
   1955 	} else if (client_connect != NULL && strstr(client_connect, "repeater")) {
   1956 		rfbLog("SSL: ssl_init[%d]: detected 'repeater' in connect string.\n", getpid());
   1957 		rfbLog("SSL: setting timeout to 1 hour: -env SSL_INIT_TIMEOUT=3600\n");
   1958 		rfbLog("SSL: use that option to set a different timeout value,\n");
   1959 		rfbLog("SSL: however note that with Windows UltraVNC repeater it\n");
   1960 		rfbLog("SSL: may timeout before your setting due to other reasons.\n");
   1961 		timeout = 3600;
   1962 	}
   1963 
   1964 	if (skip_vnc_tls) {
   1965 		rfbLog("SSL: ssl_helper[%d]: HTTPS mode, skipping check_vnc_tls_mode()\n",
   1966 		    getpid());
   1967 	} else if (!check_vnc_tls_mode(s_in, s_out, last_https)) {
   1968 		return 0;
   1969 	}
   1970 	rfbLog("SSL: ssl_init[%d]: %d/%d initialization timeout: %d secs.\n",
   1971 	    getpid(), s_in, s_out, timeout);
   1972 
   1973 	ssl = SSL_new(ctx);
   1974 	if (ssl == NULL) {
   1975 		fprintf(stderr, "SSL_new failed\n");
   1976 		return 0;
   1977 	}
   1978 	if (db > 1) fprintf(stderr, "ssl_init: 1\n");
   1979 
   1980 	SSL_set_session_id_context(ssl, sid, strlen((char *)sid));
   1981 
   1982 	if (s_in == s_out) {
   1983 		if (! SSL_set_fd(ssl, ssock)) {
   1984 			fprintf(stderr, "SSL_set_fd failed\n");
   1985 			return 0;
   1986 		}
   1987 	} else {
   1988 		if (! SSL_set_rfd(ssl, s_in)) {
   1989 			fprintf(stderr, "SSL_set_rfd failed\n");
   1990 			return 0;
   1991 		}
   1992 		if (! SSL_set_wfd(ssl, s_out)) {
   1993 			fprintf(stderr, "SSL_set_wfd failed\n");
   1994 			return 0;
   1995 		}
   1996 	}
   1997 	if (db > 1) fprintf(stderr, "ssl_init: 2\n");
   1998 
   1999 	if (ssl_client_mode) {
   2000 		SSL_set_connect_state(ssl);
   2001 	} else {
   2002 		SSL_set_accept_state(ssl);
   2003 	}
   2004 
   2005 	if (db > 1) fprintf(stderr, "ssl_init: 3\n");
   2006 
   2007 	name = get_remote_host(ssock);
   2008 	peerport = get_remote_port(ssock);
   2009 
   2010 	if (!strcmp(name, "0.0.0.0") && openssl_last_ip != NULL) {
   2011 		name = strdup(openssl_last_ip);
   2012 	}
   2013 
   2014 	if (db > 1) fprintf(stderr, "ssl_init: 4\n");
   2015 
   2016 	while (1) {
   2017 
   2018 		signal(SIGALRM, ssl_timeout);
   2019 		alarm(timeout);
   2020 
   2021 		if (ssl_client_mode) {
   2022 			if (db) fprintf(stderr, "calling SSL_connect...\n");
   2023 			rc = SSL_connect(ssl);
   2024 		} else {
   2025 			if (db) fprintf(stderr, "calling SSL_accept...\n");
   2026 			rc = SSL_accept(ssl);
   2027 		}
   2028 		err = SSL_get_error(ssl, rc);
   2029 
   2030 		alarm(0);
   2031 		signal(SIGALRM, SIG_DFL);
   2032 
   2033 		if (ssl_client_mode) {
   2034 			if (db) fprintf(stderr, "SSL_connect %d/%d\n", rc, err);
   2035 		} else {
   2036 			if (db) fprintf(stderr, "SSL_accept %d/%d\n", rc, err);
   2037 		}
   2038 		if (err == SSL_ERROR_NONE) {
   2039 			break;
   2040 		} else if (err == SSL_ERROR_WANT_READ) {
   2041 
   2042 			if (db) fprintf(stderr, "got SSL_ERROR_WANT_READ\n");
   2043 			rfbLog("SSL: ssl_helper[%d]: %s() failed for: %s:%d 1\n",
   2044 			    getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", name, peerport);
   2045 			pr_ssl_info(1);
   2046 			return 0;
   2047 
   2048 		} else if (err == SSL_ERROR_WANT_WRITE) {
   2049 
   2050 			if (db) fprintf(stderr, "got SSL_ERROR_WANT_WRITE\n");
   2051 			rfbLog("SSL: ssl_helper[%d]: %s() failed for: %s:%d 2\n",
   2052 			    getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", name, peerport);
   2053 			pr_ssl_info(1);
   2054 			return 0;
   2055 
   2056 		} else if (err == SSL_ERROR_SYSCALL) {
   2057 
   2058 			if (db) fprintf(stderr, "got SSL_ERROR_SYSCALL\n");
   2059 			rfbLog("SSL: ssl_helper[%d]: %s() failed for: %s:%d 3\n",
   2060 			    getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", name, peerport);
   2061 			pr_ssl_info(1);
   2062 			return 0;
   2063 
   2064 		} else if (err == SSL_ERROR_ZERO_RETURN) {
   2065 
   2066 			if (db) fprintf(stderr, "got SSL_ERROR_ZERO_RETURN\n");
   2067 			rfbLog("SSL: ssl_helper[%d]: %s() failed for: %s:%d 4\n",
   2068 			    getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", name, peerport);
   2069 			pr_ssl_info(1);
   2070 			return 0;
   2071 
   2072 		} else if (rc < 0) {
   2073 			unsigned long err;
   2074 			int cnt = 0;
   2075 
   2076 			rfbLog("SSL: ssl_helper[%d]: %s() *FATAL: %d SSL FAILED\n",
   2077 			    getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept", rc);
   2078 			while ((err = ERR_get_error()) != 0) {
   2079 				rfbLog("SSL: %s\n", ERR_error_string(err, NULL));
   2080 				if (cnt++ > 100) {
   2081 					break;
   2082 				}
   2083 			}
   2084 			pr_ssl_info(1);
   2085 			return 0;
   2086 
   2087 		} else if (dnow() > start + 3.0) {
   2088 
   2089 			rfbLog("SSL: ssl_helper[%d]: timeout looping %s() "
   2090 			    "fatal.\n", getpid(), ssl_client_mode ? "SSL_connect" : "SSL_accept");
   2091 			pr_ssl_info(1);
   2092 			return 0;
   2093 
   2094 		} else {
   2095 			BIO *bio = SSL_get_rbio(ssl);
   2096 			if (bio == NULL) {
   2097 				rfbLog("SSL: ssl_helper[%d]: ssl BIO is null. "
   2098 				    "fatal.\n", getpid());
   2099 				pr_ssl_info(1);
   2100 				return 0;
   2101 			}
   2102 			if (BIO_eof(bio)) {
   2103 				rfbLog("SSL: ssl_helper[%d]: ssl BIO is EOF. "
   2104 				    "fatal.\n", getpid());
   2105 				pr_ssl_info(1);
   2106 				return 0;
   2107 			}
   2108 		}
   2109 		usleep(10 * 1000);
   2110 	}
   2111 
   2112 	if (ssl_client_mode) {
   2113 		rfbLog("SSL: ssl_helper[%d]: SSL_connect() succeeded for: %s:%d\n", getpid(), name, peerport);
   2114 	} else {
   2115 		rfbLog("SSL: ssl_helper[%d]: SSL_accept() succeeded for: %s:%d\n", getpid(), name, peerport);
   2116 	}
   2117 
   2118 	pr_ssl_info(0);
   2119 
   2120 	if (SSL_get_verify_result(ssl) == X509_V_OK) {
   2121 		X509 *x;
   2122 		FILE *cr = NULL;
   2123 		if (certret != NULL) {
   2124 			cr = fopen(certret, "w");
   2125 		}
   2126 
   2127 		x = SSL_get_peer_certificate(ssl);
   2128 		if (x == NULL) {
   2129 			rfbLog("SSL: ssl_helper[%d]: accepted client %s x509 peer cert is null\n", getpid(), name);
   2130 			if (cr != NULL) {
   2131 				fprintf(cr, "NOCERT\n");
   2132 				fclose(cr);
   2133 			}
   2134 		} else {
   2135 			rfbLog("SSL: ssl_helper[%d]: accepted client %s x509 cert is:\n", getpid(), name);
   2136 #if LIBVNCSERVER_HAVE_X509_PRINT_EX_FP
   2137 			X509_print_ex_fp(stderr, x, 0, XN_FLAG_MULTILINE);
   2138 #endif
   2139 			if (cr != NULL) {
   2140 #if LIBVNCSERVER_HAVE_X509_PRINT_EX_FP
   2141 				X509_print_ex_fp(cr, x, 0, XN_FLAG_MULTILINE);
   2142 #else
   2143 				rfbLog("** not compiled with libssl X509_print_ex_fp() function **\n");
   2144 				if (users_list && strstr(users_list, "sslpeer=")) {
   2145 					rfbLog("** -users sslpeer= will not work! **\n");
   2146 				}
   2147 #endif
   2148 				fclose(cr);
   2149 			}
   2150 		}
   2151 	}
   2152 	free(name);
   2153 
   2154 	return 1;
   2155 }
   2156 
   2157 static void symmetric_encryption_xfer(int csock, int s_in, int s_out);
   2158 
   2159 static void ssl_xfer(int csock, int s_in, int s_out, int is_https) {
   2160 	int dbxfer = 0, db = 0, check_pending, fdmax, nfd, n, i, err;
   2161 	char cbuf[ABSIZE], sbuf[ABSIZE];
   2162 	int  cptr, sptr, c_rd, c_wr, s_rd, s_wr;
   2163 	fd_set rd, wr;
   2164 	struct timeval tv;
   2165 	int ssock, cnt = 0, ndata = 0;
   2166 
   2167 	/*
   2168 	 * we want to switch to a longer timeout for long term VNC
   2169 	 * connections (in case the network is not working for periods of
   2170 	 * time), but we also want the timeout shorter at the beginning
   2171 	 * in case the client went away.
   2172 	 */
   2173 	double start, now;
   2174 	int tv_https_early = 60;
   2175 	int tv_https_later = 20;
   2176 	int tv_vnc_early = 40;
   2177 	int tv_vnc_later = 43200;	/* was 300, stunnel: 43200 */
   2178 	int tv_cutover = 70;
   2179 	int tv_closing = 60;
   2180 	int tv_use;
   2181 
   2182 	if (dbxfer) {
   2183 		raw_xfer(csock, s_in, s_out);
   2184 		return;
   2185 	}
   2186 	if (enc_str != NULL) {
   2187 		if (!strcmp(enc_str, "none")) {
   2188 			usleep(250*1000);
   2189 			rfbLog("doing '-enc none' raw transfer (no encryption)\n");
   2190 			raw_xfer(csock, s_in, s_out);
   2191 		} else {
   2192 			symmetric_encryption_xfer(csock, s_in, s_out);
   2193 		}
   2194 		return;
   2195 	}
   2196 
   2197 	if (getenv("SSL_DEBUG")) {
   2198 		db = atoi(getenv("SSL_DEBUG"));
   2199 	}
   2200 
   2201 	if (db) fprintf(stderr, "ssl_xfer begin\n");
   2202 
   2203 	start = dnow();
   2204 	if (is_https) {
   2205 		tv_use = tv_https_early;
   2206 	} else {
   2207 		tv_use = tv_vnc_early;
   2208 	}
   2209 
   2210 
   2211 	/*
   2212 	 * csock: clear text socket with libvncserver.    "C"
   2213 	 * ssock: ssl data socket with remote vnc viewer. "S"
   2214 	 *
   2215 	 * to cover inetd mode, we have s_in and s_out, but in non-inetd
   2216 	 * mode they both ssock.
   2217 	 *
   2218 	 * cbuf[] is data from csock that we have read but not passed on to ssl
   2219 	 * sbuf[] is data from ssl that we have read but not passed on to csock
   2220 	 */
   2221 	for (i=0; i<ABSIZE; i++) {
   2222 		cbuf[i] = '\0';
   2223 		sbuf[i] = '\0';
   2224 	}
   2225 
   2226 	if (s_out > s_in) {
   2227 		ssock = s_out;
   2228 	} else {
   2229 		ssock = s_in;
   2230 	}
   2231 
   2232 	if (csock > ssock) {
   2233 		fdmax = csock;
   2234 	} else {
   2235 		fdmax = ssock;
   2236 	}
   2237 
   2238 	c_rd = 1;	/* clear text (libvncserver) socket open for reading */
   2239 	c_wr = 1;	/* clear text (libvncserver) socket open for writing */
   2240 	s_rd = 1;	/* ssl data (remote client)  socket open for reading */
   2241 	s_wr = 1;	/* ssl data (remote client)  socket open for writing */
   2242 
   2243 	cptr = 0;	/* offsets into ABSIZE buffers */
   2244 	sptr = 0;
   2245 
   2246 	if (vencrypt_selected > 0 || anontls_selected > 0) {
   2247 		char tmp[16];
   2248 		/* read and discard the extra RFB version */
   2249 		memset(tmp, 0, sizeof(tmp));
   2250 		read(csock, tmp, 12);
   2251 		if (0) fprintf(stderr, "extra: %s\n", tmp);
   2252 	}
   2253 
   2254 	while (1) {
   2255 		int c_to_s, s_to_c, closing;
   2256 
   2257 		if ( s_wr && (c_rd || cptr > 0) ) {
   2258 			/*
   2259 			 * S is writable and
   2260 			 * C is readable or some cbuf data remaining
   2261 			 */
   2262 			c_to_s = 1;
   2263 		} else {
   2264 			c_to_s = 0;
   2265 		}
   2266 
   2267 		if ( c_wr && (s_rd || sptr > 0) ) {
   2268 			/*
   2269 			 * C is writable and
   2270 			 * S is readable or some sbuf data remaining
   2271 			 */
   2272 			s_to_c = 1;
   2273 		} else {
   2274 			s_to_c = 0;
   2275 		}
   2276 
   2277 		if (! c_to_s && ! s_to_c) {
   2278 			/*
   2279 			 * nothing can be sent either direction.
   2280 			 * break out of the loop to finish all work.
   2281 			 */
   2282 			break;
   2283 		}
   2284 		cnt++;
   2285 
   2286 		/* set up the fd sets for the two sockets for read & write: */
   2287 
   2288 		FD_ZERO(&rd);
   2289 
   2290 		if (c_rd && cptr < ABSIZE) {
   2291 			/* we could read more from C since cbuf is not full */
   2292 			FD_SET(csock, &rd);
   2293 		}
   2294 		if (s_rd) {
   2295 			/*
   2296 			 * we could read more from S since sbuf not full,
   2297 			 * OR ssl is waiting for more BIO to be able to
   2298 			 * read and we have some C data still buffered.
   2299 			 */
   2300 			if (sptr < ABSIZE || (cptr > 0 && SSL_want_read(ssl))) {
   2301 				FD_SET(s_in, &rd);
   2302 			}
   2303 		}
   2304 
   2305 		FD_ZERO(&wr);
   2306 
   2307 		if (c_wr && sptr > 0) {
   2308 			/* we could write more to C since sbuf is not empty */
   2309 			FD_SET(csock, &wr);
   2310 		}
   2311 		if (s_wr) {
   2312 			/*
   2313 			 * we could write more to S since cbuf not empty,
   2314 			 * OR ssl is waiting for more BIO to be able
   2315 			 * write and we haven't filled up sbuf yet.
   2316 			 */
   2317 			if (cptr > 0 || (sptr < ABSIZE && SSL_want_write(ssl))) {
   2318 				FD_SET(s_out, &wr);
   2319 			}
   2320 		}
   2321 
   2322 		now = dnow();
   2323 		if (tv_cutover && now > start + tv_cutover) {
   2324 			rfbLog("SSL: ssl_xfer[%d]: tv_cutover: %d\n", getpid(),
   2325 			    tv_cutover);
   2326 			tv_cutover = 0;
   2327 			if (is_https) {
   2328 				tv_use = tv_https_later;
   2329 			} else {
   2330 				tv_use = tv_vnc_later;
   2331 			}
   2332 			/* try to clean out some zombies if we can. */
   2333 			ssl_helper_pid(0, -2);
   2334 		}
   2335 		if (ssl_timeout_secs > 0) {
   2336 			tv_use = ssl_timeout_secs;
   2337 		}
   2338 
   2339 		if ( (s_rd && c_rd) || cptr || sptr) {
   2340 			closing = 0;
   2341 		} else {
   2342 			closing = 1;
   2343 			tv_use = tv_closing;
   2344 		}
   2345 
   2346 		tv.tv_sec  = tv_use;
   2347 		tv.tv_usec = 0;
   2348 
   2349 		/*  do the select, repeat if interrupted */
   2350 		do {
   2351 			if (ssl_timeout_secs == 0) {
   2352 				nfd = select(fdmax+1, &rd, &wr, NULL, NULL);
   2353 			} else {
   2354 				nfd = select(fdmax+1, &rd, &wr, NULL, &tv);
   2355 			}
   2356 		} while (nfd < 0 && errno == EINTR);
   2357 
   2358 		if (db > 1) fprintf(stderr, "nfd: %d\n", nfd);
   2359 
   2360 if (0) fprintf(stderr, "nfd[%d]: %d  w/r csock: %d %d s_in: %d %d\n", getpid(), nfd, FD_ISSET(csock, &wr), FD_ISSET(csock, &rd), FD_ISSET(s_out, &wr), FD_ISSET(s_in, &rd));
   2361 
   2362 		if (nfd < 0) {
   2363 			rfbLog("SSL: ssl_xfer[%d]: select error: %d\n", getpid(), nfd);
   2364 			perror("select");
   2365 			/* connection finished */
   2366 			goto done;
   2367 		}
   2368 
   2369 		if (nfd == 0) {
   2370 			if (!closing && tv_cutover && ndata > 25000) {
   2371 				static int cn = 0;
   2372 				/* probably ok, early windows iconify */
   2373 				if (cn++ < 2) {
   2374 					rfbLog("SSL: ssl_xfer[%d]: early time"
   2375 					    "out: %d\n", getpid(), ndata);
   2376 				}
   2377 				continue;
   2378 			}
   2379 			rfbLog("SSL: ssl_xfer[%d]: connection timedout. %d  tv_use: %d\n",
   2380 			    getpid(), ndata, tv_use);
   2381 			/* connection finished */
   2382 			goto done;
   2383 		}
   2384 
   2385 		/* used to see if SSL_pending() should be checked: */
   2386 		check_pending = 0;
   2387 /* AUDIT */
   2388 
   2389 		if (c_wr && FD_ISSET(csock, &wr)) {
   2390 
   2391 			/* try to write some of our sbuf to C: */
   2392 			n = write(csock, sbuf, sptr);
   2393 
   2394 			if (n < 0) {
   2395 				if (errno != EINTR) {
   2396 					/* connection finished */
   2397 					goto done;
   2398 				}
   2399 				/* proceed */
   2400 			} else if (n == 0) {
   2401 				/* connection finished XXX double check */
   2402 				goto done;
   2403 			} else {
   2404 				/* shift over the data in sbuf by n */
   2405 				memmove(sbuf, sbuf + n, sptr - n);
   2406 				if (sptr == ABSIZE) {
   2407 					check_pending = 1;
   2408 				}
   2409 				sptr -= n;
   2410 
   2411 				if (! s_rd && sptr == 0) {
   2412 					/* finished sending last of sbuf */
   2413 					shutdown(csock, SHUT_WR);
   2414 					c_wr = 0;
   2415 				}
   2416 				ndata += n;
   2417 			}
   2418 		}
   2419 
   2420 		if (s_wr) {
   2421 			if ((cptr > 0 && FD_ISSET(s_out, &wr)) ||
   2422 			    (SSL_want_read(ssl) && FD_ISSET(s_in, &rd))) {
   2423 
   2424 				/* try to write some of our cbuf to S: */
   2425 
   2426 				n = SSL_write(ssl, cbuf, cptr);
   2427 				err = SSL_get_error(ssl, n);
   2428 
   2429 				if (err == SSL_ERROR_NONE) {
   2430 					/* shift over the data in cbuf by n */
   2431 					memmove(cbuf, cbuf + n, cptr - n);
   2432 					cptr -= n;
   2433 
   2434 					if (! c_rd && cptr == 0 && s_wr) {
   2435 						/* finished sending last cbuf */
   2436 						SSL_shutdown(ssl);
   2437 						s_wr = 0;
   2438 					}
   2439 					ndata += n;
   2440 
   2441 				} else if (err == SSL_ERROR_WANT_WRITE
   2442 					|| err == SSL_ERROR_WANT_READ
   2443 					|| err == SSL_ERROR_WANT_X509_LOOKUP) {
   2444 
   2445 						;	/* proceed */
   2446 
   2447 				} else if (err == SSL_ERROR_SYSCALL) {
   2448 					if (n < 0 && errno != EINTR) {
   2449 						/* connection finished */
   2450 						goto done;
   2451 					}
   2452 					/* proceed */
   2453 				} else if (err == SSL_ERROR_ZERO_RETURN) {
   2454 					/* S finished */
   2455 					s_rd = 0;
   2456 					s_wr = 0;
   2457 				} else if (err == SSL_ERROR_SSL) {
   2458 					/* connection finished */
   2459 					goto done;
   2460 				}
   2461 			}
   2462 		}
   2463 
   2464 		if (c_rd && FD_ISSET(csock, &rd)) {
   2465 
   2466 
   2467 			/* try to read some data from C into our cbuf */
   2468 
   2469 			n = read(csock, cbuf + cptr, ABSIZE - cptr);
   2470 
   2471 			if (n < 0) {
   2472 				if (errno != EINTR) {
   2473 					/* connection finished */
   2474 					goto done;
   2475 				}
   2476 				/* proceed */
   2477 			} else if (n == 0) {
   2478 				/* C is EOF */
   2479 				c_rd = 0;
   2480 				if (cptr == 0 && s_wr) {
   2481 					/* and no more in cbuf to send */
   2482 					SSL_shutdown(ssl);
   2483 					s_wr = 0;
   2484 				}
   2485 			} else {
   2486 				/* good */
   2487 
   2488 				cptr += n;
   2489 				ndata += n;
   2490 			}
   2491 		}
   2492 
   2493 		if (s_rd) {
   2494 			if ((sptr < ABSIZE && FD_ISSET(s_in, &rd)) ||
   2495 			    (SSL_want_write(ssl) && FD_ISSET(s_out, &wr)) ||
   2496 			    (check_pending && SSL_pending(ssl))) {
   2497 
   2498 				/* try to read some data from S into our sbuf */
   2499 
   2500 				n = SSL_read(ssl, sbuf + sptr, ABSIZE - sptr);
   2501 				err = SSL_get_error(ssl, n);
   2502 
   2503 				if (err == SSL_ERROR_NONE) {
   2504 					/* good */
   2505 
   2506 					sptr += n;
   2507 					ndata += n;
   2508 
   2509 				} else if (err == SSL_ERROR_WANT_WRITE
   2510 					|| err == SSL_ERROR_WANT_READ
   2511 					|| err == SSL_ERROR_WANT_X509_LOOKUP) {
   2512 
   2513 						;	/* proceed */
   2514 
   2515 				} else if (err == SSL_ERROR_SYSCALL) {
   2516 					if (n < 0) {
   2517 						if(errno != EINTR) {
   2518 							/* connection finished */
   2519 							goto done;
   2520 						}
   2521 						/* proceed */
   2522 					} else {
   2523 						/* S finished */
   2524 						s_rd = 0;
   2525 						s_wr = 0;
   2526 					}
   2527 				} else if (err == SSL_ERROR_ZERO_RETURN) {
   2528 					/* S is EOF */
   2529 					s_rd = 0;
   2530 					if (cptr == 0 && s_wr) {
   2531 						/* and no more in cbuf to send */
   2532 						SSL_shutdown(ssl);
   2533 						s_wr = 0;
   2534 					}
   2535 					if (sptr == 0 && c_wr) {
   2536 						/* and no more in sbuf to send */
   2537 						shutdown(csock, SHUT_WR);
   2538 						c_wr = 0;
   2539 					}
   2540 				} else if (err == SSL_ERROR_SSL) {
   2541 					/* connection finished */
   2542 					goto done;
   2543 				}
   2544 			}
   2545 		}
   2546 	}
   2547 
   2548 	done:
   2549 	rfbLog("SSL: ssl_xfer[%d]: closing sockets %d, %d, %d\n",
   2550 			    getpid(), csock, s_in, s_out);
   2551 	close(csock);
   2552 	close(s_in);
   2553 	close(s_out);
   2554 	return;
   2555 }
   2556 
   2557 #define MSZ 4096
   2558 static void init_prng(void) {
   2559 	int db = 0, bytes, ubytes, fd;
   2560 	char file[MSZ], dtmp[100];
   2561 	unsigned int sr;
   2562 
   2563 	RAND_file_name(file, MSZ);
   2564 
   2565 	rfbLog("RAND_file_name: %s\n", file);
   2566 
   2567 	bytes = RAND_load_file(file, -1);
   2568 	if (db) fprintf(stderr, "bytes read: %d\n", bytes);
   2569 
   2570 	ubytes = RAND_load_file("/dev/urandom", 64);
   2571 	bytes += ubytes;
   2572 	if (db) fprintf(stderr, "bytes read: %d / %d\n", bytes, ubytes);
   2573 
   2574 	/* mix in more predictable stuff as well for fallback */
   2575 	sprintf(dtmp, "/tmp/p%.8f.XXXXXX", dnow());
   2576 	fd = mkstemp(dtmp);
   2577 	RAND_add(dtmp, strlen(dtmp), 0);
   2578 	if (fd >= 0) {
   2579 		close(fd);
   2580 		unlink(dtmp);
   2581 	}
   2582 	sprintf(dtmp, "%d-%.8f", (int) getpid(), dnow());
   2583 	RAND_add(dtmp, strlen(dtmp), 0);
   2584 
   2585 	if (!RAND_status()) {
   2586 		ubytes = -1;
   2587 		rfbLog("calling RAND_poll()\n");
   2588 		RAND_poll();
   2589 	}
   2590 
   2591 	RAND_bytes((unsigned char *)&sr, 4);
   2592 	srand(sr);
   2593 
   2594 	if (bytes > 0) {
   2595 		if (! quiet) {
   2596 			rfbLog("initialized PRNG with %d random bytes.\n",
   2597 			    bytes);
   2598 		}
   2599 		if (ubytes > 32 && rnow() < 0.25) {
   2600 			RAND_write_file(file);
   2601 		}
   2602 		return;
   2603 	}
   2604 
   2605 	bytes += RAND_load_file("/dev/random", 8);
   2606 	if (db) fprintf(stderr, "bytes read: %d\n", bytes);
   2607 	RAND_poll();
   2608 
   2609 	if (! quiet) {
   2610 		rfbLog("initialized PRNG with %d random bytes.\n", bytes);
   2611 	}
   2612 }
   2613 #endif	/* FORK_OK */
   2614 #endif	/* LIBVNCSERVER_HAVE_LIBSSL */
   2615 
   2616 void check_openssl(void) {
   2617 	fd_set fds;
   2618 	struct timeval tv;
   2619 	int nfds, nmax = openssl_sock;
   2620 	static time_t last_waitall = 0;
   2621 	static double last_check = 0.0;
   2622 	double now;
   2623 
   2624 	if (! use_openssl) {
   2625 		return;
   2626 	}
   2627 
   2628 	if (time(NULL) > last_waitall + 120) {
   2629 		last_waitall = time(NULL);
   2630 		ssl_helper_pid(0, -2);	/* waitall */
   2631 	}
   2632 
   2633 	if (openssl_sock < 0 && openssl_sock6 < 0) {
   2634 		return;
   2635 	}
   2636 
   2637 	now = dnow();
   2638 	if (now < last_check + 0.5) {
   2639 		return;
   2640 	}
   2641 	last_check = now;
   2642 
   2643 	FD_ZERO(&fds);
   2644 	if (openssl_sock >= 0) {
   2645 		FD_SET(openssl_sock, &fds);
   2646 	}
   2647 	if (openssl_sock6 >= 0) {
   2648 		FD_SET(openssl_sock6, &fds);
   2649 		if (openssl_sock6 > openssl_sock) {
   2650 			nmax = openssl_sock6;
   2651 		}
   2652 	}
   2653 
   2654 	tv.tv_sec = 0;
   2655 	tv.tv_usec = 0;
   2656 
   2657 	nfds = select(nmax+1, &fds, NULL, NULL, &tv);
   2658 
   2659 	if (nfds <= 0) {
   2660 		return;
   2661 	}
   2662 
   2663 	if (openssl_sock >= 0 && FD_ISSET(openssl_sock, &fds)) {
   2664 		rfbLog("SSL: accept_openssl(OPENSSL_VNC)\n");
   2665 		accept_openssl(OPENSSL_VNC, -1);
   2666 	}
   2667 	if (openssl_sock6 >= 0 && FD_ISSET(openssl_sock6, &fds)) {
   2668 		rfbLog("SSL: accept_openssl(OPENSSL_VNC6)\n");
   2669 		accept_openssl(OPENSSL_VNC6, -1);
   2670 	}
   2671 }
   2672 
   2673 void check_https(void) {
   2674 	fd_set fds;
   2675 	struct timeval tv;
   2676 	int nfds, nmax = https_sock;
   2677 	static double last_check = 0.0;
   2678 	double now;
   2679 
   2680 	if (! use_openssl || (https_sock < 0 && https_sock6 < 0)) {
   2681 		return;
   2682 	}
   2683 
   2684 	now = dnow();
   2685 	if (now < last_check + 0.5) {
   2686 		return;
   2687 	}
   2688 	last_check = now;
   2689 
   2690 	FD_ZERO(&fds);
   2691 	if (https_sock >= 0) {
   2692 		FD_SET(https_sock, &fds);
   2693 	}
   2694 	if (https_sock6 >= 0) {
   2695 		FD_SET(https_sock6, &fds);
   2696 		if (https_sock6 > https_sock) {
   2697 			nmax = https_sock6;
   2698 		}
   2699 	}
   2700 
   2701 	tv.tv_sec = 0;
   2702 	tv.tv_usec = 0;
   2703 
   2704 	nfds = select(nmax+1, &fds, NULL, NULL, &tv);
   2705 
   2706 	if (nfds <= 0) {
   2707 		return;
   2708 	}
   2709 
   2710 	if (https_sock >= 0 && FD_ISSET(https_sock, &fds)) {
   2711 		rfbLog("SSL: accept_openssl(OPENSSL_HTTPS)\n");
   2712 		accept_openssl(OPENSSL_HTTPS, -1);
   2713 	}
   2714 	if (https_sock6 >= 0 && FD_ISSET(https_sock6, &fds)) {
   2715 		rfbLog("SSL: accept_openssl(OPENSSL_HTTPS6)\n");
   2716 		accept_openssl(OPENSSL_HTTPS6, -1);
   2717 	}
   2718 }
   2719 
   2720 void openssl_port(int restart) {
   2721 	int sock = -1, shutdown = 0;
   2722 	static int port = -1;
   2723 	static in_addr_t iface = INADDR_ANY;
   2724 	int db = 0, fd6 = -1;
   2725 
   2726 	if (! screen) {
   2727 		rfbLog("openssl_port: no screen!\n");
   2728 		clean_up_exit(1);
   2729 	}
   2730 	if (inetd) {
   2731 		ssl_initialized = 1;
   2732 		return;
   2733 	}
   2734 
   2735 	if (ipv6_listen && screen->port <= 0) {
   2736 		if (got_rfbport) {
   2737 			screen->port = got_rfbport_val;
   2738 		} else {
   2739 			int ap = 5900;
   2740 			if (auto_port > 0) {
   2741 				ap = auto_port;
   2742 			}
   2743 			screen->port = find_free_port6(ap, ap+200);
   2744 		}
   2745 		rfbLog("openssl_port: reset port from 0 => %d\n", screen->port);
   2746 	}
   2747 
   2748 	if (restart) {
   2749 		port = screen->port;
   2750 	} else if (screen->listenSock > -1 && screen->port > 0) {
   2751 		port = screen->port;
   2752 		shutdown = 1;
   2753 	} else if (ipv6_listen && screen->port > 0) {
   2754 		port = screen->port;
   2755 	} else if (screen->port == 0) {
   2756 		port = screen->port;
   2757 	}
   2758 
   2759 	iface = screen->listenInterface;
   2760 
   2761 	if (shutdown) {
   2762 		if (db) fprintf(stderr, "shutting down %d/%d\n",
   2763 		    port, screen->listenSock);
   2764 #if LIBVNCSERVER_HAS_SHUTDOWNSOCKETS
   2765 		rfbShutdownSockets(screen);
   2766 #endif
   2767 	}
   2768 
   2769 	if (openssl_sock >= 0) {
   2770 		close(openssl_sock);
   2771 		openssl_sock = -1;
   2772 	}
   2773 	if (openssl_sock6 >= 0) {
   2774 		close(openssl_sock6);
   2775 		openssl_sock6 = -1;
   2776 	}
   2777 
   2778 	if (port < 0) {
   2779 		rfbLog("openssl_port: could not obtain listening port %d\n", port);
   2780 		if (!got_rfbport && !got_ipv6_listen) {
   2781 			rfbLog("openssl_port: if this system is IPv6-only, use the -6 option\n");
   2782 		}
   2783 		clean_up_exit(1);
   2784 	} else if (port == 0) {
   2785 		/* no listen case, i.e. -connect */
   2786 		sock = -1;
   2787 	} else {
   2788 		sock = listen_tcp(port, iface, 0);
   2789 		if (ipv6_listen) {
   2790 			fd6 = listen6(port);
   2791 		} else if (!got_rfbport && !got_ipv6_listen) {
   2792 			if (sock < 0) {
   2793 				rfbLog("openssl_port: if this system is IPv6-only, use the -6 option\n");
   2794 			}
   2795 		}
   2796 		if (sock < 0) {
   2797 			if (fd6 < 0) {
   2798 				rfbLog("openssl_port: could not reopen port %d\n", port);
   2799 				if (!restart) {
   2800 					clean_up_exit(1);
   2801 				}
   2802 			} else {
   2803 				rfbLog("openssl_port: Info: listening on IPv6 only.\n");
   2804 			}
   2805 		}
   2806 	}
   2807 	rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock);
   2808 	if (ipv6_listen && port > 0) {
   2809 		if (fd6 < 0) {
   2810 			fd6 = listen6(port);
   2811 		}
   2812 		if (fd6 < 0) {
   2813 			ipv6_listen = 0;
   2814 		} else {
   2815 			rfbLog("openssl_port: listen on port/sock %d/%d (ipv6)\n",
   2816 			    port, fd6);
   2817 			openssl_sock6 = fd6;
   2818 		}
   2819 	}
   2820 	if (!quiet && sock >=0) {
   2821 		announce(port, 1, NULL);
   2822 	}
   2823 	openssl_sock = sock;
   2824 	openssl_port_num = port;
   2825 
   2826 	ssl_initialized = 1;
   2827 }
   2828 
   2829 void https_port(int restart) {
   2830 	int sock, fd6 = -1;
   2831 	static int port = 0;
   2832 	static in_addr_t iface = INADDR_ANY;
   2833 
   2834 	/* as openssl_port above: open a listening socket for pure https: */
   2835 	if (https_port_num < 0) {
   2836 		return;
   2837 	}
   2838 	if (! screen) {
   2839 		rfbLog("https_port: no screen!\n");
   2840 		clean_up_exit(1);
   2841 	}
   2842 	if (! screen->httpDir) {
   2843 		return;
   2844 	}
   2845 	if (screen->listenInterface) {
   2846 		iface = screen->listenInterface;
   2847 	}
   2848 
   2849 	if (https_port_num == 0) {
   2850 		https_port_num = find_free_port(5801, 5851);
   2851 	}
   2852 	if (ipv6_listen && https_port_num <= 0) {
   2853 		https_port_num = find_free_port6(5801, 5851);
   2854 	}
   2855 	if (https_port_num <= 0) {
   2856 		rfbLog("https_port: could not find port %d\n", https_port_num);
   2857 		clean_up_exit(1);
   2858 	}
   2859 	port = https_port_num;
   2860 
   2861 	if (port <= 0) {
   2862 		rfbLog("https_port: could not obtain listening port %d\n", port);
   2863 		if (!restart) {
   2864 			clean_up_exit(1);
   2865 		} else {
   2866 			return;
   2867 		}
   2868 	}
   2869 	if (https_sock >= 0) {
   2870 		close(https_sock);
   2871 		https_sock = -1;
   2872 	}
   2873 	if (https_sock6 >= 0) {
   2874 		close(https_sock6);
   2875 		https_sock6 = -1;
   2876 	}
   2877 	sock = listen_tcp(port, iface, 0);
   2878 	if (sock < 0) {
   2879 		rfbLog("https_port: could not open port %d\n", port);
   2880 		if (ipv6_listen) {
   2881 			fd6 = listen6(port);
   2882 		}
   2883 		if (fd6 < 0) {
   2884 			if (!restart) {
   2885 				clean_up_exit(1);
   2886 			}
   2887 		}
   2888 		rfbLog("https_port: trying IPv6 only mode.\n");
   2889 	}
   2890 	rfbLog("https_port: listen on port/sock %d/%d\n", port, sock);
   2891 	https_sock = sock;
   2892 
   2893 	if (ipv6_listen) {
   2894 		if (fd6 < 0) {
   2895 			fd6 = listen6(port);
   2896 		}
   2897 		if (fd6 < 0) {
   2898 			;
   2899 		} else {
   2900 			rfbLog("https_port: listen on port/sock %d/%d (ipv6)\n",
   2901 			    port, fd6);
   2902 			https_sock6 = fd6;
   2903 		}
   2904 		if (fd6 < 0 && https_sock < 0) {
   2905 			rfbLog("https_port: could not listen on either IPv4 or IPv6.\n");
   2906 			if (!restart) {
   2907 				clean_up_exit(1);
   2908 			}
   2909 		}
   2910 	}
   2911 }
   2912 
   2913 static void lose_ram(void) {
   2914 	/*
   2915 	 * for a forked child that will be around for a long time
   2916 	 * without doing exec().  we really should re-exec, but a pain
   2917 	 * to redo all SSL ctx.
   2918 	 */
   2919 	free_old_fb();
   2920 
   2921 	free_tiles();
   2922 }
   2923 
   2924 /* utility to keep track of existing helper processes: */
   2925 
   2926 void ssl_helper_pid(pid_t pid, int sock) {
   2927 #	define HPSIZE 256
   2928 	static pid_t helpers[HPSIZE];
   2929 	static int   sockets[HPSIZE], first = 1;
   2930 	int i, empty, set, status;
   2931 	static int db = 0;
   2932 
   2933 	if (first) {
   2934 		for (i=0; i < HPSIZE; i++)  {
   2935 			helpers[i] = 0;
   2936 			sockets[i] = 0;
   2937 		}
   2938 		if (getenv("SSL_HELPER_PID_DB")) {
   2939 			db = 1;
   2940 		}
   2941 		first = 0;
   2942 	}
   2943 
   2944 
   2945 	if (pid == 0) {
   2946 		/* killall or waitall */
   2947 		for (i=0; i < HPSIZE; i++) {
   2948 			if (helpers[i] == 0) {
   2949 				sockets[i] = -1;
   2950 				continue;
   2951 			}
   2952 			if (kill(helpers[i], 0) == 0) {
   2953 				int kret = -2;
   2954 				pid_t wret;
   2955 				if (sock != -2) {
   2956 					if (sockets[i] >= 0) {
   2957 						close(sockets[i]);
   2958 					}
   2959 					kret = kill(helpers[i], SIGTERM);
   2960 					if (kret == 0) {
   2961 						usleep(20 * 1000);
   2962 					}
   2963 				}
   2964 
   2965 #if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID
   2966 				wret = waitpid(helpers[i], &status, WNOHANG);
   2967 
   2968 if (db) fprintf(stderr, "waitpid(%d)\n", helpers[i]);
   2969 if (db) fprintf(stderr, "  waitret1=%d\n", wret);
   2970 
   2971 				if (kret == 0 && wret != helpers[i]) {
   2972 					int k;
   2973 					for (k=0; k < 10; k++) {
   2974 						usleep(100 * 1000);
   2975 						wret = waitpid(helpers[i], &status, WNOHANG);
   2976 if (db) fprintf(stderr, "  waitret2=%d\n", wret);
   2977 						if (wret == helpers[i]) {
   2978 							break;
   2979 						}
   2980 					}
   2981 				}
   2982 #endif
   2983 				if (sock == -2) {
   2984 					continue;
   2985 				}
   2986 			}
   2987 			helpers[i] = 0;
   2988 			sockets[i] = -1;
   2989 		}
   2990 		return;
   2991 	}
   2992 
   2993 if (db) fprintf(stderr, "ssl_helper_pid(%d, %d)\n", pid, sock);
   2994 
   2995 	/* add (or delete for sock == -1) */
   2996 	set = 0;
   2997 	empty = -1;
   2998 	for (i=0; i < HPSIZE; i++) {
   2999 		if (helpers[i] == pid) {
   3000 			if (sock == -1) {
   3001 #if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID
   3002 				pid_t wret;
   3003 				wret = waitpid(helpers[i], &status, WNOHANG);
   3004 
   3005 if (db) fprintf(stderr, "waitpid(%d) 2\n", helpers[i]);
   3006 if (db) fprintf(stderr, "  waitret1=%d\n", wret);
   3007 #endif
   3008 				helpers[i] = 0;
   3009 			}
   3010 			sockets[i] = sock;
   3011 			set = 1;
   3012 		} else if (empty == -1 && helpers[i] == 0) {
   3013 			empty = i;
   3014 		}
   3015 	}
   3016 	if (set || sock == -1) {
   3017 		return;	/* done */
   3018 	}
   3019 
   3020 	/* now try to store */
   3021 	if (empty >= 0) {
   3022 		helpers[empty] = pid;
   3023 		sockets[empty] = sock;
   3024 		return;
   3025 	}
   3026 	for (i=0; i < HPSIZE; i++) {
   3027 		if (helpers[i] == 0) {
   3028 			continue;
   3029 		}
   3030 		/* clear out stale pids: */
   3031 		if (kill(helpers[i], 0) != 0) {
   3032 			helpers[i] = 0;
   3033 			sockets[i] = -1;
   3034 
   3035 			if (empty == -1) {
   3036 				empty = i;
   3037 			}
   3038 		}
   3039 	}
   3040 	if (empty >= 0) {
   3041 		helpers[empty] = pid;
   3042 		sockets[empty] = sock;
   3043 	}
   3044 }
   3045 
   3046 static int is_ssl_readable(int s_in, double last_https, char *last_get,
   3047     int mode) {
   3048 	int nfd, db = 0;
   3049 	struct timeval tv;
   3050 	fd_set rd;
   3051 
   3052 	if (getenv("ACCEPT_OPENSSL_DEBUG")) {
   3053 		db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
   3054 	}
   3055 
   3056 	/*
   3057 	 * we'll do a select() on s_in for reading.  this is not an
   3058 	 * absolute proof that SSL_read is ready (XXX use SSL utility).
   3059 	 */
   3060 	tv.tv_sec  = 2;
   3061 	tv.tv_usec = 0;
   3062 
   3063 	if (mode == OPENSSL_INETD) {
   3064 		/*
   3065 		 * https via inetd is icky because x11vnc is restarted
   3066 		 * for each socket (and some clients send requests
   3067 		 * rapid fire).
   3068 		 */
   3069 		tv.tv_sec = 4;
   3070 	}
   3071 
   3072 	/*
   3073 	 * increase the timeout if we know HTTP traffic has occurred
   3074 	 * recently:
   3075 	 */
   3076 	if (dnow() < last_https + 30.0) {
   3077 		tv.tv_sec = 10;
   3078 		if (last_get && strstr(last_get, "VncViewer")) {
   3079 			tv.tv_sec = 5;
   3080 		}
   3081 	}
   3082 	if (getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT")) {
   3083 		tv.tv_sec  = atoi(getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT"));
   3084 	}
   3085 if (db) fprintf(stderr, "tv_sec: %d - '%s'\n", (int) tv.tv_sec, last_get);
   3086 
   3087 	FD_ZERO(&rd);
   3088 	FD_SET(s_in, &rd);
   3089 
   3090 	if (db) fprintf(stderr, "is_ssl_readable: begin  select(%d secs) %.6f\n", (int) tv.tv_sec, dnow());
   3091 	do {
   3092 		nfd = select(s_in+1, &rd, NULL, NULL, &tv);
   3093 	} while (nfd < 0 && errno == EINTR);
   3094 	if (db) fprintf(stderr, "is_ssl_readable: finish select(%d secs) %.6f\n", (int) tv.tv_sec, dnow());
   3095 
   3096 	if (db) fprintf(stderr, "https nfd: %d\n", nfd);
   3097 
   3098 	if (nfd <= 0 || ! FD_ISSET(s_in, &rd)) {
   3099 		return 0;
   3100 	}
   3101 	return 1;
   3102 }
   3103 
   3104 static int watch_for_http_traffic(char *buf_a, int *n_a, int raw_sock) {
   3105 	int is_http, err, n, n2;
   3106 	char *buf;
   3107 	int db = 0;
   3108 	/*
   3109 	 * sniff the first couple bytes of the stream and try to see
   3110 	 * if it is http or not.  if we read them OK, we must read the
   3111 	 * rest of the available data otherwise we may deadlock.
   3112 	 * what has been read is returned in buf_a and n_a.
   3113 	 * *buf_a is ABSIZE+1 long and zeroed.
   3114 	 */
   3115 	if (getenv("ACCEPT_OPENSSL_DEBUG")) {
   3116 		db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
   3117 	}
   3118 	if (! buf_a || ! n_a) {
   3119 		return 0;
   3120 	}
   3121 
   3122 	buf = (char *) calloc((ABSIZE+1), 1);
   3123 	*n_a = 0;
   3124 
   3125 	if (enc_str && !strcmp(enc_str, "none")) {
   3126 		n = read(raw_sock, buf, 2);
   3127 		err = SSL_ERROR_NONE;
   3128 	} else {
   3129 #if LIBVNCSERVER_HAVE_LIBSSL
   3130 		n = SSL_read(ssl, buf, 2);
   3131 		err = SSL_get_error(ssl, n);
   3132 #else
   3133 		err = n = 0;
   3134 		badnews("1 in watch_for_http_traffic");
   3135 #endif
   3136 	}
   3137 
   3138 	if (err != SSL_ERROR_NONE || n < 2) {
   3139 		if (n > 0) {
   3140 			strncpy(buf_a, buf, n);
   3141 			*n_a = n;
   3142 		}
   3143 		if (db) fprintf(stderr, "watch_for_http_traffic ssl err: %d/%d\n", err, n);
   3144 		return -1;
   3145 	}
   3146 
   3147 	/* look for GET, HEAD, POST, CONNECT */
   3148 	is_http = 0;
   3149 	if (!strncmp("GE", buf, 2)) {
   3150 		is_http = 1;
   3151 	} else if (!strncmp("HE", buf, 2)) {
   3152 		is_http = 1;
   3153 	} else if (!strncmp("PO", buf, 2)) {
   3154 		is_http = 1;
   3155 	} else if (!strncmp("CO", buf, 2)) {
   3156 		is_http = 1;
   3157 	}
   3158 	if (db) fprintf(stderr, "watch_for_http_traffic read: '%s' %d\n", buf, n);
   3159 
   3160 	/*
   3161 	 * better read all we can and fwd it along to avoid blocking
   3162 	 * in ssl_xfer().
   3163 	 */
   3164 
   3165 	if (enc_str && !strcmp(enc_str, "none")) {
   3166 		n2 = read(raw_sock, buf + n, ABSIZE - n);
   3167 	} else {
   3168 #if LIBVNCSERVER_HAVE_LIBSSL
   3169 		n2 = SSL_read(ssl, buf + n, ABSIZE - n);
   3170 #else
   3171 		n2 = 0;
   3172 		badnews("2 in watch_for_http_traffic");
   3173 #endif
   3174 	}
   3175 	if (n2 >= 0) {
   3176 		n += n2;
   3177 	}
   3178 
   3179 	*n_a = n;
   3180 
   3181 	if (db) fprintf(stderr, "watch_for_http_traffic readmore: %d\n", n2);
   3182 
   3183 	if (n > 0) {
   3184 		memcpy(buf_a, buf, n);
   3185 	}
   3186 	if (db > 1) {
   3187 		fprintf(stderr, "watch_for_http_traffic readmore: ");
   3188 		write(2, buf_a, *n_a);
   3189 		fprintf(stderr, "\n");
   3190 	}
   3191 	if (db) fprintf(stderr, "watch_for_http_traffic return: %d\n", is_http);
   3192 	return is_http;
   3193 }
   3194 
   3195 static int csock_timeout_sock = -1;
   3196 
   3197 static void csock_timeout (int sig) {
   3198 	rfbLog("sig: %d, csock_timeout.\n", sig);
   3199 	if (csock_timeout_sock >= 0) {
   3200 		close(csock_timeout_sock);
   3201 		csock_timeout_sock = -1;
   3202 	}
   3203 }
   3204 
   3205 static int check_ssl_access(char *addr) {
   3206 	static char *save_allow_once = NULL;
   3207 	static time_t time_allow_once = 0;
   3208 
   3209 	/* due to "Fetch Cert" activities for SSL really need to "allow twice" */
   3210 	if (allow_once != NULL) {
   3211 		save_allow_once = strdup(allow_once);
   3212 		time_allow_once = time(NULL);
   3213 	} else if (save_allow_once != NULL) {
   3214 		if (getenv("X11VNC_NO_SSL_ALLOW_TWICE")) {
   3215 			;
   3216 		} else if (time(NULL) < time_allow_once + 30) {
   3217 			/* give them 30 secs to check and save the fetched cert. */
   3218 			allow_once = save_allow_once;
   3219 			rfbLog("SSL: Permitting 30 sec grace period for allowonce.\n");
   3220 			rfbLog("SSL: Set X11VNC_NO_SSL_ALLOW_TWICE=1 to disable.\n");
   3221 		}
   3222 		save_allow_once = NULL;
   3223 		time_allow_once = 0;
   3224 	}
   3225 
   3226 	return check_access(addr);
   3227 }
   3228 
   3229 void accept_openssl(int mode, int presock) {
   3230 	int sock = -1, listen = -1, cport, csock, vsock;
   3231 	int peerport = 0;
   3232 	int status, n, i, db = 0;
   3233 	struct sockaddr_in addr;
   3234 #ifdef __hpux
   3235 	int addrlen = sizeof(addr);
   3236 #else
   3237 	socklen_t addrlen = sizeof(addr);
   3238 #endif
   3239 	rfbClientPtr client;
   3240 	pid_t pid;
   3241 	char uniq[] = "_evilrats_";
   3242 	char cookie[256], rcookie[256], *name = NULL;
   3243 	int vencrypt_sel = 0;
   3244 	int anontls_sel = 0;
   3245 	char *ipv6_name = NULL;
   3246 	static double last_https = 0.0;
   3247 	static char last_get[256];
   3248 	static int first = 1;
   3249 	unsigned char *rb;
   3250 
   3251 #if !LIBVNCSERVER_HAVE_LIBSSL
   3252 	if (enc_str == NULL || strcmp(enc_str, "none")) {
   3253 		badnews("0 accept_openssl");
   3254 	}
   3255 #endif
   3256 
   3257 	openssl_last_helper_pid = 0;
   3258 
   3259 	/* zero buffers for use below. */
   3260 	for (i=0; i<256; i++) {
   3261 		if (first) {
   3262 			last_get[i] = '\0';
   3263 		}
   3264 		cookie[i]  = '\0';
   3265 		rcookie[i] = '\0';
   3266 	}
   3267 	first = 0;
   3268 
   3269 	if (getenv("ACCEPT_OPENSSL_DEBUG")) {
   3270 		db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
   3271 	}
   3272 
   3273 	/* do INETD, VNC, or HTTPS cases (result is client socket or pipe) */
   3274 	if (mode == OPENSSL_INETD) {
   3275 		ssl_initialized = 1;
   3276 
   3277 	} else if (mode == OPENSSL_VNC) {
   3278 		sock = accept(openssl_sock, (struct sockaddr *)&addr, &addrlen);
   3279 		if (sock < 0)  {
   3280 			rfbLog("SSL: accept_openssl: accept connection failed\n");
   3281 			rfbLogPerror("accept");
   3282 			if (ssl_no_fail) {
   3283 				clean_up_exit(1);
   3284 			}
   3285 			return;
   3286 		}
   3287 		listen = openssl_sock;
   3288 
   3289 	} else if (mode == OPENSSL_VNC6 || mode == OPENSSL_HTTPS6) {
   3290 #if X11VNC_IPV6
   3291 		struct sockaddr_in6 a6;
   3292 		socklen_t a6len = sizeof(a6);
   3293 		int fd = (mode == OPENSSL_VNC6 ? openssl_sock6 : https_sock6);
   3294 
   3295 		sock = accept(fd, (struct sockaddr *)&a6, &a6len);
   3296 		if (sock < 0)  {
   3297 			rfbLog("SSL: accept_openssl: accept connection failed\n");
   3298 			rfbLogPerror("accept");
   3299 			if (ssl_no_fail) {
   3300 				clean_up_exit(1);
   3301 			}
   3302 			return;
   3303 		}
   3304 		ipv6_name = ipv6_getipaddr((struct sockaddr *)&a6, a6len);
   3305 		if (!ipv6_name) ipv6_name = strdup("unknown");
   3306 		listen = fd;
   3307 #endif
   3308 	} else if (mode == OPENSSL_REVERSE) {
   3309 		sock = presock;
   3310 		if (sock < 0)  {
   3311 			rfbLog("SSL: accept_openssl: connection failed\n");
   3312 			if (ssl_no_fail) {
   3313 				clean_up_exit(1);
   3314 			}
   3315 			return;
   3316 		}
   3317 		if (getenv("OPENSSL_REVERSE_DEBUG")) fprintf(stderr, "OPENSSL_REVERSE: ipv6_client_ip_str: %s\n", ipv6_client_ip_str);
   3318 		if (ipv6_client_ip_str != NULL) {
   3319 			ipv6_name = strdup(ipv6_client_ip_str);
   3320 		}
   3321 		listen = -1;
   3322 
   3323 	} else if (mode == OPENSSL_HTTPS) {
   3324 		sock = accept(https_sock, (struct sockaddr *)&addr, &addrlen);
   3325 		if (sock < 0)  {
   3326 			rfbLog("SSL: accept_openssl: accept connection failed\n");
   3327 			rfbLogPerror("accept");
   3328 			if (ssl_no_fail) {
   3329 				clean_up_exit(1);
   3330 			}
   3331 			return;
   3332 		}
   3333 		listen = https_sock;
   3334 	}
   3335 	if (db) fprintf(stderr, "SSL: accept_openssl: sock: %d\n", sock);
   3336 
   3337 	if (openssl_last_ip) {
   3338 		free(openssl_last_ip);
   3339 		openssl_last_ip = NULL;
   3340 	}
   3341 	if (mode == OPENSSL_INETD) {
   3342 		openssl_last_ip = get_remote_host(fileno(stdin));
   3343 	} else if (mode == OPENSSL_VNC6 || mode == OPENSSL_HTTPS6) {
   3344 		openssl_last_ip = ipv6_name;
   3345 	} else if (mode == OPENSSL_REVERSE && ipv6_name != NULL) {
   3346 		openssl_last_ip = ipv6_name;
   3347 	} else {
   3348 		openssl_last_ip = get_remote_host(sock);
   3349 	}
   3350 
   3351 	if (!check_ssl_access(openssl_last_ip)) {
   3352 		rfbLog("SSL: accept_openssl: denying client %s\n", openssl_last_ip);
   3353 		rfbLog("SSL: accept_openssl: does not match -allow or other reason.\n");
   3354 		close(sock);
   3355 		sock = -1;
   3356 		if (ssl_no_fail) {
   3357 			clean_up_exit(1);
   3358 		}
   3359 		return;
   3360 	}
   3361 
   3362 	/* now make a listening socket for child to connect back to us by: */
   3363 
   3364 	cport = find_free_port(20000, 22000);
   3365 	if (! cport && ipv6_listen) {
   3366 		rfbLog("SSL: accept_openssl: seeking IPv6 port.\n");
   3367 		cport = find_free_port6(20000, 22000);
   3368 		rfbLog("SSL: accept_openssl: IPv6 port: %d\n", cport);
   3369 	}
   3370 	if (! cport) {
   3371 		rfbLog("SSL: accept_openssl: could not find open port.\n");
   3372 		close(sock);
   3373 		if (mode == OPENSSL_INETD || ssl_no_fail) {
   3374 			clean_up_exit(1);
   3375 		}
   3376 		return;
   3377 	}
   3378 	if (db) fprintf(stderr, "accept_openssl: cport: %d\n", cport);
   3379 
   3380 	csock = listen_tcp(cport, htonl(INADDR_LOOPBACK), 1);
   3381 
   3382 	if (csock < 0) {
   3383 		rfbLog("SSL: accept_openssl: could not listen on port %d.\n",
   3384 		    cport);
   3385 		close(sock);
   3386 		if (mode == OPENSSL_INETD || ssl_no_fail) {
   3387 			clean_up_exit(1);
   3388 		}
   3389 		return;
   3390 	}
   3391 	if (db) fprintf(stderr, "accept_openssl: csock: %d\n", csock);
   3392 
   3393 	fflush(stderr);
   3394 
   3395 	/*
   3396 	 * make a simple cookie to id the child socket, not foolproof
   3397 	 * but hard to guess exactly (just worrying about local lusers
   3398 	 * here, since we use INADDR_LOOPBACK).
   3399 	 */
   3400 	rb = (unsigned char *) calloc(6, 1);
   3401 #if LIBVNCSERVER_HAVE_LIBSSL
   3402 	RAND_bytes(rb, 6);
   3403 #endif
   3404 	sprintf(cookie, "RB=%d%d%d%d%d%d/%f%f/%p",
   3405 	    rb[0], rb[1], rb[2], rb[3], rb[4], rb[5],
   3406             dnow() - x11vnc_start, x11vnc_start, (void *)rb);
   3407 
   3408 	if (mode == OPENSSL_VNC6) {
   3409 		name = strdup(ipv6_name);
   3410 		peerport = get_remote_port(sock);
   3411 	} else if (mode == OPENSSL_REVERSE && ipv6_name != NULL) {
   3412 		name = strdup(ipv6_name);
   3413 		peerport = get_remote_port(sock);
   3414 	} else if (mode != OPENSSL_INETD) {
   3415 		name = get_remote_host(sock);
   3416 		peerport = get_remote_port(sock);
   3417 	} else {
   3418 		openssl_last_ip = get_remote_host(fileno(stdin));
   3419 		peerport = get_remote_port(fileno(stdin));
   3420 		if (openssl_last_ip) {
   3421 			name = strdup(openssl_last_ip);
   3422 		} else {
   3423 			name = strdup("unknown");
   3424 		}
   3425 	}
   3426 	if (name) {
   3427 		if (mode == OPENSSL_INETD) {
   3428 			rfbLog("SSL: (inetd) spawning helper process "
   3429 			    "to handle: %s:%d\n", name, peerport);
   3430 		} else {
   3431 			rfbLog("SSL: spawning helper process to handle: "
   3432 			    "%s:%d\n", name, peerport);
   3433 		}
   3434 		free(name);
   3435 		name = NULL;
   3436 	}
   3437 
   3438 	if (certret) {
   3439 		free(certret);
   3440 	}
   3441 	if (certret_str) {
   3442 		free(certret_str);
   3443 		certret_str = NULL;
   3444 	}
   3445 	certret = strdup("/tmp/x11vnc-certret.XXXXXX");
   3446 	omode = umask(077);
   3447 	certret_fd = mkstemp(certret);
   3448 	umask(omode);
   3449 	if (certret_fd < 0) {
   3450 		free(certret);
   3451 		certret = NULL;
   3452 		certret_fd = -1;
   3453 	}
   3454 
   3455 	if (dhret) {
   3456 		free(dhret);
   3457 	}
   3458 	if (dhret_str) {
   3459 		free(dhret_str);
   3460 		dhret_str = NULL;
   3461 	}
   3462 	dhret = strdup("/tmp/x11vnc-dhret.XXXXXX");
   3463 	omode = umask(077);
   3464 	dhret_fd = mkstemp(dhret);
   3465 	umask(omode);
   3466 	if (dhret_fd < 0) {
   3467 		free(dhret);
   3468 		dhret = NULL;
   3469 		dhret_fd = -1;
   3470 	}
   3471 
   3472 	/* now fork the child to handle the SSL: */
   3473 	pid = fork();
   3474 
   3475 	if (pid > 0) {
   3476 		rfbLog("SSL: helper for peerport %d is pid %d: \n",
   3477 		    peerport, (int) pid);
   3478 	}
   3479 
   3480 	if (pid < 0) {
   3481 		rfbLog("SSL: accept_openssl: could not fork.\n");
   3482 		rfbLogPerror("fork");
   3483 		close(sock);
   3484 		close(csock);
   3485 		if (mode == OPENSSL_INETD || ssl_no_fail) {
   3486 			clean_up_exit(1);
   3487 		}
   3488 		return;
   3489 
   3490 	} else if (pid == 0) {
   3491 		int s_in, s_out, httpsock = -1;
   3492 		int vncsock;
   3493 		int i, have_httpd = 0;
   3494 		int f_in  = fileno(stdin);
   3495 		int f_out = fileno(stdout);
   3496 		int skip_vnc_tls = mode == OPENSSL_HTTPS ? 1 : 0;
   3497 
   3498 		if (db) fprintf(stderr, "helper pid in: %d %d %d %d\n", f_in, f_out, sock, listen);
   3499 
   3500 		/* reset all handlers to default (no interrupted() calls) */
   3501 		unset_signals();
   3502 
   3503 		/* close all non-essential fd's */
   3504 		for (i=0; i<256; i++) {
   3505 			if (mode == OPENSSL_INETD) {
   3506 				if (i == f_in || i == f_out) {
   3507 					continue;
   3508 				}
   3509 			}
   3510 			if (i == sock) {
   3511 				continue;
   3512 			}
   3513 			if (i == 2) {
   3514 				continue;
   3515 			}
   3516 			close(i);
   3517 		}
   3518 
   3519 		/*
   3520 		 * sadly, we are a long lived child and so the large
   3521 		 * framebuffer memory areas will soon differ from parent.
   3522 		 * try to free as much as possible.
   3523 		 */
   3524 		lose_ram();
   3525 
   3526 		/* now connect back to parent socket: */
   3527 		vncsock = connect_tcp("127.0.0.1", cport);
   3528 		if (vncsock < 0) {
   3529 			rfbLog("SSL: ssl_helper[%d]: could not connect"
   3530 			    " back to: %d\n", getpid(), cport);
   3531 			rfbLog("SSL: ssl_helper[%d]: exit case 1 (no local vncsock)\n", getpid());
   3532 			exit(1);
   3533 		}
   3534 		if (db) fprintf(stderr, "vncsock %d\n", vncsock);
   3535 
   3536 		/* try to initialize SSL with the remote client */
   3537 
   3538 		if (mode == OPENSSL_INETD) {
   3539 			s_in  = fileno(stdin);
   3540 			s_out = fileno(stdout);
   3541 		} else {
   3542 			s_in = s_out = sock;
   3543 		}
   3544 
   3545 		if (! ssl_init(s_in, s_out, skip_vnc_tls, last_https)) {
   3546 			close(vncsock);
   3547 			rfbLog("SSL: ssl_helper[%d]: exit case 2 (ssl_init failed)\n", getpid());
   3548 			exit(1);
   3549 		}
   3550 
   3551 		if (vencrypt_selected != 0) {
   3552 			char *tbuf;
   3553 			tbuf = (char *) malloc(strlen(cookie) + 100);
   3554 			sprintf(tbuf, "%s,VENCRYPT=%d,%s", uniq, vencrypt_selected, cookie);
   3555 			write(vncsock, tbuf, strlen(cookie));
   3556 			goto wrote_cookie;
   3557 		} else if (anontls_selected != 0) {
   3558 			char *tbuf;
   3559 			tbuf = (char *) malloc(strlen(cookie) + 100);
   3560 			sprintf(tbuf, "%s,ANONTLS=%d,%s", uniq, anontls_selected, cookie);
   3561 			write(vncsock, tbuf, strlen(cookie));
   3562 			goto wrote_cookie;
   3563 		}
   3564 
   3565 		/*
   3566 		 * things get messy below since we are trying to do
   3567 		 * *both* VNC and Java applet httpd through the same
   3568 		 * SSL socket.
   3569 		 */
   3570 
   3571 		if (! screen) {
   3572 			close(vncsock);
   3573 			exit(1);
   3574 		}
   3575 		if (screen->httpListenSock >= 0 && screen->httpPort > 0) {
   3576 			have_httpd = 1;
   3577 		} else if (ipv6_http_fd >= 0) {
   3578 			have_httpd = 1;
   3579 		} else if (screen->httpListenSock == -2) {
   3580 			have_httpd = 1;
   3581 		}
   3582 		if (mode == OPENSSL_HTTPS && ! have_httpd) {
   3583 			rfbLog("SSL: accept_openssl[%d]: no httpd socket for "
   3584 			    "-https mode\n", getpid());
   3585 			close(vncsock);
   3586 			rfbLog("SSL: ssl_helper[%d]: exit case 3 (no httpd sock)\n", getpid());
   3587 			exit(1);
   3588 		}
   3589 
   3590 		if (have_httpd) {
   3591 			int n = 0, is_http = 0;
   3592 			int hport = screen->httpPort;
   3593 			char *iface = NULL;
   3594 			char *buf, *tbuf;
   3595 
   3596 			buf  = (char *) calloc((ABSIZE+1), 1);
   3597 			tbuf = (char *) calloc((2*ABSIZE+1), 1);
   3598 
   3599 			if (mode == OPENSSL_HTTPS) {
   3600 				/*
   3601 				 * for this mode we know it is HTTP traffic
   3602 				 * so we skip trying to guess.
   3603 				 */
   3604 				is_http = 1;
   3605 				n = 0;
   3606 				goto connect_to_httpd;
   3607 			}
   3608 
   3609 			/*
   3610 			 * Check if there is stuff to read from remote end
   3611 			 * if so it is likely a GET or HEAD.
   3612 			 */
   3613 			if (! is_ssl_readable(s_in, last_https, last_get,
   3614 			    mode)) {
   3615 				goto write_cookie;
   3616 			}
   3617 
   3618 			/*
   3619 			 * read first 2 bytes to try to guess.  sadly,
   3620 			 * the user is often pondering a "non-verified
   3621 			 * cert" dialog for a long time before the GET
   3622 			 * is ever sent.  So often we timeout here.
   3623 			 */
   3624 
   3625 			if (db) fprintf(stderr, "watch_for_http_traffic\n");
   3626 
   3627 			is_http = watch_for_http_traffic(buf, &n, s_in);
   3628 
   3629 			if (is_http < 0 || is_http == 0) {
   3630 				/*
   3631 				 * error or http not detected, fall back
   3632 				 * to normal VNC socket.
   3633 				 */
   3634 				if (db) fprintf(stderr, "is_http err: %d n: %d\n", is_http, n);
   3635 				write(vncsock, cookie, strlen(cookie));
   3636 				if (n > 0) {
   3637 					write(vncsock, buf, n);
   3638 				}
   3639 				goto wrote_cookie;
   3640 			}
   3641 
   3642 			if (db) fprintf(stderr, "is_http: %d n: %d\n",
   3643 			    is_http, n);
   3644 			if (db) fprintf(stderr, "buf: '%s'\n", buf);
   3645 
   3646 			if (strstr(buf, "/request.https.vnc.connection")) {
   3647 				char reply[] = "HTTP/1.0 200 OK\r\n"
   3648 				    "Content-Type: octet-stream\r\n"
   3649 				    "Connection: Keep-Alive\r\n"
   3650 				    "VNC-Server: x11vnc\r\n"
   3651 				    "Pragma: no-cache\r\n\r\n";
   3652 				/*
   3653 				 * special case proxy coming thru https
   3654 				 * instead of a direct SSL connection.
   3655 				 */
   3656 				rfbLog("Handling VNC request via https GET. [%d]\n", getpid());
   3657 				rfbLog("-- %s\n", buf);
   3658 
   3659 				if (strstr(buf, "/reverse.proxy")) {
   3660 					char *buf2;
   3661 					int n, ptr;
   3662 #if !LIBVNCSERVER_HAVE_LIBSSL
   3663 					write(s_out, reply, strlen(reply));
   3664 #else
   3665 					SSL_write(ssl, reply, strlen(reply));
   3666 #endif
   3667 
   3668 					buf2  = (char *) calloc((8192+1), 1);
   3669 					n = 0;
   3670 					ptr = 0;
   3671 					while (ptr < 8192) {
   3672 #if !LIBVNCSERVER_HAVE_LIBSSL
   3673 						n = read(s_in, buf2 + ptr, 1);
   3674 #else
   3675 						n = SSL_read(ssl, buf2 + ptr, 1);
   3676 #endif
   3677 						if (n > 0) {
   3678 							ptr += n;
   3679 						}
   3680 						if (db) fprintf(stderr, "buf2: '%s'\n", buf2);
   3681 
   3682 						if (strstr(buf2, "\r\n\r\n")) {
   3683 							break;
   3684 						}
   3685 					}
   3686 					free(buf2);
   3687 				}
   3688 				goto write_cookie;
   3689 
   3690 			} else if (strstr(buf, "/check.https.proxy.connection")) {
   3691 				char reply[] = "HTTP/1.0 200 OK\r\n"
   3692 				    "Connection: close\r\n"
   3693 				    "Content-Type: octet-stream\r\n"
   3694 				    "VNC-Server: x11vnc\r\n"
   3695 				    "Pragma: no-cache\r\n\r\n";
   3696 
   3697 				rfbLog("Handling Check HTTPS request via https GET. [%d]\n", getpid());
   3698 				rfbLog("-- %s\n", buf);
   3699 
   3700 #if !LIBVNCSERVER_HAVE_LIBSSL
   3701 				write(s_out, reply, strlen(reply));
   3702 #else
   3703 				SSL_write(ssl, reply, strlen(reply));
   3704 				SSL_shutdown(ssl);
   3705 #endif
   3706 
   3707 				strcpy(tbuf, uniq);
   3708 				strcat(tbuf, cookie);
   3709 				write(vncsock, tbuf, strlen(tbuf));
   3710 				close(vncsock);
   3711 
   3712 				rfbLog("SSL: ssl_helper[%d]: exit case 4 (check.https.proxy.connection)\n", getpid());
   3713 				exit(0);
   3714 			}
   3715 			connect_to_httpd:
   3716 
   3717 			/*
   3718 			 * Here we go... no turning back.  we have to
   3719 			 * send failure to parent and close socket to have
   3720 			 * http processed at all in a timely fashion...
   3721 			 */
   3722 
   3723 			/* send the failure tag: */
   3724 			strcpy(tbuf, uniq);
   3725 
   3726 			if (https_port_redir < 0 || (strstr(buf, "PORT=") || strstr(buf, "port="))) {
   3727 				char *q = strstr(buf, "Host:");
   3728 				int fport = 443, match = 0;
   3729 				char num[16];
   3730 
   3731 				if (q && strstr(q, "\n")) {
   3732 				    q += strlen("Host:") + 1;
   3733 				    while (*q != '\n') {
   3734 					int p;
   3735 					if (*q == ':' && sscanf(q, ":%d", &p) == 1) {
   3736 						if (p > 0 && p < 65536) {
   3737 							fport = p;
   3738 							match = 1;
   3739 							break;
   3740 						}
   3741 					}
   3742 					q++;
   3743 				    }
   3744 				}
   3745 				if (!match || !https_port_redir) {
   3746 					int p;
   3747 					if (sscanf(buf, "PORT=%d,", &p) == 1) {
   3748 						if (p > 0 && p < 65536) {
   3749 							fport = p;
   3750 						}
   3751 					} else if (sscanf(buf, "port=%d,", &p) == 1) {
   3752 						if (p > 0 && p < 65536) {
   3753 							fport = p;
   3754 						}
   3755 					}
   3756 				}
   3757 				sprintf(num, "HP=%d,", fport);
   3758 				strcat(tbuf, num);
   3759 			}
   3760 
   3761 			if (strstr(buf, "HTTP/") != NULL)  {
   3762 				char *q, *str;
   3763 				/*
   3764 				 * Also send back the GET line for heuristics.
   3765 				 * (last_https, get file).
   3766 				 */
   3767 				str = strdup(buf);
   3768 				q = strstr(str, "HTTP/");
   3769 				if (q != NULL) {
   3770 					*q = '\0';
   3771 					strcat(tbuf, str);
   3772 				}
   3773 				free(str);
   3774 			}
   3775 
   3776 			/*
   3777 			 * Also send the cookie to pad out the number of
   3778 			 * bytes to more than the parent wants to read.
   3779 			 * Since this is the failure case, it does not
   3780 			 * matter that we send more than strlen(cookie).
   3781 			 */
   3782 			strcat(tbuf, cookie);
   3783 			write(vncsock, tbuf, strlen(tbuf));
   3784 
   3785 			usleep(150*1000);
   3786 			if (db) fprintf(stderr, "close vncsock: %d\n", vncsock);
   3787 			close(vncsock);
   3788 
   3789 			/* now, finally, connect to the libvncserver httpd: */
   3790 			if (screen->listenInterface == htonl(INADDR_ANY) ||
   3791 			    screen->listenInterface == htonl(INADDR_NONE)) {
   3792 				iface = "127.0.0.1";
   3793 			} else {
   3794 				struct in_addr in;
   3795 				in.s_addr = screen->listenInterface;
   3796 				iface = inet_ntoa(in);
   3797 			}
   3798 			if (iface == NULL || !strcmp(iface, "")) {
   3799 				iface = "127.0.0.1";
   3800 			}
   3801 			if (db) fprintf(stderr, "iface: %s:%d\n", iface, hport);
   3802 			usleep(150*1000);
   3803 
   3804 			httpsock = connect_tcp(iface, hport);
   3805 
   3806 			if (httpsock < 0) {
   3807 				/* UGH, after all of that! */
   3808 				rfbLog("Could not connect to httpd socket!\n");
   3809 				rfbLog("SSL: ssl_helper[%d]: exit case 5.\n", getpid());
   3810 				exit(1);
   3811 			}
   3812 			if (db) fprintf(stderr, "ssl_helper[%d]: httpsock: %d %d\n",
   3813 			    getpid(), httpsock, n);
   3814 
   3815 			/*
   3816 			 * send what we read to httpd, and then connect
   3817 			 * the rest of the SSL session to it:
   3818 			 */
   3819 			if (n > 0) {
   3820 				char *s = getenv("X11VNC_EXTRA_HTTPS_PARAMS");
   3821 				int did_extra = 0;
   3822 
   3823 				if (db) fprintf(stderr, "sending http buffer httpsock: %d n=%d\n'%s'\n", httpsock, n, buf);
   3824 				if (s != NULL) {
   3825 					char *q = strstr(buf, " HTTP/");
   3826 					if (q) {
   3827 						int m;
   3828 						*q = '\0';
   3829 						m = strlen(buf);
   3830 						write(httpsock, buf, m);
   3831 						write(httpsock, s, strlen(s));
   3832 						*q = ' ';
   3833 						write(httpsock, q, n-m);
   3834 						did_extra = 1;
   3835 					}
   3836 				}
   3837 				if (!did_extra) {
   3838 					write(httpsock, buf, n);
   3839 				}
   3840 			}
   3841 			ssl_xfer(httpsock, s_in, s_out, is_http);
   3842 			rfbLog("SSL: ssl_helper[%d]: exit case 6 (https ssl_xfer done)\n", getpid());
   3843 			exit(0);
   3844 		}
   3845 
   3846 		/*
   3847 		 * ok, back from the above https mess, simply send the
   3848 		 * cookie back to the parent (who will attach us to
   3849 		 * libvncserver), and connect the rest of the SSL session
   3850 		 * to it.
   3851 		 */
   3852 		write_cookie:
   3853 		write(vncsock, cookie, strlen(cookie));
   3854 
   3855 		wrote_cookie:
   3856 		ssl_xfer(vncsock, s_in, s_out, 0);
   3857 		rfbLog("SSL: ssl_helper[%d]: exit case 7 (ssl_xfer done)\n", getpid());
   3858 		if (0) usleep(50 * 1000);
   3859 		exit(0);
   3860 	}
   3861 	/* parent here */
   3862 
   3863 	if (mode != OPENSSL_INETD) {
   3864 		close(sock);
   3865 	}
   3866 	if (db) fprintf(stderr, "helper process is: %d\n", pid);
   3867 
   3868 	/* accept connection from our child.  */
   3869 	signal(SIGALRM, csock_timeout);
   3870 	csock_timeout_sock = csock;
   3871 	alarm(20);
   3872 
   3873 	vsock = accept(csock, (struct sockaddr *)&addr, &addrlen);
   3874 
   3875 	alarm(0);
   3876 	signal(SIGALRM, SIG_DFL);
   3877 	close(csock);
   3878 
   3879 
   3880 	if (vsock < 0) {
   3881 		rfbLog("SSL: accept_openssl: connection from ssl_helper[%d] FAILED.\n", pid);
   3882 		rfbLogPerror("accept");
   3883 
   3884 		kill(pid, SIGTERM);
   3885 		waitpid(pid, &status, WNOHANG);
   3886 		if (mode == OPENSSL_INETD || ssl_no_fail) {
   3887 			clean_up_exit(1);
   3888 		}
   3889 		if (certret_fd >= 0) {
   3890 			close(certret_fd);
   3891 			certret_fd = -1;
   3892 		}
   3893 		if (certret) {
   3894 			unlink(certret);
   3895 		}
   3896 		if (dhret_fd >= 0) {
   3897 			close(dhret_fd);
   3898 			dhret_fd = -1;
   3899 		}
   3900 		if (dhret) {
   3901 			unlink(dhret);
   3902 		}
   3903 		return;
   3904 	}
   3905 	if (db) fprintf(stderr, "accept_openssl: vsock: %d\n", vsock);
   3906 
   3907 	n = read(vsock, rcookie, strlen(cookie));
   3908 	if (n < 0 && errno != 0) {
   3909 		rfbLogPerror("read");
   3910 	}
   3911 
   3912 	if (certret) {
   3913 		struct stat sbuf;
   3914 		sbuf.st_size = 0;
   3915 		if (certret_fd >= 0 && stat(certret, &sbuf) == 0 && sbuf.st_size > 0) {
   3916 			certret_str = (char *) calloc(sbuf.st_size+1, 1);
   3917 			read(certret_fd, certret_str, sbuf.st_size);
   3918 			close(certret_fd);
   3919 			certret_fd = -1;
   3920 		}
   3921 		if (certret_fd >= 0) {
   3922 			close(certret_fd);
   3923 			certret_fd = -1;
   3924 		}
   3925 		unlink(certret);
   3926 		if (certret_str && strstr(certret_str, "NOCERT") == certret_str) {
   3927 			free(certret_str);
   3928 			certret_str = NULL;
   3929 		}
   3930 		if (0 && certret_str) {
   3931 			fprintf(stderr, "certret_str[%d]:\n%s\n", (int) sbuf.st_size, certret_str);
   3932 		}
   3933 	}
   3934 
   3935 	if (dhret) {
   3936 		struct stat sbuf;
   3937 		sbuf.st_size = 0;
   3938 		if (dhret_fd >= 0 && stat(dhret, &sbuf) == 0 && sbuf.st_size > 0) {
   3939 			dhret_str = (char *) calloc(sbuf.st_size+1, 1);
   3940 			read(dhret_fd, dhret_str, sbuf.st_size);
   3941 			close(dhret_fd);
   3942 			dhret_fd = -1;
   3943 		}
   3944 		if (dhret_fd >= 0) {
   3945 			close(dhret_fd);
   3946 			dhret_fd = -1;
   3947 		}
   3948 		unlink(dhret);
   3949 		if (dhret_str && strstr(dhret_str, "NOCERT") == dhret_str) {
   3950 			free(dhret_str);
   3951 			dhret_str = NULL;
   3952 		}
   3953 		if (dhret_str) {
   3954 			if (new_dh_params == NULL) {
   3955 				fprintf(stderr, "dhret_str[%d]:\n%s\n", (int) sbuf.st_size, dhret_str);
   3956 				new_dh_params = strdup(dhret_str);
   3957 			}
   3958 		}
   3959 	}
   3960 
   3961 	if (0) {
   3962 		fprintf(stderr, "rcookie: %s\n", rcookie);
   3963 		fprintf(stderr, "cookie:  %s\n", cookie);
   3964 	}
   3965 
   3966 	if (strstr(rcookie, uniq) == rcookie) {
   3967 		char *q = strstr(rcookie, "RB=");
   3968 		if (q && strstr(cookie, q) == cookie) {
   3969 			vencrypt_sel = 0;
   3970 			anontls_sel = 0;
   3971 			q = strstr(rcookie, "VENCRYPT=");
   3972 			if (q && sscanf(q, "VENCRYPT=%d,", &vencrypt_sel) == 1) {
   3973 				if (vencrypt_sel != 0) {
   3974 					rfbLog("SSL: VENCRYPT mode=%d accepted. helper[%d]\n", vencrypt_sel, pid);
   3975 					goto accept_client;
   3976 				}
   3977 			}
   3978 			q = strstr(rcookie, "ANONTLS=");
   3979 			if (q && sscanf(q, "ANONTLS=%d,", &anontls_sel) == 1) {
   3980 				if (anontls_sel != 0) {
   3981 					rfbLog("SSL: ANONTLS mode=%d accepted. helper[%d]\n", anontls_sel, pid);
   3982 					goto accept_client;
   3983 				}
   3984 			}
   3985 		}
   3986 	}
   3987 
   3988 	if (n != (int) strlen(cookie) || strncmp(cookie, rcookie, n)) {
   3989 		rfbLog("SSL: accept_openssl: cookie from ssl_helper[%d] FAILED. %d\n", pid, n);
   3990 		if (db) fprintf(stderr, "'%s'\n'%s'\n", cookie, rcookie);
   3991 		close(vsock);
   3992 
   3993 		if (strstr(rcookie, uniq) == rcookie) {
   3994 			int i;
   3995 			double https_download_wait_time = 15.0;
   3996 
   3997 			if (getenv("X11VNC_HTTPS_DOWNLOAD_WAIT_TIME")) {
   3998 				https_download_wait_time = atof(getenv("X11VNC_HTTPS_DOWNLOAD_WAIT_TIME"));
   3999 			}
   4000 
   4001 			rfbLog("SSL: BUT WAIT! HTTPS for helper process[%d] succeeded. Good.\n", pid);
   4002 			if (mode != OPENSSL_HTTPS) {
   4003 				last_https = dnow();
   4004 				for (i=0; i<256; i++) {
   4005 					last_get[i] = '\0';
   4006 				}
   4007 				strncpy(last_get, rcookie, 100);
   4008 				if (db) fprintf(stderr, "last_get: '%s'\n", last_get);
   4009 			}
   4010 			if (rcookie && strstr(rcookie, "VncViewer.class")) {
   4011 				rfbLog("\n");
   4012 				rfbLog("helper[%d]:\n", pid);
   4013 				rfbLog("***********************************************************\n");
   4014 				rfbLog("SSL: WARNING CLIENT ASKED FOR NONEXISTENT 'VncViewer.class'\n");
   4015 				rfbLog("SSL: USER NEEDS TO MAKE SURE THE JAVA PLUGIN IS INSTALLED\n");
   4016 				rfbLog("SSL: AND WORKING PROPERLY (e.g. a test-java-plugin page.)\n");
   4017 				rfbLog("SSL: AND/OR USER NEEDS TO **RESTART** HIS WEB BROWSER.\n");
   4018 				rfbLog("SSL: SOMETIMES THE BROWSER 'REMEMBERS' FAILED APPLET DOWN-\n");
   4019 				rfbLog("SSL: LOADS AND RESTARTING IT IS THE ONLY WAY TO FIX THINGS.\n");
   4020 				rfbLog("***********************************************************\n");
   4021 				rfbLog("\n");
   4022 			}
   4023 			ssl_helper_pid(pid, -2);
   4024 
   4025 			if (https_port_redir) {
   4026 				double start;
   4027 				int origport = screen->port;
   4028 				int useport = screen->port;
   4029 				int saw_httpsock = 0;
   4030 				/* to expand $PORT correctly in index.vnc */
   4031 				if (https_port_redir < 0) {
   4032 					char *q = strstr(rcookie, "HP=");
   4033 					if (q) {
   4034 						int p;
   4035 						if (sscanf(q, "HP=%d,", &p) == 1) {
   4036 							useport = p;
   4037 						}
   4038 					}
   4039 				} else {
   4040 					useport = https_port_redir;
   4041 				}
   4042 				screen->port = useport;
   4043 				if (origport != useport) {
   4044 					rfbLog("SSL: -httpsredir guess port: %d  helper[%d]\n", screen->port, pid);
   4045 				}
   4046 
   4047 				start = dnow();
   4048 				while (dnow() < start + https_download_wait_time) {
   4049 					if (screen->httpSock >= 0) saw_httpsock = 1;
   4050 					rfbPE(10000);
   4051 					usleep(10000);
   4052 					if (screen->httpSock >= 0) saw_httpsock = 1;
   4053 					waitpid(pid, &status, WNOHANG);
   4054 					if (kill(pid, 0) != 0) {
   4055 						rfbLog("SSL: helper[%d] pid finished\n", pid);
   4056 						break;
   4057 					}
   4058 					if (0 && saw_httpsock && screen->httpSock < 0) {
   4059 						/* this check can kill the helper too soon. */
   4060 						rfbLog("SSL: httpSock for helper[%d] went away\n", pid);
   4061 						break;
   4062 					}
   4063 				}
   4064 				rfbLog("SSL: guessing child helper[%d] https finished. dt=%.6f\n",
   4065 				    pid, dnow() - start);
   4066 
   4067 				rfbPE(10000);
   4068 				rfbPE(10000);
   4069 				rfbPE(10000);
   4070 
   4071 				screen->port = origport;
   4072 				ssl_helper_pid(0, -2);
   4073 				if (mode == OPENSSL_INETD) {
   4074 					clean_up_exit(1);
   4075 				}
   4076 			} else if (mode == OPENSSL_INETD) {
   4077 				double start;
   4078 				int saw_httpsock = 0;
   4079 
   4080 				/* to expand $PORT correctly in index.vnc */
   4081 				if (screen->port == 0) {
   4082 					int fd = fileno(stdin);
   4083 					if (getenv("X11VNC_INETD_PORT")) {
   4084 						/* mutex */
   4085 						screen->port = atoi(getenv(
   4086 						    "X11VNC_INETD_PORT"));
   4087 					} else {
   4088 						int tport = get_local_port(fd);
   4089 						if (tport > 0) {
   4090 							screen->port = tport;
   4091 						}
   4092 					}
   4093 				}
   4094 				rfbLog("SSL: screen->port %d for helper[%d]\n", screen->port, pid);
   4095 
   4096 				/* kludge for https fetch via inetd */
   4097 				start = dnow();
   4098 				while (dnow() < start + https_download_wait_time) {
   4099 					if (screen->httpSock >= 0) saw_httpsock = 1;
   4100 					rfbPE(10000);
   4101 					usleep(10000);
   4102 					if (screen->httpSock >= 0) saw_httpsock = 1;
   4103 					waitpid(pid, &status, WNOHANG);
   4104 					if (kill(pid, 0) != 0) {
   4105 						rfbLog("SSL: helper[%d] pid finished\n", pid);
   4106 						break;
   4107 					}
   4108 					if (0 && saw_httpsock && screen->httpSock < 0) {
   4109 						/* this check can kill the helper too soon. */
   4110 						rfbLog("SSL: httpSock for helper[%d] went away\n", pid);
   4111 						break;
   4112 					}
   4113 				}
   4114 				rfbLog("SSL: OPENSSL_INETD guessing "
   4115 				    "child helper[%d] https finished. dt=%.6f\n",
   4116 				    pid, dnow() - start);
   4117 
   4118 				rfbPE(10000);
   4119 				rfbPE(10000);
   4120 				rfbPE(10000);
   4121 
   4122 				ssl_helper_pid(0, -2);
   4123 				clean_up_exit(1);
   4124 			}
   4125 			/* this will actually only get earlier https */
   4126 			ssl_helper_pid(0, -2);
   4127 			return;
   4128 		}
   4129 		kill(pid, SIGTERM);
   4130 		waitpid(pid, &status, WNOHANG);
   4131 		if (mode == OPENSSL_INETD || ssl_no_fail) {
   4132 			clean_up_exit(1);
   4133 		}
   4134 		return;
   4135 	}
   4136 
   4137 	accept_client:
   4138 
   4139 	if (db) fprintf(stderr, "accept_openssl: cookie good: %s\n", cookie);
   4140 
   4141 	rfbLog("SSL: handshake with helper process[%d] succeeded.\n", pid);
   4142 
   4143 	openssl_last_helper_pid = pid;
   4144 	ssl_helper_pid(pid, vsock);
   4145 
   4146 	if (vnc_redirect) {
   4147 		vnc_redirect_sock = vsock;
   4148 		openssl_last_helper_pid = 0;
   4149 		return;
   4150 	}
   4151 
   4152 	client = create_new_client(vsock, 0);
   4153 	openssl_last_helper_pid = 0;
   4154 
   4155 	if (client) {
   4156 		int swt = 0;
   4157 		if (mode == OPENSSL_VNC6 && openssl_last_ip != NULL) {
   4158 			swt = 1;
   4159 		} else if (mode == OPENSSL_REVERSE && ipv6_name != NULL && openssl_last_ip != NULL) {
   4160 			swt = 1;
   4161 		}
   4162 		if (swt) {
   4163 			if (client->host) {
   4164 				free(client->host);
   4165 			}
   4166 			client->host = strdup(openssl_last_ip);
   4167 		}
   4168 		if (db) fprintf(stderr, "accept_openssl: client %p\n", (void *) client);
   4169 		if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) screen->newClientHook);
   4170 		if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) new_client);
   4171 		if (mode == OPENSSL_INETD) {
   4172 			inetd_client = client;
   4173 			client->clientGoneHook = client_gone;
   4174 		}
   4175 		if (openssl_last_ip &&
   4176 		    strpbrk(openssl_last_ip, "0123456789") == openssl_last_ip) {
   4177 			client->host = strdup(openssl_last_ip);
   4178 		}
   4179 		if (vencrypt_sel != 0) {
   4180 			client->protocolMajorVersion = 3;
   4181 			client->protocolMinorVersion = 8;
   4182 #if LIBVNCSERVER_HAVE_LIBSSL
   4183 			if (!finish_vencrypt_auth(client, vencrypt_sel)) {
   4184 				rfbCloseClient(client);
   4185 				client = NULL;
   4186 			}
   4187 #else
   4188 			badnews("3 accept_openssl");
   4189 #endif
   4190 		} else if (anontls_sel != 0) {
   4191 			client->protocolMajorVersion = 3;
   4192 			client->protocolMinorVersion = 8;
   4193 			rfbAuthNewClient(client);
   4194 		}
   4195 		if (use_threads && client != NULL) {
   4196 			rfbStartOnHoldClient(client);
   4197 		}
   4198 		/* try to get RFB proto done now. */
   4199 		progress_client();
   4200 	} else {
   4201 		rfbLog("SSL: accept_openssl: rfbNewClient failed.\n");
   4202 		close(vsock);
   4203 
   4204 		kill(pid, SIGTERM);
   4205 		waitpid(pid, &status, WNOHANG);
   4206 		if (mode == OPENSSL_INETD || ssl_no_fail) {
   4207 			clean_up_exit(1);
   4208 		}
   4209 		return;
   4210 	}
   4211 }
   4212 
   4213 void raw_xfer(int csock, int s_in, int s_out) {
   4214 	char buf0[8192];
   4215 	int sz = 8192, n, m, status, db = 1;
   4216 	char *buf;
   4217 #ifdef FORK_OK
   4218 	pid_t par = getpid();
   4219 	pid_t pid = fork();
   4220 
   4221 	buf = buf0;
   4222 	if (vnc_redirect) {
   4223 		/* change buf size some direction. */
   4224 	}
   4225 
   4226 	if (getenv("X11VNC_DEBUG_RAW_XFER")) {
   4227 		db = atoi(getenv("X11VNC_DEBUG_RAW_XFER"));
   4228 	}
   4229 	if (pid < 0) {
   4230 		exit(1);
   4231 	}
   4232 	/* this is for testing or special helper usage, no SSL just socket redir */
   4233 	if (pid) {
   4234 		if (db) rfbLog("raw_xfer start: %d -> %d/%d\n", csock, s_in, s_out);
   4235 
   4236 		while (1) {
   4237 			n = read(csock, buf, sz);
   4238 			if (n == 0 || (n < 0 && errno != EINTR) ) {
   4239 				break;
   4240 			} else if (n > 0) {
   4241 				int len = n;
   4242 				char *src = buf;
   4243 				if (db > 1) write(2, buf, n);
   4244 				while (len > 0) {
   4245 					m = write(s_out, src, len);
   4246 					if (m > 0) {
   4247 						src += m;
   4248 						len -= m;
   4249 						continue;
   4250 					}
   4251 					if (m < 0 && (errno == EINTR || errno == EAGAIN)) {
   4252 						continue;
   4253 					}
   4254 if (db) rfbLog("raw_xfer bad write:  %d -> %d | %d/%d  errno=%d\n", csock, s_out, m, n, errno);
   4255 					break;
   4256 				}
   4257 			}
   4258 		}
   4259 		usleep(250*1000);
   4260 		kill(pid, SIGTERM);
   4261 		waitpid(pid, &status, WNOHANG);
   4262 		if (db) rfbLog("raw_xfer done:  %d -> %d\n", csock, s_out);
   4263 
   4264 	} else {
   4265 		if (db) usleep(50*1000);
   4266 		if (db) rfbLog("raw_xfer start: %d <- %d\n", csock, s_in);
   4267 
   4268 		while (1) {
   4269 			n = read(s_in, buf, sz);
   4270 			if (n == 0 || (n < 0 && errno != EINTR) ) {
   4271 				break;
   4272 			} else if (n > 0) {
   4273 				int len = n;
   4274 				char *src = buf;
   4275 				if (db > 1) write(2, buf, n);
   4276 				while (len > 0) {
   4277 					m = write(csock, src, len);
   4278 					if (m > 0) {
   4279 						src += m;
   4280 						len -= m;
   4281 						continue;
   4282 					}
   4283 					if (m < 0 && (errno == EINTR || errno == EAGAIN)) {
   4284 						continue;
   4285 					}
   4286 		if (db) rfbLog("raw_xfer bad write:  %d <- %d | %d/%d errno=%d\n", csock, s_in, m, n, errno);
   4287 					break;
   4288 				}
   4289 			}
   4290 		}
   4291 		usleep(250*1000);
   4292 		kill(par, SIGTERM);
   4293 		waitpid(par, &status, WNOHANG);
   4294 		if (db) rfbLog("raw_xfer done:  %d <- %d\n", csock, s_in);
   4295 	}
   4296 	close(csock);
   4297 	close(s_in);
   4298 	close(s_out);
   4299 #endif	/* FORK_OK */
   4300 }
   4301 
   4302 /* compile with -DENC_HAVE_OPENSSL=0 to disable enc stuff but still have ssl */
   4303 
   4304 #define ENC_MODULE
   4305 
   4306 #if LIBVNCSERVER_HAVE_LIBSSL
   4307 #ifndef ENC_HAVE_OPENSSL
   4308 #define ENC_HAVE_OPENSSL 1
   4309 #endif
   4310 #else
   4311 #define ENC_HAVE_OPENSSL 0
   4312 #endif
   4313 
   4314 #define ENC_DISABLE_SHOW_CERT
   4315 
   4316 #include "enc.h"
   4317 
   4318 static void symmetric_encryption_xfer(int csock, int s_in, int s_out) {
   4319 	char tmp[100];
   4320 	char *cipher, *keyfile, *q;
   4321 
   4322 	if (! enc_str) {
   4323 		return;
   4324 	}
   4325 	cipher = (char *) malloc(strlen(enc_str) + 100);
   4326 	q = strchr(enc_str, ':');
   4327 	if (!q) return;
   4328 	*q = '\0';
   4329 	if (getenv("X11VNC_USE_ULTRADSM_IV")) {
   4330 		sprintf(cipher, "rev:%s", enc_str);
   4331 	} else {
   4332 		sprintf(cipher, "noultra:rev:%s", enc_str);
   4333 	}
   4334 	keyfile = strdup(q+1);
   4335 	*q = ':';
   4336 
   4337 
   4338 	/* TBD: s_in != s_out */
   4339 	if (s_out) {}
   4340 
   4341 	sprintf(tmp, "fd=%d,%d", s_in, csock);
   4342 
   4343 	enc_do(cipher, keyfile, "-1", tmp);
   4344 }
   4345 
   4346