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