~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/x11vnc/sslhelper.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20080617134654-2y5m7ki93r5c1ysf
Tags: upstream-1.0.9~rc3
ImportĀ upstreamĀ versionĀ 1.0.9~rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -- sslhelper.c -- */
 
2
 
 
3
#include "x11vnc.h"
 
4
#include "inet.h"
 
5
#include "cleanup.h"
 
6
#include "screen.h"
 
7
#include "scan.h"
 
8
#include "connections.h"
 
9
#include "sslcmds.h"
 
10
 
 
11
#define OPENSSL_INETD 1
 
12
#define OPENSSL_VNC   2
 
13
#define OPENSSL_HTTPS 3
 
14
#define OPENSSL_REVERSE 4
 
15
 
 
16
#define DO_DH 0
 
17
 
 
18
#if LIBVNCSERVER_HAVE_FORK
 
19
#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID
 
20
#define FORK_OK
 
21
#endif
 
22
#endif
 
23
 
 
24
#ifdef NO_SSL_OR_UNIXPW
 
25
#undef FORK_OK
 
26
#undef LIBVNCSERVER_HAVE_LIBSSL
 
27
#define LIBVNCSERVER_HAVE_LIBSSL 0
 
28
#endif
 
29
 
 
30
 
 
31
int openssl_sock = -1;
 
32
int openssl_port_num = 0;
 
33
int https_sock = -1;
 
34
pid_t openssl_last_helper_pid = 0;
 
35
char *openssl_last_ip = NULL;
 
36
 
 
37
static char *certret = NULL;
 
38
static int certret_fd = -1;
 
39
static mode_t omode;
 
40
char *certret_str = NULL;
 
41
 
 
42
void raw_xfer(int csock, int s_in, int s_out);
 
43
 
 
44
#if !LIBVNCSERVER_HAVE_LIBSSL
 
45
int openssl_present(void) {return 0;}
 
46
static void badnews(void) {
 
47
        use_openssl = 0;
 
48
        use_stunnel = 0;
 
49
        rfbLog("** not compiled with libssl OpenSSL support **\n");
 
50
        clean_up_exit(1);
 
51
}
 
52
void openssl_init(int isclient) {badnews();}
 
53
void openssl_port(void) {badnews();}
 
54
void https_port(void) {badnews();}
 
55
void check_openssl(void) {if (use_openssl) badnews();}
 
56
void check_https(void) {if (use_openssl) badnews();}
 
57
void ssl_helper_pid(pid_t pid, int sock) {badnews(); sock = pid;}
 
58
void accept_openssl(int mode, int presock) {mode = 0; presock = 0; badnews();}
 
59
char *find_openssl_bin(void) {badnews(); return NULL;}
 
60
char *get_saved_pem(char *string, int create) {badnews(); return NULL;}
 
61
#else
 
62
 
 
63
/*
 
64
 * This is because on older systems both zlib.h and ssl.h define
 
65
 * 'free_func' nothing we do below (currently) induces an external
 
66
 * dependency on 'free_func'.
 
67
 */
 
68
#define free_func my_jolly_little_free_func
 
69
 
 
70
#include <openssl/ssl.h>
 
71
#include <openssl/err.h>
 
72
#include <openssl/rand.h>
 
73
 
 
74
int openssl_present(void);
 
75
void openssl_init(int isclient);
 
76
void openssl_port(void);
 
77
void check_openssl(void);
 
78
void check_https(void);
 
79
void ssl_helper_pid(pid_t pid, int sock);
 
80
void accept_openssl(int mode, int presock);
 
81
char *find_openssl_bin(void);
 
82
char *get_saved_pem(char *string, int create);
 
83
 
 
84
static SSL_CTX *ctx = NULL;
 
85
static RSA *rsa_512 = NULL;
 
86
static RSA *rsa_1024 = NULL;
 
87
static SSL *ssl = NULL;
 
88
 
 
89
 
 
90
static void init_prng(void);
 
91
static void sslerrexit(void);
 
92
static char *get_input(char *tag, char **in);
 
93
static char *create_tmp_pem(char *path, int prompt);
 
94
static int  ssl_init(int s_in, int s_out);
 
95
static void ssl_xfer(int csock, int s_in, int s_out, int is_https);
 
96
 
 
97
#ifndef FORK_OK
 
98
void openssl_init(int isclient) {
 
99
        rfbLog("openssl_init: fork is not supported. cannot create"
 
100
            " ssl helper process.\n");
 
101
        clean_up_exit(1);
 
102
}
 
103
int openssl_present(void) {return 0;}
 
104
#else
 
105
int openssl_present(void) {return 1;}
 
106
 
 
107
static void sslerrexit(void) {
 
108
        unsigned long err = ERR_get_error();
 
109
        
 
110
        if (err) {
 
111
                char str[256];
 
112
                ERR_error_string(err, str);
 
113
                fprintf(stderr, "ssl error: %s\n", str);
 
114
        }
 
115
        clean_up_exit(1);
 
116
}
 
117
 
 
118
char *get_saved_pem(char *save, int create) {
 
119
        char *s = NULL, *path, *cdir, *tmp;
 
120
        int prompt = 0, len;
 
121
        struct stat sbuf;
 
122
 
 
123
        if (! save) {
 
124
                rfbLog("get_saved_pem: save string is null.\n");
 
125
                clean_up_exit(1);
 
126
        }
 
127
 
 
128
        if (strstr(save, "SAVE_PROMPT") == save) {
 
129
                prompt = 1;
 
130
                s = save + strlen("SAVE_PROMPT");
 
131
        } else if (strstr(save, "SAVE") == save) {
 
132
                s = save + strlen("SAVE");
 
133
        } else {
 
134
                rfbLog("get_saved_pem: invalid save string: %s\n", save);
 
135
                clean_up_exit(1);
 
136
        }
 
137
        if (strchr(s, '/')) {
 
138
                rfbLog("get_saved_pem: invalid save string: %s\n", s);
 
139
                clean_up_exit(1);
 
140
        }
 
141
 
 
142
        cdir = get_Cert_dir(NULL, &tmp);
 
143
        if (! cdir || ! tmp) {
 
144
                rfbLog("get_saved_pem: could not find Cert dir.\n");
 
145
                clean_up_exit(1);
 
146
        }
 
147
 
 
148
        len = strlen(cdir) + strlen("/server.pem") + strlen(s) + 1;
 
149
 
 
150
        path = (char *) malloc(len);
 
151
        sprintf(path, "%s/server%s.pem", cdir, s);
 
152
 
 
153
        if (stat(path, &sbuf) != 0) {
 
154
                char *new = NULL;
 
155
                if (create) {
 
156
                        new = create_tmp_pem(path, prompt);
 
157
                        if (! getenv("X11VNC_SSL_NO_PASSPHRASE") && ! inetd) {
 
158
                                sslEncKey(new, 0);
 
159
                        }
 
160
                }
 
161
                return new;
 
162
        }
 
163
 
 
164
        if (! quiet) {
 
165
                char line[1024];
 
166
                int on = 0;
 
167
                FILE *in = fopen(path, "r");
 
168
                if (in != NULL) {
 
169
                        rfbLog("\n");
 
170
                        rfbLog("Using SSL Certificate:\n");
 
171
                        fprintf(stderr, "\n");
 
172
                        while (fgets(line, 1024, in) != NULL) {
 
173
                                if (strstr(line, "BEGIN CERTIFICATE")) {
 
174
                                        on = 1;
 
175
                                }
 
176
                                if (on) {
 
177
                                        fprintf(stderr, "%s", line);
 
178
                                }
 
179
                                if (strstr(line, "END CERTIFICATE")) {
 
180
                                        on = 0;
 
181
                                }
 
182
                                if (strstr(line, "PRIVATE KEY")) {
 
183
                                        on = 0;
 
184
                                }
 
185
                        }
 
186
                        fprintf(stderr, "\n");
 
187
                        fclose(in);
 
188
                }
 
189
        }
 
190
        return strdup(path);
 
191
}
 
192
 
 
193
static char *get_input(char *tag, char **in) {
 
194
        char line[1024], *str;
 
195
 
 
196
        if (! tag || ! in || ! *in) {
 
197
                return NULL;
 
198
        }
 
199
 
 
200
        fprintf(stderr, "%s:\n     [%s] ", tag, *in);
 
201
        if (fgets(line, 1024, stdin) == NULL) {
 
202
                rfbLog("could not read stdin!\n");
 
203
                rfbLogPerror("fgets");
 
204
                clean_up_exit(1);
 
205
        }
 
206
        if ((str = strrchr(line, '\n')) != NULL) {
 
207
                *str = '\0';
 
208
        }
 
209
        str = lblanks(line);
 
210
        if (!strcmp(str, "")) {
 
211
                return *in;
 
212
        } else {
 
213
                return strdup(line);
 
214
        }
 
215
}
 
216
 
 
217
char *find_openssl_bin(void) {
 
218
        char *path, *exe, *p, *gp;
 
219
        struct stat sbuf;
 
220
        int found_openssl = 0;
 
221
        char extra[] = ":/usr/bin:/bin:/usr/sbin:/usr/local/bin"
 
222
            ":/usr/local/sbin:/usr/sfw/bin";
 
223
        
 
224
        gp = getenv("PATH");
 
225
        if (! gp) {
 
226
                fprintf(stderr, "could not find openssl(1) program in PATH.\n");
 
227
                return NULL;
 
228
        }
 
229
 
 
230
        path = (char *) malloc(strlen(gp) + strlen(extra) + 1);
 
231
        strcpy(path, gp);
 
232
        strcat(path, extra);
 
233
 
 
234
        /* find openssl binary: */
 
235
        exe = (char *) malloc(strlen(path) + strlen("/openssl") + 1);
 
236
        p = strtok(path, ":");
 
237
 
 
238
        while (p) {
 
239
                sprintf(exe, "%s/openssl", p);
 
240
                if (stat(exe, &sbuf) == 0) {
 
241
                        if (! S_ISDIR(sbuf.st_mode)) {
 
242
                                found_openssl = 1;
 
243
                                break;
 
244
                        }
 
245
                }
 
246
                p = strtok(NULL, ":");
 
247
        }
 
248
        free(path);
 
249
 
 
250
        if (! found_openssl) {
 
251
                fprintf(stderr, "could not find openssl(1) program in PATH.\n");
 
252
                fprintf(stderr, "(also checked: %s)\n", extra);
 
253
                return NULL;
 
254
        }
 
255
        return exe;
 
256
}
 
257
 
 
258
/* uses /usr/bin/openssl to create a tmp cert */
 
259
 
 
260
static char *create_tmp_pem(char *pathin, int prompt) {
 
261
        pid_t pid, pidw;
 
262
        FILE *in, *out;
 
263
        char cnf[] = "/tmp/x11vnc-cnf.XXXXXX";
 
264
        char pem[] = "/tmp/x11vnc-pem.XXXXXX";
 
265
        char str[8*1024], line[1024], *exe;
 
266
        int cnf_fd, pem_fd, status, show_cert = 1;
 
267
        char *days;
 
268
        char *C, *L, *OU, *O, *CN, *EM;
 
269
        char tmpl[] = 
 
270
"[ req ]\n"
 
271
"prompt = no\n"
 
272
"default_bits = 2048\n"
 
273
"encrypt_key = yes\n"
 
274
"distinguished_name = req_dn\n"
 
275
"x509_extensions = cert_type\n"
 
276
"\n"
 
277
"[ req_dn ]\n"
 
278
"countryName=%s\n"
 
279
"localityName=%s\n"
 
280
"organizationalUnitName=%s\n"
 
281
"organizationName=%s\n"
 
282
"commonName=%s\n"
 
283
"emailAddress=%s\n"
 
284
"\n"
 
285
"[ cert_type ]\n"
 
286
"nsCertType = server\n"
 
287
;
 
288
 
 
289
        C = strdup("AU");
 
290
        L = strdup(UT.sysname ? UT.sysname : "unknown-os");
 
291
        snprintf(line, 1024, "%s-%f", UT.nodename ? UT.nodename :
 
292
            "unknown-node", dnow());
 
293
        line[1024-1] = '\0';
 
294
 
 
295
        OU = strdup(line);
 
296
        O = strdup("x11vnc");
 
297
        if (pathin) {
 
298
                snprintf(line, 1024, "x11vnc-SELF-SIGNED-CERT-%d", getpid());
 
299
        } else {
 
300
                snprintf(line, 1024, "x11vnc-SELF-SIGNED-TEMPORARY-CERT-%d",
 
301
                    getpid());
 
302
        }
 
303
        line[1024-1] = '\0';
 
304
        CN = strdup(line);
 
305
        EM = strdup("x11vnc@server.nowhere");
 
306
 
 
307
        /* ssl */
 
308
        if (no_external_cmds || !cmd_ok("ssl")) {
 
309
                rfbLog("create_tmp_pem: cannot run external commands.\n");      
 
310
                return NULL;
 
311
        }
 
312
 
 
313
        rfbLog("\n");   
 
314
        if (pathin) {
 
315
                rfbLog("Creating a self-signed PEM certificate...\n");  
 
316
        } else {
 
317
                rfbLog("Creating a temporary, self-signed PEM certificate...\n");       
 
318
        }
 
319
 
 
320
        rfbLog("\n");   
 
321
        rfbLog("This will NOT prevent man-in-the-middle attacks UNLESS you\n"); 
 
322
        rfbLog("get the certificate information to the VNC viewers SSL\n");     
 
323
        rfbLog("tunnel configuration or you take the extra steps to sign it\n");
 
324
        rfbLog("with a CA key. However, it will prevent passive network\n");
 
325
        rfbLog("sniffing.\n");  
 
326
        rfbLog("\n");   
 
327
        rfbLog("The cert inside -----BEGIN CERTIFICATE-----\n");        
 
328
        rfbLog("                           ....\n");    
 
329
        rfbLog("                -----END CERTIFICATE-----\n");  
 
330
        rfbLog("printed below may be used on the VNC viewer-side to\n");        
 
331
        rfbLog("authenticate this server for this session.  See the -ssl\n");
 
332
        rfbLog("help output and the FAQ for how to create a permanent\n");
 
333
        rfbLog("server certificate.\n");        
 
334
        rfbLog("\n");   
 
335
 
 
336
        exe = find_openssl_bin();
 
337
        if (! exe) {
 
338
                return NULL;
 
339
        }
 
340
 
 
341
        /* create template file with our made up stuff: */
 
342
        if (prompt) {
 
343
                fprintf(stderr, "\nReply to the following prompts to set"
 
344
                    " your Certificate parameters.\n");
 
345
                fprintf(stderr, "(press Enter to accept the default in [...], "
 
346
                    "or type in the value you want)\n\n");
 
347
                C = get_input("CountryName", &C);
 
348
                L = get_input("LocalityName", &L);
 
349
                OU = get_input("OrganizationalUnitName", &OU);
 
350
                O = get_input("OrganizationalName", &O);
 
351
                CN = get_input("CommonName", &CN);
 
352
                EM = get_input("EmailAddress", &EM);
 
353
        }
 
354
        sprintf(str, tmpl, C, L, OU, O, CN, EM);
 
355
 
 
356
        cnf_fd = mkstemp(cnf);
 
357
        pem_fd = mkstemp(pem);
 
358
 
 
359
        if (cnf_fd < 0 || pem_fd < 0) {
 
360
                return NULL;
 
361
        }
 
362
 
 
363
        close(pem_fd);
 
364
 
 
365
        write(cnf_fd, str, strlen(str));
 
366
        close(cnf_fd);
 
367
 
 
368
        if (pathin) {
 
369
                days = "365";
 
370
        } else {
 
371
                days = "30";
 
372
        }
 
373
 
 
374
        /* make RSA key */
 
375
        pid = fork();
 
376
        if (pid < 0) {
 
377
                return NULL;
 
378
        } else if (pid == 0) {
 
379
                int i;
 
380
                for (i=0; i<256; i++) {
 
381
                        close(i);
 
382
                }
 
383
                execlp(exe, exe, "req", "-new", "-x509", "-nodes",
 
384
                    "-days", days, "-config", cnf, "-out", pem,
 
385
                    "-keyout", pem, (char *)0);
 
386
                exit(1);
 
387
        }
 
388
        pidw = waitpid(pid, &status, 0); 
 
389
        if (pidw != pid) {
 
390
                return NULL;
 
391
        }
 
392
        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
 
393
                ;
 
394
        } else {
 
395
                return NULL;
 
396
        }
 
