1 /*
2  * ultravnc_dsm_helper.c unix/openssl UltraVNC encryption encoder/decoder.
3  *                       (also a generic symmetric encryption tunnel)
4  *                       (also a generic TCP relay and supports IPv6)
5  *
6  * compile via:
7 
8    cc       -O -o ultravnc_dsm_helper ultravnc_dsm_helper.c -lssl -lcrypto
9    cc -DDBG -O -o ultravnc_dsm_helper ultravnc_dsm_helper.c -lssl -lcrypto
10 
11  *
12  * See usage below for how to run it.
13  *
14  * Note: since the UltraVNC DSM plugin implementation changes the RFB
15  * (aka VNC) protocol (extra data is sent), you will *ALSO* need to modify
16  * your VNC viewer or server to discard (or insert) this extra data.
17  *
18  * This tool knows nothing about the RFB protocol: it simply
19  * encrypts/decrypts a stream using a symmetric cipher, arc4 and aesv2,
20  * (others have been added, see usage).  It could be used as a general
21  * encrypted tunnel:
22  *
23  *   any-client <=> ultravnc_dsm_helper <--network--> ultravnc_dsm_helper(reverse mode) <=> any-server
24  *
25  * e.g. to connect a non-ultra-dsm-vnc viewer to a non-ultra-dsm-vnc server
26  * without using SSH or SSL.
27  *
28  * It can also be used as a general TCP relay (no encryption.)
29  *
30  * It supports IPv6 and so can also be used as a IPv6 gateway.
31  *
32  * -----------------------------------------------------------------------
33  * Copyright (C) 2008-2010 Karl J. Runge <runge@karlrunge.com>
34  * All rights reserved.
35  *
36  *  This is free software; you can redistribute it and/or modify
37  *  it under the terms of the GNU General Public License as published by
38  *  the Free Software Foundation; version 2 of the License, or (at
39  *  your option) any later version.
40  *
41  *  This software is distributed in the hope that it will be useful,
42  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
43  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44  *  GNU General Public License for more details.
45  *
46  *  You should have received a copy of the GNU General Public License
47  *  along with this software; if not, write to the Free Software
48  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
49  *  USA  or see <http://www.gnu.org/licenses/>.
50  *
51  *  In addition, as a special exception, Karl J. Runge gives permission
52  *  to link the code of its release of ultravnc_dsm_helper with the
53  *  OpenSSL project's "OpenSSL" library (or with modified versions of it
54  *  that use the same license as the "OpenSSL" library), and distribute
55  *  the linked executables.  You must obey the GNU General Public License
56  *  in all respects for all of the code used other than "OpenSSL".  If you
57  *  modify this file, you may extend this exception to your version of the
58  *  file, but you are not obligated to do so.  If you do not wish to do
59  *  so, delete this exception statement from your version.
60  * -----------------------------------------------------------------------
61  */
62 
63 static char *usage =
64     "\n"
65     "ultravnc_dsm_helper: a symmetric encryption tunnel. version 0.2\n"
66     "\n"
67     "       Created to enable encrypted VNC connections to UltraVNC, it can act as\n"
68     "       a general encrypted tunnel between any two applications.  It can also\n"
69     "       be used as a general TCP relay (i.e. no encryption) or an IPv6 gateway.\n"
70     "\n"
71     "Usage: ultravnc_dsm_helper cipher keyfile listenport remotehost:port\n"
72     "       ultravnc_dsm_helper relay listenport remotehost:port\n"
73     "       ultravnc_dsm_helper showcert remotehost:port\n"
74     "\n"
75     "e.g.:  ultravnc_dsm_helper arc4 ./arc4.key 5901 snoopy.net:5900\n"
76     "\n"
77     "       IPv6 is supported: both IPv4 and IPv6 are attempted to listen on (port\n"
78     "               'listenport'.)  For connections to remotehost, if IPv4 fails\n"
79     "               then IPv6 is tried.  Set the env. var ULTRAVNC_DSM_HELPER_NOIPV6\n"
80     "               to completely disable the use of IPv6.\n"
81     "\n"
82     "\n"
83     "       cipher: specify 'msrc4', 'msrc4_sc', 'arc4', 'aesv2', 'aes-cfb',\n"
84     "               'aes256', 'blowfish', '3des', 'securevnc'.\n"
85     "\n"
86     "               Also 'none', 'relay', or 'showcert'.  See below for details.\n"
87     "\n"
88     "         'msrc4_sc' enables a workaround for UVNC SC -plugin use.\n"
89     "            (it might not be required in SC circa 2009 and later; try 'msrc4'.)\n"
90     "\n"
91     "         use 'securevnc' for SecureVNCPlugin (RSA key exchange).  'keyfile' is\n"
92     "           used as a server RSA keystore in this mode.  If 'keyfile' does not\n"
93     "           exist the user is prompted whether to save the key or not (a MD5\n"
94     "           hash of it is shown)  If 'keyfile' already exists the server key\n"
95     "           must match its contents or the connection is dropped.\n"
96     "\n"
97     "           HOWEVER, if 'keyfile' ends in the string 'ClientAuth.pkey', then the\n"
98     "           normal SecureVNCPlugin client key authentication is performed.\n"
99     "           If you want to do both have 'keyfile' end with 'ClientAuth.pkey.rsa'\n"
100     "           that file will be used for the RSA keystore, and the '.rsa' will be\n"
101     "           trimmed off and the remaining name used as the Client Auth file.\n"
102     "\n"
103     "         use '.' to have it try to guess the cipher from the keyfile name,\n"
104     "           e.g. 'arc4.key' implies arc4, 'rc4.key' implies msrc4, etc.\n"
105     "\n"
106     "         use 'rev:arc4', etc. to reverse the roles of encrypter and decrypter.\n"
107     "           (i.e. if you want to use it for a vnc server, not vnc viewer)\n"
108     "\n"
109     "         use 'noultra:...' to skip steps involving salt and IV to try to be\n"
110     "           compatible with UltraVNC DSM, i.e. assume a normal symmetric cipher\n"
111     "           at the other end.\n"
112     "\n"
113     "         use 'noultra:rev:...' if both are to be supplied.\n"
114     "\n"
115     "\n"
116     "       keyfile: file holding the key (16 bytes for arc4 and aesv2, 87 for msrc4)\n"
117     "           E.g. dd if=/dev/random of=./my.key bs=16 count=1\n"
118     "           keyfile can also be pw=<string> to use \"string\" for the key.\n"
119     "           Or for 'securevnc' the RSA keystore and/or ClientAuth file.\n"
120     "\n"
121     "\n"
122     "       listenport: port to listen for incoming connection on. (use 0 to connect\n"
123     "                   to stdio, use a negative value to force localhost listening)\n"
124     "\n"
125     "\n"
126     "       remotehost:port: host and port to connect to. (e.g. ultravnc server)\n"
127     "\n"
128     "\n"
129     "       Also: cipher may be cipher@n,m where n is the salt size and m is the\n"
130     "       initialization vector size. E.g. aesv2@8,16  Use n=-1 to disable salt\n"
131     "       and the MD5 hash (i.e. insert the keydata directly into the cipher.)\n"
132     "\n"
133     "       Use cipher@md+n,m to change the message digest. E.g. arc4@sha+8,16\n"
134     "       Supported: 'md5', 'sha', 'sha1', 'ripemd160'.\n"
135     "\n"
136     "\n"
137     "       TCP Relay mode: to connect without any encryption use a cipher type of\n"
138     "       either 'relay' or 'none' (both are the equivalent):\n"
139     "\n"
140     "         ultravnc_dsm_helper relay listenport remotehost:port\n"
141     "         ultravnc_dsm_helper none  listenport remotehost:port\n"
142     "\n"
143     "       where 'relay' or 'none' is a literal string.\n"
144     "       Note that for this mode no keyfile is suppled.\n"
145     "       Note that this mode can act as an IPv4 to IPv6 gateway.\n"
146     "\n"
147     "         ultravnc_dsm_helper relay 8080 ipv6.beijing2008.cn:80\n"
148     "\n"
149     "\n"
150     "       SSL Show Certificate mode:  Set the cipher to 'showcert' to fetch\n"
151     "       the SSL certificate from remotehost:port and print it to the stdout.\n"
152     "       No certificate authentication or verification is performed.  E.g.\n"
153     "\n"
154     "         ultravnc_dsm_helper showcert www.verisign.com:443\n"
155     "\n"
156     "       (the output resembles that of 'openssl s_client ...')  Set the env var\n"
157     "       ULTRAVNC_DSM_HELPER_SHOWCERT_ADH=1 for Anonymous Diffie Hellman mode.\n"
158     "\n"
159     "\n"
160     "       Looping Mode:  Set the env. var. ULTRAVNC_DSM_HELPER_LOOP=1 to have it\n"
161     "       restart itself after every disconnection in an endless loop.  It pauses\n"
162     "       500 msec before restarting.  Use ULTRAVNC_DSM_HELPER_LOOP=N to set the\n"
163     "       pause to N msec.\n"
164     "\n"
165     "       You can also set the env. var. ULTRAVNC_DSM_HELPER_BG to have the\n"
166     "       program fork into the background for each connection, thereby acting\n"
167     "       as a simple daemon.\n"
168 ;
169 
170 /*
171  * We can also run as a module included into x11vnc (-enc option)
172  * The includer must set ENC_MODULE and ENC_HAVE_OPENSSL.
173  *
174  * Note that when running as a module we still assume we have been
175  * forked off of the parent process and are communicating back to it
176  * via a socket.  So we *still* exit(3) at the end or on error.  And
177  * the global settings won't work.
178  */
179 #ifdef ENC_MODULE
180 #  define main __enc_main
181 static char *prog = "enc_helper";
182 #else
183 #  define ENC_HAVE_OPENSSL 1
184 static char *prog = "ultravnc_dsm_helper";
185 #endif
186 
187 /* unix includes */
188 #include <sys/types.h>
189 #include <sys/stat.h>
190 #include <unistd.h>
191 #include <stdlib.h>
192 #include <unistd.h>
193 #include <stdio.h>
194 #include <fcntl.h>
195 
196 #include <string.h>
197 #include <errno.h>
198 #include <signal.h>
199 
200 #include <sys/socket.h>
201 #include <netinet/in.h>
202 #include <netinet/tcp.h>
203 #include <arpa/inet.h>
204 #include <netdb.h>
205 
206 
207 /* Solaris (sysv?) needs INADDR_NONE */
208 #ifndef INADDR_NONE
209 #define INADDR_NONE ((in_addr_t) 0xffffffff)
210 #endif
211 
212 /* openssl includes */
213 #if ENC_HAVE_OPENSSL
214 #include <openssl/evp.h>
215 #include <openssl/rand.h>
216 #include <openssl/rsa.h>
217 #include <openssl/err.h>
218 #include <openssl/ssl.h>
219 #include <openssl/rsa.h>
220 static const EVP_CIPHER *Cipher;
221 static const EVP_MD *Digest;
222 #endif
223 
224 static char *cipher = NULL;	/* name of cipher, e.g. "aesv2" */
225 static int reverse = 0;		/* listening connection */
226 static int msrc4_sc = 0;	/* enables workaround for SC I/II */
227 static int noultra = 0;		/* manage salt/iv differently from ultradsm */
228 static int nomd = 0;		/* use the keydata directly, no md5 or salt */
229 static int pw_in = 0;		/* pw=.... read in */
230 
231 
232 /* The data that was read in from key file (or pw=password) */
233 static char keydata[1024];
234 static int keydata_len;
235 
236 /* Size of salt and IV; based on UltraVNC DSM */
237 #define SALT 16
238 #define MSRC4_SALT 11
239 #define IVEC 16
240 
241 /* Set default values of salt and IV */
242 static int salt_size = SALT;
243 static int ivec_size = IVEC;
244 
245 /* To track parent and child pids */
246 static pid_t parent, child;
247 
248 /* transfer buffer size */
249 #define BSIZE 8192
250 
251 /* Some very verbose debugging stuff I enable for testing */
252 #ifdef DBG
253 #  include "dbg.h"
254 #else
255 #  define DEC_CT_DBG(p, n)
256 #  define DEC_PT_DBG(p, n)
257 #  define ENC_CT_DBG(p, n)
258 #  define ENC_PT_DBG(p, n)
259 #  define PRINT_IVEC
260 #  define PRINT_KEYDATA
261 #  define PRINT_KEYSTR_AND_FRIENDS
262 #  define PRINT_LOOP_DBG1
263 #  define PRINT_LOOP_DBG2
264 #  define PRINT_LOOP_DBG3
265 #endif
266 
267 /* SecureVNCPlugin from: http://adamwalling.com/SecureVNC/ */
268 #define SECUREVNC_RSA_PUBKEY_SIZE 270
269 #define SECUREVNC_ENCRYPTED_KEY_SIZE 256
270 #define SECUREVNC_SIGNATURE_SIZE 256
271 #define SECUREVNC_KEY_SIZE 16
272 #define SECUREVNC_RESERVED_SIZE 4
273 #define SECUREVNC_RC4_DROP_BYTES 3072
274 #define SECUREVNC_RAND_KEY_SOURCE 1024
275 static int securevnc = 0;
276 static int securevnc_arc4 = 0;
277 static char *securevnc_file = NULL;
278 
279 static void enc_connections(int, char*, int);
280 
281 #if !ENC_HAVE_OPENSSL
282 
283 /* In case we are a module and there is no OpenSSL buildtime support */
284 
enc_do(char * ciph,char * keyfile,char * lport,char * rhp)285 void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
286 	fprintf(stderr, "%s: not compiled with OpenSSL\n", prog);
287 	exit(1);
288 }
289 
290 #else
291 
292 #if defined(NO_EVP_aes_256_cfb) || (defined (__SVR4) && defined (__sun) && !defined(EVP_aes_256_cfb) && !defined(ASSUME_EVP_aes_256_cfb))
293 /*
294  * For Solaris 10 missing 192 & 256 bit crypto.
295  * Note that EVP_aes_256_cfb is a macro.
296  */
297 #undef EVP_aes_256_cfb
298 #define EVP_aes_256_cfb() EVP_aes_128_cfb(); {fprintf(stderr, "Not compiled with EVP_aes_256_cfb() 'aes256' support.\n"); exit(1);}
299 #endif
300 
301 /* If we are a module, enc_do() is the only interface we export.  */
302 
303 
304 /* This works out key type & etc., reads key, calls enc_connections */
305 
enc_do(char * ciph,char * keyfile,char * lport,char * rhp)306 void enc_do(char *ciph, char *keyfile, char *lport, char *rhp) {
307 
308 	struct stat sb;
309 	char *q, *p, *connect_host;
310 	char tmp[16];
311 	int fd, len = 0, listen_port = 0, connect_port, mbits;
312 
313 	q = ciph;
314 
315 	/* check for noultra mode: */
316 	if (strstr(q, "noultra:") == q) {
317 		noultra = 1;
318 		q += strlen("noultra:");
319 	}
320 
321 	/* check for reverse mode: */
322 	if (strstr(q, "rev:") == q) {
323 		reverse = 1;
324 		q += strlen("rev:");
325 	}
326 
327 	/* work out which cipher and set Cipher to the selected one. */
328 	if (!strcasecmp(q, "msrc4")) {
329 		Cipher = EVP_rc4();		cipher = "msrc4";
330 
331 	} else if (!strcasecmp(q, "msrc4_sc")) {
332 		Cipher = EVP_rc4();		cipher = "msrc4";
333 		msrc4_sc = 1;			/* no salt/iv workaround */
334 
335 	} else if (strstr(q, "arc4") == q) {
336 		Cipher = EVP_rc4();		cipher = "arc4";
337 
338 	} else if (strstr(q, "aesv2") == q || strstr(q, "aes-ofb") == q) {
339 		Cipher = EVP_aes_128_ofb();	cipher = "aesv2";
340 
341 	} else if (strstr(q, "aes-cfb") == q) {
342 		Cipher = EVP_aes_128_cfb();	cipher = "aes-cfb";
343 
344 	} else if (strstr(q, "aes256") == q) {
345 		Cipher = EVP_aes_256_cfb();	cipher = "aes256";
346 
347 	} else if (strstr(q, "blowfish") == q) {
348 		Cipher = EVP_bf_cfb();		cipher = "blowfish";
349 
350 	} else if (strstr(q, "3des") == q) {
351 		Cipher = EVP_des_ede3_cfb();	cipher = "3des";
352 
353 	} else if (strstr(q, "securevnc") == q) {
354 		Cipher = EVP_aes_128_ofb();	cipher = "securevnc";
355 		securevnc = 1;
356 
357 	} else if (strstr(q, "none") == q || strstr(q, "relay") == q) {
358 		cipher = "none";
359 
360 	} else if (strstr(q, "showcert") == q) {
361 		cipher = "showcert";
362 
363 	} else if (strstr(q, ".") == q) {
364 		/* otherwise, try to guess cipher from key filename: */
365 		if (strstr(keyfile, "arc4.key")) {
366 			Cipher = EVP_rc4();		cipher = "arc4";
367 
368 		} else if (strstr(keyfile, "rc4.key")) {
369 			Cipher = EVP_rc4();		cipher = "msrc4";
370 
371 		} else if (strstr(keyfile, "aesv2.key")) {
372 			Cipher = EVP_aes_128_ofb();	cipher = "aesv2";
373 
374 		} else if (strstr(keyfile, "aes-cfb.key")) {
375 			Cipher = EVP_aes_128_cfb();	cipher = "aes-cfb";
376 
377 		} else if (strstr(keyfile, "aes256.key")) {
378 			Cipher = EVP_aes_256_cfb();	cipher = "aes256";
379 
380 		} else if (strstr(keyfile, "blowfish.key")) {
381 			Cipher = EVP_bf_cfb();		cipher = "blowfish";
382 
383 		} else if (strstr(keyfile, "3des.key")) {
384 			Cipher = EVP_des_ede3_cfb();	cipher = "3des";
385 
386 		} else if (strstr(keyfile, "securevnc.")) {
387 			Cipher = EVP_aes_128_ofb();	cipher = "securevnc";
388 			securevnc = 1;
389 
390 		} else {
391 			fprintf(stderr, "cannot figure out cipher, supply 'msrc4', 'arc4', or 'aesv2' ...\n");
392 			exit(1);
393 		}
394 	} else {
395 		fprintf(stderr, "cannot figure out cipher, supply 'msrc4', 'arc4', or 'aesv2' ...\n");
396 		exit(1);
397 	}
398 
399 	/* set the default message digest (md5) */
400 	if (!securevnc) {
401 		Digest = EVP_md5();
402 	} else {
403 		Digest = EVP_sha1();
404 	}
405 
406 	/*
407 	 * Look for user specified salt and IV sizes at the end
408 	 * ( ciph@salt,iv and ciph@[md+]salt,iv ):
409 	 */
410 	p = strchr(q, '@');
411 	if (p) {
412 		int s, v;
413 		p++;
414 		if (strstr(p, "md5+") == p) {
415 			Digest = EVP_md5();        p += strlen("md5+");
416 		} else if (strstr(p, "sha+") == p) {
417 			fprintf(stderr, "%s: obsolete hash algorithm: SHA-0\n",
418 			    prog, s);
419 			exit(1);
420 		} else if (strstr(p, "sha1+") == p) {
421 			Digest = EVP_sha1();       p += strlen("sha1+");
422 		} else if (strstr(p, "ripe+") == p) {
423 			Digest = EVP_ripemd160();  p += strlen("ripe+");
424 		} else if (strstr(p, "ripemd160+") == p) {
425 			Digest = EVP_ripemd160();  p += strlen("ripemd160+");
426 		}
427 		if (sscanf(p, "%d,%d", &s, &v) == 2) {
428 			/* cipher@n,m */
429 			if (-1 <= s && s <= SALT) {
430 				salt_size = s;
431 			} else {
432 				fprintf(stderr, "%s: invalid salt size: %d\n",
433 				    prog, s);
434 				exit(1);
435 			}
436 			if (0 <= v && v <= EVP_MAX_IV_LENGTH) {
437 				ivec_size = v;
438 			} else {
439 				fprintf(stderr, "%s: invalid IV size: %d\n",
440 				    prog, v);
441 				exit(1);
442 			}
443 		} else if (sscanf(p, "%d", &s) == 1) {
444 			/* cipher@n */
445 			if (-1 <= s && s <= SALT) {
446 				salt_size = s;
447 			} else {
448 				fprintf(stderr, "%s: invalid salt size: %d\n",
449 				    prog, s);
450 				exit(1);
451 			}
452 		}
453 		if (salt_size == -1) {
454 			/* let salt = -1 mean skip both MD5 and salt */
455 			nomd = 1;
456 			salt_size = 0;
457 		}
458 	}
459 
460 	/* port to listen on (0 => stdio, negative => localhost) */
461 	if (lport != NULL) {
462 		listen_port = atoi(lport);
463 	}
464 
465 	/* extract remote hostname and port */
466 	q = strrchr(rhp, ':');
467 	if (q) {
468 		connect_port = atoi(q+1);
469 		*q = '\0';
470 	} else {
471 		/* otherwise guess VNC display 0 ... */
472 		connect_port = 5900;
473 	}
474 	connect_host = strdup(rhp);
475 
476 	/* check for and read in the key file */
477 	memset(keydata, 0, sizeof(keydata));
478 
479 	if (!strcmp(cipher, "none")) {
480 		goto readed_in;
481 	}
482 	if (!strcmp(cipher, "showcert")) {
483 		goto readed_in;
484 	}
485 
486 	if (securevnc) {
487 		/* note the keyfile for rsa verification later */
488 		if (keyfile != NULL && strcasecmp(keyfile, "none")) {
489 			securevnc_file = keyfile;
490 		}
491 		goto readed_in;
492 	}
493 
494 	if (stat(keyfile, &sb) != 0) {
495 		if (strstr(keyfile, "pw=") == keyfile) {
496 			/* user specified key/password on cmdline */
497 			int i;
498 			len = 0;
499 			pw_in = 1;
500 			for (i=0; i < (int) strlen(keyfile); i++) {
501 				/* load the string to keydata: */
502 				int n = i + strlen("pw=");
503 				keydata[i] = keyfile[n];
504 				if (keyfile[n] == '\0') break;
505 				len++;
506 				if (i > 100) break;
507 			}
508 			goto readed_in;
509 		}
510 		/* otherwise invalid file */
511 		perror("stat");
512 		exit(1);
513 	}
514 	if (sb.st_size > 1024) {
515 		fprintf(stderr, "%s: key file too big.\n", prog);
516 		exit(1);
517 	}
518 	fd = open(keyfile, O_RDONLY);
519 	if (fd < 0) {
520 		perror("open");
521 		exit(1);
522 	}
523 
524 	/* read it all in */
525 	len = (int) read(fd, keydata, (size_t) sb.st_size);
526 	if (len != sb.st_size) {
527 		perror("read");
528 		fprintf(stderr, "%s, could not read key file.\n", prog);
529 		exit(1);
530 	}
531 	close(fd);
532 
533 	readed_in:
534 
535 
536 	/* check for ultravnc msrc4 format 'rc4.key' */
537 	mbits = 0;
538 	if (strstr(keydata, "128 bit") == keydata) {
539 		mbits = 128;
540 	} else if (strstr(keydata, " 56 bit") == keydata) {
541 		mbits = 56;
542 	} else if (strstr(keydata, " 40 bit") == keydata) {
543 		mbits = 40;
544 	}
545 	if (mbits > 0) {
546 		/* 4 is for int key length, 12 is for BLOBHEADER. */
547 		int i, offset = strlen("xxx bit") + 4 + 12;
548 
549 		/* the key is stored in reverse order! */
550 		len = mbits/8;
551 		for (i=0; i < len; i++) {
552 			tmp[i] = keydata[offset + len - i - 1];
553 		}
554 
555 		/* clear keydata and then copy the reversed bytes there: */
556 		memset(keydata, 0, sizeof(keydata));
557 		memcpy(keydata, tmp, len);
558 	}
559 
560 	keydata_len = len;
561 
562 	/* initialize random */
563 	RAND_poll();
564 
565 	/*
566 	 * Setup connections, then transfer data when they are all
567 	 * hooked up.
568 	 */
569 	enc_connections(listen_port, connect_host, connect_port);
570 }
571 #endif
572 
enc_raw_xfer(int sock_fr,int sock_to)573 static void enc_raw_xfer(int sock_fr, int sock_to) {
574 
575 	unsigned char buf[BSIZE];
576 	unsigned char *psrc = NULL;
577 	int len, m, n = 0;
578 
579 	/* zero the buffers */
580 	memset(buf, 0, BSIZE);
581 
582 	/* now loop forever processing the data stream */
583 	while (1) {
584 		errno = 0;
585 
586 		/* general case of loop, read some in: */
587 		n = read(sock_fr, buf, BSIZE);
588 
589 		if (n == 0 || (n < 0 && errno != EINTR)) {
590 			/* failure to read any data, it is EOF or fatal error */
591 			int err = errno;
592 
593 			/* debug output: */
594 			fprintf(stderr, "%s: input stream finished: n=%d, err=%d", prog, n, err);
595 
596 			/* EOF or fatal error */
597 			break;
598 
599 		} else if (n > 0) {
600 
601 			/* write data to the other end: */
602 			len = n;
603 			psrc = buf;
604 			while (len > 0) {
605 				errno = 0;
606 				m = write(sock_to, psrc, len);
607 
608 				if (m > 0) {
609 					/* scoot them by how much was written: */
610 					psrc += m;
611 					len  -= m;
612 				}
613 				if (m < 0 && (errno == EINTR || errno == EAGAIN)) {
614 					/* interrupted or blocked */
615 					continue;
616 				}
617 				/* EOF or fatal error */
618 				break;
619 			}
620 		} else {
621 			/* this is EINTR */
622 		}
623 	}
624 
625 	/* transfer done (viewer exited or some error) */
626 
627 	fprintf(stderr, "\n%s: close sock_to\n", prog);
628 	close(sock_to);
629 
630 	fprintf(stderr,   "%s: close sock_fr\n", prog);
631 	close(sock_fr);
632 
633 	/* kill our partner after 1 secs. */
634 	sleep(1);
635 	if (child)  {
636 		if (kill(child, SIGTERM) == 0) {
637 			fprintf(stderr, "%s[%d]: killed my partner: %d\n",
638 			    prog, (int) getpid(), (int) child);
639 		}
640 	} else {
641 		if (kill(parent, SIGTERM) == 0) {
642 			fprintf(stderr, "%s[%d]: killed my partner: %d\n",
643 			    prog, (int) getpid(), (int) parent);
644 		}
645 	}
646 }
647 
648 #if ENC_HAVE_OPENSSL
649 /*
650  * Initialize cipher context and then loop till EOF doing transfer &
651  * encrypt or decrypt.
652  */
enc_xfer(int sock_fr,int sock_to,int encrypt)653 static void enc_xfer(int sock_fr, int sock_to, int encrypt) {
654 	/*
655 	 * We keep both E and D aspects in case we revert back to a
656 	 * single process calling select(2) on all fds...
657 	 */
658 	unsigned char E_keystr[EVP_MAX_KEY_LENGTH];
659 	unsigned char D_keystr[EVP_MAX_KEY_LENGTH];
660 	//openssl1.1.patch - Do NOT create two context and only use one
661 	// - that's silly.
662 	//EVP_CIPHER_CTX *E_ctx, *D_ctx;
663 	EVP_CIPHER_CTX *ctx;
664 
665 	unsigned char buf[BSIZE], out[BSIZE];
666 	unsigned char *psrc = NULL, *keystr;
667 	unsigned char salt[SALT+1];
668 	unsigned char ivec_real[EVP_MAX_IV_LENGTH];
669 	unsigned char *ivec = ivec_real;
670 
671 	int i, cnt, len, m, n = 0, vb = 0, first = 1;
672 	int whoops = 1; /* for the msrc4 problem */
673 	char *encstr, *encsym;
674 
675 	/* zero the buffers */
676 	memset(buf,  0, BSIZE);
677 	memset(out,  0, BSIZE);
678 	memset(salt, 0, sizeof(salt));
679 	memset(ivec_real, 0, sizeof(ivec_real));
680 	memset(E_keystr, 0, sizeof(E_keystr));
681 	memset(D_keystr, 0, sizeof(D_keystr));
682 
683 	if (!strcmp(cipher, "msrc4")) {
684 		salt_size = MSRC4_SALT; /* 11 vs. 16 */
685 	}
686 
687 	if (msrc4_sc) {
688 		whoops = 1;	/* force workaround in SC mode */
689 	}
690 
691 	if (getenv("ENCRYPT_VERBOSE")) {
692 		vb = 1;	/* let user turn on some debugging via env. var. */
693 	}
694 
695 	/*
696 	 * reverse mode, e.g. we help a vnc server instead of a viewer.
697 	 */
698 	if (reverse) {
699 		encrypt = (!encrypt);
700 	}
701 	encstr = encrypt ? "encrypt" : "decrypt";  /* string for messages */
702 	encsym = encrypt ? "+" : "-";
703 
704 	/* use the encryption/decryption context variables below */
705 	ctx = EVP_CIPHER_CTX_new();
706 	if (!ctx) {
707 	    fprintf(stderr, "Failed to create encryption/decryption context.\n");
708 	    goto finished;
709 	}
710 	if (encrypt) {
711 		keystr = E_keystr;
712 	} else {
713 		keystr = D_keystr;
714 	}
715 
716 	if (securevnc) {
717 		first = 0;	/* no need for salt+iv on first time */
718 		salt_size = 0;	/* we want no salt */
719 		n = 0;		/* nothing read */
720 		ivec_size = 0;	/* we want no IV. */
721 		ivec = NULL;
722 	} else if (encrypt) {
723 		/* encrypter initializes the salt and initialization vector */
724 
725 		/*
726 		 * Our salt is 16 bytes but I believe only the first 8
727 		 * bytes are used by EVP_BytesToKey(3).  Since we send it
728 		 * to the other "plugin" we need to keep it 16.  Also,
729 		 * the IV size can depend on the cipher type.  Again, 16.
730 		 */
731 		RAND_bytes(salt, salt_size);
732 		RAND_bytes(ivec, ivec_size);
733 
734 		/* place them in the send buffer: */
735 		memcpy(buf, salt, salt_size);
736 		memcpy(buf+salt_size, ivec, ivec_size);
737 
738 		n = salt_size + ivec_size;
739 
740 		ENC_PT_DBG(buf, n);
741 
742 	} else {
743 		/* decrypter needs to read salt + iv from the wire: */
744 
745 		/* sleep 100 ms (TODO: select on fd) */
746 		struct timeval tv;
747 		tv.tv_sec  = 0;
748 		tv.tv_usec = 100 * 1000;
749 		select(1, NULL, NULL, NULL, &tv);
750 
751 		if (salt_size+ivec_size == 0) {
752 			n = 0;	/* no salt or iv, skip reading. */
753 		} else {
754 			n = read(sock_fr, buf, salt_size+ivec_size+96);
755 		}
756 		if (n == 0 && salt_size+ivec_size > 0) {
757 			fprintf(stderr, "%s: decrypt finished.\n", prog);
758 			goto finished;
759 		}
760 		if (n < salt_size+ivec_size) {
761 		    if (msrc4_sc && n == 12) {
762 			fprintf(stderr, "%s: only %d bytes read. Assuming "
763 			    "UVNC Single Click server.\n", prog, n);
764 		    } else {
765 			if (n < 0) perror("read");
766 			fprintf(stderr, "%s: could not read enough for salt "
767 			    "and ivec: n=%d\n", prog, n);
768 			goto finished;
769 		    }
770 		}
771 
772 		DEC_CT_DBG(buf, n);
773 
774 		if (msrc4_sc && n == 12) {
775 			; /* send it as is */
776 		} else {
777 			/* extract them to their buffers: */
778 			memcpy(salt, buf, salt_size);
779 			memcpy(ivec, buf+salt_size, ivec_size);
780 
781 			/* the rest is some encrypted data: */
782 			n = n - salt_size - ivec_size;
783 			psrc = buf + salt_size + ivec_size;
784 
785 			if (n > 0) {
786 				/*
787 				 * copy it down to the start of buf for
788 				 * sending below:
789 				 */
790 				for (i=0; i < n; i++) {
791 					buf[i] = psrc[i];
792 				}
793 			}
794 		}
795 	}
796 
797 	/* debug output */
798 	PRINT_KEYDATA;
799 	PRINT_IVEC;
800 
801 	if (!strcmp(cipher, "msrc4")) {
802 		/* special cases for MSRC4: */
803 
804 		if (whoops) {
805 			fprintf(stderr, "%s: %s - WARNING: MSRC4 mode and IGNORING random salt\n", prog, encstr);
806 			fprintf(stderr, "%s: %s - WARNING: and initialization vector!!\n", prog, encstr);
807 			if (pw_in) {
808 			    /* for pw=xxxx a md5 hash is used */
809 			    EVP_BytesToKey(Cipher, Digest, NULL, (unsigned char *) keydata,
810 			        keydata_len, 1, keystr, NULL);
811 			    EVP_CipherInit_ex(ctx, Cipher, NULL, keystr, NULL,
812 			        encrypt);
813 			} else {
814 			    /* otherwise keydata as is */
815 			    EVP_CipherInit_ex(ctx, Cipher, NULL,
816 			        (unsigned char *) keydata, NULL, encrypt);
817 			}
818 		} else {
819 			/* XXX might not be correct, just exit. */
820 			fprintf(stderr, "%s: %s - Not sure about msrc4 && !whoops case, exiting.\n", prog, encstr);
821 			exit(1);
822 
823 			EVP_BytesToKey(Cipher, Digest, NULL, (unsigned char *) keydata,
824 			    keydata_len, 1, keystr, ivec);
825 			EVP_CipherInit_ex(ctx, Cipher, NULL, keystr, ivec,
826 			    encrypt);
827 		}
828 
829 	} else {
830 		unsigned char *in_salt = NULL;
831 
832 		/* check salt and IV source and size. */
833 		if (securevnc) {
834 			in_salt = NULL;
835 		} else if (salt_size <= 0) {
836 			/* let salt_size = 0 mean keep it out of the MD5 */
837 			fprintf(stderr, "%s: %s - WARNING: no salt\n",
838 			    prog, encstr);
839 			in_salt = NULL;
840 		} else {
841 			in_salt = salt;
842 		}
843 
844 		if (ivec_size < EVP_CIPHER_iv_length(Cipher) && !securevnc) {
845 			fprintf(stderr, "%s: %s - WARNING: short IV %d < %d\n",
846 			    prog, encstr, ivec_size, EVP_CIPHER_iv_length(Cipher));
847 		}
848 
849 		/* make the hashed value and place in keystr */
850 
851 		/*
852 		 * XXX N.B.: DSM plugin had count=0, and overwrote ivec
853 		 * by not passing NULL iv.
854 		 */
855 
856 		if (nomd) {
857 			/* special mode: no salt or md5, use keydata directly */
858 
859 			int sz = keydata_len < EVP_MAX_KEY_LENGTH ?
860 			    keydata_len : EVP_MAX_KEY_LENGTH;
861 
862 			fprintf(stderr, "%s: %s - WARNING: no-md5 specified: ignoring salt & hash\n", prog, encstr);
863 			memcpy(keystr, keydata, sz);
864 
865 		} else if (noultra && ivec_size > 0) {
866 			/* "normal" mode, don't overwrite ivec. */
867 
868 			EVP_BytesToKey(Cipher, Digest, in_salt, (unsigned char *) keydata,
869 			    keydata_len, 1, keystr, NULL);
870 
871 		} else {
872 			/*
873 			 * Ultra DSM compatibility mode.  Note that this
874 			 * clobbers the ivec we set up above!  Under
875 			 * noultra we overwrite ivec only if ivec_size=0.
876 			 *
877 			 * SecureVNC also goes through here. in_salt and ivec are NULL.
878 			 * And ivec is NULL below in the EVP_CipherInit_ex() call.
879 			 */
880 			EVP_BytesToKey(Cipher, Digest, in_salt, (unsigned char *) keydata,
881 			    keydata_len, 1, keystr, ivec);
882 		}
883 
884 
885 
886 		/* set the cipher & initialize */
887 
888 		/*
889 		 * XXX N.B.: DSM plugin implementation had encrypt=1
890 		 * for both (i.e. perfectly symmetric)
891 		 */
892 
893 		EVP_CipherInit_ex(ctx, Cipher, NULL, keystr, ivec, encrypt);
894 	}
895 
896 	if (securevnc && securevnc_arc4) {
897 		/* need to discard initial 3072 bytes */
898 		unsigned char buf1[SECUREVNC_RC4_DROP_BYTES];
899 		unsigned char buf2[SECUREVNC_RC4_DROP_BYTES];
900 		int cnt = 0;
901 		EVP_CipherUpdate(ctx, buf1, &cnt, buf2, SECUREVNC_RC4_DROP_BYTES);
902 	}
903 
904 	/* debug output */
905 	PRINT_KEYSTR_AND_FRIENDS;
906 
907 	/* now loop forever processing the data stream */
908 
909 	while (1) {
910 		errno = 0;
911 		if (first && n > 0) {
912 			if (encrypt && msrc4_sc) {
913 				/* skip sending salt+iv */
914 				first = 0;
915 				continue;
916 			} else {
917 				/* use that first block of data placed in buf */
918 			}
919 		} else if (first && n == 0 && salt_size + ivec_size == 0) {
920 			first = 0;
921 			continue;
922 		} else {
923 			/* general case of loop, read some in: */
924 			n = read(sock_fr, buf, BSIZE);
925 		}
926 
927 		/* debug output: */
928 		if (vb) fprintf(stderr, "%s%d/%d ", encsym, n, errno);
929 		PRINT_LOOP_DBG1;
930 
931 		if (n == 0 || (n < 0 && errno != EINTR)) {
932 			/* failure to read any data, it is EOF or fatal error */
933 			int err = errno;
934 
935 			/* debug output: */
936 			PRINT_LOOP_DBG2;
937 			fprintf(stderr, "%s: %s - input stream finished: n=%d, err=%d", prog, encstr, n, err);
938 
939 			/* EOF or fatal error */
940 			break;
941 
942 		} else if (n > 0) {
943 			/* we read in some data, now transform it: */
944 
945 			if (first && encrypt) {
946 				/* first time, copy the salt and ivec to out[] for sending */
947 				memcpy(out, buf, n);
948 				cnt = n;
949 
950 			} else if (!EVP_CipherUpdate(ctx, out, &cnt, buf, n)) {
951 				/* otherwise, we transform the data */
952 				fprintf(stderr, "%s: enc_xfer EVP_CipherUpdate failed.\n", prog);
953 				break;
954 			}
955 
956 			/* debug output: */
957 			if (vb) fprintf(stderr, "%sc%d/%d ", encsym, cnt, n);
958 			PRINT_LOOP_DBG3;
959 
960 			/* write transformed data to the other end: */
961 			len = cnt;
962 			psrc = out;
963 			while (len > 0) {
964 				errno = 0;
965 				m = write(sock_to, psrc, len);
966 
967 				/* debug output: */
968 				if (vb) fprintf(stderr, "m%s%d/%d ", encsym, m, errno);
969 
970 				if (m > 0) {
971 					/* scoot them by how much was written: */
972 					psrc += m;
973 					len  -= m;
974 				}
975 				if (m < 0 && (errno == EINTR || errno == EAGAIN)) {
976 					/* interrupted or blocked */
977 					continue;
978 				}
979 				/* EOF or fatal error */
980 				break;
981 			}
982 		} else {
983 			/* this is EINTR */
984 		}
985 		first = 0;
986 	}
987 
988 	/* transfer done (viewer exited or some error) */
989 	finished:
990 
991 	if (ctx) EVP_CIPHER_CTX_free(ctx);
992 	fprintf(stderr, "\n%s: %s - close sock_to\n", prog, encstr);
993 	close(sock_to);
994 
995 	fprintf(stderr,   "%s: %s - close sock_fr\n", prog, encstr);
996 	close(sock_fr);
997 
998 	/* kill our partner after 2 secs. */
999 	sleep(2);
1000 	if (child)  {
1001 		if (kill(child, SIGTERM) == 0) {
1002 			fprintf(stderr, "%s[%d]: %s - killed my partner: %d\n",
1003 			    prog, (int) getpid(), encstr, (int) child);
1004 		}
1005 	} else {
1006 		if (kill(parent, SIGTERM) == 0) {
1007 			fprintf(stderr, "%s[%d]: %s - killed my partner: %d\n",
1008 			    prog, (int) getpid(), encstr, (int) parent);
1009 		}
1010 	}
1011 }
1012 
securevnc_server_rsa_save_dialog(char * file,char * md5str,unsigned char * rsabuf)1013 static int securevnc_server_rsa_save_dialog(char *file, char *md5str, unsigned char* rsabuf) {
1014 	/* since we are likely running in the background, use this kludge by running tk */
1015 	FILE *p;
1016 	char str[2], *q = file, *cmd = getenv("WISH") ? getenv("WISH") : "wish";
1017 	int rc;
1018 
1019 	memset(str, 0, sizeof(str));
1020 
1021 	p = popen(cmd, "w");
1022 	if (p == NULL) {
1023 		fprintf(stderr, "checkserver_rsa: could not run: %s\n", cmd);
1024 		return 0;
1025 	}
1026 
1027 	/* start piping tk/tcl code to it: */
1028 	fprintf(p, "wm withdraw .\n");
1029 	fprintf(p, "set x [expr [winfo screenwidth  .]/2]\n");
1030 	fprintf(p, "set y [expr [winfo screenheight .]/2]\n");
1031 	fprintf(p, "wm geometry . +$x+$y; update\n");
1032 	fprintf(p, "catch {option add *Dialog.msg.font {helvetica -14 bold}}\n");
1033 	fprintf(p, "catch {option add *Dialog.msg.wrapLength 6i}\n");
1034 	fprintf(p, "set ans [tk_messageBox -title \"Save and Trust UltraVNC RSA Key?\" -icon question ");
1035 	fprintf(p, "-type yesno -message \"Save and Trust UltraVNC SecureVNCPlugin RSA Key\\n\\n");
1036 	fprintf(p, "With MD5 sum: %s\\n\\n", md5str);
1037 	fprintf(p, "In file: ");
1038 	while (*q != '\0') {
1039 		/* sanitize user supplied string: */
1040 		str[0] = *q;
1041 		if (strpbrk(str, "[](){}`'\"$&*|<>") == NULL) {
1042 			fprintf(p, "%s", str);
1043 		}
1044 		q++;
1045 	}
1046 	fprintf(p, " ?\"]\n");
1047 	fprintf(p, "if { $ans == \"yes\" } {destroy .; exit 0} else {destroy .; exit 1}\n");
1048 	rc = pclose(p);
1049 	if (rc == 0) {
1050 		fprintf(stderr, "checkserver_rsa: query returned: %d.  saving it.\n", rc);
1051 		p = fopen(file, "w");
1052 		if (p == NULL) {
1053 			fprintf(stderr, "checkserver_rsa: could not open %s\n", file);
1054 			return 0;
1055 		}
1056 		write(fileno(p), rsabuf, SECUREVNC_RSA_PUBKEY_SIZE);
1057 		fclose(p);
1058 		return 2;
1059 	} else {
1060 		fprintf(stderr, "checkserver_rsa: query returned: %d.  NOT saving it.\n", rc);
1061 		return -1;
1062 	}
1063 }
1064 
rsa_md5_sum(unsigned char * rsabuf)1065 static char *rsa_md5_sum(unsigned char* rsabuf) {
1066 	EVP_MD_CTX *md = EVP_MD_CTX_create();
1067 	char digest[EVP_MAX_MD_SIZE], tmp[16];
1068 	char md5str[EVP_MAX_MD_SIZE * 8];
1069 	unsigned int i, size = 0;
1070 
1071 	EVP_DigestInit(md, EVP_md5());
1072 	EVP_DigestUpdate(md, rsabuf, SECUREVNC_RSA_PUBKEY_SIZE);
1073 	EVP_DigestFinal(md, (unsigned char *)digest, &size);
1074 
1075 	memset(md5str, 0, sizeof(md5str));
1076 	for (i=0; i < size; i++) {
1077 		unsigned char uc = (unsigned char) digest[i];
1078 		sprintf(tmp, "%02x", (int) uc);
1079 		strcat(md5str, tmp);
1080 	}
1081 	EVP_MD_CTX_destroy(md);
1082 	return strdup(md5str);
1083 }
1084 
securevnc_check_server_rsa(char * file,unsigned char * rsabuf)1085 static int securevnc_check_server_rsa(char *file, unsigned char *rsabuf) {
1086 	struct stat sb;
1087 	unsigned char filebuf[SECUREVNC_RSA_PUBKEY_SIZE];
1088 	char *md5str = rsa_md5_sum(rsabuf);
1089 
1090 	if (!file) {
1091 		return 0;
1092 	}
1093 
1094 	memset(filebuf, 0, sizeof(filebuf));
1095 	if (stat(file, &sb) == 0) {
1096 		int n, fd, i, ok = 1;
1097 
1098 		if (sb.st_size != SECUREVNC_RSA_PUBKEY_SIZE) {
1099 			fprintf(stderr, "checkserver_rsa: file is wrong size: %d != %d '%s'\n",
1100 			    (int) sb.st_size, SECUREVNC_RSA_PUBKEY_SIZE, file);
1101 			return 0;
1102 		}
1103 
1104 		fd = open(file, O_RDONLY);
1105 		if (fd < 0) {
1106 			fprintf(stderr, "checkserver_rsa: could not open: '%s'\n", file);
1107 			return 0;
1108 		}
1109 
1110 		n = (int) read(fd, filebuf, SECUREVNC_RSA_PUBKEY_SIZE);
1111 		close(fd);
1112 		if (n != SECUREVNC_RSA_PUBKEY_SIZE) {
1113 			fprintf(stderr, "checkserver_rsa: could not read all of file: %d != %d '%s'\n",
1114 			    n, SECUREVNC_RSA_PUBKEY_SIZE, file);
1115 			return 0;
1116 		}
1117 
1118 		for (i=0; i < SECUREVNC_RSA_PUBKEY_SIZE; i++) {
1119 			if (filebuf[i] != rsabuf[i]) {
1120 				ok = 0;
1121 			}
1122 		}
1123 		if (!ok) {
1124 			char *str1 = rsa_md5_sum(rsabuf);
1125 			char *str2 = rsa_md5_sum(filebuf);
1126 			fprintf(stderr, "checkserver_rsa: rsa keystore contents differ for '%s'\n", file);
1127 			fprintf(stderr, "checkserver_rsa: MD5 sum of server key: %s\n", str1);
1128 			fprintf(stderr, "checkserver_rsa: MD5 sum of keystore:   %s\n", str2);
1129 		}
1130 		return ok;
1131 	} else {
1132 
1133 		fprintf(stderr, "checkserver_rsa: rsa keystore file does not exist: '%s'\n", file);
1134 		fprintf(stderr, "checkserver_rsa: asking user if we should store rsa key in it.\n\n");
1135 		fprintf(stderr, "checkserver_rsa: RSA key has MD5 sum: %s\n\n", md5str);
1136 
1137 		return securevnc_server_rsa_save_dialog(file, md5str, rsabuf);
1138 	}
1139 }
1140 
load_client_auth(char * file)1141 static RSA *load_client_auth(char *file) {
1142 	struct stat sb;
1143 	int fd, n;
1144 	char *contents;
1145 	RSA *rsa;
1146 
1147 	if (!file) {
1148 		return NULL;
1149 	}
1150 	if (stat(file, &sb) != 0) {
1151 		return NULL;
1152 	}
1153 
1154 	fd = open(file, O_RDONLY);
1155 	if (fd < 0) {
1156 		fprintf(stderr, "load_client_auth: could not open: '%s'\n", file);
1157 		return NULL;
1158 	}
1159 
1160 	contents = (char *) malloc(sb.st_size);
1161 	n = (int) read(fd, contents, sb.st_size);
1162 	close(fd);
1163 
1164 	if (n != sb.st_size)  {
1165 		fprintf(stderr, "load_client_auth: could not read all of: '%s'\n", file);
1166 		free(contents);
1167 		return NULL;
1168 	}
1169 
1170 	rsa = d2i_RSAPrivateKey(NULL, (const unsigned char **) ((void *) &contents), sb.st_size);
1171 	if (!rsa) {
1172 		fprintf(stderr, "load_client_auth: d2i_RSAPrivateKey failed for: '%s'\n", file);
1173 		return NULL;
1174 	}
1175 
1176 	if (RSA_check_key(rsa) != 1) {
1177 		fprintf(stderr, "load_client_auth: rsa key invalid: '%s'\n", file);
1178 		return NULL;
1179 	}
1180 
1181 	return rsa;
1182 }
1183 
sslexit(char * msg)1184 static void sslexit(char *msg) {
1185 	fprintf(stderr, "%s: %s\n", msg, ERR_error_string(ERR_get_error(), NULL));
1186 	exit(1);
1187 }
1188 
securevnc_setup(int conn1,int conn2)1189 static void securevnc_setup(int conn1, int conn2) {
1190 	RSA *rsa = NULL;
1191 	EVP_CIPHER_CTX *init_ctx = EVP_CIPHER_CTX_new();
1192 	unsigned char keystr[EVP_MAX_KEY_LENGTH];
1193 	unsigned char *rsabuf, *rsasav;
1194 	unsigned char *encrypted_keybuf;
1195 	unsigned char *initkey;
1196 	unsigned int server_flags = 0;
1197 	unsigned char one = 1, zero = 0, sig = 16;
1198 	unsigned char b1, b2, b3, b4;
1199 	unsigned char buf[BSIZE], to_viewer[BSIZE];
1200 	int to_viewer_len = 0;
1201 	int n = 0, len, rc;
1202 	int server = reverse ? conn1 : conn2;
1203 	int viewer = reverse ? conn2 : conn1;
1204 	char *client_auth = NULL;
1205 	int client_auth_req = 0;
1206 	int keystore_verified = 0;
1207 
1208 	ERR_load_crypto_strings();
1209 
1210 	if (!init_ctx) sslexit("securevnc_setup: EVP_CIPHER_CTX_new() failed");
1211 
1212 	/* alloc and read from server the 270 comprising the rsa public key: */
1213 	rsabuf = (unsigned char *) calloc(SECUREVNC_RSA_PUBKEY_SIZE, 1);
1214 	rsasav = (unsigned char *) calloc(SECUREVNC_RSA_PUBKEY_SIZE, 1);
1215 	len = 0;
1216 	while (len < SECUREVNC_RSA_PUBKEY_SIZE) {
1217 		n = read(server, rsabuf + len, SECUREVNC_RSA_PUBKEY_SIZE - len);
1218 		if (n == 0 || (n < 0 && errno != EINTR)) {
1219 			fprintf(stderr, "securevnc_setup: fail read rsabuf: n=%d len=%d\n", n, len);
1220 			exit(1);
1221 		}
1222 		len += n;
1223 	}
1224 	if (len != SECUREVNC_RSA_PUBKEY_SIZE) {
1225 		fprintf(stderr, "securevnc_setup: fail final read rsabuf: n=%d len=%d\n", n, len);
1226 		exit(1);
1227 	}
1228 	fprintf(stderr, "securevnc_setup: rsa data read len: %d\n", len);
1229 	memcpy(rsasav, rsabuf, SECUREVNC_RSA_PUBKEY_SIZE);
1230 
1231 	fprintf(stderr, "securevnc_setup: RSA key has MD5 sum: %s\n", rsa_md5_sum(rsabuf));
1232 	fprintf(stderr, "securevnc_setup:\n");
1233 	fprintf(stderr, "securevnc_setup: One way to print out the SecureVNC Server key MD5 sum is:\n\n");
1234 	fprintf(stderr, "openssl rsa -inform DER -outform DER -pubout -in ./Server_SecureVNC.pkey | dd bs=1 skip=24 | md5sum\n\n");
1235 	if (securevnc_file == NULL) {
1236 		fprintf(stderr, "securevnc_setup:\n");
1237 		fprintf(stderr, "securevnc_setup: ** WARNING: ULTRAVNC SERVER RSA KEY NOT VERIFIED.   **\n");
1238 		fprintf(stderr, "securevnc_setup: ** WARNING: A MAN-IN-THE-MIDDLE ATTACK IS POSSIBLE. **\n");
1239 		fprintf(stderr, "securevnc_setup:\n");
1240 	} else {
1241 		char *q = strrchr(securevnc_file, 'C');
1242 		int skip = 0;
1243 		if (q) {
1244 			if (!strcmp(q, "ClientAuth.pkey")) {
1245 				client_auth = strdup(securevnc_file);
1246 				skip = 1;
1247 			} else if (!strcmp(q, "ClientAuth.pkey.rsa")) {
1248 				client_auth = strdup(securevnc_file);
1249 				q = strrchr(client_auth, '.');
1250 				*q = '\0';
1251 			}
1252 		}
1253 		if (!skip) {
1254 			rc = securevnc_check_server_rsa(securevnc_file, rsabuf);
1255 		}
1256 		if (skip) {
1257 			;
1258 		} else if (rc == 0) {
1259 			fprintf(stderr, "securevnc_setup:\n");
1260 			fprintf(stderr, "securevnc_setup: VERIFY_ERROR: SERVER RSA KEY DID NOT MATCH:\n");
1261 			fprintf(stderr, "securevnc_setup:     %s\n", securevnc_file);
1262 			fprintf(stderr, "securevnc_setup:\n");
1263 			exit(1);
1264 		} else if (rc == -1) {
1265 			fprintf(stderr, "securevnc_setup: User cancelled the save and hence the connection.\n");
1266 			fprintf(stderr, "securevnc_setup:     %s\n", securevnc_file);
1267 			exit(1);
1268 		} else if (rc == 1) {
1269 			fprintf(stderr, "securevnc_setup: VERIFY SUCCESS: server rsa key matches the contents of:\n");
1270 			fprintf(stderr, "securevnc_setup:     %s\n", securevnc_file);
1271 			keystore_verified = 1;
1272 		} else if (rc == 2) {
1273 			fprintf(stderr, "securevnc_setup: Server rsa key stored in:\n");
1274 			fprintf(stderr, "securevnc_setup:     %s\n", securevnc_file);
1275 			keystore_verified = 2;
1276 		}
1277 	}
1278 
1279 	/*
1280 	 * read in the server flags. Note that SecureVNCPlugin sends these
1281 	 * in little endian and not network order!!
1282 	 */
1283 	read(server, (char *) &b1, 1);
1284 	read(server, (char *) &b2, 1);
1285 	read(server, (char *) &b3, 1);
1286 	read(server, (char *) &b4, 1);
1287 
1288 	server_flags = 0;
1289 	server_flags |= ((unsigned int) b4) << 24;
1290 	server_flags |= ((unsigned int) b3) << 16;
1291 	server_flags |= ((unsigned int) b2) << 8;
1292 	server_flags |= ((unsigned int) b1) << 0;
1293 	fprintf(stderr, "securevnc_setup: server_flags: 0x%08x\n", server_flags);
1294 
1295 	/* check for arc4 usage: */
1296 	if (server_flags & 0x1) {
1297 		fprintf(stderr, "securevnc_setup: server uses AES cipher.\n");
1298 	} else {
1299 		fprintf(stderr, "securevnc_setup: server uses ARC4 cipher.\n");
1300 		securevnc_arc4 = 1;
1301 		Cipher = EVP_rc4();
1302 	}
1303 
1304 	/* check for client auth signature requirement: */
1305 	if (server_flags & (sig << 24)) {
1306 		fprintf(stderr, "securevnc_setup: server requires Client Auth signature.\n");
1307 		client_auth_req = 1;
1308 		if (!client_auth) {
1309 			fprintf(stderr, "securevnc_setup: However, NO *ClientAuth.pkey keyfile was supplied on our\n");
1310 			fprintf(stderr, "securevnc_setup: command line.  Exiting.\n");
1311 			exit(1);
1312 		}
1313 	}
1314 
1315 	/*
1316 	 * The first packet 'RFB 003.006' is obscured with key
1317 	 * that is a sha1 hash of public key.  So make this tmp key now:
1318  	 *
1319 	 */
1320 	initkey = (unsigned char *) calloc(SECUREVNC_KEY_SIZE, 1);
1321 	EVP_BytesToKey(EVP_rc4(), EVP_sha1(), NULL, rsabuf, SECUREVNC_RSA_PUBKEY_SIZE, 1, initkey, NULL);
1322 
1323 	/* expand the transported rsabuf into an rsa object */
1324 	rsa = d2i_RSAPublicKey(NULL, (const unsigned char **) &rsabuf, SECUREVNC_RSA_PUBKEY_SIZE);
1325 	if (rsa == NULL) {
1326 		sslexit("securevnc_setup: failed to create rsa");
1327 	}
1328 
1329 	/*
1330 	 * Back to the work involving the tmp obscuring key:
1331 	 */
1332 	rc = EVP_CipherInit_ex(init_ctx, EVP_rc4(), NULL, initkey, NULL, 1);
1333 	if (rc == 0) {
1334 		sslexit("securevnc_setup: EVP_CipherInit_ex(init_ctx) failed");
1335 	}
1336 
1337 	/* for the first obscured packet, read what we can... */
1338 	n = read(server, (char *) buf, BSIZE);
1339 	fprintf(stderr, "securevnc_setup: data read: %d\n", n);
1340 	if (n < 0) {
1341 		exit(1);
1342 	}
1343 	fprintf(stderr, "securevnc_setup: initial data[%d]: ", n);
1344 
1345 	/* decode with the tmp key */
1346 	if (n > 0) {
1347 		memset(to_viewer, 0, sizeof(to_viewer));
1348 		if (EVP_CipherUpdate(init_ctx, to_viewer, &len, buf, n) == 0) {
1349 			sslexit("securevnc_setup: EVP_CipherUpdate(init_ctx) failed");
1350 			exit(1);
1351 		}
1352 		to_viewer_len = len;
1353 	}
1354 	EVP_CIPHER_CTX_free(init_ctx);
1355 	free(initkey);
1356 
1357 	/* print what we would send to the viewer (sent below): */
1358 	write(2, to_viewer, 12);	/* and first 12 bytes 'RFB ...' as message */
1359 
1360 	/* now create the random session key: */
1361 	encrypted_keybuf = (unsigned char*) calloc(RSA_size(rsa), 1);
1362 
1363 	fprintf(stderr, "securevnc_setup: creating random session key: %d/%d\n",
1364 	    SECUREVNC_KEY_SIZE, SECUREVNC_RAND_KEY_SOURCE);
1365 	keydata_len = SECUREVNC_RAND_KEY_SOURCE;
1366 
1367 	rc = RAND_bytes((unsigned char *)keydata, SECUREVNC_RAND_KEY_SOURCE);
1368 	if (rc <= 0) {
1369 		fprintf(stderr, "securevnc_setup: RAND_bytes() failed: %s\n", ERR_error_string(ERR_get_error(), NULL));
1370 		rc = RAND_pseudo_bytes((unsigned char *)keydata, SECUREVNC_RAND_KEY_SOURCE);
1371 		fprintf(stderr, "securevnc_setup: RAND_pseudo_bytes() rc=%d\n", rc);
1372 		if (getenv("RANDSTR")) {
1373 			char *s = getenv("RANDSTR");
1374 			fprintf(stderr, "securevnc_setup: seeding with RANDSTR len=%d\n", strlen(s));
1375 			RAND_add(s, strlen(s), strlen(s));
1376 		}
1377 	}
1378 
1379 	/* N.B. this will be repeated in enc_xfer() setup. */
1380 	EVP_BytesToKey(Cipher, Digest, NULL, (unsigned char *) keydata, keydata_len, 1, keystr, NULL);
1381 
1382 	/* encrypt the session key with the server's public rsa key: */
1383 	n = RSA_public_encrypt(SECUREVNC_KEY_SIZE, keystr, encrypted_keybuf, rsa, RSA_PKCS1_PADDING);
1384 	if (n == -1) {
1385 		sslexit("securevnc_setup: RSA_public_encrypt() failed");
1386 		exit(1);
1387 	}
1388 	fprintf(stderr, "securevnc_setup: encrypted session key size: %d. sending to server.\n", n);
1389 
1390 	/* send it to the server: */
1391 	write(server, encrypted_keybuf, n);
1392 	free(encrypted_keybuf);
1393 
1394 	/*
1395 	 * Reply back with flags indicating cipher (same as one sent to
1396 	 * us) and we do not want client-side auth.
1397 	 *
1398 	 * We send it out on the wire in little endian order:
1399 	 */
1400 	if (securevnc_arc4) {
1401 		write(server, (char *)&zero, 1);
1402 	} else {
1403 		write(server, (char *)&one, 1);
1404 	}
1405 	write(server, (char *)&zero, 1);
1406 	write(server, (char *)&zero, 1);
1407 	if (client_auth_req) {
1408 		write(server, (char *)&sig, 1);
1409 	} else {
1410 		write(server, (char *)&zero, 1);
1411 	}
1412 
1413 	if (client_auth_req && client_auth) {
1414 		RSA *client_rsa = load_client_auth(client_auth);
1415 		EVP_MD_CTX *dctx = EVP_MD_CTX_create();
1416 		unsigned char digest[EVP_MAX_MD_SIZE], *signature;
1417 		unsigned int ndig = 0, nsig = 0;
1418 
1419 		if (0) {
1420 			/* for testing only, use the wrong RSA key: */
1421 			client_rsa = RSA_generate_key(2048, 0x10001, NULL, NULL);
1422 		}
1423 
1424 		if (client_rsa == NULL) {
1425 			fprintf(stderr, "securevnc_setup: problem reading rsa key from '%s'\n", client_auth);
1426 			exit(1);
1427 		}
1428 
1429 		EVP_DigestInit(dctx, EVP_sha1());
1430 		EVP_DigestUpdate(dctx, keystr, SECUREVNC_KEY_SIZE);
1431 		/*
1432 		 * Without something like the following MITM is still possible.
1433 		 * This is because the MITM knows keystr and can use it with
1434 		 * the server connection as well, and then he just forwards our
1435 		 * signed digest.  The additional information below would be the
1436 		 * MITM's rsa public key, and so the real VNC server will notice
1437 		 * the difference.  And MITM can't sign keystr+server_rsa.pub since
1438 		 * he doesn't have Viewer_ClientAuth.pkey.
1439 		 */
1440 		if (0) {
1441 			EVP_DigestUpdate(dctx, rsasav, SECUREVNC_RSA_PUBKEY_SIZE);
1442 			if (!keystore_verified) {
1443 				fprintf(stderr, "securevnc_setup:\n");
1444 				fprintf(stderr, "securevnc_setup: Warning: even *WITH* Client Authentication in SecureVNC,\n");
1445 				fprintf(stderr, "securevnc_setup: an attacker may be able to trick you into connecting to his\n");
1446 				fprintf(stderr, "securevnc_setup: fake VNC server and supplying VNC or Windows passwords, etc.\n");
1447 				fprintf(stderr, "securevnc_setup: To increase security manually verify the Server RSA key's MD5\n");
1448 				fprintf(stderr, "securevnc_setup: checksum and then have SSVNC save the key in its keystore to\n");
1449 				fprintf(stderr, "securevnc_setup: be used to verify the server in subsequent connections.\n");
1450 				fprintf(stderr, "securevnc_setup:\n");
1451 			}
1452 		} else {
1453 			if (!keystore_verified) {
1454 				fprintf(stderr, "securevnc_setup:\n");
1455 				fprintf(stderr, "securevnc_setup: WARNING: THE FIRST VERSION OF THE SECUREVNC PROTOCOL IS\n");
1456 				fprintf(stderr, "securevnc_setup: WARNING: BEING USED.  *EVEN* WITH CLIENT AUTHENTICATION IT\n");
1457 				fprintf(stderr, "securevnc_setup: WARNING: IS SUSCEPTIBLE TO A MAN-IN-THE-MIDDLE ATTACK.\n");
1458 				fprintf(stderr, "securevnc_setup: To increase security manually verify the Server RSA key's MD5\n");
1459 				fprintf(stderr, "securevnc_setup: checksum and then have SSVNC save the key in its keystore to\n");
1460 				fprintf(stderr, "securevnc_setup: be used to verify the server in subsequent connections.\n");
1461 				fprintf(stderr, "securevnc_setup:\n");
1462 			}
1463 		}
1464 		EVP_DigestFinal(dctx, (unsigned char *)digest, &ndig);
1465 		EVP_MD_CTX_destroy(dctx);
1466 
1467 		signature = (unsigned char *) calloc(RSA_size(client_rsa), 1);
1468 		RSA_sign(NID_sha1, digest, ndig, signature, &nsig, client_rsa);
1469 
1470 		fprintf(stderr, "securevnc_setup: sending ClientAuth.pkey signed data: %d\n", nsig);
1471 		write(server, signature, nsig);
1472 		free(signature);
1473 
1474 		RSA_free(client_rsa);
1475 	}
1476 
1477 	fprintf(stderr, "securevnc_setup: done.\n");
1478 
1479 	/* now send the 'RFB ...' to the viewer */
1480 	if (to_viewer_len > 0) {
1481 		write(viewer, to_viewer, to_viewer_len);
1482 	}
1483 }
1484 
1485 #ifndef ENC_DISABLE_SHOW_CERT
enc_sslerrexit(void)1486 static void enc_sslerrexit(void) {
1487 	unsigned long err = ERR_get_error();
1488 
1489 	if (err) {
1490 		char str[256];
1491 		ERR_error_string(err, str);
1492 		fprintf(stdout, "ssl error: %s\n", str);
1493 	}
1494 	exit(1);
1495 }
1496 #endif
1497 
show_cert(int sock)1498 static void show_cert(int sock) {
1499 #ifndef ENC_DISABLE_SHOW_CERT
1500 	SSL_CTX *ctx;
1501 	SSL *ssl = NULL;
1502 	STACK_OF(X509) *sk = NULL;
1503 	X509 *peer = NULL;
1504 	SSL_CIPHER *c;
1505 	BIO *bio;
1506 	unsigned char *sid =  (unsigned char *) "ultravnc_dsm_helper SID";
1507 	long mode;
1508 	int i;
1509 
1510 	fprintf(stdout, "CONNECTED(%08X)\n",sock);
1511 
1512 	SSL_library_init();
1513 	SSL_load_error_strings();
1514 
1515 	if (!RAND_status()) {
1516 		RAND_poll();
1517 	}
1518 	/* this is not for a secured connection. */
1519 	for (i=0; i < 100; i++) {
1520 		if (!RAND_status()) {
1521 			char tmp[32];
1522 			sprintf(tmp, "%d", getpid() * (17 + i));
1523 			RAND_add(tmp, strlen(tmp), 5);
1524 		} else {
1525 			break;
1526 		}
1527 	}
1528 
1529 	ctx = SSL_CTX_new( SSLv23_client_method() );
1530 	if (ctx == NULL) {
1531 		fprintf(stdout, "show_cert: SSL_CTX_new failed.\n");
1532 		close(sock);
1533 		enc_sslerrexit();
1534 	}
1535 
1536 	mode = 0;
1537 	mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
1538 	mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
1539 	SSL_CTX_set_mode(ctx, mode);
1540 
1541 	if (getenv("ULTRAVNC_DSM_HELPER_SHOWCERT_ADH")) {
1542 		SSL_CTX_set_cipher_list(ctx, "ADH:@STRENGTH");
1543 		SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
1544 	}
1545 
1546 	ssl = SSL_new(ctx);
1547 
1548 	if (ssl == NULL) {
1549 		fprintf(stdout, "show_cert: SSL_new failed.\n");
1550 		close(sock);
1551 		enc_sslerrexit();
1552 	}
1553 
1554 	SSL_set_session_id_context(ssl, sid, strlen((char *)sid));
1555 
1556 	if (! SSL_set_fd(ssl, sock)) {
1557 		fprintf(stdout, "show_cert: SSL_set_fd failed.\n");
1558 		close(sock);
1559 		enc_sslerrexit();
1560 	}
1561 
1562 	SSL_set_connect_state(ssl);
1563 
1564 	if (SSL_connect(ssl) <= 0) {
1565 		unsigned long err = ERR_get_error();
1566 		fprintf(stdout, "show_cert: SSL_connect failed.\n");
1567 		if (err) {
1568 			char str[256];
1569 			ERR_error_string(err, str);
1570 			fprintf(stdout, "ssl error: %s\n", str);
1571 		}
1572 	}
1573 
1574 	SSL_get_verify_result(ssl);
1575 
1576 	sk = SSL_get_peer_cert_chain(ssl);
1577 	if (sk != NULL) {
1578 		fprintf(stdout, "---\nCertificate chain\n");
1579 		for (i=0; i < sk_X509_num(sk); i++) {
1580 			char buf[2048];
1581 			X509_NAME_oneline(X509_get_subject_name(sk_X509_value(sk,i)), buf, sizeof buf);
1582 			fprintf(stdout, "%2d s:%s\n", i, buf);
1583 			X509_NAME_oneline(X509_get_issuer_name(sk_X509_value(sk,i)), buf, sizeof buf);
1584 			fprintf(stdout, "   i:%s\n", buf);
1585 		}
1586 	} else {
1587 		fprintf(stdout, "show_cert: SSL_get_peer_cert_chain failed.\n");
1588 	}
1589 	fprintf(stdout, "---\n");
1590 	peer = SSL_get_peer_certificate(ssl);
1591 	bio = BIO_new_fp(stdout, BIO_NOCLOSE);
1592 	if (peer != NULL) {
1593 		char buf[2048];
1594 		BIO_printf(bio,"Server certificate\n");
1595 		PEM_write_bio_X509(bio, peer);
1596 
1597 		X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof buf);
1598 		BIO_printf(bio,"subject=%s\n",buf);
1599 		X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof buf);
1600 		BIO_printf(bio,"issuer=%s\n",buf);
1601 	} else {
1602 		fprintf(stdout, "show_cert: SSL_get_peer_certificate failed.\n");
1603 	}
1604 
1605 	c = SSL_get_current_cipher(ssl);
1606 	BIO_printf(bio,"---\nNew, %s, Cipher is %s\n", SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
1607 
1608 	if (peer != NULL) {
1609 		EVP_PKEY *pktmp;
1610 		pktmp = X509_get_pubkey(peer);
1611 		BIO_printf(bio,"Server public key is %d bit\n", EVP_PKEY_bits(pktmp));
1612 		EVP_PKEY_free(pktmp);
1613 	}
1614 	BIO_printf(bio,"---\nDONE\n---\n");
1615 
1616 	fflush(stdout);
1617 
1618 #endif
1619 	close(sock);
1620 	exit(0);
1621 }
1622 
1623 #ifndef SOL_IPV6
1624 #ifdef  IPPROTO_IPV6
1625 #define SOL_IPV6 IPPROTO_IPV6
1626 #endif
1627 #endif
1628 
1629 /*
1630  * Listens on incoming port for a client, then connects to remote server.
1631  * Then forks into two processes one is the encrypter the other the
1632  * decrypter.
1633  */
enc_connections(int listen_port,char * connect_host,int connect_port)1634 static void enc_connections(int listen_port, char *connect_host, int connect_port) {
1635 	int listen_fd = -1, listen_fd6 = -1, conn1 = -1, conn2 = -1, ret, one = 1;
1636 	socklen_t clen;
1637 	struct hostent *hp;
1638 	struct sockaddr_in client, server;
1639 	fd_set fds;
1640 	int maxfd = -1;
1641 
1642 	/* zero means use stdio (preferably from socketpair()) */
1643 	if (listen_port == 0) {
1644 		conn1 = fileno(stdin);
1645 		goto use_stdio;
1646 	}
1647 
1648 	if (!strcmp(cipher, "showcert")) {
1649 		goto use_stdio;
1650 	}
1651 
1652 	/* fd=n,m means use the supplied already established sockets */
1653 	if (sscanf(connect_host, "fd=%d,%d", &conn1, &conn2) == 2) {
1654 		goto use_input_fds;
1655 	}
1656 
1657 	/* create the listening socket: */
1658 	memset(&client, 0, sizeof(client));
1659 	client.sin_family = AF_INET;
1660 	if (listen_port < 0) {
1661 		/* negative port means use loopback */
1662 		client.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1663 		client.sin_port = htons(-listen_port);
1664 	} else {
1665 		client.sin_addr.s_addr = htonl(INADDR_ANY);
1666 		client.sin_port = htons(listen_port);
1667 	}
1668 
1669 	listen_fd = socket(AF_INET, SOCK_STREAM, 0);
1670 	if (listen_fd < 0) {
1671 		perror("socket");
1672 		goto try6;
1673 	}
1674 
1675 	ret = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
1676 	    (char *)&one, sizeof(one));
1677 	if (ret < 0) {
1678 		perror("setsockopt");
1679 		close(listen_fd);
1680 		listen_fd = -1;
1681 		goto try6;
1682 	}
1683 
1684 	ret = bind(listen_fd, (struct sockaddr *) &client, sizeof(client));
1685 	if (ret < 0) {
1686 		perror("bind");
1687 		close(listen_fd);
1688 		listen_fd = -1;
1689 		goto try6;
1690 	}
1691 
1692 	ret = listen(listen_fd, 2);
1693 	if (ret < 0) {
1694 		perror("listen");
1695 		close(listen_fd);
1696 		listen_fd = -1;
1697 		goto try6;
1698 	}
1699 
1700 	try6:
1701 #ifdef AF_INET6
1702 	if (!getenv("ULTRAVNC_DSM_HELPER_NOIPV6")) {
1703 		struct sockaddr_in6 sin;
1704 		int one = 1, sock = -1;
1705 
1706 		sock = socket(AF_INET6, SOCK_STREAM, 0);
1707 		if (sock < 0) {
1708 			perror("socket6");
1709 			goto fail;
1710 		}
1711 
1712 		if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
1713 			perror("setsockopt6 SO_REUSEADDR");
1714 			close(sock);
1715 			sock = -1;
1716 			goto fail;
1717 		}
1718 
1719 #if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
1720 		if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
1721 			perror("setsockopt6 IPV6_V6ONLY");
1722 			close(sock);
1723 			sock = -1;
1724 			goto fail;
1725 		}
1726 #endif
1727 
1728 		memset((char *)&sin, 0, sizeof(sin));
1729 		sin.sin6_family = AF_INET6;
1730 
1731 		if (listen_port < 0) {
1732 			sin.sin6_addr = in6addr_loopback;
1733 			sin.sin6_port = htons(-listen_port);
1734 		} else {
1735 			sin.sin6_addr = in6addr_any;
1736 			sin.sin6_port = htons(listen_port);
1737 		}
1738 
1739 		if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
1740 			perror("bind6");
1741 			close(sock);
1742 			sock = -1;
1743 			goto fail;
1744 		}
1745 
1746 		if (listen(sock, 2) < 0) {
1747 			perror("listen6");
1748 			close(sock);
1749 			sock = -1;
1750 			goto fail;
1751 		}
1752 
1753 		fail:
1754 		listen_fd6 = sock;
1755 	}
1756 #endif
1757 
1758 	if (listen_fd < 0 && listen_fd6 < 0) {
1759 		fprintf(stderr, "%s: could not listen on port: %d\n",
1760 		    prog, listen_port);
1761 		exit(1);
1762 	}
1763 
1764 	fprintf(stderr, "%s: waiting for connection on port: %d\n",
1765 	    prog, listen_port);
1766 
1767 	/* wait for a connection: */
1768 	FD_ZERO(&fds);
1769 	if (listen_fd >= 0) {
1770 		FD_SET(listen_fd, &fds);
1771 		if (listen_fd > maxfd) {
1772 			maxfd = listen_fd;
1773 		}
1774 	}
1775 	if (listen_fd6 >= 0) {
1776 		FD_SET(listen_fd6, &fds);
1777 		if (listen_fd6 > maxfd) {
1778 			maxfd = listen_fd6;
1779 		}
1780 	}
1781 	if (select(maxfd+1, &fds, NULL, NULL, NULL) <= 0) {
1782 		perror("select");
1783 		exit(1);
1784 	}
1785 
1786 	if (FD_ISSET(listen_fd, &fds)) {
1787 		clen = sizeof(client);
1788 		conn1 = accept(listen_fd, (struct sockaddr *) &client, &clen);
1789 		if (conn1 < 0) {
1790 			perror("accept");
1791 			exit(1);
1792 		}
1793 	} else if (FD_ISSET(listen_fd6, &fds)) {
1794 #ifdef AF_INET6
1795 		struct sockaddr_in6 addr;
1796 		socklen_t addrlen = sizeof(addr);
1797 
1798 		conn1 = accept(listen_fd6, (struct sockaddr *) &addr, &addrlen);
1799 		if (conn1 < 0) {
1800 			perror("accept6");
1801 			exit(1);
1802 		}
1803 #else
1804 		fprintf(stderr, "No IPv6 / AF_INET6 support.\n");
1805 		exit(1);
1806 #endif
1807 	}
1808 
1809 	if (setsockopt(conn1, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) {
1810 		perror("setsockopt TCP_NODELAY");
1811 		exit(1);
1812 	}
1813 
1814 	/* done with the listening socket(s): */
1815 	if (listen_fd >= 0) {
1816 		close(listen_fd);
1817 	}
1818 	if (listen_fd6 >= 0) {
1819 		close(listen_fd6);
1820 	}
1821 
1822 	if (getenv("ULTRAVNC_DSM_HELPER_BG")) {
1823 		int p, n;
1824 		if ((p = fork()) > 0)  {
1825 			fprintf(stderr, "%s: putting child %d in background.\n",
1826 			    prog, p);
1827 			exit(0);
1828 		} else if (p == -1) {
1829 			fprintf(stderr, "%s: could not fork\n", prog);
1830 			perror("fork");
1831 			exit(1);
1832 		}
1833 		if (setsid() == -1) {
1834 			fprintf(stderr, "%s: setsid failed\n", prog);
1835 			perror("setsid");
1836 			exit(1);
1837 		}
1838 		/* adjust our stdio */
1839 		n = open("/dev/null", O_RDONLY);
1840 		dup2(n, 0);
1841 		dup2(n, 1);
1842 		dup2(n, 2);
1843 		if (n > 2) {
1844 			close(n);
1845 		}
1846 	}
1847 
1848 	use_stdio:
1849 
1850 	fprintf(stderr, "%s: got connection: %d\n", prog, conn1);
1851 
1852 	/* now connect to remote server: */
1853 	memset(&server, 0, sizeof(server));
1854 	server.sin_family = AF_INET;
1855 	server.sin_port = htons(connect_port);
1856 
1857 	if ((server.sin_addr.s_addr = inet_addr(connect_host)) == htonl(INADDR_NONE)) {
1858 		if (!(hp = gethostbyname(connect_host))) {
1859 			perror("gethostbyname");
1860 			goto tryconn6;
1861 		}
1862 		server.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
1863 	}
1864 
1865 	conn2 = socket(AF_INET, SOCK_STREAM, 0);
1866 	if (conn2 < 0) {
1867 		perror("socket");
1868 		goto tryconn6;
1869 	}
1870 
1871 	if (connect(conn2, (struct sockaddr *)&server, (sizeof(server))) < 0) {
1872 		perror("connect");
1873 		goto tryconn6;
1874 	}
1875 
1876 	tryconn6:
1877 #ifdef AF_INET6
1878 	if (conn2 < 0 && !getenv("ULTRAVNC_DSM_HELPER_NOIPV6")) {
1879 		int err;
1880 		struct addrinfo *ai;
1881 		struct addrinfo hints;
1882 		char service[32];
1883 
1884 		fprintf(stderr, "connect[ipv6]: trying to connect via IPv6 to %s\n", connect_host);
1885 		conn2 = -1;
1886 
1887 		memset(&hints, 0, sizeof(hints));
1888 		sprintf(service, "%d", connect_port);
1889 
1890 		hints.ai_family = AF_UNSPEC;
1891 		hints.ai_socktype = SOCK_STREAM;
1892 #ifdef AI_ADDRCONFIG
1893 		hints.ai_flags |= AI_ADDRCONFIG;
1894 #endif
1895 #ifdef AI_NUMERICSERV
1896 		hints.ai_flags |= AI_NUMERICSERV;
1897 #endif
1898 
1899 		err = getaddrinfo(connect_host, service, &hints, &ai);
1900 		if (err != 0) {
1901 			fprintf(stderr, "getaddrinfo[%d]: %s\n", err, gai_strerror(err));
1902 		} else {
1903 			struct addrinfo *ap = ai;
1904 			while (ap != NULL) {
1905 				int fd = -1;
1906 				fd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
1907 				if (fd == -1) {
1908 					perror("socket6");
1909 				} else {
1910 					int dmsg = 0;
1911 					int res = connect(fd, ap->ai_addr, ap->ai_addrlen);
1912 #if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
1913 					if (res != 0) {
1914 						int zero = 0;
1915 						perror("connect6");
1916 						dmsg = 1;
1917 						if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (char *)&zero, sizeof(zero)) == 0) {
1918 							fprintf(stderr, "connect[ipv6]: trying again with IPV6_V6ONLY=0\n");
1919 							res = connect(fd, ap->ai_addr, ap->ai_addrlen);
1920 							dmsg = 0;
1921 						}
1922 					}
1923 #endif
1924 					if (res == 0) {
1925 						conn2 = fd;
1926 						break;
1927 					} else {
1928 						if (!dmsg) perror("connect6");
1929 						close(fd);
1930 					}
1931 				}
1932 				ap = ap->ai_next;
1933 			}
1934 			freeaddrinfo(ai);
1935 		}
1936 	}
1937 #endif
1938 	if (conn2 < 0) {
1939 		fprintf(stderr, "could not connect to %s\n", connect_host);
1940 		exit(1);
1941 	}
1942 	if (conn2 >= 0 && setsockopt(conn2, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) {
1943 		perror("setsockopt TCP_NODELAY");
1944 	}
1945 
1946 	use_input_fds:
1947 
1948 	if (!strcmp(cipher, "showcert")) {
1949 		show_cert(conn2);
1950 		close(conn2);
1951 		exit(0);
1952 	}
1953 
1954 	if (securevnc) {
1955 		securevnc_setup(conn1, conn2);
1956 	}
1957 
1958 	/* fork into two processes; one for each direction: */
1959 	parent = getpid();
1960 
1961 	child = fork();
1962 
1963 	if (child == (pid_t) -1) {
1964 		/* couldn't fork... */
1965 		perror("fork");
1966 		close(conn1);
1967 		close(conn2);
1968 		exit(1);
1969 	}
1970 
1971 	/* Do transfer/encode/decode loop: */
1972 
1973 	if (child == 0) {
1974 		/* encrypter: local-viewer -> remote-server */
1975 		if (!strcmp(cipher, "none") || !strcmp(cipher, "relay")) {
1976 			enc_raw_xfer(conn1, conn2);
1977 		} else {
1978 			enc_xfer(conn1, conn2, 1);
1979 		}
1980 	} else {
1981 		/* decrypter: remote-server -> local-viewer */
1982 		if (!strcmp(cipher, "none") || !strcmp(cipher, "relay")) {
1983 			enc_raw_xfer(conn2, conn1);
1984 		} else {
1985 			enc_xfer(conn2, conn1, 0);
1986 		}
1987 	}
1988 }
1989 #endif /* ENC_HAVE_OPENSSL */
1990 
doloop(int argc,char * argv[])1991 static void doloop (int argc, char *argv[]) {
1992 	int ms = atoi(getenv("ULTRAVNC_DSM_HELPER_LOOP"));
1993 	if (ms > 0) {
1994 		char *cmd;
1995 		int i, len = 0;
1996 		for (i = 0; i < argc; i++) {
1997 			len += strlen(argv[i]) + 2;
1998 		}
1999 		cmd = (char *)malloc(len);
2000 		cmd[0] = '\0';
2001 		for (i = 0; i < argc; i++) {
2002 			strcat(cmd, argv[i]);
2003 			if (i < argc - 1) {
2004 				strcat(cmd, " ");
2005 			}
2006 		}
2007 
2008 		putenv("ULTRAVNC_DSM_HELPER_LOOP_SET=1");
2009 		if (ms == 1) {
2010 			ms = 500;
2011 		}
2012 		i = 0;
2013 		while (1) {
2014 			fprintf(stderr, "loop running[%d]: %s\n", ++i, cmd);
2015 			system(cmd);
2016 			usleep(1000 * ms);
2017 		}
2018 	}
2019 }
2020 
main(int argc,char * argv[])2021 int main (int argc, char *argv[]) {
2022 	char *kf, *q;
2023 
2024 	if (getenv("ULTRAVNC_DSM_HELPER_LOOP")) {
2025 		if (!getenv("ULTRAVNC_DSM_HELPER_LOOP_SET")) {
2026 			doloop(argc, argv);
2027 		}
2028 	}
2029 
2030 	if (argc == 3) {
2031 		if (!strcmp(argv[1], "showcert")) {
2032 			enc_do(argv[1], NULL, NULL, argv[2]);
2033 			return 0;
2034 		}
2035 	}
2036 	if (argc == 4) {
2037 		if (!strcmp(argv[1], "none") || !strcmp(argv[1], "relay")) {
2038 			enc_do(argv[1], NULL, argv[2], argv[3]);
2039 			return 0;
2040 		}
2041 	}
2042 	if (argc < 5) {
2043 		fprintf(stdout, "%s\n", usage);
2044 		exit(1);
2045 	}
2046 
2047 	/* guard against pw= on cmdline (e.g. linux) */
2048 	kf = strdup(argv[2]);
2049 	q = strstr(argv[2], "pw=");
2050 	if (q) {
2051 		while (*q != '\0') {
2052 			*q = '\0';	/* now ps(1) won't show it */
2053 			q++;
2054 		}
2055 	}
2056 
2057 	enc_do(argv[1], kf, argv[3], argv[4]);
2058 
2059 	return 0;
2060 }
2061 
2062 /*
2063  * a crude utility to have this work "keyless" i.e. the vnc password
2064  * is used instead of a pre-shared key file.
2065  */
2066 
2067 /*
2068 
2069 #!/usr/bin/perl
2070 #
2071 # md5_to_rc4key.pl
2072 #
2073 # This program requires md5sum(1) installed on your machine.
2074 #
2075 # It translates a VNC password to a ultravnc dsm plugin
2076 # compatible key file.
2077 #
2078 # Supply VNC password on cmdline, capture in key file:
2079 #
2080 #	md5_to_rc4key.pl swordfish    > rc4.key
2081 #	md5_to_rc4key.pl -a swordfish > arc4.key
2082 #
2083 # Use rc4.key with ultravnc_dsm_helper in msrc4 mode,
2084 # or arc4.key in either arc4 or aesv4 mode.
2085 #
2086 #
2087 $rfmt = 1;
2088 if ($ARGV[0] eq '-a') {
2089 	$rfmt = 0;
2090 	shift;
2091 }
2092 
2093 # n.b. this is not super secure against bad locals...
2094 
2095 $pw = shift;
2096 $tmp = "/tmp/md5out.$$";
2097 
2098 open(MD5, "| md5sum > $tmp");
2099 print MD5 $pw;
2100 close MD5;
2101 
2102 $md5 = `cat $tmp`;
2103 unlink $tmp;
2104 
2105 ($md5, $junk) = split(/\s/, $md5);
2106 
2107 print "128 bit" if $rfmt;
2108 print 'a' x 4	if $rfmt;
2109 print 'b' x 12	if $rfmt;
2110 
2111 $str = '';
2112 foreach $d (split(//, $md5)) {
2113 	$str .= $d;
2114 	if (length($str) == 2) {
2115 		push @key, $str;
2116 		$str = '';
2117 	}
2118 }
2119 
2120 @key = (reverse @key) if $rfmt;
2121 
2122 foreach $h (@key) {
2123 	$c = pack('c', hex("0x$h"));
2124 	print $c;
2125 }
2126 
2127 print 'c' x 48	if $rfmt;
2128 
2129 */
2130