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