397
 
 
398
#if DO_DH
 
399
        /* make DH parameters */
 
400
        pid = fork();
 
401
        if (pid < 0) {
 
402
                return NULL;
 
403
        } else if (pid == 0) {
 
404
                int i;
 
405
                for (i=0; i<256; i++) {
 
406
                        close(i);
 
407
                }
 
408
                /* rather slow at 1024 */
 
409
                execlp(exe, exe, "dhparam", "-out", cnf, "512", (char *)0);
 
410
                exit(1);
 
411
        }
 
412
        pidw = waitpid(pid, &status, 0); 
 
413
        if (pidw != pid) {
 
414
                return NULL;
 
415
        }
 
416
        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
 
417
                ;
 
418
        } else {
 
419
                return NULL;
 
420
        }
 
421
 
 
422
        /* append result: */
 
423
        in = fopen(cnf, "r");
 
424
        if (in == NULL) {
 
425
                return NULL;
 
426
        }
 
427
        out = fopen(pem, "a");
 
428
        if (out == NULL) {
 
429
                fclose(in);
 
430
                return NULL;
 
431
        }
 
432
        while (fgets(line, 1024, in) != NULL) {
 
433
                fprintf(out, "%s", line);
 
434
        }
 
435
        fclose(in);
 
436
        fclose(out);
 
437
#endif
 
438
 
 
439
        unlink(cnf);
 
440
        free(exe);
 
441
 
 
442
        if (pathin != NULL) {
 
443
                char *q, *pathcrt = strdup(pathin);
 
444
                FILE *crt = NULL;
 
445
                int on = 0;
 
446
 
 
447
                q = strrchr(pathcrt, '/');
 
448
                if (q) {
 
449
                        q = strstr(q, ".pem");
 
450
                        if (q) {
 
451
                                *(q+1) = 'c';
 
452
                                *(q+2) = 'r';
 
453
                                *(q+3) = 't';
 
454
                                crt = fopen(pathcrt, "w");
 
455
                        }
 
456
                }
 
457
                if (crt == NULL) {
 
458
                        rfbLog("could not open: %s\n", pathcrt);
 
459
                        rfbLogPerror("fopen");
 
460
                        return NULL;
 
461
                }
 
462
 
 
463
                out = fopen(pathin, "w");
 
464
                chmod(pathin,  0600);
 
465
                if (out == NULL) {
 
466
                        rfbLog("could not open: %s\n", pathin);
 
467
                        rfbLogPerror("fopen");
 
468
                        fclose(crt);
 
469
                        return NULL;
 
470
                }
 
471
 
 
472
                in = fopen(pem, "r");
 
473
                if (in == NULL) {
 
474
                        rfbLog("could not open: %s\n", pem);
 
475
                        rfbLogPerror("fopen");
 
476
                        fclose(out);
 
477
                        fclose(crt);
 
478
                        unlink(pathin);
 
479
                        unlink(pathcrt);
 
480
                        return NULL;
 
481
                }
 
482
                while (fgets(line, 1024, in) != NULL) {
 
483
                        if (strstr(line, "BEGIN CERTIFICATE")) {
 
484
                                on = 1;
 
485
                        }
 
486
                        fprintf(out, "%s", line);
 
487
                        if (on) {
 
488
                                fprintf(crt, "%s", line);
 
489
                        }
 
490
                        if (strstr(line, "END CERTIFICATE")) {
 
491
                                on = 0;
 
492
                        }
 
493
                        if (strstr(line, "PRIVATE KEY")) {
 
494
                                on = 0;
 
495
                        }
 
496
                }
 
497
                fclose(in);
 
498
                fclose(out);
 
499
                fclose(crt);
 
500
        }
 
501
 
 
502
        if (show_cert) {
 
503
                char cmd[100];
 
504
                if (inetd) {
 
505
                        sprintf(cmd, "openssl x509 -text -in '%s' 1>&2", pem);
 
506
                } else {
 
507
                        sprintf(cmd, "openssl x509 -text -in '%s'", pem);
 
508
                }
 
509
                fprintf(stderr, "\n");
 
510
                system(cmd);
 
511
                fprintf(stderr, "\n");
 
512
        }
 
513
 
 
514
        if (pathin) {
 
515
                unlink(pem);
 
516
                return strdup(pathin);
 
517
        } else {
 
518
                return strdup(pem);
 
519
        }
 
520
}
 
521
 
 
522
static int pem_passwd_callback(char *buf, int size, int rwflag,
 
523
    void *userdata) {
 
524
        char *q, line[1024];
 
525
 
 
526
        if (! buf) {
 
527
                exit(1);
 
528
        }
 
529
 
 
530
        fprintf(stderr, "\nA passphrase is needed to unlock an OpenSSL "
 
531
            "private key (PEM file).\n");
 
532
        fprintf(stderr, "Enter passphrase> ");
 
533
        system("stty -echo");
 
534
        if(fgets(line, 1024, stdin) == NULL) {
 
535
                fprintf(stdout, "\n");
 
536
                system("stty echo");
 
537
                exit(1);
 
538
        }
 
539
        system("stty echo");
 
540
        fprintf(stdout, "\n\n");
 
541
        q = strrchr(line, '\n');
 
542
        if (q) {
 
543
                *q = '\0';
 
544
        }
 
545
        line[1024 - 1] = '\0';
 
546
        strncpy(buf, line, size);                                  
 
547
        buf[size - 1] = '\0';
 
548
 
 
549
        if (0) rwflag = 0;      /* compiler warning. */
 
550
        if (0) userdata = 0;    /* compiler warning. */
 
551
 
 
552
        return strlen(buf);
 
553
}
 
554
 
 
555
static int appendfile(FILE *out, char *infile) {
 
556
        char line[1024];
 
557
        FILE *in;
 
558
 
 
559
        if (! infile) {
 
560
                rfbLog("appendfile: null infile.\n");
 
561
                return 0;
 
562
        }
 
563
        if (! out) {
 
564
                rfbLog("appendfile: null out handle.\n");
 
565
                return 0;
 
566
        }
 
567
 
 
568
        in = fopen(infile, "r");
 
569
 
 
570
        if (in == NULL) {
 
571
                rfbLog("appendfile: %s\n", infile);
 
572
                rfbLogPerror("fopen");
 
573
                return 0;
 
574
        }
 
575
 
 
576
        while (fgets(line, 1024, in) != NULL) {
 
577
                fprintf(out, "%s", line);
 
578
        }
 
579
        fclose(in);
 
580
        return 1;
 
581
}
 
582
        
 
583
static char *get_ssl_verify_file(char *str_in) {
 
584
        char *p, *str, *cdir, *tmp;
 
585
        char *tfile, *tfile2;
 
586
        FILE *file;
 
587
        struct stat sbuf;
 
588
        int count = 0;
 
589
 
 
590
        if (! str_in) {
 
591
                rfbLog("get_ssl_verify_file: no filename\n");
 
592
                exit(1);
 
593
        }
 
594
 
 
595
        if (stat(str_in, &sbuf) == 0) {
 
596
                /* assume he knows what he is doing. */
 
597
                return str_in;
 
598
        }
 
599
 
 
600
        cdir = get_Cert_dir(NULL, &tmp);
 
601
        if (! cdir || ! tmp) {
 
602
                rfbLog("get_ssl_verify_file: invalid cert-dir.\n");
 
603
                exit(1);
 
604
        }
 
605
 
 
606
        tfile  = (char *) malloc(strlen(tmp) + 1024);
 
607
        tfile2 = (char *) malloc(strlen(tmp) + 1024);
 
608
 
 
609
        sprintf(tfile, "%s/sslverify-load-%d.crts", tmp, getpid());
 
610
 
 
611
        file = fopen(tfile, "w");
 
612
        chmod(tfile, 0600);
 
613
        if (file == NULL) {
 
614
                rfbLog("get_ssl_verify_file: %s\n", tfile);
 
615
                rfbLogPerror("fopen");
 
616
                exit(1);
 
617
        }
 
618
 
 
619
        str = strdup(str_in);
 
620
        p = strtok(str, ",");
 
621
 
 
622
        while (p) {
 
623
                if (!strcmp(p, "CA")) {
 
624
                        sprintf(tfile2, "%s/CA/cacert.pem", cdir);
 
625
                        if (! appendfile(file, tfile2)) {
 
626
                                unlink(tfile);
 
627
                                exit(1);
 
628
                        }
 
629
                        fprintf(stderr, "sslverify: loaded %s\n", tfile2);
 
630
                        count++;
 
631
 
 
632
                } else if (!strcmp(p, "clients")) {
 
633
                        DIR *dir;
 
634
                        struct dirent *dp;
 
635
 
 
636
                        sprintf(tfile2, "%s/clients", cdir);
 
637
                        dir = opendir(tfile2);
 
638
                        if (! dir) {
 
639
                                rfbLog("get_ssl_verify_file: %s\n", tfile2);
 
640
                                rfbLogPerror("opendir");
 
641
                                unlink(tfile);
 
642
                                exit(1);
 
643
                        }
 
644
                        while ( (dp = readdir(dir)) != NULL) {
 
645
                                char *n = dp->d_name;
 
646
                                char *q = strstr(n, ".crt");
 
647
 
 
648
                                if (! q || strlen(q) != strlen(".crt")) {
 
649
                                        continue;
 
650
                                }
 
651
                                if (strlen(n) > 512) {
 
652
                                        continue;
 
653
                                }
 
654
 
 
655
                                sprintf(tfile2, "%s/clients/%s", cdir, n);
 
656
                                if (! appendfile(file, tfile2)) {
 
657
                                        unlink(tfile);
 
658
                                        exit(1);
 
659
                                }
 
660
                                fprintf(stderr, "sslverify: loaded %s\n",
 
661
                                    tfile2);
 
662
                                count++;
 
663
                        }
 
664
                        closedir(dir);
 
665
                        
 
666
                } else {
 
667
                        if (strlen(p) > 512) {
 
668
                                unlink(tfile);
 
669
                                exit(1);
 
670
                        }
 
671
                        sprintf(tfile2, "%s/clients/%s.crt", cdir, p);
 
672
                        if (stat(tfile2, &sbuf) != 0) {
 
673
                                sprintf(tfile2, "%s/clients/%s", cdir, p);
 
674
                        }
 
675
                        if (! appendfile(file, tfile2)) {
 
676
                                unlink(tfile);
 
677
                                exit(1);
 
678
                        }
 
679
                        fprintf(stderr, "sslverify: loaded %s\n", tfile2);
 
680
                        count++;
 
681
                }
 
682
                p = strtok(NULL, ",");
 
683
        }
 
684
        fclose(file);
 
685
        free(tfile2);
 
686
        free(str);
 
687
 
 
688
        fprintf(stderr, "sslverify: using %d client certs in %s\n", count,
 
689
            tfile);
 
690
 
 
691
        return tfile;
 
692
}
 
693
 
 
694
int ssl_client_mode = 0;
 
