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