blob: 55d49bbef524e214e5c3b0a28087fed9c112170b [file] [log] [blame]
San Mehata430b2b2014-09-23 08:30:51 -07001/*
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 */