695
 
 
696
void openssl_init(int isclient) {
 
697
        int db = 0, tmp_pem = 0, do_dh;
 
698
        FILE *in;
 
699
        double ds;
 
700
        long mode;
 
701
        static int first = 1;
 
702
 
 
703
        do_dh = DO_DH;
 
704
 
 
705
        if (! quiet) {
 
706
                rfbLog("\n");
 
707
                rfbLog("Initializing SSL (%s connect mode).\n", isclient ? "client":"server");
 
708
        }
 
709
        if (first) {
 
710
                if (db) fprintf(stderr, "\nSSL_load_error_strings()\n");
 
711
 
 
712
                SSL_load_error_strings();
 
713
 
 
714
                if (db) fprintf(stderr, "SSL_library_init()\n");
 
715
 
 
716
                SSL_library_init();
 
717
 
 
718
                if (db) fprintf(stderr, "init_prng()\n");
 
719
 
 
720
                init_prng();
 
721
 
 
722
                first = 0;
 
723
        }
 
724
 
 
725
        if (isclient) {
 
726
                ssl_client_mode = 1;
 
727
        } else {
 
728
                ssl_client_mode = 0;
 
729
        }
 
730
 
 
731
        if (ssl_client_mode) {
 
732
                if (db) fprintf(stderr, "SSLv23_client_method()\n");
 
733
                ctx = SSL_CTX_new( SSLv23_client_method() );
 
734
        } else {
 
735
                if (db) fprintf(stderr, "SSLv23_server_method()\n");
 
736
                ctx = SSL_CTX_new( SSLv23_server_method() );
 
737
        }
 
738
 
 
739
        if (ctx == NULL) {
 
740
                rfbLog("openssl_init: SSL_CTX_new failed.\n");  
 
741
                sslerrexit();
 
742
        }
 
743
 
 
744
        ds = dnow();
 
745
        rsa_512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
 
746
        if (rsa_512 == NULL) {
 
747
                rfbLog("openssl_init: RSA_generate_key(512) failed.\n");        
 
748
                sslerrexit();
 
749
        }
 
750
 
 
751
        rfbLog("created  512 bit temporary RSA key: %.3fs\n", dnow() - ds);
 
752
 
 
753
        ds = dnow();
 
754
        rsa_1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
 
755
        if (rsa_1024 == NULL) {
 
756
                rfbLog("openssl_init: RSA_generate_key(1024) failed.\n");       
 
757
                sslerrexit();
 
758
        }
 
759
 
 
760
        rfbLog("created 1024 bit temporary RSA key: %.3fs\n", dnow() - ds);
 
761
 
 
762
        if (db) fprintf(stderr, "SSL_CTX_set_tmp_rsa()\n");
 
763
 
 
764
        if (! SSL_CTX_set_tmp_rsa(ctx, rsa_1024)) {
 
765
                rfbLog("openssl_init: SSL_CTX_set_tmp_rsa(1024) failed.\n");    
 
766
                sslerrexit();
 
767
        }
 
768
 
 
769
        mode = 0;
 
770
        mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
 
771
        mode |= SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
 
772
        SSL_CTX_set_mode(ctx, mode);
 
773
 
 
774
        SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
 
775
        SSL_CTX_set_timeout(ctx, 300);
 
776
 
 
777
        ds = dnow();
 
778
        if (! openssl_pem) {
 
779
                openssl_pem = create_tmp_pem(NULL, 0);
 
780
                if (! openssl_pem) {
 
781
                        rfbLog("openssl_init: could not create temporary,"
 
782
                            " self-signed PEM.\n");     
 
783
                        clean_up_exit(1);
 
784
                }
 
785
                tmp_pem = 1;
 
786
 
 
787
        } else if (strstr(openssl_pem, "SAVE") == openssl_pem) {
 
788
                openssl_pem = get_saved_pem(openssl_pem, 1);
 
789
                if (! openssl_pem) {
 
790
                        rfbLog("openssl_init: could not create or open"
 
791
                            " saved PEM:\n", openssl_pem);      
 
792
                        clean_up_exit(1);
 
793
                }
 
794
                tmp_pem = 0;
 
795
        }
 
796
 
 
797
        rfbLog("using PEM %s  %.3fs\n", openssl_pem, dnow() - ds);
 
798
 
 
799
        SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_callback);
 
800
 
 
801
        if (do_dh) {
 
802
                DH *dh;
 
803
                BIO *bio;
 
804
 
 
805
                ds = dnow();
 
806
                in = fopen(openssl_pem, "r");
 
807
                if (in == NULL) {
 
808
                        rfbLogPerror("fopen");
 
809
                        clean_up_exit(1);
 
810
                }
 
811
                bio = BIO_new_fp(in, BIO_CLOSE|BIO_FP_TEXT);
 
812
                if (! bio) {
 
813
                        rfbLog("openssl_init: BIO_new_fp() failed.\n"); 
 
814
                        sslerrexit();
 
815
                }
 
816
                dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
 
817
                if (dh == NULL) {
 
818
                        rfbLog("openssl_init: PEM_read_bio_DHparams() failed.\n");      
 
819
                        BIO_free(bio);
 
820
                        sslerrexit();
 
821
                }
 
822
                BIO_free(bio);
 
823
                SSL_CTX_set_tmp_dh(ctx, dh);
 
824
                rfbLog("loaded Diffie Hellman %d bits, %.3fs\n",
 
825
                    8*DH_size(dh), dnow()-ds);
 
826
                DH_free(dh);
 
827
        }
 
828
 
 
829
        if (! SSL_CTX_use_certificate_chain_file(ctx, openssl_pem)) {
 
830
                rfbLog("openssl_init: SSL_CTX_use_certificate_chain_file() failed.\n"); 
 
831
                sslerrexit();
 
832
        }
 
833
        if (! SSL_CTX_use_RSAPrivateKey_file(ctx, openssl_pem,
 
834
            SSL_FILETYPE_PEM)) {
 
835
                rfbLog("openssl_init: SSL_CTX_set_tmp_rsa(1024) failed.\n");    
 
836
                sslerrexit();
 
837
        }
 
838
        if (! SSL_CTX_check_private_key(ctx)) {
 
839
                rfbLog("openssl_init: SSL_CTX_set_tmp_rsa(1024) failed.\n");    
 
840
                sslerrexit();
 
841
        }
 
842
 
 
843
        if (tmp_pem && ! getenv("X11VNC_KEEP_TMP_PEM")) {
 
844
                if (getenv("X11VNC_SHOW_TMP_PEM")) {
 
845
                        FILE *in = fopen(openssl_pem, "r");
 
846
                        if (in != NULL) {
 
847
                                char line[128];
 
848
                                fprintf(stderr, "\n");
 
849
                                while (fgets(line, 128, in) != NULL) {
 
850
                                        fprintf(stderr, "%s", line);
 
851
                                }
 
852
                                fprintf(stderr, "\n");
 
853
                                fclose(in);
 
854
                        }
 
855
                }
 
856
                unlink(openssl_pem);
 
857
                free(openssl_pem);
 
858
                openssl_pem = NULL;
 
859
        }
 
860
 
 
861
        if (ssl_verify) {
 
862
                struct stat sbuf;
 
863
                char *file;
 
864
                int lvl;
 
865
 
 
866
                file = get_ssl_verify_file(ssl_verify);
 
867
 
 
868
                if (!file || stat(file, &sbuf) != 0) {
 
869
                        rfbLog("openssl_init: -sslverify does not exists %s.\n",
 
870
                            file ? file : "null");      
 
871
                        rfbLogPerror("stat");
 
872
                        clean_up_exit(1);
 
873
                }
 
874
                if (! S_ISDIR(sbuf.st_mode)) {
 
875
                        if (! SSL_CTX_load_verify_locations(ctx, file, NULL)) {
 
876
                                rfbLog("openssl_init: SSL_CTX_load_verify_"
 
877
                                    "locations() failed.\n");   
 
878
                                sslerrexit();
 
879
                        }
 
880
                } else {
 
881
                        if (! SSL_CTX_load_verify_locations(ctx, NULL, file)) {
 
882
                                rfbLog("openssl_init: SSL_CTX_load_verify_"
 
883
                                    "locations() failed.\n");   
 
884
                                sslerrexit();
 
885
                        }
 
886
                }
 
887
 
 
888
                lvl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER;
 
889
                SSL_CTX_set_verify(ctx, lvl, NULL);
 
890
                if (strstr(file, "tmp/sslverify-load-")) {
 
891
                        /* temporary file */
 
892
                        unlink(file);
 
893
                }
 
894
        } else {
 
895
                SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
 
896
        }
 
897
 
 
898
        rfbLog("\n");
 
899
}
 
900
 
 
901
void openssl_port(void) {
 
902
        int sock, shutdown = 0;
 
903
        static int port = 0;
 
904
        static in_addr_t iface = INADDR_ANY;
 
905
        int db = 0;
 
906
 
 
907
        if (! screen) {
 
908
                rfbLog("openssl_port: no screen!\n");
 
909
                clean_up_exit(1);
 
910
        }
 
911
        if (inetd) {
 
912
                ssl_initialized = 1;
 
913
                return;
 
914
        }
 
915
 
 
916
        if (screen->listenSock > -1 && screen->port > 0) {
 
917
                port = screen->port;
 
918
                shutdown = 1;
 
919
        }
 
920
        if (screen->listenInterface) {
 
921
                iface = screen->listenInterface;
 
922
        }
 
923
 
 
924
        if (shutdown) {
 
925
                if (db) fprintf(stderr, "shutting down %d/%d\n",
 
926
                    port, screen->listenSock);
 
927
                rfbShutdownSockets(screen);
 
928
        }
 
929
 
 
930
        sock = rfbListenOnTCPPort(port, iface);
 
931
        if (sock < 0) {
 
932
                rfbLog("openssl_port: could not reopen port %d\n", port);
 
933
                clean_up_exit(1);
 
934
        }
 
935
        rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock);
 
936
        if (!quiet) {
 
937
                announce(port, 1, NULL);
 
938
        }
 
939
        openssl_sock = sock;
 
940
        openssl_port_num = port;
 
941
 
 
942
        ssl_initialized = 1;
 
943
}
 
944
 
 
945
 
 
946
void https_port(void) {
 
947
        int sock;
 
948
        static int port = 0;
 
949
        static in_addr_t iface = INADDR_ANY;
 
950
        int db = 0;
 
951
 
 
952
        /* as openssl_port above: open a listening socket for pure https: */
 
953
        if (https_port_num < 0) {
 
954
                return;
 
955
        }
 
956
        if (! screen) {
 
957
                rfbLog("https_port: no screen!\n");
 
958
                clean_up_exit(1);
 
959
        }
 
960
        if (screen->listenInterface) {
 
961
                iface = screen->listenInterface;
 
962
        }
 
963
 
 
964
        if (https_port_num == 0) {
 
965
                https_port_num = find_free_port(5801, 5851);
 
966
        }
 
967
        if (https_port_num <= 0) {
 
968
                rfbLog("https_port: could not find port %d\n", https_port_num);
 
969
                clean_up_exit(1);
 
970
        }
 
971
        port = https_port_num;
 
972
 
 
973
        sock = rfbListenOnTCPPort(port, iface);
 
974
        if (sock < 0) {
 
975
                rfbLog("https_port: could not open port %d\n", port);
 
976
                clean_up_exit(1);
 
977
        }
 
978
        if (db) fprintf(stderr, "https_port: listen on port/sock %d/%d\n",
 
979
            port, sock);
 
980
 
 
981
        https_sock = sock;
 
982
}
 
983
 
 
984
static void lose_ram(void) {
 
985
        /*
 
986
         * for a forked child that will be around for a long time
 
987
         * without doing exec().  we really should re-exec, but a pain
 
988
         * to redo all SSL ctx.
 
989
         */
 
990
        free_old_fb();
 
991
 
 
992
        free_tiles();
 
993
}
 
994
 
 
995
/* utility to keep track of existing helper processes: */
 
996
 
 
997
void ssl_helper_pid(pid_t pid, int sock) {
 
998
#       define HPSIZE 256
 
999
        static pid_t helpers[HPSIZE];
 
1000
        static int   sockets[HPSIZE], first = 1;
 
1001
        int i, empty, set, status, db = 0;
 
1002
 
 
1003
        if (first) {
 
1004
                for (i=0; i < HPSIZE; i++)  {
 
1005
                        helpers[i] = 0;
 
1006
                        sockets[i] = 0;
 
1007
                }
 
1008
                first = 0;
 
1009
        }
 
1010
 
 
1011
        if (pid == 0) {
 
1012
                /* killall */
 
1013
                for (i=0; i < HPSIZE; i++) {
 
1014
                        if (helpers[i] == 0) {
 
1015
                                sockets[i] = -1;
 
1016
                                continue;
 
1017
                        }
 
1018
                        if (kill(helpers[i], 0) == 0) {
 
1019
                                if (sock != -2) {
 
1020
                                        if (sockets[i] >= 0) {
 
1021
                                                close(sockets[i]);
 
1022
                                        }
 
1023
                                        kill(helpers[i], SIGTERM);
 
1024
                                }
 
1025
 
 
1026
#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID 
 
1027
if (db) fprintf(stderr, "waitpid(%d)\n", helpers[i]);
 
1028
                                waitpid(helpers[i], &status, WNOHANG); 
 
1029
#endif
 
1030
                                if (sock == -2) {
 
1031
                                        continue;
 
1032
                                }
 
1033
                        }
 
1034
                        helpers[i] = 0;
 
1035
                        sockets[i] = -1;
 
1036
                }
 
1037
                return;
 
1038
        }
 
1039
 
 
1040
if (db) fprintf(stderr, "ssl_helper_pid(%d, %d)\n", pid, sock);
 
1041
 
 
1042
        /* add (or delete for sock == -1) */
 
1043
        set = 0;
 
1044
        empty = -1;
 
1045
        for (i=0; i < HPSIZE; i++) {
 
1046
                if (helpers[i] == pid) {
 
1047
                        if (sock == -1) {
 
1048
 
 
1049
#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID 
 
1050
if (db) fprintf(stderr, "waitpid(%d) 2\n", helpers[i]);
 
1051
                                waitpid(helpers[i], &status, WNOHANG); 
 
1052
#endif
 
1053
                                helpers[i] = 0;
 
1054
                        }
 
1055
                        sockets[i] = sock;
 
1056
                        set = 1;
 
1057
                } else if (empty == -1 && helpers[i] == 0) {
 
1058
                        empty = i;
 
1059
                }
 
1060
        }
 
1061
        if (set || sock == -1) {
 
1062
                return; /* done */
 
1063
        }
 
1064
 
 
1065
        /* now try to store */
 
1066
        if (empty >= 0) {
 
1067
                helpers[empty] = pid;
 
1068
                sockets[empty] = sock;
 
1069
                return;
 
1070
        }
 
1071
        for (i=0; i < HPSIZE; i++) {
 
1072
                if (helpers[i] == 0) {
 
1073
                        continue;
 
1074
                }
 
1075
                /* clear out stale pids: */
 
1076
                if (kill(helpers[i], 0) != 0) {
 
1077
                        helpers[i] = 0;
 
1078
                        sockets[i] = -1;
 
1079
                        
 
1080
                        if (empty == -1) {
 
1081
                                empty = i;
 
1082
                        }
 
1083
                }
 
1084
        }
 
1085
        if (empty >= 0) {
 
1086
                helpers[empty] = pid;
 
1087
                sockets[empty] = sock;
 
1088
        }
 
1089
}
 
