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 /* -- sslcmds.c -- */
34
35 #include "x11vnc.h"
36 #include "inet.h"
37 #include "cleanup.h"
38 #include "sslhelper.h"
39 #include "ssltools.h"
40 #include "connections.h"
41
42 #if LIBVNCSERVER_HAVE_FORK
43 #if LIBVNCSERVER_HAVE_SYS_WAIT_H
44 #if LIBVNCSERVER_HAVE_WAITPID
45 #define SSLCMDS
46 #endif
47 #endif
48 #endif
49
50
51 void check_stunnel(void);
52 int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport);
53 void stop_stunnel(void);
54 void setup_stunnel(int rport, int *argc, char **argv);
55 char *get_Cert_dir(char *cdir_in, char **tmp_in);
56 void sslScripts(void);
57 void sslGenCA(char *cdir);
58 void sslGenCert(char *ty, char *nm);
59 void sslEncKey(char *path, int info_only);
60
61 static pid_t stunnel_pid = 0;
62
check_stunnel(void)63 void check_stunnel(void) {
64 static time_t last_check = 0;
65 time_t now = time(NULL);
66
67 if (last_check + 3 >= now) {
68 return;
69 }
70 last_check = now;
71
72 /* double check that stunnel is still running: */
73
74 if (stunnel_pid > 0) {
75 int status;
76 #ifdef SSLCMDS
77 waitpid(stunnel_pid, &status, WNOHANG);
78 #endif
79 if (kill(stunnel_pid, 0) != 0) {
80 #ifdef SSLCMDS
81 waitpid(stunnel_pid, &status, WNOHANG);
82 #endif
83 rfbLog("stunnel subprocess %d died.\n", stunnel_pid);
84 stunnel_pid = 0;
85 clean_up_exit(1);
86 }
87 }
88 }
89
start_stunnel(int stunnel_port,int x11vnc_port,int hport,int x11vnc_hport)90 int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport) {
91 #ifdef SSLCMDS
92 char extra[] = ":/usr/sbin:/usr/local/sbin:/dist/sbin";
93 char *path, *p, *exe;
94 char *stunnel_path = NULL;
95 struct stat verify_buf;
96 struct stat crl_buf;
97 int status, tmp_pem = 0;
98
99 if (stunnel_pid) {
100 stop_stunnel();
101 }
102 stunnel_pid = 0;
103
104 path = getenv("PATH");
105 if (! path) {
106 path = strdup(extra+1);
107 } else {
108 char *pt = path;
109 path = (char *) malloc(strlen(path)+strlen(extra)+1);
110 if (! path) {
111 return 0;
112 }
113 strcpy(path, pt);
114 strcat(path, extra);
115 }
116
117 exe = (char *) malloc(strlen(path) + 1 + strlen("stunnel4") + 1);
118
119 p = strtok(path, ":");
120
121 exe[0] = '\0';
122
123 while (p) {
124 struct stat sbuf;
125
126 sprintf(exe, "%s/%s", p, "stunnel4");
127 if (! stunnel_path && stat(exe, &sbuf) == 0) {
128 if (! S_ISDIR(sbuf.st_mode)) {
129 stunnel_path = exe;
130 break;
131 }
132 }
133
134 sprintf(exe, "%s/%s", p, "stunnel");
135 if (! stunnel_path && stat(exe, &sbuf) == 0) {
136 if (! S_ISDIR(sbuf.st_mode)) {
137 stunnel_path = exe;
138 break;
139 }
140 }
141
142 p = strtok(NULL, ":");
143 }
144 if (path) {
145 free(path);
146 }
147
148 if (getenv("STUNNEL_PROG")) {
149 free(exe);
150 exe = strdup(getenv("STUNNEL_PROG"));
151 stunnel_path = exe;
152 }
153
154 if (! stunnel_path) {
155 free(exe);
156 return 0;
157 }
158 if (stunnel_path[0] == '\0') {
159 free(exe);
160 return 0;
161 }
162
163 /* stunnel */
164 if (no_external_cmds || !cmd_ok("stunnel")) {
165 rfbLogEnable(1);
166 rfbLog("start_stunnel: cannot run external commands in -nocmds mode:\n");
167 rfbLog(" \"%s\"\n", stunnel_path);
168 rfbLog(" exiting.\n");
169 clean_up_exit(1);
170 }
171
172 if (! quiet) {
173 rfbLog("\n");
174 rfbLog("starting ssl tunnel: %s %d -> %d\n", stunnel_path,
175 stunnel_port, x11vnc_port);
176 }
177
178 if (stunnel_pem && strstr(stunnel_pem, "SAVE") == stunnel_pem) {
179 stunnel_pem = get_saved_pem(stunnel_pem, 1);
180 if (! stunnel_pem) {
181 rfbLog("start_stunnel: could not create or open"
182 " saved PEM.\n");
183 clean_up_exit(1);
184 }
185 } else if (!stunnel_pem) {
186 stunnel_pem = create_tmp_pem(NULL, 0);
187 if (! stunnel_pem) {
188 rfbLog("start_stunnel: could not create temporary,"
189 " self-signed PEM.\n");
190 clean_up_exit(1);
191 }
192 tmp_pem = 1;
193 if (getenv("X11VNC_SHOW_TMP_PEM")) {
194 FILE *in = fopen(stunnel_pem, "r");
195 if (in != NULL) {
196 char line[128];
197 fprintf(stderr, "\n");
198 while (fgets(line, 128, in) != NULL) {
199 fprintf(stderr, "%s", line);
200 }
201 fprintf(stderr, "\n");
202 fclose(in);
203 }
204 }
205 }
206
207 if (ssl_verify) {
208 char *file = get_ssl_verify_file(ssl_verify);
209 if (file) {
210 ssl_verify = file;
211 }
212 if (stat(ssl_verify, &verify_buf) != 0) {
213 rfbLog("stunnel: %s does not exist.\n", ssl_verify);
214 clean_up_exit(1);
215 }
216 }
217 if (ssl_crl) {
218 if (stat(ssl_crl, &crl_buf) != 0) {
219 rfbLog("stunnel: %s does not exist.\n", ssl_crl);
220 clean_up_exit(1);
221 }
222 }
223
224 stunnel_pid = fork();
225
226 if (stunnel_pid < 0) {
227 stunnel_pid = 0;
228 free(exe);
229 return 0;
230 }
231
232 if (stunnel_pid == 0) {
233 FILE *in;
234 char fd[20];
235 int i;
236 char *st_if = getenv("STUNNEL_LISTEN");
237
238 if (st_if == NULL) {
239 st_if = "";
240 } else {
241 st_if = (char *) malloc(strlen(st_if) + 2);
242 sprintf(st_if, "%s:", getenv("STUNNEL_LISTEN"));
243 }
244
245
246 for (i=3; i<256; i++) {
247 close(i);
248 }
249
250 if (use_stunnel == 3) {
251 char sp[30], xp[30], *a = NULL;
252 char *st = stunnel_path;
253 char *pm = stunnel_pem;
254 char *sv = ssl_verify;
255
256 sprintf(sp, "%d", stunnel_port);
257 sprintf(xp, "%d", x11vnc_port);
258
259 if (ssl_verify) {
260 if(S_ISDIR(verify_buf.st_mode)) {
261 a = "-a";
262 } else {
263 a = "-A";
264 }
265 }
266
267 if (ssl_crl) {
268 rfbLog("stunnel: stunnel3 does not support CRL. %s\n", ssl_crl);
269 clean_up_exit(1);
270 }
271
272 if (stunnel_pem && ssl_verify) {
273 /* XXX double check -v 2 */
274 execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
275 "none", "-p", pm, a, sv, "-v", "2",
276 (char *) NULL);
277 } else if (stunnel_pem && !ssl_verify) {
278 execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
279 "none", "-p", pm,
280 (char *) NULL);
281 } else if (!stunnel_pem && ssl_verify) {
282 execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
283 "none", a, sv, "-v", "2",
284 (char *) NULL);
285 } else {
286 execlp(st, st, "-f", "-d", sp, "-r", xp, "-P",
287 "none", (char *) NULL);
288 }
289 exit(1);
290 }
291
292 in = tmpfile();
293 if (! in) {
294 exit(1);
295 }
296
297 fprintf(in, "foreground = yes\n");
298 fprintf(in, "pid =\n");
299 if (stunnel_pem) {
300 fprintf(in, "cert = %s\n", stunnel_pem);
301 }
302 if (ssl_crl) {
303 if(S_ISDIR(crl_buf.st_mode)) {
304 fprintf(in, "CRLpath = %s\n", ssl_crl);
305 } else {
306 fprintf(in, "CRLfile = %s\n", ssl_crl);
307 }
308 }
309 if (ssl_verify) {
310 if(S_ISDIR(verify_buf.st_mode)) {
311 fprintf(in, "CApath = %s\n", ssl_verify);
312 } else {
313 fprintf(in, "CAfile = %s\n", ssl_verify);
314 }
315 fprintf(in, "verify = 2\n");
316 }
317 fprintf(in, ";debug = 7\n\n");
318 fprintf(in, "[x11vnc_stunnel]\n");
319 fprintf(in, "accept = %s%d\n", st_if, stunnel_port);
320 fprintf(in, "connect = %d\n", x11vnc_port);
321
322 if (hport > 0 && x11vnc_hport > 0) {
323 fprintf(in, "\n[x11vnc_http]\n");
324 fprintf(in, "accept = %s%d\n", st_if, hport);
325 fprintf(in, "connect = %d\n", x11vnc_hport);
326 }
327
328 fflush(in);
329 rewind(in);
330
331 if (getenv("STUNNEL_DEBUG")) {
332 char line[1000];
333 fprintf(stderr, "\nstunnel config contents:\n\n");
334 while (fgets(line, sizeof(line), in) != NULL) {
335 fprintf(stderr, "%s", line);
336 }
337 fprintf(stderr, "\n");
338 rewind(in);
339 }
340
341 sprintf(fd, "%d", fileno(in));
342 execlp(stunnel_path, stunnel_path, "-fd", fd, (char *) NULL);
343 exit(1);
344 }
345
346 free(exe);
347 usleep(750 * 1000);
348
349 waitpid(stunnel_pid, &status, WNOHANG);
350
351 if (ssl_verify && strstr(ssl_verify, "/sslverify-tmp-load-")) {
352 /* temporary file */
353 usleep(1000 * 1000);
354 unlink(ssl_verify);
355 }
356 if (tmp_pem) {
357 /* temporary cert */
358 usleep(1500 * 1000);
359 unlink(stunnel_pem);
360 }
361
362 if (kill(stunnel_pid, 0) != 0) {
363 waitpid(stunnel_pid, &status, WNOHANG);
364 stunnel_pid = 0;
365 return 0;
366 }
367
368 if (! quiet) {
369 rfbLog("stunnel pid is: %d\n", (int) stunnel_pid);
370 }
371
372 return 1;
373 #else
374 return 0;
375 #endif
376 }
377
stop_stunnel(void)378 void stop_stunnel(void) {
379 int status;
380 if (! stunnel_pid) {
381 return;
382 }
383 #ifdef SSLCMDS
384 kill(stunnel_pid, SIGTERM);
385 usleep (150 * 1000);
386 kill(stunnel_pid, SIGKILL);
387 usleep (50 * 1000);
388 waitpid(stunnel_pid, &status, WNOHANG);
389 #endif
390 stunnel_pid = 0;
391 }
392
setup_stunnel(int rport,int * argc,char ** argv)393 void setup_stunnel(int rport, int *argc, char **argv) {
394 int i, xport = 0, hport = 0, xhport = 0;
395
396 if (! rport && argc && argv) {
397 for (i=0; i< *argc; i++) {
398 if (argv[i] && !strcmp(argv[i], "-rfbport")) {
399 if (i < *argc - 1) {
400 rport = atoi(argv[i+1]);
401 }
402 }
403 }
404 }
405
406 if (! rport) {
407 /* we do our own autoprobing then... */
408 rport = find_free_port(5900, 5999);
409 if (! rport) {
410 goto stunnel_fail;
411 }
412 }
413
414 xport = find_free_port(5950, 5999);
415 if (! xport) {
416 goto stunnel_fail;
417 }
418
419 if (https_port_num > 0) {
420 hport = https_port_num;
421 }
422
423 if (! hport && argc && argv) {
424 for (i=0; i< *argc; i++) {
425 if (argv[i] && !strcmp(argv[i], "-httpport")) {
426 if (i < *argc - 1) {
427 hport = atoi(argv[i+1]);
428 }
429 }
430 }
431 }
432
433 if (! hport && http_try_it) {
434 hport = find_free_port(rport-100, rport-1);
435 if (! hport) {
436 goto stunnel_fail;
437 }
438 }
439 if (hport) {
440 xhport = find_free_port(5850, 5899);
441 if (! xhport) {
442 goto stunnel_fail;
443 }
444 stunnel_http_port = hport;
445 }
446
447
448 if (start_stunnel(rport, xport, hport, xhport)) {
449 int tweaked = 0;
450 char tmp[30];
451 sprintf(tmp, "%d", xport);
452 if (argc && argv) {
453 for (i=0; i < *argc; i++) {
454 if (argv[i] && !strcmp(argv[i], "-rfbport")) {
455 if (i < *argc - 1) {
456 /* replace orig value */
457 argv[i+i] = strdup(tmp);
458 tweaked = 1;
459 break;
460 }
461 }
462 }
463 if (! tweaked) {
464 i = *argc;
465 argv[i] = strdup("-rfbport");
466 argv[i+1] = strdup(tmp);
467 *argc += 2;
468 got_rfbport = 1;
469 got_rfbport_val = atoi(tmp);
470 }
471 }
472 stunnel_port = rport;
473 ssl_initialized = 1;
474 return;
475 }
476
477 stunnel_fail:
478 rfbLog("failed to start stunnel.\n");
479 clean_up_exit(1);
480 }
481
get_Cert_dir(char * cdir_in,char ** tmp_in)482 char *get_Cert_dir(char *cdir_in, char **tmp_in) {
483 char *cdir, *home, *tmp;
484 struct stat sbuf;
485 int i;
486 char *cases1[] = {"/.vnc", "/.vnc/certs", "/.vnc/certs/CA"};
487 char *cases2[] = {"", "/CA", "/tmp"};
488
489 if (cdir_in != NULL) {
490 cdir = cdir_in;
491 } else {
492 cdir = ssl_certs_dir;
493 }
494
495 if (cdir == NULL) {
496 home = get_home_dir();
497 if (! home) {
498 return NULL;
499 }
500 cdir = (char *) malloc(strlen(home) + strlen("/.vnc/certs/CA") + 1);
501 for (i=0; i<3; i++) {
502 sprintf(cdir, "%s%s", home, cases1[i]);
503 if (stat(cdir, &sbuf) != 0) {
504 rfbLog("creating dir: %s\n", cdir);
505 if (mkdir(cdir, 0755) != 0) {
506 rfbLog("could not create directory %s\n", cdir);
507 rfbLogPerror("mkdir");
508 return NULL;
509 }
510 } else if (! S_ISDIR(sbuf.st_mode)) {
511 rfbLog("not a directory: %s\n", cdir);
512 return NULL;
513 }
514 }
515 sprintf(cdir, "%s%s", home, cases1[1]);
516 }
517
518 tmp = (char *) malloc(strlen(cdir) + strlen("/tmp") + 1);
519 for (i=0; i<3; i++) {
520 int ret;
521 sprintf(tmp, "%s%s", cdir, cases2[i]);
522 if (stat(tmp, &sbuf) != 0) {
523 rfbLog("creating dir: %s\n", tmp);
524 if (! strcmp(cases2[i], "/tmp")) {
525 ret = mkdir(tmp, 0700);
526 } else {
527 ret = mkdir(tmp, 0755);
528 }
529
530 if (ret != 0) {
531 rfbLog("could not create directory %s\n", tmp);
532 rfbLogPerror("mkdir");
533 return NULL;
534 }
535 } else if (! S_ISDIR(sbuf.st_mode)) {
536 rfbLog("not a directory: %s\n", tmp);
537 return NULL;
538 }
539 }
540 sprintf(tmp, "%s/tmp", cdir);
541 *tmp_in = tmp;
542 return cdir;
543 }
544
getsslscript(char * cdir,char * name,char * script)545 static char *getsslscript(char *cdir, char *name, char *script) {
546 char *openssl = find_openssl_bin();
547 char *tmp, *scr, *cdir_use;
548 FILE *out;
549
550 if (! openssl || openssl[0] == '\0') {
551 exit(1);
552 }
553
554 if (!name || !script) {
555 exit(1);
556 }
557
558 cdir_use = get_Cert_dir(cdir, &tmp);
559 if (!cdir_use || !tmp) {
560 exit(1);
561 }
562
563 scr = (char *) malloc(strlen(tmp) + 1 + strlen(name) + 30);
564
565 sprintf(scr, "%s/%s.%d.sh", tmp, name, getpid());
566 out = fopen(scr, "w");
567 if (! out) {
568 rfbLog("could not open: %s\n", scr);
569 rfbLogPerror("fopen");
570 exit(1);
571 }
572 fprintf(out, "%s", script);
573 fclose(out);
574
575 rfbLog("Using openssl: %s\n", openssl);
576 rfbLog("Using certs dir: %s\n", cdir_use);
577 fprintf(stderr, "\n");
578
579 set_env("BASE_DIR", cdir_use);
580 set_env("OPENSSL", openssl);
581
582 return scr;
583 }
584
sslScripts(void)585 void sslScripts(void) {
586 fprintf(stdout, "======================================================\n");
587 fprintf(stdout, "genCA script for '-sslGenCA':\n\n");
588 fprintf(stdout, "%s\n", genCA);
589 fprintf(stdout, "======================================================\n");
590 fprintf(stdout, "genCert script for '-sslGenCert', etc.:\n\n");
591 fprintf(stdout, "%s\n", genCert);
592 }
593
sslGenCA(char * cdir)594 void sslGenCA(char *cdir) {
595 char *cmd, *scr = getsslscript(cdir, "genca", genCA);
596
597 if (! scr) {
598 exit(1);
599 }
600
601 cmd = (char *)malloc(strlen("/bin/sh ") + strlen(scr) + 1);
602 sprintf(cmd, "/bin/sh %s", scr);
603
604 system(cmd);
605 unlink(scr);
606
607 free(cmd);
608 free(scr);
609 }
610
sslGenCert(char * ty,char * nm)611 void sslGenCert(char *ty, char *nm) {
612 char *cmd, *scr = getsslscript(NULL, "gencert", genCert);
613
614 if (! scr) {
615 exit(1);
616 }
617
618 cmd = (char *)malloc(strlen("/bin/sh ") + strlen(scr) + 1);
619 sprintf(cmd, "/bin/sh %s", scr);
620
621 if (! ty) {
622 set_env("TYPE", "");
623 } else {
624 set_env("TYPE", ty);
625 }
626 if (! nm) {
627 set_env("NAME", "");
628 } else {
629 char *q = strstr(nm, "SAVE-");
630 if (!strcmp(nm, "SAVE")) {
631 set_env("NAME", "");
632 } else if (q == nm) {
633 q += strlen("SAVE-");
634 set_env("NAME", q);
635 } else {
636 set_env("NAME", nm);
637 }
638 }
639
640 system(cmd);
641 unlink(scr);
642
643 free(cmd);
644 free(scr);
645 }
646
sslEncKey(char * path,int mode)647 void sslEncKey(char *path, int mode) {
648 char *openssl = find_openssl_bin();
649 char *scr, *cert = NULL, *tca, *cdir = NULL;
650 char line[1024], tmp[] = "/tmp/x11vnc-tmp.XXXXXX";
651 int tmp_fd, incert, info_only = 0, delete_only = 0, listlong = 0;
652 struct stat sbuf;
653 FILE *file;
654 static int depth = 0;
655
656 if (depth > 0) {
657 /* get_saved_pem may call us back. */
658 return;
659 }
660
661 if (! path) {
662 return;
663 }
664
665 depth++;
666
667 if (mode == 1) {
668 info_only = 1;
669 } else if (mode == 2) {
670 delete_only = 1;
671 }
672
673 if (! openssl) {
674 exit(1);
675 }
676
677 cdir = get_Cert_dir(NULL, &tca);
678 if (! cdir || ! tca) {
679 fprintf(stderr, "could not find Cert dir\n");
680 exit(1);
681 }
682
683 if (!strcasecmp(path, "LL") || !strcasecmp(path, "LISTL")) {
684 listlong = 1;
685 path = "LIST";
686 }
687
688 if (strstr(path, "SAVE") == path) {
689 char *p = get_saved_pem(path, 0);
690 if (p == NULL) {
691 fprintf(stderr, "could not find saved pem "
692 "matching: %s\n", path);
693 exit(1);
694 }
695 path = p;
696
697 } else if (!strcmp(path, "CA")) {
698 tca = (char *) malloc(strlen(cdir)+strlen("/CA/cacert.pem")+1);
699 sprintf(tca, "%s/CA/cacert.pem", cdir);
700 path = tca;
701
702 } else if (info_only && (!strcasecmp(path, "LIST") ||
703 !strcasecmp(path, "LS") || !strcasecmp(path, "ALL"))) {
704
705 if (! program_name || strchr(program_name, ' ')) {
706 fprintf(stderr, "bad program name.\n");
707 exit(1);
708 }
709 if (strchr(cdir, '\'')) {
710 fprintf(stderr, "bad certdir char: %s\n", cdir);
711 exit(1);
712 }
713
714 tca = (char *) malloc(2*strlen(cdir)+strlen(program_name)+1000);
715
716 sprintf(tca, "find '%s' | egrep '/(CA|tmp|clients)$|"
717 "\\.(crt|pem|key|req)$' | grep -v CA/newcerts", cdir);
718
719 if (!strcasecmp(path, "ALL")) {
720 /* ugh.. */
721 strcat(tca, " | egrep -v 'private/cakey.pem|"
722 "(CA|tmp|clients)$' | xargs -n1 ");
723 strcat(tca, program_name);
724 strcat(tca, " -ssldir '");
725 strcat(tca, cdir);
726 strcat(tca, "' -sslCertInfo 2>&1 ");
727 } else if (listlong) {
728 strcat(tca, " | xargs ls -ld ");
729 }
730 system(tca);
731 free(tca);
732
733 depth--;
734 return;
735
736 } else if (info_only && (!strcasecmp(path, "HASHON")
737 || !strcasecmp(path, "HASHOFF"))) {
738
739 tmp_fd = mkstemp(tmp);
740 if (tmp_fd < 0) {
741 exit(1);
742 }
743
744 write(tmp_fd, genCert, strlen(genCert));
745 close(tmp_fd);
746
747 scr = (char *) malloc(strlen("/bin/sh ") + strlen(tmp) + 1);
748 sprintf(scr, "/bin/sh %s", tmp);
749
750 set_env("BASE_DIR", cdir);
751 set_env("OPENSSL", openssl);
752 set_env("TYPE", "server");
753 if (!strcasecmp(path, "HASHON")) {
754 set_env("HASHON", "1");
755 } else {
756 set_env("HASHOFF", "1");
757 }
758 system(scr);
759 unlink(tmp);
760 free(scr);
761
762 depth--;
763 return;
764 }
765
766
767 if (stat(path, &sbuf) != 0) {
768 if (strstr(path, "client") || strchr(path, '/') == NULL) {
769 int i;
770 tca = (char *) malloc(strlen(cdir) + strlen(path) + 100);
771 for (i = 1; i <= 15; i++) {
772 tca[0] = '\0';
773 if ( i == 1) {
774 sprintf(tca, "%s/%s", cdir, path);
775 } else if (i == 2 && mode > 0) {
776 sprintf(tca, "%s/%s.crt", cdir, path);
777 } else if (i == 3) {
778 sprintf(tca, "%s/%s.pem", cdir, path);
779 } else if (i == 4 && mode > 1) {
780 sprintf(tca, "%s/%s.req", cdir, path);
781 } else if (i == 5 && mode > 1) {
782 sprintf(tca, "%s/%s.key", cdir, path);
783 } else if (i == 6) {
784 sprintf(tca, "%s/clients/%s", cdir, path);
785 } else if (i == 7 && mode > 0) {
786 sprintf(tca, "%s/clients/%s.crt", cdir, path);
787 } else if (i == 8) {
788 sprintf(tca, "%s/clients/%s.pem", cdir, path);
789 } else if (i == 9 && mode > 1) {
790 sprintf(tca, "%s/clients/%s.req", cdir, path);
791 } else if (i == 10 && mode > 1) {
792 sprintf(tca, "%s/clients/%s.key", cdir, path);
793 } else if (i == 11) {
794 sprintf(tca, "%s/server-%s", cdir, path);
795 } else if (i == 12 && mode > 0) {
796 sprintf(tca, "%s/server-%s.crt", cdir, path);
797 } else if (i == 13) {
798 sprintf(tca, "%s/server-%s.pem", cdir, path);
799 } else if (i == 14 && mode > 1) {
800 sprintf(tca, "%s/server-%s.req", cdir, path);
801 } else if (i == 15 && mode > 1) {
802 sprintf(tca, "%s/server-%s.key", cdir, path);
803 }
804 if (tca[0] == '\0') {
805 continue;
806 }
807 if (stat(tca, &sbuf) == 0) {
808 path = tca;
809 break;
810 }
811 }
812 }
813 }
814
815 if (stat(path, &sbuf) != 0) {
816 rfbLog("sslEncKey: %s\n", path);
817 rfbLogPerror("stat");
818 exit(1);
819 }
820
821 if (! info_only) {
822 cert = (char *) malloc(2*(sbuf.st_size + 1024));
823 file = fopen(path, "r");
824 if (file == NULL) {
825 rfbLog("sslEncKey: %s\n", path);
826 rfbLogPerror("fopen");
827 exit(1);
828 }
829 incert = 0;
830 cert[0] = '\0';
831 while (fgets(line, 1024, file) != NULL) {
832 if (strstr(line, "-----BEGIN CERTIFICATE-----")
833 == line) {
834 incert = 1;
835 }
836 if (incert) {
837 if (strlen(cert)+strlen(line) <
838 2 * (size_t) sbuf.st_size) {
839 strcat(cert, line);
840 }
841 }
842 if (strstr(line, "-----END CERTIFICATE-----")
843 == line) {
844 incert = 0;
845 }
846 }
847 fclose(file);
848 }
849
850 tmp_fd = mkstemp(tmp);
851 if (tmp_fd < 0) {
852 exit(1);
853 }
854
855 write(tmp_fd, genCert, strlen(genCert));
856 close(tmp_fd);
857
858 scr = (char *) malloc(strlen("/bin/sh ") + strlen(tmp) + 1);
859 sprintf(scr, "/bin/sh %s", tmp);
860
861 set_env("BASE_DIR", "/no/such/dir");
862 set_env("OPENSSL", openssl);
863 set_env("TYPE", "server");
864 if (info_only) {
865 set_env("INFO_ONLY", path);
866 } else if (delete_only) {
867 set_env("DELETE_ONLY", path);
868 } else {
869 set_env("ENCRYPT_ONLY", path);
870 }
871 system(scr);
872 unlink(tmp);
873
874 if (! mode && cert && cert[0] != '\0') {
875 int got_cert = 0;
876 file = fopen(path, "r");
877 if (file == NULL) {
878 rfbLog("sslEncKey: %s\n", path);
879 rfbLogPerror("fopen");
880 exit(1);
881 }
882 while (fgets(line, 1024, file) != NULL) {
883 if (strstr(line, "-----BEGIN CERTIFICATE-----")
884 == line) {
885 got_cert++;
886 }
887 if (strstr(line, "-----END CERTIFICATE-----")
888 == line) {
889 got_cert++;
890 }
891 }
892 fclose(file);
893 if (got_cert < 2) {
894 file = fopen(path, "a");
895 if (file == NULL) {
896 rfbLog("sslEncKey: %s\n", path);
897 rfbLogPerror("fopen");
898 exit(1);
899 }
900 fprintf(file, "%s", cert);
901 fclose(file);
902 }
903 free(cert);
904 }
905
906 depth--;
907 }
908
909