Home | History | Annotate | Download | only in x11vnc
      1 /*
      2    Copyright (C) 2002-2010 Karl J. Runge <runge (at) karlrunge.com>
      3    All rights reserved.
      4 
      5 This file is part of x11vnc.
      6 
      7 x11vnc is free software; you can redistribute it and/or modify
      8 it under the terms of the GNU General Public License as published by
      9 the Free Software Foundation; either version 2 of the License, or (at
     10 your option) any later version.
     11 
     12 x11vnc is distributed in the hope that it will be useful,
     13 but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with x11vnc; if not, write to the Free Software
     19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
     20 or see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, as a special exception, Karl J. Runge
     23 gives permission to link the code of its release of x11vnc with the
     24 OpenSSL project's "OpenSSL" library (or with modified versions of it
     25 that use the same license as the "OpenSSL" library), and distribute
     26 the linked executables.  You must obey the GNU General Public License
     27 in all respects for all of the code used other than "OpenSSL".  If you
     28 modify this file, you may extend this exception to your version of the
     29 file, but you are not obligated to do so.  If you do not wish to do
     30 so, delete this exception statement from your version.
     31 */
     32 
     33 #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 (at) 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 
    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 
    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 		} 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 
    612 static 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  */
    692 static 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 
   1051 static 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 
   1103 static 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 
   1122 static 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 
   1178 static 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 
   1221 static void sslexit(char *msg) {
   1222 	fprintf(stderr, "%s: %s\n", msg, ERR_error_string(ERR_get_error(), NULL));
   1223 	exit(1);
   1224 }
   1225 
   1226 static 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
   1521 static 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 
   1533 static 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  */
   1669 static 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 
   2026 static 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 
   2056 extern 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;
   2123 if ($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 
   2133 open(MD5, "| md5sum > $tmp");
   2134 print MD5 $pw;
   2135 close MD5;
   2136 
   2137 $md5 = `cat $tmp`;
   2138 unlink $tmp;
   2139 
   2140 ($md5, $junk) = split(/\s/, $md5);
   2141 
   2142 print "128 bit" if $rfmt;
   2143 print 'a' x 4	if $rfmt;
   2144 print 'b' x 12	if $rfmt;
   2145 
   2146 $str = '';
   2147 foreach $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 
   2157 foreach $h (@key) {
   2158 	$c = pack('c', hex("0x$h"));
   2159 	print $c;
   2160 }
   2161 
   2162 print 'c' x 48	if $rfmt;
   2163 
   2164 */
   2165 #endif /* _X11VNC_ENC_H */
   2166