1090
 
 
1091
static int is_ssl_readable(int s_in, time_t last_https, char *last_get,
 
1092
    int mode) {
 
1093
        int nfd, db = 0;
 
1094
        struct timeval tv;
 
1095
        fd_set rd;
 
1096
 
 
1097
        if (getenv("ACCEPT_OPENSSL_DEBUG")) {
 
1098
                db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
 
1099
        }
 
1100
 
 
1101
        /*
 
1102
         * we'll do a select() on s_in for reading.  this is not an
 
1103
         * absolute proof that SSL_read is ready (XXX use SSL utility).
 
1104
         */
 
1105
        tv.tv_sec  = 2;
 
1106
        tv.tv_usec = 0;
 
1107
 
 
1108
        if (mode == OPENSSL_INETD) {
 
1109
                /*
 
1110
                 * https via inetd is icky because x11vnc is restarted
 
1111
                 * for each socket (and some clients send requests
 
1112
                 * rapid fire).
 
1113
                 */
 
1114
                tv.tv_sec  = 6;
 
1115
        }
 
1116
 
 
1117
        /*
 
1118
         * increase the timeout if we know HTTP traffic has occurred
 
1119
         * recently:
 
1120
         */
 
1121
        if (time(NULL) < last_https + 30) {
 
1122
                tv.tv_sec  = 8;
 
1123
                if (last_get && strstr(last_get, "VncViewer")) {
 
1124
                        tv.tv_sec  = 4;
 
1125
                }
 
1126
        }
 
1127
        if (getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT")) {
 
1128
                tv.tv_sec  = atoi(getenv("X11VNC_HTTPS_VS_VNC_TIMEOUT"));
 
1129
        }
 
1130
if (db) fprintf(stderr, "tv_sec: %d - %s\n", (int) tv.tv_sec, last_get);
 
1131
 
 
1132
        FD_ZERO(&rd);
 
1133
        FD_SET(s_in, &rd);
 
1134
 
 
1135
        do {
 
1136
                nfd = select(s_in+1, &rd, NULL, NULL, &tv);
 
1137
        } while (nfd < 0 && errno == EINTR);
 
1138
 
 
1139
        if (db) fprintf(stderr, "https nfd: %d\n", nfd);
 
1140
 
 
1141
        if (nfd <= 0 || ! FD_ISSET(s_in, &rd)) {
 
1142
                return 0;
 
1143
        }
 
1144
        return 1;
 
1145
}
 
1146
 
 
1147
#define ABSIZE 16384
 
1148
static int watch_for_http_traffic(char *buf_a, int *n_a) {
 
1149
        int is_http, err, n, n2;
 
1150
        char *buf;
 
1151
        int db = 0;
 
1152
        /*
 
1153
         * sniff the first couple bytes of the stream and try to see
 
1154
         * if it is http or not.  if we read them OK, we must read the
 
1155
         * rest of the available data otherwise we may deadlock.
 
1156
         * what has been read is returned in buf_a and n_a.
 
1157
         * *buf_a is ABSIZE+1 long and zeroed.
 
1158
         */
 
1159
        if (getenv("ACCEPT_OPENSSL_DEBUG")) {
 
1160
                db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
 
1161
        }
 
1162
        if (! buf_a || ! n_a) {
 
1163
                return 0;
 
1164
        }
 
1165
 
 
1166
        buf = (char *) calloc((ABSIZE+1), 1);
 
1167
        *n_a = 0;
 
1168
 
 
1169
        n = SSL_read(ssl, buf, 2);
 
1170
        err = SSL_get_error(ssl, n);
 
1171
 
 
1172
        if (err != SSL_ERROR_NONE || n < 2) {
 
1173
                if (n > 0) {
 
1174
                        strncpy(buf_a, buf, n);
 
1175
                        *n_a = n;
 
1176
                }
 
1177
                if (db) fprintf(stderr, "watch_for_http_traffic ssl err: %d/%d\n", err, n);
 
1178
                return -1;
 
1179
        }
 
1180
 
 
1181
        /* look for GET, HEAD, POST, CONNECT */
 
1182
        is_http = 0;
 
1183
        if (!strncmp("GE", buf, 2)) {
 
1184
                is_http = 1;
 
1185
        } else if (!strncmp("HE", buf, 2)) {
 
1186
                is_http = 1;
 
1187
        } else if (!strncmp("PO", buf, 2)) {
 
1188
                is_http = 1;
 
1189
        } else if (!strncmp("CO", buf, 2)) {
 
1190
                is_http = 1;
 
1191
        }
 
1192
        if (db) fprintf(stderr, "watch_for_http_traffic read: '%s' %d\n", buf, n);
 
1193
 
 
1194
        /*
 
1195
         * better read all we can and fwd it along to avoid blocking
 
1196
         * in ssl_xfer().
 
1197
         */
 
1198
 
 
1199
        n2 = SSL_read(ssl, buf + n, ABSIZE - n);
 
1200
        if (n2 >= 0) {
 
1201
                n += n2;
 
1202
        }
 
1203
 
 
1204
        *n_a = n;
 
1205
 
 
1206
        if (db) fprintf(stderr, "watch_for_http_traffic readmore: %d\n", n2);
 
1207
 
 
1208
        if (n > 0) {
 
1209
                memcpy(buf_a, buf, n);
 
1210
        }
 
1211
        if (db > 1) {
 
1212
                fprintf(stderr, "watch_for_http_traffic readmore: ");
 
1213
                write(2, buf_a, *n_a);
 
1214
                fprintf(stderr, "\n");
 
1215
        }
 
1216
        if (db) fprintf(stderr, "watch_for_http_traffic return: %d\n", is_http);
 
1217
        return is_http;
 
1218
}
 
1219
 
 
1220
static int csock_timeout_sock = -1;
 
1221
 
 
1222
static void csock_timeout (int sig) {
 
1223
        rfbLog("sig: %d, csock_timeout.\n", sig);
 
1224
        if (csock_timeout_sock >= 0) {
 
1225
                close(csock_timeout_sock);
 
1226
                csock_timeout_sock = -1;
 
1227
        }
 
1228
}
 
1229
 
 
1230
static int wait_conn(int sock) {
 
1231
        int conn;
 
1232
        struct sockaddr_in addr;
 
1233
#ifdef __hpux
 
1234
        int addrlen = sizeof(addr);
 
1235
#else
 
1236
        socklen_t addrlen = sizeof(addr);
 
1237
#endif
 
1238
 
 
1239
        signal(SIGALRM, csock_timeout);
 
1240
        csock_timeout_sock = sock;
 
1241
        
 
1242
        alarm(15);
 
1243
        conn = accept(sock, (struct sockaddr *)&addr, &addrlen);
 
1244
        alarm(0);
 
1245
 
 
1246
        signal(SIGALRM, SIG_DFL);
 
1247
        return conn;
 
1248
}
 
1249
 
 
1250
int proxy_hack(int vncsock, int listen, int s_in, int s_out, char *cookie,
 
1251
    int mode) {
 
1252
        int sock1, db = 0;
 
1253
        char reply[] = "HTTP/1.1 200 OK\r\n"
 
1254
            "Content-Type: octet-stream\r\n"
 
1255
            "Pragma: no-cache\r\n\r\n";
 
1256
        char reply0[] = "HTTP/1.0 200 OK\r\n"
 
1257
            "Content-Type: octet-stream\r\n"
 
1258
            "Content-Length: 9\r\n"
 
1259
            "Pragma: no-cache\r\n\r\nGO_AHEAD\n";
 
1260
 
 
1261
        rfbLog("SSL: accept_openssl: detected https proxied connection"
 
1262
            " request.\n");
 
1263
 
 
1264
        if (getenv("ACCEPT_OPENSSL_DEBUG")) {
 
1265
                db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
 
1266
        }
 
1267
 
 
1268
        SSL_write(ssl, reply0, strlen(reply0));
 
1269
        SSL_shutdown(ssl);
 
1270
        SSL_shutdown(ssl);
 
1271
        close(s_in);
 
1272
        close(s_out);
 
1273
        SSL_free(ssl);
 
1274
 
 
1275
        if (mode == OPENSSL_VNC) {
 
1276
                listen = openssl_sock;
 
1277
        } else if (mode == OPENSSL_HTTPS) {
 
1278
                listen = https_sock;
 
1279
        } else {
 
1280
                /* inetd */
 
1281
                return 0;
 
1282
        }
 
1283
 
 
1284
        sock1 = wait_conn(listen);
 
1285
 
 
1286
        if (csock_timeout_sock < 0 || sock1 < 0) {
 
1287
                close(sock1);
 
1288
                return 0;
 
1289
        }
 
1290
 
 
1291
if (db) fprintf(stderr, "got applet input sock1: %d\n", sock1);
 
1292
 
 
1293
        if (! ssl_init(sock1, sock1)) {
 
1294
if (db) fprintf(stderr, "ssl_init FAILED\n");
 
1295
                exit(1);
 
1296
        }
 
1297
 
 
1298
        SSL_write(ssl, reply, strlen(reply));
 
1299
 
 
1300
        {
 
1301
                char *buf;
 
1302
                int n = 0, ptr = 0;
 
1303
        
 
1304
                buf  = (char *) calloc((8192+1), 1);
 
1305
                while (ptr < 8192) {
 
1306
                        n = SSL_read(ssl, buf + ptr, 8192 - ptr);
 
1307
                        if (n > 0) {
 
1308
                                ptr += n;
 
1309
                        }
 
1310
if (db) fprintf(stderr, "buf: '%s'\n", buf);
 
1311
                        if (strstr(buf, "\r\n\r\n")) {
 
1312
                                break;
 
1313
                        }
 
1314
                }
 
1315
        }
 
1316
 
 
1317
        if (cookie) {
 
1318
                write(vncsock, cookie, strlen(cookie));
 
1319
        }
 
1320
        ssl_xfer(vncsock, sock1, sock1, 0);
 
1321
 
 
1322
        return 1;
 
1323
}
 
