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