1324
 
 
1325
void accept_openssl(int mode, int presock) {
 
1326
        int sock = -1, listen = -1, cport, csock, vsock;        
 
1327
        int peerport = 0;
 
1328
        int status, n, i, db = 0;
 
1329
        struct sockaddr_in addr;
 
1330
#ifdef __hpux
 
1331
        int addrlen = sizeof(addr);
 
1332
#else
 
1333
        socklen_t addrlen = sizeof(addr);
 
1334
#endif
 
1335
        rfbClientPtr client;
 
1336
        pid_t pid;
 
1337
        char uniq[] = "_evilrats_";
 
1338
        char cookie[128], rcookie[128], *name = NULL;
 
1339
        static time_t last_https = 0;
 
1340
        static char last_get[128];
 
1341
        static int first = 1;
 
1342
 
 
1343
        openssl_last_helper_pid = 0;
 
1344
 
 
1345
        /* zero buffers for use below. */
 
1346
        for (i=0; i<128; i++) {
 
1347
                if (first) {
 
1348
                        last_get[i] = '\0';
 
1349
                }
 
1350
                cookie[i]  = '\0';
 
1351
                rcookie[i] = '\0';
 
1352
        }
 
1353
        first = 0;
 
1354
 
 
1355
        if (getenv("ACCEPT_OPENSSL_DEBUG")) {
 
1356
                db = atoi(getenv("ACCEPT_OPENSSL_DEBUG"));
 
1357
        }
 
1358
 
 
1359
        /* do INETD, VNC, or HTTPS cases (result is client socket or pipe) */
 
1360
        if (mode == OPENSSL_INETD) {
 
1361
                ssl_initialized = 1;
 
1362
 
 
1363
        } else if (mode == OPENSSL_VNC) {
 
1364
                sock = accept(openssl_sock, (struct sockaddr *)&addr, &addrlen);
 
1365
                if (sock < 0)  {
 
1366
                        rfbLog("SSL: accept_openssl: accept connection failed\n");
 
1367
                        rfbLogPerror("accept");
 
1368
                        if (ssl_no_fail) {
 
1369
                                clean_up_exit(1);
 
1370
                        }
 
1371
                        return;
 
1372
                }
 
1373
                listen = openssl_sock;
 
1374
 
 
1375
        } else if (mode == OPENSSL_REVERSE) {
 
1376
                sock = presock;
 
1377
                if (sock < 0)  {
 
1378
                        rfbLog("SSL: accept_openssl: connection failed\n");
 
1379
                        if (ssl_no_fail) {
 
1380
                                clean_up_exit(1);
 
1381
                        }
 
1382
                        return;
 
1383
                }
 
1384
                listen = -1;
 
1385
 
 
1386
        } else if (mode == OPENSSL_HTTPS) {
 
1387
                sock = accept(https_sock, (struct sockaddr *)&addr, &addrlen);
 
1388
                if (sock < 0)  {
 
1389
                        rfbLog("SSL: accept_openssl: accept connection failed\n");
 
1390
                        rfbLogPerror("accept");
 
1391
                        if (ssl_no_fail) {
 
1392
                                clean_up_exit(1);
 
1393
                        }
 
1394
                        return;
 
1395
                }
 
1396
                listen = https_sock;
 
1397
        }
 
1398
        if (db) fprintf(stderr, "SSL: accept_openssl: sock: %d\n", sock);
 
1399
 
 
1400
        if (openssl_last_ip) {
 
1401
                free(openssl_last_ip);
 
1402
                openssl_last_ip = NULL;
 
1403
        }
 
1404
        if (mode == OPENSSL_INETD) {
 
1405
                openssl_last_ip = get_remote_host(fileno(stdin));
 
1406
        } else {
 
1407
                openssl_last_ip = get_remote_host(sock);
 
1408
        }
 
1409
 
 
1410
        /* now make a listening socket for child to connect back to us by: */
 
1411
 
 
1412
        cport = find_free_port(20000, 0);
 
1413
        if (! cport) {
 
1414
                rfbLog("SSL: accept_openssl: could not find open port.\n");
 
1415
                close(sock);
 
1416
                if (mode == OPENSSL_INETD || ssl_no_fail) {
 
1417
                        clean_up_exit(1);
 
1418
                }
 
1419
                return;
 
1420
        }
 
1421
        if (db) fprintf(stderr, "accept_openssl: cport: %d\n", cport);
 
1422
 
 
1423
        csock = rfbListenOnTCPPort(cport, htonl(INADDR_LOOPBACK));
 
1424
 
 
1425
        if (csock < 0) {
 
1426
                rfbLog("SSL: accept_openssl: could not listen on port %d.\n",
 
1427
                    cport);
 
1428
                close(sock);
 
1429
                if (mode == OPENSSL_INETD || ssl_no_fail) {
 
1430
                        clean_up_exit(1);
 
1431
                }
 
1432
                return;
 
1433
        }
 
1434
        if (db) fprintf(stderr, "accept_openssl: csock: %d\n", csock);
 
1435
 
 
1436
        fflush(stderr);
 
1437
 
 
1438
        /*
 
1439
         * make a simple cookie to id the child socket, not foolproof
 
1440
         * but hard to guess exactly (just worrying about local lusers
 
1441
         * here, since we use INADDR_LOOPBACK).
 
1442
         */
 
1443
        sprintf(cookie, "%f/%f", dnow(), x11vnc_start);
 
1444
 
 
1445
        if (mode != OPENSSL_INETD) {
 
1446
                name = get_remote_host(sock);
 
1447
                peerport = get_remote_port(sock);
 
1448
        } else {
 
1449
                openssl_last_ip = get_remote_host(fileno(stdin));
 
1450
                peerport = get_remote_port(fileno(stdin));
 
1451
                if (openssl_last_ip) {
 
1452
                        name = strdup(openssl_last_ip);
 
1453
                } else {
 
1454
                        name = strdup("unknown");
 
1455
                }
 
1456
        }
 
1457
        if (name) {
 
1458
                if (mode == OPENSSL_INETD) {
 
1459
                        rfbLog("SSL: (inetd) spawning helper process "
 
1460
                            "to handle: %s:%d\n", name, peerport);
 
1461
                } else {
 
1462
                        rfbLog("SSL: spawning helper process to handle: "
 
1463
                            "%s:%d\n", name, peerport);
 
1464
                }
 
1465
                free(name);
 
1466
                name = NULL;
 
1467
        }
 
1468
 
 
1469
        if (certret) {
 
1470
                free(certret);
 
1471
        }
 
1472
        if (certret_str) {
 
1473
                free(certret_str);
 
1474
                certret_str = NULL;
 
1475
        }
 
1476
        certret = strdup("/tmp/x11vnc-certret.XXXXXX");
 
1477
        omode = umask(077);
 
1478
        certret_fd = mkstemp(certret);
 
1479
        umask(omode);
 
1480
        if (certret_fd < 0) {
 
1481
                free(certret);
 
1482
                certret = NULL;
 
1483
                certret_fd = -1;
 
1484
        }
 
1485
 
 
1486
        /* now fork the child to handle the SSL: */
 
1487
        pid = fork();
 
1488
 
 
1489
        if (pid < 0) {
 
1490
                rfbLog("SSL: accept_openssl: could not fork.\n");
 
1491
                rfbLogPerror("fork");
 
1492
                close(sock);
 
1493
                close(csock);
 
1494
                if (mode == OPENSSL_INETD || ssl_no_fail) {
 
1495
                        clean_up_exit(1);
 
1496
                }
 
1497
                return;
 
1498
 
 
1499
        } else if (pid == 0) {
 
1500
                int s_in, s_out, httpsock = -1;
 
1501
                int vncsock;
 
1502
                int i, have_httpd = 0;
 
1503
                int f_in  = fileno(stdin);
 
1504
                int f_out = fileno(stdout);
 
1505
 
 
1506
                if (db) fprintf(stderr, "helper pid in: %d %d %d %d\n", f_in, f_out, sock, listen);
 
1507
 
 
1508
                /* reset all handlers to default (no interrupted() calls) */
 
1509
                unset_signals();
 
1510
 
 
1511
                /* close all non-essential fd's */
 
1512
                for (i=0; i<256; i++) {
 
1513
                        if (mode == OPENSSL_INETD) {
 
1514
                                if (i == f_in || i == f_out) {
 
1515
                                        continue;
 
1516
                                }
 
1517
                        }
 
1518
                        if (i == sock) {
 
1519
                                continue;
 
1520
                        }
 
1521
                        if (i == 2) {
 
1522
                                continue;
 
1523
                        }
 
1524
                        close(i);
 
1525
                }
 
1526
 
 
1527
                /*
 
1528
                 * sadly, we are a long lived child and so the large
 
1529
                 * framebuffer memory areas will soon differ from parent.
 
1530
                 * try to free as much as possible.
 
1531
                 */
 
1532
                lose_ram();
 
1533
 
 
1534
                /* now connect back to parent socket: */
 
1535
                vncsock = rfbConnectToTcpAddr("127.0.0.1", cport);
 
1536
                if (vncsock < 0) {
 
1537
                        rfbLog("SSL: ssl_helper[%d]: could not connect"
 
1538
                            " back to: %d\n", getpid(), cport);
 
1539
                        exit(1);
 
1540
                }
 
1541
                if (db) fprintf(stderr, "vncsock %d\n", vncsock);
 
1542
 
 
1543
                /* try to initialize SSL with the remote client */
 
1544
 
 
1545
                if (mode == OPENSSL_INETD) {
 
1546
                        s_in  = fileno(stdin);
 
1547
                        s_out = fileno(stdout);
 
1548
                } else {
 
1549
                        s_in = s_out = sock;
 
1550
                }
 
1551
 
 
1552
                if (! ssl_init(s_in, s_out)) {
 
1553
                        close(vncsock);
 
1554
                        exit(1);
 
1555
                }
 
1556
 
 
1557
                /*
 
1558
                 * things get messy below since we are trying to do
 
1559
                 * *both* VNC and Java applet httpd through the same
 
1560
                 * SSL socket.
 
1561
                 */
 
1562
 
 
1563
                if (! screen) {
 
1564
                        close(vncsock);
 
1565
                        exit(1);
 
1566
                }
 
1567
                if (screen->httpListenSock >= 0 && screen->httpPort > 0) {
 
1568
                        have_httpd = 1;
 
1569
                }
 
1570
                if (mode == OPENSSL_HTTPS && ! have_httpd) {
 
1571
                        rfbLog("SSL: accept_openssl[%d]: no httpd socket for "
 
1572
                            "-https mode\n", getpid());
 
1573
                        close(vncsock);
 
1574
                        exit(1);
 
1575
                }
 
1576
 
 
1577
                if (have_httpd) {
 
1578
                        int n = 0, is_http;
 
1579
                        int hport = screen->httpPort; 
 
1580
                        char *iface = NULL;
 
1581
                        char *buf, *tbuf;
 
1582
 
 
1583
                        buf  = (char *) calloc((ABSIZE+1), 1);
 
1584
                        tbuf = (char *) calloc((2*ABSIZE+1), 1);
 
1585
 
 
1586
                        if (mode == OPENSSL_HTTPS) {
 
1587
                                /*
 
1588
                                 * for this mode we know it is HTTP traffic
 
1589
                                 * so we skip trying to guess.
 
1590
                                 */
 
1591
                                is_http = 1;
 
1592
                                n = 0;
 
1593
                                goto connect_to_httpd;
 
1594
                        }
 
1595
 
 
1596
                        /*
 
1597
                         * Check if there is stuff to read from remote end
 
1598
                         * if so it is likely a GET or HEAD.
 
1599
                         */
 
1600
                        if (! is_ssl_readable(s_in, last_https, last_get,
 
1601
                            mode)) {
 
1602
                                goto write_cookie;
 
1603
                        }
 
1604
        
 
1605
                        /* 
 
1606
                         * read first 2 bytes to try to guess.  sadly,
 
1607
                         * the user is often pondering a "non-verified
 
1608
                         * cert" dialog for a long time before the GET
 
1609
                         * is ever sent.  So often we timeout here.
 
1610
                         */
 
1611
 
 
1612
                        if (db) fprintf(stderr, "watch_for_http_traffic\n");
 
1613
 
 
1614
                        is_http = watch_for_http_traffic(buf, &n);
 
1615
 
 
1616
                        if (is_http < 0 || is_http == 0) {
 
1617
                                /*
 
1618
                                 * error or http not detected, fall back
 
1619
                                 * to normal VNC socket.
 
1620
                                 */
 
1621
                                if (db) fprintf(stderr, "is_http err: %d n: %d\n", is_http, n);
 
1622
                                write(vncsock, cookie, strlen(cookie));
 
1623
                                if (n > 0) {
 
1624
                                        write(vncsock, buf, n);
 
1625
                                }
 
1626
                                goto wrote_cookie;
 
1627
                        }
 
1628
 
 
1629
                        if (db) fprintf(stderr, "is_http: %d n: %d\n",
 
1630
                            is_http, n);
 
1631
                        if (db) fprintf(stderr, "buf: '%s'\n", buf);
 
1632
 
 
1633
                        if (strstr(buf, "/request.https.vnc.connection")) {
 
1634
                                char reply[] = "HTTP/1.0 200 OK\r\n"
 
1635
                                    "Content-Type: octet-stream\r\n"
 
1636
                                    "Connection: Keep-Alive\r\n"
 
1637
                                    "Pragma: no-cache\r\n\r\n";
 
1638
                                /*
 
1639
                                 * special case proxy coming thru https
 
1640
                                 * instead of a direct SSL connection.
 
1641
                                 */
 
1642
                                rfbLog("Handling VNC request via https GET. [%d]\n", getpid());
 
1643
                                rfbLog("-- %s\n", buf);
 
1644
 
 
1645
                                if (strstr(buf, "/reverse.proxy")) {
 
1646
                                        char *buf2;
 
1647
                                        int n, ptr;
 
1648
                                        SSL_write(ssl, reply, strlen(reply));
 
1649
                                
 
1650
                                        buf2  = (char *) calloc((8192+1), 1);
 
1651
                                        n = 0;
 
1652
                                        ptr = 0;
 
1653
                                        while (ptr < 8192) {
 
1654
                                                n = SSL_read(ssl, buf2 + ptr, 1);
 
1655
                                                if (n > 0) {
 
1656
                                                        ptr += n;
 
1657
                                                }
 
1658
                        if (db) fprintf(stderr, "buf2: '%s'\n", buf2);
 
1659
 
 
1660
                                                if (strstr(buf2, "\r\n\r\n")) {
 
1661
                                                        break;
 
1662
                                                }
 
1663
                                        }
 
1664
                                        free(buf2);
 
1665
                                }
 
1666
                                goto write_cookie;
 
1667
 
 
1668
                        } else if (strstr(buf, "/check.https.proxy.connection")) {
 
1669
                                char reply[] = "HTTP/1.0 200 OK\r\n"
 
1670
                                    "Connection: close\r\n"
 
1671
                                    "Content-Type: octet-stream\r\n"
 
1672
                                    "Pragma: no-cache\r\n\r\n";
 
1673
 
 
1674
                                rfbLog("Handling Check HTTPS request via https GET. [%d]\n", getpid());
 
1675
                                rfbLog("-- %s\n", buf);
 
1676
 
 
1677
                                SSL_write(ssl, reply, strlen(reply));
 
1678
                                SSL_shutdown(ssl);
 
1679
 
 
1680
                                strcpy(tbuf, uniq);
 
1681
                                strcat(tbuf, cookie);
 
1682
                                write(vncsock, tbuf, strlen(tbuf));
 
1683
                                close(vncsock);
 
1684
 
 
1685
                                exit(0);
 
1686
                        }
 
1687
                        connect_to_httpd:
 
1688
 
 
1689
                        /*
 
1690
                         * Here we go... no turning back.  we have to
 
1691
                         * send failure to parent and close socket to have
 
1692
                         * http processed at all in a timely fashion...
 
1693
                         */
 
1694
 
 
1695
                        /* send the failure tag: */
 
1696
                        strcpy(tbuf, uniq);
 
1697
 
 
1698
                        if (https_port_redir < 0) {
 
1699
                                char *q = strstr(buf, "Host:");
 
1700
                                int fport = 443;
 
1701
                                char num[16];
 
1702
                                if (q && strstr(q, "\n")) {
 
1703
                                    q += strlen("Host:") + 1;
 
1704
                                    while (*q != '\n') {
 
1705
                                        int p;
 
1706
                                        if (*q == ':' && sscanf(q, ":%d", &p) == 1) {
 
1707
                                                if (p > 0 && p < 65536) {
 
1708
                                                        fport = p;
 
1709
                                                        break;
 
1710
                                                }
 
1711
                                        }
 
1712
                                        q++;
 
1713
                                    }
 
1714
                                }
 
1715
                                sprintf(num, "HP=%d,", fport);
 
1716
                                strcat(tbuf, num);
 
1717
                        }
 
1718
 
 
1719
                        if (strstr(buf, "HTTP/") != NULL)  {
 
1720
                                char *q, *str;
 
1721
                                /*
 
1722
                                 * Also send back the GET line for heuristics.
 
1723
                                 * (last_https, get file).
 
1724
                                 */
 
1725
                                str = strdup(buf);
 
1726
                                q = strstr(str, "HTTP/");
 
1727
                                if (q != NULL) {
 
1728
                                        *q = '\0';      
 
1729
                                        strcat(tbuf, str);
 
1730
                                }
 
1731
                                free(str);
 
1732
                        }
 
1733
 
 
1734
                        /*
 
1735
                         * Also send the cookie to pad out the number of
 
1736
                         * bytes to more than the parent wants to read.
 
1737
                         * Since this is the failure case, it does not
 
1738
                         * matter that we send more than strlen(cookie).
 
1739
                         */
 
1740
                        strcat(tbuf, cookie);
 
1741
                        write(vncsock, tbuf, strlen(tbuf));
 
1742
 
 
1743
                        usleep(150*1000);
 
1744
if (db) fprintf(stderr, "close vncsock: %d\n", vncsock);
 
1745
                        close(vncsock);
 
1746
 
 
1747
                        /* now, finally, connect to the libvncserver httpd: */
 
1748
                        if (screen->listenInterface == htonl(INADDR_ANY) ||
 
1749
                            screen->listenInterface == htonl(INADDR_NONE)) {
 
1750
                                iface = "127.0.0.1";
 
1751
                        } else {
 
1752
                                struct in_addr in;
 
1753
                                in.s_addr = screen->listenInterface;
 
1754
                                iface = inet_ntoa(in);
 
1755
                        }
 
1756
                        if (iface == NULL || !strcmp(iface, "")) {
 
1757
                                iface = "127.0.0.1";
 
1758
                        }
 
1759
if (db) fprintf(stderr, "iface: %s\n", iface);
 
1760
                        usleep(150*1000);
 
1761
 
 
1762
                        httpsock = rfbConnectToTcpAddr(iface, hport);
 
1763
 
 
1764
                        if (httpsock < 0) {
 
1765
                                /* UGH, after all of that! */
 
1766
                                rfbLog("Could not connect to httpd socket!\n");
 
1767
                                exit(1);
 
1768
                        }
 
1769
                        if (db) fprintf(stderr, "ssl_helper[%d]: httpsock: %d %d\n",
 
1770
                            getpid(), httpsock, n);
 
1771
 
 
1772
                        /*
 
1773
                         * send what we read to httpd, and then connect
 
1774
                         * the rest of the SSL session to it:
 
1775
                         */
 
1776
                        if (n > 0) {
 
1777
                                write(httpsock, buf, n);
 
1778
                        }
 
1779
                        ssl_xfer(httpsock, s_in, s_out, is_http);
 
1780
                        exit(0);
 
1781
                }
 
1782
 
 
1783
                /*
 
1784
                 * ok, back from the above https mess, simply send the
 
1785
                 * cookie back to the parent (who will attach us to
 
1786
                 * libvncserver), and connect the rest of the SSL session
 
1787
                 * to it.
 
1788
                 */
 
1789
                write_cookie:
 
1790
                write(vncsock, cookie, strlen(cookie));
 
1791
 
 
1792
                wrote_cookie:
 
1793
                ssl_xfer(vncsock, s_in, s_out, 0);
 
1794
 
 
1795
                exit(0);
 
1796
        }
 
1797
        /* parent here */
 
1798
 
 
1799
        if (mode != OPENSSL_INETD) {
 
1800
                close(sock);
 
1801
        }
 
1802
        if (db) fprintf(stderr, "helper process is: %d\n", pid);
 
1803
 
 
1804
        /* accept connection from our child.  */
 
1805
        signal(SIGALRM, csock_timeout);
 
1806
        csock_timeout_sock = csock;
 
1807
        alarm(20);
 
1808
 
 
1809
        vsock = accept(csock, (struct sockaddr *)&addr, &addrlen);
 
1810
 
 
1811
        alarm(0);
 
1812
        signal(SIGALRM, SIG_DFL);
 
1813
        close(csock);
 
1814
 
 
1815
 
 
1816
        if (vsock < 0) {
 
1817
                rfbLog("SSL: accept_openssl: connection from ssl_helper FAILED.\n");
 
1818
                rfbLogPerror("accept");
 
1819
 
 
1820
                kill(pid, SIGTERM);
 
1821
                waitpid(pid, &status, WNOHANG); 
 
1822
                if (mode == OPENSSL_INETD || ssl_no_fail) {
 
1823
                        clean_up_exit(1);
 
1824
                }
 
1825
                if (certret_fd >= 0) {
 
1826
                        close(certret_fd);
 
1827
                        certret_fd = -1;
 
1828
                }
 
1829
                if (certret) {
 
1830
                        unlink(certret);
 
1831
                }
 
1832
                return;
 
1833
        }
 
1834
        if (db) fprintf(stderr, "accept_openssl: vsock: %d\n", vsock);
 
1835
 
 
1836
        n = read(vsock, rcookie, strlen(cookie));
 
1837
        if (n < 0 && errno != 0) {
 
1838
                rfbLogPerror("read");
 
1839
        }
 
1840
 
 
1841
        if (certret) {
 
1842
                struct stat sbuf;
 
1843
                sbuf.st_size = 0;
 
1844
                if (certret_fd >= 0 && stat(certret, &sbuf) == 0 && sbuf.st_size > 0) {
 
1845
                        certret_str = (char *) malloc(sbuf.st_size+1);
 
1846
                        read(certret_fd, certret_str, sbuf.st_size);
 
1847
                        close(certret_fd);
 
1848
                        certret_fd = -1;
 
1849
                }
 
1850
                if (certret_fd >= 0) {
 
1851
                        close(certret_fd);
 
1852
                        certret_fd = -1;
 
1853
                }
 
1854
                unlink(certret);
 
1855
                if (certret_str && strstr(certret_str, "NOCERT") == certret_str) {
 
1856
                        free(certret_str);
 
1857
                        certret_str = NULL;
 
1858
                }
 
1859
                if (0 && certret_str) {
 
1860
                        fprintf(stderr, "certret_str[%d]:\n%s\n", (int) sbuf.st_size, certret_str);
 
1861
                }
 
1862
        }
 
1863
 
 
1864
        if (n != (int) strlen(cookie) || strncmp(cookie, rcookie, n)) {
 
1865
                rfbLog("SSL: accept_openssl: cookie from ssl_helper FAILED. %d\n", n);
 
1866
                if (db) fprintf(stderr, "'%s'\n'%s'\n", cookie, rcookie);
 
1867
                close(vsock);
 
1868
 
 
1869
                if (strstr(rcookie, uniq) == rcookie) {
 
1870
                        int i;
 
1871
                        rfbLog("SSL: BUT WAIT! HTTPS for helper process succeeded. Good.\n");
 
1872
                        if (mode != OPENSSL_HTTPS) {
 
1873
                                last_https = time(NULL);
 
1874
                                for (i=0; i<128; i++) {
 
1875
                                        last_get[i] = '\0';
 
1876
                                }
 
1877
                                strncpy(last_get, rcookie, 100);
 
1878
                                if (db) fprintf(stderr, "last_get: '%s'\n", last_get);
 
1879
                        }
 
1880
                        if (rcookie && strstr(rcookie, "VncViewer.class")) {
 
1881
                                rfbLog("\n");
 
1882
                                rfbLog("***********************************************************\n");
 
1883
                                rfbLog("SSL: WARNING CLIENT ASKED FOR NONEXISTENT 'VncViewer.class'\n");
 
1884
                                rfbLog("SSL: USER NEEDS TO **RESTART** HIS WEB BROWSER.\n");
 
1885
                                rfbLog("***********************************************************\n");
 
1886
                                rfbLog("\n");
 
1887
                        }
 
1888
                        ssl_helper_pid(pid, -2);
 
1889
 
 
1890
                        if (https_port_redir) {
 
1891
                                double start;
 
1892
                                int origport = screen->port;
 
1893
                                int useport = screen->port;
 
1894
                                /* to expand $PORT correctly in index.vnc */
 
1895
                                if (https_port_redir < 0) {
 
1896
                                        char *q = strstr(rcookie, "HP=");
 
1897
                                        if (q) {
 
1898
                                                int p;
 
1899
                                                if (sscanf(q, "HP=%d,", &p) == 1) {
 
1900
                                                        useport = p;
 
1901
                                                }
 
1902
                                        }
 
1903
                                } else {
 
1904
                                        useport = https_port_redir;
 
1905
                                }
 
1906
                                screen->port = useport;
 
1907
                                if (origport != useport) {
 
1908
                                        rfbLog("SSL: -httpsredir guess port: %d\n", screen->port);
 
1909
                                }
 
1910
 
 
1911
                                start = dnow();
 
1912
                                while (dnow() < start + 10.0) {
 
1913
                                        rfbPE(10000);
 
1914
                                        usleep(10000);
 
1915
                                        waitpid(pid, &status, WNOHANG); 
 
1916
                                        if (kill(pid, 0) != 0) {
 
1917
                                                rfbPE(10000);
 
1918
                                                rfbPE(10000);
 
1919
                                                break;
 
1920
                                        }
 
1921
                                }
 
1922
                                screen->port = origport;
 
1923
                                rfbLog("SSL: guessing child https finished.\n");
 
1924
                                if (mode == OPENSSL_INETD) {
 
1925
                                        clean_up_exit(1);
 
1926
                                }
 
1927
                        } else if (mode == OPENSSL_INETD) {
 
1928
                                double start;
 
1929
                                /* to expand $PORT correctly in index.vnc */
 
1930
                                if (screen->port == 0) {
 
1931
                                        int fd = fileno(stdin);
 
1932
                                        if (getenv("X11VNC_INETD_PORT")) {
 
1933
                                                screen->port = atoi(getenv(
 
1934
                                                    "X11VNC_INETD_PORT"));
 
1935
                                        } else {
 
1936
                                                int tport = get_local_port(fd);
 
1937
                                                if (tport > 0) {
 
1938
                                                        screen->port = tport;
 
1939
                                                }
 
1940
                                        }
 
1941
                                }
 
1942
                                rfbLog("SSL: screen->port %d\n", screen->port);
 
1943
 
 
1944
                                /* kludge for https fetch via inetd */
 
1945
                                start = dnow();
 
1946
                                while (dnow() < start + 10.0) {
 
1947
                                        rfbPE(10000);
 
1948
                                        usleep(10000);
 
1949
                                        waitpid(pid, &status, WNOHANG); 
 
1950
                                        if (kill(pid, 0) != 0) {
 
1951
                                                rfbPE(10000);
 
1952
                                                rfbPE(10000);
 
1953
                                                break;
 
1954
                                        }
 
1955
                                }
 
1956
                                rfbLog("SSL: OPENSSL_INETD guessing "
 
1957
                                    "child https finished.\n");
 
1958
                                clean_up_exit(1);
 
1959
                        }
 
1960
                        return;
 
1961
                }
 
1962
                kill(pid, SIGTERM);
 
1963
                waitpid(pid, &status, WNOHANG); 
 
1964
                if (mode == OPENSSL_INETD || ssl_no_fail) {
 
1965
                        clean_up_exit(1);
 
1966
                }
 
1967
                return;
 
1968
        }
 
1969
        if (db) fprintf(stderr, "accept_openssl: cookie good: %s\n", cookie);
 
1970
 
 
1971
        rfbLog("SSL: handshake with helper process succeeded.\n");
 
1972
 
 
1973
        openssl_last_helper_pid = pid;
 
1974
        ssl_helper_pid(pid, vsock);
 
1975
 
 
1976
        if (vnc_redirect) {
 
1977
                vnc_redirect_sock = vsock;
 
1978
                openssl_last_helper_pid = 0;
 
1979
                return;
 
1980
        }
 
1981
 
 
1982
        client = rfbNewClient(screen, vsock);
 
1983
        openssl_last_helper_pid = 0;
 
1984
 
 
1985
        if (client) {
 
1986
                if (db) fprintf(stderr, "accept_openssl: client %p\n", (void *) client);
 
1987
                if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) screen->newClientHook);
 
1988
                if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) new_client);
 
1989
                if (mode == OPENSSL_INETD) {
 
1990
                        inetd_client = client;
 
1991
                        client->clientGoneHook = client_gone;
 
1992
                }
 
1993
                if (openssl_last_ip &&
 
1994
                    strpbrk(openssl_last_ip, "0123456789") == openssl_last_ip) {
 
1995
                        client->host = strdup(openssl_last_ip);
 
1996
                }
 
1997
        } else {
 
1998
                rfbLog("SSL: accept_openssl: rfbNewClient failed.\n");
 
1999
                close(vsock);
 
2000
 
 
2001
                kill(pid, SIGTERM);
 
2002
                waitpid(pid, &status, WNOHANG); 
 
2003
                if (mode == OPENSSL_INETD || ssl_no_fail) {
 
2004
                        clean_up_exit(1);
 
2005
                }
 
2006
                return;
 
2007
        }
 
2008
}
 
2009
 
 
2010
static void ssl_timeout (int sig) {
 
2011
        rfbLog("sig: %d, ssl_init timed out.\n", sig);
 
2012
        exit(1);
 
2013
}
 
2014
 
 
2015
static int ssl_init(int s_in, int s_out) {
 
2016
        unsigned char *sid = (unsigned char *) "x11vnc SID";
 
2017
        char *name;
 
2018
        int peerport = 0;
 
2019
        int db = 0, rc, err;
 
2020
        int ssock = s_in;
 
2021
        double start = dnow();
 
2022
        int timeout = 20;
 
2023
 
 
2024
        if (getenv("SSL_DEBUG")) {
 
2025
                db = atoi(getenv("SSL_DEBUG"));
 
2026
        }
 
2027
        if (db) fprintf(stderr, "ssl_init: %d/%d\n", s_in, s_out);
 
2028
 
 
2029
        ssl = SSL_new(ctx);
 
2030
        if (ssl == NULL) {
 
2031
                fprintf(stderr, "SSL_new failed\n");
 
2032
                return 0;
 
2033
        }
 
2034
if (db > 1) fprintf(stderr, "ssl_init: 1\n");
 
2035
 
 
2036
        SSL_set_session_id_context(ssl, sid, strlen((char *)sid));
 
2037
 
 
2038
        if (s_in == s_out) {
 
2039
                if (! SSL_set_fd(ssl, ssock)) {
 
2040
                        fprintf(stderr, "SSL_set_fd failed\n");
 
2041
                        return 0;
 
2042
                }
 
2043
        } else {
 
2044
                if (! SSL_set_rfd(ssl, s_in)) {
 
2045
                        fprintf(stderr, "SSL_set_rfd failed\n");
 
2046
                        return 0;
 
2047
                }
 
2048
                if (! SSL_set_wfd(ssl, s_out)) {
 
2049
                        fprintf(stderr, "SSL_set_wfd failed\n");
 
2050
                        return 0;
 
2051
                }
 
2052
        }
 
2053
if (db > 1) fprintf(stderr, "ssl_init: 2\n");
 
2054
 
 
2055
        if (ssl_client_mode) {
 
2056
                SSL_set_connect_state(ssl);
 
2057
        } else {
 
2058
                SSL_set_accept_state(ssl);
 
2059
        }
 
2060
 
 
2061
if (db > 1) fprintf(stderr, "ssl_init: 3\n");
 
2062
 
 
2063
        name = get_remote_host(ssock);
 
2064
        peerport = get_remote_port(ssock);
 
2065
 
 
2066
if (db > 1) fprintf(stderr, "ssl_init: 4\n");
 
2067
 
 
2068
        while (1) {
 
2069
                if (db) fprintf(stderr, "calling SSL_accept...\n");
 
2070
 
 
2071
                signal(SIGALRM, ssl_timeout);
 
2072
                alarm(timeout);
 
2073
 
 
2074
                if (ssl_client_mode) {
 
2075
                        rc = SSL_connect(ssl);
 
2076
                } else {
 
2077
                        rc = SSL_accept(ssl);
 
2078
                }
 
2079
                err = SSL_get_error(ssl, rc);
 
2080
 
 
2081
                alarm(0);
 
2082
                signal(SIGALRM, SIG_DFL);
 
2083
 
 
2084
                if (db) fprintf(stderr, "SSL_accept %d/%d\n", rc, err);
 
2085
                if (err == SSL_ERROR_NONE) {
 
2086
                        break;
 
2087
                } else if (err == SSL_ERROR_WANT_READ) {
 
2088
 
 
2089
                        if (db) fprintf(stderr, "got SSL_ERROR_WANT_READ\n");
 
2090
                        rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n",
 
2091
                            getpid(), name, peerport);
 
2092
                        return 0;
 
2093
                        
 
2094
                } else if (err == SSL_ERROR_WANT_WRITE) {
 
2095
 
 
2096
                        if (db) fprintf(stderr, "got SSL_ERROR_WANT_WRITE\n");
 
2097
                        rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n",
 
2098
                            getpid(), name, peerport);
 
2099
                        return 0;
 
2100
 
 
2101
                } else if (err == SSL_ERROR_SYSCALL) {
 
2102
 
 
2103
                        if (db) fprintf(stderr, "got SSL_ERROR_SYSCALL\n");
 
2104
                        rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n",
 
2105
                            getpid(), name, peerport);
 
2106
                        return 0;
 
2107
 
 
2108
                } else if (err == SSL_ERROR_ZERO_RETURN) {
 
2109
 
 
2110
                        if (db) fprintf(stderr, "got SSL_ERROR_ZERO_RETURN\n");
 
2111
                        rfbLog("SSL: ssl_helper[%d]: SSL_accept() failed for: %s:%d\n",
 
2112
                            getpid(), name, peerport);
 
2113
                        return 0;
 
2114
 
 
2115
                } else if (rc < 0) {
 
2116
 
 
2117
                        rfbLog("SSL: ssl_helper[%d]: SSL_accept() *FATAL: %d\n", getpid(), rc);
 
2118
                        return 0;
 
2119
 
 
2120
                } else if (dnow() > start + 3.0) {
 
2121
 
 
2122
                        rfbLog("SSL: ssl_helper[%d]: timeout looping SSL_accept() "
 
2123
                            "fatal.\n", getpid());
 
2124
                        return 0;
 
2125
 
 
2126
                } else {
 
2127
                        BIO *bio = SSL_get_rbio(ssl);
 
2128
                        if (bio == NULL) {
 
2129
                                rfbLog("SSL: ssl_helper[%d]: ssl BIO is null. "
 
2130
                                    "fatal.\n", getpid());
 
2131
                                return 0;
 
2132
                        }
 
2133
                        if (BIO_eof(bio)) {
 
2134
                                rfbLog("SSL: ssl_helper[%d]: ssl BIO is EOF. "
 
2135
                                    "fatal.\n", getpid());
 
2136
                                return 0;
 
2137
                        }
 
2138
                }
 
2139
                usleep(10 * 1000);
 
2140
        }
 
2141
 
 
2142
        rfbLog("SSL: ssl_helper[%d]: SSL_accept() succeeded for: %s:%d\n", getpid(), name, peerport);
 
2143
 
 
2144
        if (SSL_get_verify_result(ssl) == X509_V_OK) {
 
2145
                X509 *x;
 
2146
                FILE *cr = NULL;
 
2147
                if (certret != NULL) {
 
2148
                        cr = fopen(certret, "w");
 
2149
                }
 
2150
                
 
2151
                x = SSL_get_peer_certificate(ssl);      
 
2152
                if (x == NULL) {
 
2153
                        rfbLog("SSL: ssl_helper[%d]: accepted client %s x509 peer cert is null\n", getpid(), name);
 
2154
                        if (cr != NULL) {
 
2155
                                fprintf(cr, "NOCERT\n");
 
2156
                                fclose(cr);
 
2157
                        }
 
2158
                } else {
 
2159
                        rfbLog("SSL: ssl_helper[%d]: accepted client %s x509 cert is:\n", getpid(), name);
 
2160
                        X509_print_ex_fp(stderr, x, 0, XN_FLAG_MULTILINE);
 
2161
                        if (cr != NULL) {
 
2162
                                X509_print_ex_fp(cr, x, 0, XN_FLAG_MULTILINE);
 
2163
                                fclose(cr);
 
2164
                        }
 
2165
                }
 
2166
        }
 
2167
        free(name);
 
2168
 
 
2169
        return 1;
 
2170
}
 
2171
 
 
2172
static void ssl_xfer(int csock, int s_in, int s_out, int is_https) {
 
2173
        int dbxfer = 0, db = 0, check_pending, fdmax, nfd, n, i, err;
 
2174
        char cbuf[ABSIZE], sbuf[ABSIZE];
 
2175
        int  cptr, sptr, c_rd, c_wr, s_rd, s_wr;
 
2176
        fd_set rd, wr;
 
2177
        struct timeval tv;
 
2178
        int ssock, cnt = 0, ndata = 0;
 
2179
 
 
2180
        /*
 
2181
         * we want to switch to a longer timeout for long term VNC
 
2182
         * connections (in case the network is not working for periods of
 
2183
         * time), but we also want the timeout shorter at the beginning
 
2184
         * in case the client went away.
 
2185
         */
 
2186
        time_t start;
 
2187
        int tv_https_early = 60;
 
2188
        int tv_https_later = 20;
 
2189
        int tv_vnc_early = 25;
 
2190
        int tv_vnc_later = 43200;       /* was 300, stunnel: 43200 */
 
2191
        int tv_cutover = 70;
 
2192
        int tv_closing = 60;
 
2193
        int tv_use;
 
2194
 
 
2195
        if (dbxfer) {
 
2196
                raw_xfer(csock, s_in, s_out);
 
2197
                return;
 
2198
        }
 
2199
        if (getenv("SSL_DEBUG")) {
 
2200
                db = atoi(getenv("SSL_DEBUG"));
 
2201
        }
 
2202
 
 
2203
        if (db) fprintf(stderr, "ssl_xfer begin\n");
 
2204
 
 
2205
        start = time(NULL);
 
2206
        if (is_https) {
 
2207
                tv_use = tv_https_early;
 
2208
        } else {
 
2209
                tv_use = tv_vnc_early;
 
2210
        }
 
2211
        
 
2212
 
 
2213
        /*
 
2214
         * csock: clear text socket with libvncserver.    "C"
 
2215
         * ssock: ssl data socket with remote vnc viewer. "S"
 
2216
         *
 
2217
         * to cover inetd mode, we have s_in and s_out, but in non-inetd
 
2218
         * mode they both ssock.
 
2219
         *
 
2220
         * cbuf[] is data from csock that we have read but not passed on to ssl 
 
2221
         * sbuf[] is data from ssl that we have read but not passed on to csock 
 
2222
         */
 
2223
        for (i=0; i<ABSIZE; i++) {
 
2224
                cbuf[i] = '\0';
 
2225
                sbuf[i] = '\0';
 
2226
        }
 
2227
                
 
2228
        if (s_out > s_in) {
 
2229
                ssock = s_out;
 
2230
        } else {
 
2231
                ssock = s_in;
 
2232
        }
 
2233
 
 
2234
        if (csock > ssock) {
 
2235
                fdmax = csock; 
 
2236
        } else {
 
2237
                fdmax = ssock; 
 
2238
        }
 
2239
 
 
2240
        c_rd = 1;       /* clear text (libvncserver) socket open for reading */
 
2241
        c_wr = 1;       /* clear text (libvncserver) socket open for writing */
 
2242
        s_rd = 1;       /* ssl data (remote client)  socket open for reading */
 
2243
        s_wr = 1;       /* ssl data (remote client)  socket open for writing */
 
2244
 
 
2245
        cptr = 0;       /* offsets into ABSIZE buffers */
 
2246
        sptr = 0;
 
2247
 
 
2248
        while (1) {
 
2249
                int c_to_s, s_to_c, closing;
 
2250
 
 
2251
                if ( s_wr && (c_rd || cptr > 0) ) {
 
2252
                        /* 
 
2253
                         * S is writable and 
 
2254
                         * C is readable or some cbuf data remaining
 
2255
                         */
 
2256
                        c_to_s = 1;
 
2257
                } else {
 
2258
                        c_to_s = 0;
 
2259
                }
 
2260
 
 
2261
                if ( c_wr && (s_rd || sptr > 0) ) {
 
2262
                        /* 
 
2263
                         * C is writable and 
 
2264
                         * S is readable or some sbuf data remaining
 
2265
                         */
 
2266
                        s_to_c = 1;
 
2267
                } else {
 
2268
                        s_to_c = 0;
 
2269
                }
 
2270
 
 
2271
                if (! c_to_s && ! s_to_c) {
 
2272
                        /*
 
2273
                         * nothing can be sent either direction.
 
2274
                         * break out of the loop to finish all work.
 
2275
                         */
 
2276
                        break;
 
2277
                }
 
2278
                cnt++;
 
2279
 
 
2280
                /* set up the fd sets for the two sockets for read & write: */
 
2281
 
 
2282
                FD_ZERO(&rd);
 
2283
 
 
2284
                if (c_rd && cptr < ABSIZE) {
 
2285
                        /* we could read more from C since cbuf is not full */
 
2286
                        FD_SET(csock, &rd);
 
2287
                }
 
2288
                if (s_rd) {
 
2289
                        /*
 
2290
                         * we could read more from S since sbuf not full,
 
2291
                         * OR ssl is waiting for more BIO to be able to
 
2292
                         * read and we have some C data still buffered.
 
2293
                         */
 
2294
                        if (sptr < ABSIZE || (cptr > 0 && SSL_want_read(ssl))) {
 
2295
                                FD_SET(s_in, &rd);
 
2296
                        }
 
2297
                }
 
2298
                
 
2299
                FD_ZERO(&wr);
 
2300
 
 
2301
                if (c_wr && sptr > 0) {
 
2302
                        /* we could write more to C since sbuf is not empty */
 
2303
                        FD_SET(csock, &wr);
 
2304
                }
 
2305
                if (s_wr) {
 
2306
                        /*
 
2307
                         * we could write more to S since cbuf not empty,
 
2308
                         * OR ssl is waiting for more BIO to be able
 
2309
                         * write and we haven't filled up sbuf yet.
 
2310
                         */
 
2311
                        if (cptr > 0 || (sptr < ABSIZE && SSL_want_write(ssl))) {
 
2312
                                FD_SET(s_out, &wr);
 
2313
                        }
 
2314
                }
 
2315
 
 
2316
                if (tv_cutover && time(NULL) > start + tv_cutover) {
 
2317
                        rfbLog("SSL: ssl_xfer[%d]: tv_cutover: %d\n", getpid(),
 
2318
                            tv_cutover);
 
2319
                        tv_cutover = 0;
 
2320
                        if (is_https) {
 
2321
                                tv_use = tv_https_later;
 
2322
                        } else {
 
2323
                                tv_use = tv_vnc_later;
 
2324
                        }
 
2325
                }
 
2326
                if (ssl_timeout_secs > 0) {
 
2327
                        tv_use = ssl_timeout_secs;
 
2328
                }
 
2329
 
 
2330
                if ( (s_rd && c_rd) || cptr || sptr) {
 
2331
                        closing = 0;
 
2332
                } else {
 
2333
                        closing = 1;
 
2334
                        tv_use = tv_closing;
 
2335
                }
 
2336
                tv.tv_sec  = tv_use;
 
2337
                tv.tv_usec = 0;
 
2338
 
 
2339
                /*  do the select, repeat if interrupted */
 
2340
                do {
 
2341
                        if (ssl_timeout_secs == 0) {
 
2342
                                nfd = select(fdmax+1, &rd, &wr, NULL, NULL);
 
2343
                        } else {
 
2344
                                nfd = select(fdmax+1, &rd, &wr, NULL, &tv);
 
2345
                        }
 
2346
                } while (nfd < 0 && errno == EINTR);
 
2347
 
 
2348
                if (db > 1) fprintf(stderr, "nfd: %d\n", nfd);
 
2349
 
 
2350
                if (nfd < 0) {
 
2351
                        rfbLog("SSL: ssl_xfer[%d]: select error: %d\n", getpid(), nfd);
 
2352
                        perror("select");
 
2353
                        /* connection finished */
 
2354
                        return; 
 
2355
                }
 
2356
 
 
2357
                if (nfd == 0) {
 
2358
                        if (!closing && tv_cutover && ndata > 25000) {
 
2359
                                static int cn = 0;
 
2360
                                /* probably ok, early windows iconify */
 
2361
                                if (cn++ < 2) {
 
2362
                                        rfbLog("SSL: ssl_xfer[%d]: early time"
 
2363
                                            "out: %d\n", getpid(), ndata);
 
2364
                                }
 
2365
                                continue;
 
2366
                        }
 
2367
                        rfbLog("SSL: ssl_xfer[%d]: connection timedout. %d\n",
 
2368
                            getpid(), ndata);
 
2369
                        /* connection finished */
 
2370
                        return;
 
2371
                }
 
2372
 
 
2373
                /* used to see if SSL_pending() should be checked: */
 
2374
                check_pending = 0;
 
2375
/* AUDIT */
 
2376
 
 
2377
                if (c_wr && FD_ISSET(csock, &wr)) {
 
2378
 
 
2379
                        /* try to write some of our sbuf to C: */
 
2380
                        n = write(csock, sbuf, sptr); 
 
2381
 
 
2382
                        if (n < 0) {
 
2383
                                if (errno != EINTR) {
 
2384
                                        /* connection finished */
 
2385
                                        return;
 
2386
                                }
 
2387
                                /* proceed */
 
2388
                        } else if (n == 0) {
 
2389
                                /* connection finished XXX double check */
 
2390
                                return;
 
2391
                        } else {
 
2392
                                /* shift over the data in sbuf by n */
 
2393
                                memmove(sbuf, sbuf + n, sptr - n);
 
2394
                                if (sptr == ABSIZE) {
 
2395
                                        check_pending = 1;
 
2396
                                }
 
2397
                                sptr -= n;
 
2398
 
 
2399
                                if (! s_rd && sptr == 0) {
 
2400
                                        /* finished sending last of sbuf */
 
2401
                                        shutdown(csock, SHUT_WR);
 
2402
                                        c_wr = 0;
 
2403
                                }
 
2404
                                ndata += n;
 
2405
                        }
 
2406
                }
 
2407
 
 
2408
                if (s_wr) {
 
2409
                        if ((cptr > 0 && FD_ISSET(s_out, &wr)) ||
 
2410
                            (SSL_want_read(ssl) && FD_ISSET(s_in, &rd))) {
 
2411
 
 
2412
                                /* try to write some of our cbuf to S: */
 
2413
 
 
2414
                                n = SSL_write(ssl, cbuf, cptr);
 
2415
                                err = SSL_get_error(ssl, n);
 
2416
 
 
2417
                                if (err == SSL_ERROR_NONE) {
 
2418
                                        /* shift over the data in cbuf by n */
 
2419
                                        memmove(cbuf, cbuf + n, cptr - n);
 
2420
                                        cptr -= n;
 
2421
 
 
2422
                                        if (! c_rd && cptr == 0 && s_wr) {
 
2423
                                                /* finished sending last cbuf */
 
2424
                                                SSL_shutdown(ssl);
 
2425
                                                s_wr = 0;
 
2426
                                        }
 
2427
                                        ndata += n;
 
2428
 
 
2429
                                } else if (err == SSL_ERROR_WANT_WRITE
 
2430
                                        || err == SSL_ERROR_WANT_READ
 
2431
                                        || err == SSL_ERROR_WANT_X509_LOOKUP) {
 
2432
 
 
2433
                                                ;       /* proceed */
 
2434
 
 
2435
                                } else if (err == SSL_ERROR_SYSCALL) {
 
2436
                                        if (n < 0 && errno != EINTR) {
 
2437
                                                /* connection finished */
 
2438
                                                return;
 
2439
                                        }
 
2440
                                        /* proceed */
 
2441
                                } else if (err == SSL_ERROR_ZERO_RETURN) {
 
2442
                                        /* S finished */
 
2443
                                        s_rd = 0;
 
2444
                                        s_wr = 0;
 
2445
                                } else if (err == SSL_ERROR_SSL) {
 
2446
                                        /* connection finished */
 
2447
                                        return;
 
2448
                                }
 
2449
                        }
 
2450
                }
 
2451
 
 
2452
                if (c_rd && FD_ISSET(csock, &rd)) {
 
2453
 
 
2454
 
 
2455
                        /* try to read some data from C into our cbuf */
 
2456
 
 
2457
                        n = read(csock, cbuf + cptr, ABSIZE - cptr);
 
2458
 
 
2459
                        if (n < 0) {
 
2460
                                if (errno != EINTR) {
 
2461
                                        /* connection finished */
 
2462
                                        return;
 
2463
                                }
 
2464
                                /* proceed */
 
2465
                        } else if (n == 0) {
 
2466
                                /* C is EOF */
 
2467
                                c_rd = 0;
 
2468
                                if (cptr == 0 && s_wr) {
 
2469
                                        /* and no more in cbuf to send */
 
2470
                                        SSL_shutdown(ssl);
 
2471
                                        s_wr = 0;
 
2472
                                }
 
2473
                        } else {
 
2474
                                /* good */
 
2475
 
 
2476
                                cptr += n;
 
2477
                                ndata += n;
 
2478
                        }
 
2479
                }
 
2480
 
 
2481
                if (s_rd) {
 
2482
                        if ((sptr < ABSIZE && FD_ISSET(s_in, &rd)) ||
 
2483
                            (SSL_want_write(ssl) && FD_ISSET(s_out, &wr)) ||
 
2484
                            (check_pending && SSL_pending(ssl))) {
 
2485
 
 
2486
                                /* try to read some data from S into our sbuf */
 
2487
 
 
2488
                                n = SSL_read(ssl, sbuf + sptr, ABSIZE - sptr);
 
2489
                                err = SSL_get_error(ssl, n);
 
2490
 
 
2491
                                if (err == SSL_ERROR_NONE) {
 
2492
                                        /* good */
 
2493
 
 
2494
                                        sptr += n;
 
2495
                                        ndata += n;
 
2496
 
 
2497
                                } else if (err == SSL_ERROR_WANT_WRITE
 
2498
                                        || err == SSL_ERROR_WANT_READ
 
2499
                                        || err == SSL_ERROR_WANT_X509_LOOKUP) {
 
2500
 
 
2501
                                                ;       /* proceed */
 
2502
 
 
2503
                                } else if (err == SSL_ERROR_SYSCALL) {
 
2504
                                        if (n < 0) {
 
2505
                                                if(errno != EINTR) {
 
2506
                                                        /* connection finished */
 
2507
                                                        return;
 
2508
                                                }
 
2509
                                                /* proceed */
 
2510
                                        } else {
 
2511
                                                /* S finished */
 
2512
                                                s_rd = 0;
 
2513
                                                s_wr = 0;
 
2514
                                        }
 
2515
                                } else if (err == SSL_ERROR_ZERO_RETURN) {
 
2516
                                        /* S is EOF */
 
2517
                                        s_rd = 0;
 
2518
                                        if (cptr == 0 && s_wr) {
 
2519
                                                /* and no more in cbuf to send */
 
2520
                                                SSL_shutdown(ssl);
 
2521
                                                s_wr = 0;
 
2522
                                        }
 
2523
                                        if (sptr == 0 && c_wr) {
 
2524
                                                /* and no more in sbuf to send */
 
2525
                                                shutdown(csock, SHUT_WR);
 
2526
                                                c_wr = 0;
 
2527
                                        }
 
2528
                                } else if (err == SSL_ERROR_SSL) {
 
2529
                                        /* connection finished */
 
2530
                                        return;
 
2531
                                }
 
2532
                        }
 
2533
                }
 
2534
        }
 
2535
}
 
2536
 
 
2537
void check_openssl(void) {
 
2538
        fd_set fds;
 
2539
        struct timeval tv;
 
2540
        int nfds;
 
2541
        static time_t last_waitall = 0;
 
2542
        static double last_check = 0.0;
 
2543
        double now;
 
2544
 
 
2545
        if (! use_openssl || openssl_sock < 0) {
 
2546
                return;
 
2547
        }
 
2548
 
 
2549
        now = dnow();
 
2550
        if (now < last_check + 0.5) {
 
2551
                return;
 
2552
        }
 
2553
        last_check = now;
 
2554
 
 
2555
        if (time(NULL) > last_waitall + 150) {
 
2556
                last_waitall = time(NULL);
 
2557
                ssl_helper_pid(0, -2);  /* waitall */
 
2558
        }
 
2559
 
 
2560
        FD_ZERO(&fds);
 
2561
        FD_SET(openssl_sock, &fds);
 
2562
 
 
2563
        tv.tv_sec = 0;
 
2564
        tv.tv_usec = 0;
 
2565
 
 
2566
        nfds = select(openssl_sock+1, &fds, NULL, NULL, &tv);
 
2567
 
 
2568
        if (nfds <= 0) {
 
2569
                return;
 
2570
        }
 
2571
        
 
2572
        rfbLog("SSL: accept_openssl(OPENSSL_VNC)\n");
 
2573
        accept_openssl(OPENSSL_VNC, -1);
 
2574
}
 
2575
 
 
2576
void check_https(void) {
 
2577
        fd_set fds;
 
2578
        struct timeval tv;
 
2579
        int nfds;
 
2580
        static double last_check = 0.0;
 
2581
        double now;
 
2582
 
 
2583
        if (! use_openssl || https_sock < 0) {
 
2584
                return;
 
2585
        }
 
2586
 
 
2587
        now = dnow();
 
2588
        if (now < last_check + 0.5) {
 
2589
                return;
 
2590
        }
 
2591
        last_check = now;
 
2592
 
 
2593
        FD_ZERO(&fds);
 
2594
        FD_SET(https_sock, &fds);
 
2595
 
 
2596
        tv.tv_sec = 0;
 
2597
        tv.tv_usec = 0;
 
2598
 
 
2599
        nfds = select(https_sock+1, &fds, NULL, NULL, &tv);
 
2600
 
 
2601
        if (nfds <= 0) {
 
2602
                return;
 
2603
        }
 
2604
        rfbLog("SSL: accept_openssl(OPENSSL_HTTPS)\n");
 
2605
        accept_openssl(OPENSSL_HTTPS, -1);
 
2606
}
 
2607
 
 
2608
#define MSZ 4096
 
2609
static void init_prng(void) {
 
2610
        int db = 0, bytes;
 
2611
        char file[MSZ];
 
2612
 
 
2613
        RAND_file_name(file, MSZ);
 
2614
 
 
2615
        rfbLog("RAND_file_name: %s\n", file);
 
2616
 
 
2617
        bytes = RAND_load_file(file, -1);
 
2618
        if (db) fprintf(stderr, "bytes read: %d\n", bytes);
 
2619
        
 
2620
        bytes += RAND_load_file("/dev/urandom", 64);
 
2621
        if (db) fprintf(stderr, "bytes read: %d\n", bytes);
 
2622
        
 
2623
        if (bytes > 0) {
 
2624
                if (! quiet) {
 
2625
                        rfbLog("initialized PRNG with %d random bytes.\n",
 
2626
                            bytes);
 
2627
                }
 
2628
                return;
 
2629
        }
 
2630
 
 
2631
        bytes += RAND_load_file("/dev/random", 8);
 
2632
        if (db) fprintf(stderr, "bytes read: %d\n", bytes);
 
2633
        if (! quiet) {
 
2634
                rfbLog("initialized PRNG with %d random bytes.\n", bytes);
 
2635
        }
 
2636
}
 
2637
#endif  /* FORK_OK */
 
2638
#endif  /* LIBVNCSERVER_HAVE_LIBSSL */
 
2639
 
 
2640
void raw_xfer(int csock, int s_in, int s_out) {
 
2641
        char buf0[8192];
 
2642
        int sz = 8192, n, m, status, db = 1;
 
2643
        char *buf;
 
2644
#ifdef FORK_OK
 
2645
        pid_t par = getpid();
 
2646
        pid_t pid = fork();
 
2647
 
 
2648
        buf = buf0;
 
2649
        if (vnc_redirect) {
 
2650
                /* change buf size some direction. */
 
2651
        }
 
2652
 
 
2653
        /* this is for testing, no SSL just socket redir */
 
2654
        if (pid < 0) {
 
2655
                exit(1);
 
2656
        }
 
2657
        if (pid) {
 
2658
                if (db) fprintf(stderr, "raw_xfer start: %d -> %d/%d\n", csock, s_in, s_out);
 
2659
 
 
2660
                while (1) {
 
2661
                        n = read(csock, buf, sz);
 
2662
                        if (n == 0 || (n < 0 && errno != EINTR) ) {
 
2663
                                break;
 
2664
                        } else if (n > 0) {
 
2665
                                int len = n;
 
2666
                                char *src = buf;
 
2667
                                if (db > 1) write(2, buf, n);
 
2668
                                while (len > 0) {
 
2669
                                        m = write(s_out, src, len);
 
2670
                                        if (m > 0) {
 
2671
                                                src += m;
 
2672
                                                len -= m;
 
2673
                                                continue;
 
2674
                                        }
 
2675
                                        if (m < 0 && (errno == EINTR || errno == EAGAIN)) {
 
2676
                                                continue;
 
2677
                                        }
 
2678
if (db) fprintf(stderr, "raw_xfer bad write:  %d -> %d | %d/%d  errno=%d\n", csock, s_out, m, n, errno);
 
2679
                                        break;
 
2680
                                }
 
2681
                        }
 
2682
                }
 
2683
                usleep(250*1000);
 
2684
                kill(pid, SIGTERM);
 
2685
                waitpid(pid, &status, WNOHANG); 
 
2686
                if (db) fprintf(stderr, "raw_xfer done:  %d -> %d\n", csock, s_out);
 
2687
 
 
2688
        } else {
 
2689
                if (db) fprintf(stderr, "raw_xfer start: %d <- %d\n", csock, s_in);
 
2690
 
 
2691
                while (1) {
 
2692
                        n = read(s_in, buf, sz);
 
2693
                        if (n == 0 || (n < 0 && errno != EINTR) ) {
 
2694
                                break;
 
2695
                        } else if (n > 0) {
 
2696
                                int len = n;
 
2697
                                char *src = buf;
 
2698
                                if (db > 1) write(2, buf, n);
 
2699
                                while (len > 0) {
 
2700
                                        m = write(csock, src, len);
 
2701
                                        if (m > 0) {
 
2702
                                                src += m;
 
2703
                                                len -= m;
 
2704
                                                continue;
 
2705
                                        }
 
2706
                                        if (m < 0 && (errno == EINTR || errno == EAGAIN)) {
 
2707
                                                continue;
 
2708
                                        }
 
2709
                if (db) fprintf(stderr, "raw_xfer bad write:  %d <- %d | %d/%d errno=%d\n", csock, s_in, m, n, errno);
 
2710
                                        break;
 
2711
                                }
 
2712
                        }
 
2713
                }
 
2714
                usleep(250*1000);
 
2715
                kill(par, SIGTERM);
 
2716
                waitpid(par, &status, WNOHANG); 
 
2717
                if (db) fprintf(stderr, "raw_xfer done:  %d <- %d\n", csock, s_in);
 
2718
        }
 
2719
        close(csock);
 
2720
        close(s_in);
 
2721
        close(s_out);
 
2722
#endif  /* FORK_OK */
 
2723
}
 
2724