1 /*-
2 * SSLsplit - transparent SSL/TLS interception
3 * https://www.roe.ch/SSLsplit
4 *
5 * Copyright (c) 2009-2019, Daniel Roethlisberger <daniel@roe.ch>.
6 * Copyright (c) 2017-2021, Soner Tari <sonertari@gmail.com>.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "opts.h"
31 #include "filter.h"
32
33 #include "sys.h"
34 #include "log.h"
35 #include "defaults.h"
36 #include "util.h"
37
38 #include <string.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/resource.h>
42
43 #ifndef OPENSSL_NO_DH
44 #include <openssl/dh.h>
45 #endif /* !OPENSSL_NO_DH */
46 #include <openssl/x509.h>
47
48 /*
49 * Temporary struct used while configuring proxyspec.
50 * These vars are used while configuring proxyspecs,
51 * and freed right after they are used, not in proxyspec_free().
52 */
53 typedef struct spec_addrs {
54 int af;
55 char *addr;
56 char *divert_addr;
57 char *target_addr;
58 } spec_addrs_t;
59
60 /*
61 * The topmost caller must exit with EXIT_FAILURE.
62 * Returning -1 instead of calling exit() is necessary for reporting the
63 * include file the error has occurred in.
64 */
65 int
oom_return(const char * argv0)66 oom_return(const char *argv0)
67 {
68 fprintf(stderr, "%s: out of memory\n", argv0);
69 return -1;
70 }
71
72 void *
oom_return_null(const char * argv0)73 oom_return_null(const char *argv0)
74 {
75 fprintf(stderr, "%s: out of memory\n", argv0);
76 return NULL;
77 }
78
79 int
oom_return_na()80 oom_return_na()
81 {
82 fprintf(stderr, "Out of memory\n");
83 return -1;
84 }
85
86 void *
oom_return_na_null()87 oom_return_na_null()
88 {
89 fprintf(stderr, "Out of memory\n");
90 return NULL;
91 }
92
93 /*
94 * Load a cert/chain/key combo from a single PEM file.
95 * Returns NULL on failure.
96 */
97 cert_t *
opts_load_cert_chain_key(const char * filename)98 opts_load_cert_chain_key(const char *filename)
99 {
100 cert_t *cert;
101
102 cert = cert_new_load(filename);
103 if (!cert) {
104 log_err_level_printf(LOG_CRIT, "Failed to load cert and key from PEM file "
105 "'%s'\n", filename);
106 return NULL;
107 }
108 if (X509_check_private_key(cert->crt, cert->key) != 1) {
109 log_err_level_printf(LOG_CRIT, "Cert does not match key in PEM file "
110 "'%s':\n", filename);
111 ERR_print_errors_fp(stderr);
112 return NULL;
113 }
114
115 #ifdef DEBUG_CERTIFICATE
116 log_dbg_printf("Loaded '%s':\n", filename);
117 log_dbg_print_free(ssl_x509_to_str(cert->crt));
118 log_dbg_print_free(ssl_x509_to_pem(cert->crt));
119 #endif /* DEBUG_CERTIFICATE */
120 return cert;
121 }
122
123 conn_opts_t *
conn_opts_new(void)124 conn_opts_new(void)
125 {
126 conn_opts_t *conn_opts = malloc(sizeof(conn_opts_t));
127 if (!conn_opts)
128 return oom_return_na_null();
129 memset(conn_opts, 0, sizeof(conn_opts_t));
130
131 conn_opts->sslcomp = 1;
132 conn_opts->chain = sk_X509_new_null();
133 conn_opts->sslmethod = SSLv23_method;
134 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L)
135 conn_opts->minsslversion = TLS1_VERSION;
136 #ifdef HAVE_TLSV13
137 conn_opts->maxsslversion = TLS1_3_VERSION;
138 #else /* !HAVE_TLSV13 */
139 conn_opts->maxsslversion = TLS1_2_VERSION;
140 #endif /* !HAVE_TLSV13 */
141 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
142 conn_opts->remove_http_referer = 1;
143 conn_opts->verify_peer = 1;
144 #ifndef WITHOUT_USERAUTH
145 conn_opts->user_timeout = 300;
146 #endif /* !WITHOUT_USERAUTH */
147 conn_opts->max_http_header_size = 8192;
148 return conn_opts;
149 }
150
151 opts_t *
opts_new(void)152 opts_new(void)
153 {
154 opts_t *opts;
155
156 opts = malloc(sizeof(opts_t));
157 if (!opts)
158 return oom_return_na_null();
159 memset(opts, 0, sizeof(opts_t));
160
161 opts->divert = 1;
162 return opts;
163 }
164
165 global_t *
global_new(void)166 global_new(void)
167 {
168 global_t *global;
169
170 global = malloc(sizeof(global_t));
171 if (!global)
172 return oom_return_na_null();
173 memset(global, 0, sizeof(global_t));
174
175 global->leafkey_rsabits = DFLT_LEAFKEY_RSABITS;
176 global->conn_idle_timeout = 120;
177 global->expired_conn_check_period = 10;
178 global->stats_period = 1;
179
180 global->conn_opts = conn_opts_new();
181 if (!global->conn_opts)
182 return NULL;
183 global->opts = opts_new();
184 if (!global->opts)
185 return NULL;
186 global->opts->global = global;
187 return global;
188 }
189
190 void
conn_opts_free(conn_opts_t * conn_opts)191 conn_opts_free(conn_opts_t *conn_opts)
192 {
193 if (conn_opts->clientcrt) {
194 X509_free(conn_opts->clientcrt);
195 }
196 if (conn_opts->clientkey) {
197 EVP_PKEY_free(conn_opts->clientkey);
198 }
199 if (conn_opts->cacrt) {
200 X509_free(conn_opts->cacrt);
201 }
202 if (conn_opts->cakey) {
203 EVP_PKEY_free(conn_opts->cakey);
204 }
205 if (conn_opts->chain) {
206 sk_X509_pop_free(conn_opts->chain, X509_free);
207 }
208 #ifndef OPENSSL_NO_DH
209 if (conn_opts->dh) {
210 DH_free(conn_opts->dh);
211 }
212 #endif /* !OPENSSL_NO_DH */
213 #ifndef OPENSSL_NO_ECDH
214 if (conn_opts->ecdhcurve) {
215 free(conn_opts->ecdhcurve);
216 }
217 #endif /* !OPENSSL_NO_ECDH */
218 if (conn_opts->ciphers) {
219 free(conn_opts->ciphers);
220 }
221 if (conn_opts->ciphersuites) {
222 free(conn_opts->ciphersuites);
223 }
224 #ifndef WITHOUT_USERAUTH
225 if (conn_opts->user_auth_url) {
226 free(conn_opts->user_auth_url);
227 }
228 #endif /* !WITHOUT_USERAUTH */
229
230 memset(conn_opts, 0, sizeof(conn_opts_t));
231 free(conn_opts);
232 }
233
234 void
opts_free(opts_t * opts)235 opts_free(opts_t *opts)
236 {
237 #ifndef WITHOUT_USERAUTH
238 filter_userlist_free(opts->divertusers);
239 filter_userlist_free(opts->passusers);
240 #endif /* !WITHOUT_USERAUTH */
241
242 // No need to call filter_macro_free() or filter_rules_free() here,
243 // macros and filter rules are freed after setting filter rules during startup
244 filter_free(opts);
245
246 memset(opts, 0, sizeof(opts_t));
247 free(opts);
248 }
249
250 static void
spec_addrs_free(spec_addrs_t * spec_addrs)251 spec_addrs_free(spec_addrs_t *spec_addrs)
252 {
253 if (spec_addrs->addr)
254 free(spec_addrs->addr);
255 if (spec_addrs->divert_addr)
256 free(spec_addrs->divert_addr);
257 if (spec_addrs->target_addr)
258 free(spec_addrs->target_addr);
259 memset(spec_addrs, 0, sizeof(spec_addrs_t));
260 free(spec_addrs);
261 }
262
263 /*
264 * Clear and free a proxy spec.
265 */
266 void
proxyspec_free(proxyspec_t * spec)267 proxyspec_free(proxyspec_t *spec)
268 {
269 if (spec->conn_opts)
270 conn_opts_free(spec->conn_opts);
271 if (spec->opts)
272 opts_free(spec->opts);
273 if (spec->natengine)
274 free(spec->natengine);
275 memset(spec, 0, sizeof(proxyspec_t));
276 free(spec);
277 }
278
279 /*
280 * Clear and free all proxy specs.
281 */
282 void
global_proxyspec_free(proxyspec_t * spec)283 global_proxyspec_free(proxyspec_t *spec)
284 {
285 do {
286 proxyspec_t *next = spec->next;
287 proxyspec_free(spec);
288 spec = next;
289 } while (spec);
290 }
291
292 void
tmp_opts_free(tmp_opts_t * tmp_opts)293 tmp_opts_free(tmp_opts_t *tmp_opts)
294 {
295 if (tmp_opts->cacrt_str) {
296 free(tmp_opts->cacrt_str);
297 tmp_opts->cacrt_str = NULL;
298 }
299 if (tmp_opts->cakey_str) {
300 free(tmp_opts->cakey_str);
301 tmp_opts->cakey_str = NULL;
302 }
303 if (tmp_opts->chain_str) {
304 free(tmp_opts->chain_str);
305 tmp_opts->chain_str = NULL;
306 }
307 if (tmp_opts->clientcrt_str) {
308 free(tmp_opts->clientcrt_str);
309 tmp_opts->clientcrt_str = NULL;
310 }
311 if (tmp_opts->clientkey_str) {
312 free(tmp_opts->clientkey_str);
313 tmp_opts->clientkey_str = NULL;
314 }
315 if (tmp_opts->leafcrlurl_str) {
316 free(tmp_opts->leafcrlurl_str);
317 tmp_opts->leafcrlurl_str = NULL;
318 }
319 if (tmp_opts->dh_str) {
320 free(tmp_opts->dh_str);
321 tmp_opts->dh_str = NULL;
322 }
323 free(tmp_opts);
324 }
325
326 void
global_free(global_t * global)327 global_free(global_t *global)
328 {
329 if (global->spec) {
330 global_proxyspec_free(global->spec);
331 }
332 if (global->leafcertdir) {
333 free(global->leafcertdir);
334 }
335 if (global->defaultleafcert) {
336 cert_free(global->defaultleafcert);
337 }
338 if (global->dropuser) {
339 free(global->dropuser);
340 }
341 if (global->dropgroup) {
342 free(global->dropgroup);
343 }
344 if (global->jaildir) {
345 free(global->jaildir);
346 }
347 if (global->pidfile) {
348 free(global->pidfile);
349 }
350 if (global->conffile) {
351 free(global->conffile);
352 }
353 if (global->connectlog) {
354 free(global->connectlog);
355 }
356 if (global->contentlog) {
357 free(global->contentlog);
358 }
359 if (global->certgendir) {
360 free(global->certgendir);
361 }
362 if (global->contentlog_basedir) {
363 free(global->contentlog_basedir);
364 }
365 if (global->masterkeylog) {
366 free(global->masterkeylog);
367 }
368 if (global->pcaplog) {
369 free(global->pcaplog);
370 }
371 if (global->pcaplog_basedir) {
372 free(global->pcaplog_basedir);
373 }
374 #ifndef WITHOUT_MIRROR
375 if (global->mirrorif) {
376 free(global->mirrorif);
377 }
378 if (global->mirrortarget) {
379 free(global->mirrortarget);
380 }
381 #endif /* !WITHOUT_MIRROR */
382 #ifndef WITHOUT_USERAUTH
383 if (global->userdb_path) {
384 free(global->userdb_path);
385 }
386 if (global->userdb) {
387 // sqlite3.h: "Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op."
388 sqlite3_finalize(global->update_user_atime);
389 sqlite3_close(global->userdb);
390 }
391 #endif /* !WITHOUT_USERAUTH */
392 if (global->conn_opts) {
393 conn_opts_free(global->conn_opts);
394 }
395 if (global->opts) {
396 opts_free(global->opts);
397 }
398 if (global->leafkey) {
399 EVP_PKEY_free(global->leafkey);
400 }
401 #ifndef OPENSSL_NO_ENGINE
402 if (global->openssl_engine) {
403 free(global->openssl_engine);
404 }
405 #endif /* !OPENSSL_NO_ENGINE */
406
407 memset(global, 0, sizeof(global_t));
408 free(global);
409 }
410
411 /*
412 * Return 1 if global_t contains a proxyspec that (eventually) uses SSL/TLS,
413 * 0 otherwise. When 0, it is safe to assume that no SSL/TLS operations
414 * will take place with this configuration.
415 */
416 int
global_has_ssl_spec(global_t * global)417 global_has_ssl_spec(global_t *global)
418 {
419 proxyspec_t *p = global->spec;
420 while (p) {
421 if (p->ssl || p->upgrade)
422 return 1;
423 p = p->next;
424 }
425 return 0;
426 }
427
428 /*
429 * Return 1 if global_t contains a proxyspec with dns, 0 otherwise.
430 */
431 int
global_has_dns_spec(global_t * global)432 global_has_dns_spec(global_t *global)
433 {
434 proxyspec_t *p = global->spec;
435 while (p) {
436 if (p->dns)
437 return 1;
438 p = p->next;
439 }
440 return 0;
441 }
442
443 #ifndef WITHOUT_USERAUTH
444 /*
445 * Return 1 if global_t contains a proxyspec with user_auth, 0 otherwise.
446 */
447 int
global_has_userauth_spec(global_t * global)448 global_has_userauth_spec(global_t *global)
449 {
450 proxyspec_t *p = global->spec;
451 while (p) {
452 if (p->conn_opts->user_auth)
453 return 1;
454
455 filter_rule_t *rule = p->opts->filter_rules;
456 while (rule) {
457 if (rule->action.conn_opts)
458 if (rule->action.conn_opts->user_auth)
459 return 1;
460 rule = rule->next;
461 }
462
463 p = p->next;
464 }
465 return 0;
466 }
467 #endif /* !WITHOUT_USERAUTH */
468
469 /*
470 * Return 1 if global_t contains a proxyspec with cakey defined, 0 otherwise.
471 */
472 int
global_has_cakey_spec(global_t * global)473 global_has_cakey_spec(global_t *global)
474 {
475 proxyspec_t *p = global->spec;
476 while (p) {
477 if (p->conn_opts->cakey)
478 return 1;
479
480 filter_rule_t *rule = p->opts->filter_rules;
481 while (rule) {
482 if (rule->action.conn_opts)
483 if (rule->action.conn_opts->cakey)
484 return 1;
485 rule = rule->next;
486 }
487
488 p = p->next;
489 }
490 return 0;
491 }
492
493 #ifndef WITHOUT_USERAUTH
494 static int WUNRES
opts_set_user_auth_url(conn_opts_t * conn_opts,const char * argv0,const char * optarg)495 opts_set_user_auth_url(conn_opts_t *conn_opts, const char * argv0, const char *optarg)
496 {
497 if (conn_opts->user_auth_url)
498 free(conn_opts->user_auth_url);
499 conn_opts->user_auth_url = strdup(optarg);
500 if (!conn_opts->user_auth_url)
501 return oom_return(argv0);
502 #ifdef DEBUG_OPTS
503 log_dbg_printf("UserAuthURL: %s\n", conn_opts->user_auth_url);
504 #endif /* DEBUG_OPTS */
505 return 0;
506 }
507 #endif /* !WITHOUT_USERAUTH */
508
509 tmp_opts_t *
tmp_opts_copy(tmp_opts_t * src_tmp_opts)510 tmp_opts_copy(tmp_opts_t *src_tmp_opts)
511 {
512 tmp_opts_t *tmp_opts = malloc(sizeof(tmp_opts_t));
513 if (!tmp_opts)
514 return oom_return_na_null();
515 memset(tmp_opts, 0, sizeof(tmp_opts_t));
516
517 if (src_tmp_opts->cacrt_str)
518 tmp_opts->cacrt_str = strdup(src_tmp_opts->cacrt_str);
519 if (src_tmp_opts->cakey_str)
520 tmp_opts->cakey_str = strdup(src_tmp_opts->cakey_str);
521 if (src_tmp_opts->chain_str)
522 tmp_opts->chain_str = strdup(src_tmp_opts->chain_str);
523 if (src_tmp_opts->clientcrt_str)
524 tmp_opts->clientcrt_str = strdup(src_tmp_opts->clientcrt_str);
525 if (src_tmp_opts->clientkey_str)
526 tmp_opts->clientkey_str = strdup(src_tmp_opts->clientkey_str);
527 if (src_tmp_opts->leafcrlurl_str)
528 tmp_opts->leafcrlurl_str = strdup(src_tmp_opts->leafcrlurl_str);
529 if (src_tmp_opts->dh_str)
530 tmp_opts->dh_str = strdup(src_tmp_opts->dh_str);
531 tmp_opts->split = src_tmp_opts->split;
532 tmp_opts->include = src_tmp_opts->include;
533 #ifdef DEBUG_PROXY
534 tmp_opts->line_num = src_tmp_opts->line_num;
535 #endif /* DEBUG_PROXY */
536
537 return tmp_opts;
538 }
539
540 conn_opts_t *
conn_opts_copy(conn_opts_t * conn_opts,const char * argv0,tmp_opts_t * tmp_opts)541 conn_opts_copy(conn_opts_t *conn_opts, const char *argv0, tmp_opts_t *tmp_opts)
542 {
543 #ifdef DEBUG_OPTS
544 log_dbg_printf("Copy conn_opts\n");
545 #endif /* DEBUG_OPTS */
546
547 conn_opts_t *cops = conn_opts_new();
548 if (!cops)
549 return NULL;
550
551 cops->sslcomp = conn_opts->sslcomp;
552 #ifdef HAVE_SSLV2
553 cops->no_ssl2 = conn_opts->no_ssl2;
554 #endif /* HAVE_SSLV2 */
555 #ifdef HAVE_SSLV3
556 cops->no_ssl3 = conn_opts->no_ssl3;
557 #endif /* HAVE_SSLV3 */
558 #ifdef HAVE_TLSV10
559 cops->no_tls10 = conn_opts->no_tls10;
560 #endif /* HAVE_TLSV10 */
561 #ifdef HAVE_TLSV11
562 cops->no_tls11 = conn_opts->no_tls11;
563 #endif /* HAVE_TLSV11 */
564 #ifdef HAVE_TLSV12
565 cops->no_tls12 = conn_opts->no_tls12;
566 #endif /* HAVE_TLSV12 */
567 #ifdef HAVE_TLSV13
568 cops->no_tls13 = conn_opts->no_tls13;
569 #endif /* HAVE_TLSV13 */
570 cops->passthrough = conn_opts->passthrough;
571 cops->deny_ocsp = conn_opts->deny_ocsp;
572 cops->sslmethod = conn_opts->sslmethod;
573 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L)
574 cops->sslversion = conn_opts->sslversion;
575 cops->minsslversion = conn_opts->minsslversion;
576 cops->maxsslversion = conn_opts->maxsslversion;
577 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
578 cops->remove_http_accept_encoding = conn_opts->remove_http_accept_encoding;
579 cops->remove_http_referer = conn_opts->remove_http_referer;
580 cops->verify_peer = conn_opts->verify_peer;
581 cops->allow_wrong_host = conn_opts->allow_wrong_host;
582 #ifndef WITHOUT_USERAUTH
583 cops->user_auth = conn_opts->user_auth;
584 cops->user_timeout = conn_opts->user_timeout;
585 #endif /* !WITHOUT_USERAUTH */
586 cops->validate_proto = conn_opts->validate_proto;
587 cops->reconnect_ssl = conn_opts->reconnect_ssl;
588 cops->max_http_header_size = conn_opts->max_http_header_size;
589
590 // Pass NULL as tmp_opts param, so we don't reassign the var to itself
591 // That would be harmless but incorrect
592 if (tmp_opts && tmp_opts->chain_str) {
593 if (opts_set_chain(cops, argv0, tmp_opts->chain_str, NULL) == -1)
594 return NULL;
595 }
596 if (tmp_opts && tmp_opts->leafcrlurl_str) {
597 if (opts_set_leafcrlurl(cops, argv0, tmp_opts->leafcrlurl_str, NULL) == -1)
598 return NULL;
599 }
600 if (tmp_opts && tmp_opts->cacrt_str) {
601 if (opts_set_cacrt(cops, argv0, tmp_opts->cacrt_str, NULL) == -1)
602 return NULL;
603 }
604 if (tmp_opts && tmp_opts->cakey_str) {
605 if (opts_set_cakey(cops, argv0, tmp_opts->cakey_str, NULL) == -1)
606 return NULL;
607 }
608 if (tmp_opts && tmp_opts->clientcrt_str) {
609 if (opts_set_clientcrt(cops, argv0, tmp_opts->clientcrt_str, NULL) == -1)
610 return NULL;
611 }
612 if (tmp_opts && tmp_opts->clientkey_str) {
613 if (opts_set_clientkey(cops, argv0, tmp_opts->clientkey_str, NULL) == -1)
614 return NULL;
615 }
616 #ifndef OPENSSL_NO_DH
617 if (tmp_opts && tmp_opts->dh_str) {
618 if (opts_set_dh(cops, argv0, tmp_opts->dh_str, NULL) == -1)
619 return NULL;
620 }
621 #endif /* !OPENSSL_NO_DH */
622 #ifndef OPENSSL_NO_ECDH
623 if (conn_opts->ecdhcurve) {
624 if (opts_set_ecdhcurve(cops, argv0, conn_opts->ecdhcurve) == -1)
625 return NULL;
626 }
627 #endif /* !OPENSSL_NO_ECDH */
628 if (conn_opts->ciphers) {
629 if (opts_set_ciphers(cops, argv0, conn_opts->ciphers) == -1)
630 return NULL;
631 }
632 if (conn_opts->ciphersuites) {
633 if (opts_set_ciphersuites(cops, argv0, conn_opts->ciphersuites) == -1)
634 return NULL;
635 }
636 #ifndef WITHOUT_USERAUTH
637 if (conn_opts->user_auth_url) {
638 if (opts_set_user_auth_url(cops, argv0, conn_opts->user_auth_url) == -1)
639 return NULL;
640 }
641 #endif /* !WITHOUT_USERAUTH */
642 return cops;
643 }
644
645 static opts_t * WUNRES
global_opts_copy(global_t * global,const char * argv0,tmp_opts_t * tmp_opts)646 global_opts_copy(global_t *global, const char *argv0, tmp_opts_t *tmp_opts)
647 {
648 #ifdef DEBUG_OPTS
649 log_dbg_printf("Copy global opts\n");
650 #endif /* DEBUG_OPTS */
651
652 opts_t *opts = opts_new();
653 if (!opts)
654 return NULL;
655 opts->global = global;
656
657 opts->divert = global->opts->divert;
658
659 #ifndef WITHOUT_USERAUTH
660 if (filter_userlist_copy(global->opts->divertusers, argv0, &opts->divertusers) == -1)
661 return oom_return_null(argv0);
662
663 if (filter_userlist_copy(global->opts->passusers, argv0, &opts->passusers) == -1)
664 return oom_return_null(argv0);
665 #endif /* !WITHOUT_USERAUTH */
666
667 if (filter_macro_copy(global->opts->macro, argv0, opts) == -1)
668 return oom_return_null(argv0);
669
670 if (filter_rule_copy(global->opts->filter_rules, argv0, opts, tmp_opts) == -1)
671 return oom_return_null(argv0);
672
673 return opts;
674 }
675
676 proxyspec_t *
proxyspec_new(global_t * global,const char * argv0,tmp_opts_t * tmp_opts)677 proxyspec_new(global_t *global, const char *argv0, tmp_opts_t *tmp_opts)
678 {
679 proxyspec_t *spec = malloc(sizeof(proxyspec_t));
680 if (!spec)
681 return oom_return_null(argv0);
682 memset(spec, 0, sizeof(proxyspec_t));
683 spec->conn_opts = conn_opts_copy(global->conn_opts, argv0, tmp_opts);
684 if (!spec->conn_opts)
685 return NULL;
686 spec->opts = global_opts_copy(global, argv0, tmp_opts);
687 if (!spec->opts)
688 return NULL;
689 return spec;
690 }
691
692 int
proxyspec_set_proto(proxyspec_t * spec,const char * value)693 proxyspec_set_proto(proxyspec_t *spec, const char *value)
694 {
695 /* Defaults */
696 spec->ssl = 0;
697 spec->http = 0;
698 spec->upgrade = 0;
699 spec->pop3 = 0;
700 spec->smtp = 0;
701 if (!strcmp(value, "tcp")) {
702 /* use defaults */
703 } else
704 if (!strcmp(value, "ssl")) {
705 spec->ssl = 1;
706 } else
707 if (!strcmp(value, "http")) {
708 spec->http = 1;
709 } else
710 if (!strcmp(value, "https")) {
711 spec->ssl = 1;
712 spec->http = 1;
713 } else
714 if (!strcmp(value, "autossl")) {
715 spec->upgrade = 1;
716 } else
717 if (!strcmp(value, "pop3")) {
718 spec->pop3 = 1;
719 } else
720 if (!strcmp(value, "pop3s")) {
721 spec->ssl = 1;
722 spec->pop3 = 1;
723 } else
724 if (!strcmp(value, "smtp")) {
725 spec->smtp = 1;
726 } else
727 if (!strcmp(value, "smtps")) {
728 spec->ssl = 1;
729 spec->smtp = 1;
730 } else {
731 fprintf(stderr, "Unknown connection "
732 "type '%s'\n", value);
733 return -1;
734 }
735 #ifdef DEBUG_OPTS
736 log_dbg_printf("Proto: %s\n", value);
737 #endif /* DEBUG_OPTS */
738 return 0;
739 }
740
741 static int WUNRES
proxyspec_set_listen_addr(proxyspec_t * spec,char * addr,char * port,const char * natengine)742 proxyspec_set_listen_addr(proxyspec_t *spec, char *addr, char *port, const char *natengine)
743 {
744 int af = sys_sockaddr_parse(&spec->listen_addr,
745 &spec->listen_addrlen,
746 addr, port,
747 sys_get_af(addr),
748 EVUTIL_AI_PASSIVE);
749 if (af == -1) {
750 return -1;
751 }
752 if (natengine) {
753 spec->natengine = strdup(natengine);
754 if (!spec->natengine)
755 return oom_return_na();
756 } else {
757 spec->natengine = NULL;
758 }
759 #ifdef DEBUG_OPTS
760 log_dbg_printf("Addr: [%s]:%s, %s\n", addr, port, natengine);
761 #endif /* DEBUG_OPTS */
762 return af;
763 }
764
765 static void
opts_set_divert(opts_t * opts)766 opts_set_divert(opts_t *opts)
767 {
768 opts->divert = 1;
769 #ifdef DEBUG_OPTS
770 log_dbg_printf("Divert: yes\n");
771 #endif /* DEBUG_OPTS */
772 }
773
774 void
opts_unset_divert(opts_t * opts)775 opts_unset_divert(opts_t *opts)
776 {
777 opts->divert = 0;
778 #ifdef DEBUG_OPTS
779 log_dbg_printf("Divert: no\n");
780 #endif /* DEBUG_OPTS */
781 }
782
783 static int WUNRES
proxyspec_set_divert_addr(proxyspec_t * spec,char * addr,char * port)784 proxyspec_set_divert_addr(proxyspec_t *spec, char *addr, char *port)
785 {
786 if (sys_sockaddr_parse(&spec->divert_addr,
787 &spec->divert_addrlen,
788 addr, port, AF_INET, EVUTIL_AI_PASSIVE) == -1) {
789 return -1;
790 }
791 #ifdef DEBUG_OPTS
792 log_dbg_printf("DivertAddr: [%s]:%s\n", addr, port);
793 #endif /* DEBUG_OPTS */
794 return 0;
795 }
796
797 static int WUNRES
proxyspec_set_return_addr(proxyspec_t * spec,char * addr)798 proxyspec_set_return_addr(proxyspec_t *spec, char *addr)
799 {
800 if (sys_sockaddr_parse(&spec->return_addr,
801 &spec->return_addrlen,
802 addr, "0", AF_INET, EVUTIL_AI_PASSIVE) == -1) {
803 return -1;
804 }
805 #ifdef DEBUG_OPTS
806 log_dbg_printf("ReturnAddr: [%s]\n", addr);
807 #endif /* DEBUG_OPTS */
808 return 0;
809 }
810
811 static int WUNRES
proxyspec_set_target_addr(proxyspec_t * spec,char * addr,char * port,int af)812 proxyspec_set_target_addr(proxyspec_t *spec, char *addr, char *port, int af)
813 {
814 if (sys_sockaddr_parse(&spec->connect_addr,
815 &spec->connect_addrlen,
816 addr, port, af, 0) == -1) {
817 return -1;
818 }
819 /* explicit target address */
820 free(spec->natengine);
821 spec->natengine = NULL;
822 #ifdef DEBUG_OPTS
823 log_dbg_printf("TargetAddr: [%s]:%s\n", addr, port);
824 #endif /* DEBUG_OPTS */
825 return 0;
826 }
827
828 static int WUNRES
proxyspec_set_sni_port(proxyspec_t * spec,char * port)829 proxyspec_set_sni_port(proxyspec_t *spec, char *port)
830 {
831 if (!spec->ssl) {
832 fprintf(stderr,
833 "SNI hostname lookup "
834 "only works for ssl "
835 "and https proxyspecs"
836 "\n");
837 return -1;
838 }
839 /* SNI dstport */
840 spec->sni_port = atoi(port);
841 if (!spec->sni_port) {
842 fprintf(stderr, "Invalid port '%s'\n", port);
843 return -1;
844 }
845 spec->dns = 1;
846 free(spec->natengine);
847 spec->natengine = NULL;
848 #ifdef DEBUG_OPTS
849 log_dbg_printf("SNIPort: %u\n", spec->sni_port);
850 #endif /* DEBUG_OPTS */
851 return 0;
852 }
853
854 static int WUNRES
proxyspec_set_natengine(proxyspec_t * spec,const char * natengine)855 proxyspec_set_natengine(proxyspec_t *spec, const char *natengine)
856 {
857 // Double checks if called by proxyspec_parse()
858 if (nat_exist(natengine)) {
859 /* natengine */
860 free(spec->natengine);
861 spec->natengine = strdup(natengine);
862 if (!spec->natengine) {
863 fprintf(stderr, "Out of memory\n");
864 return -1;
865 }
866 } else {
867 fprintf(stderr, "No such nat engine '%s'\n", natengine);
868 return -1;
869 }
870 #ifdef DEBUG_OPTS
871 log_dbg_printf("NatEngine: %s\n", spec->natengine);
872 #endif /* DEBUG_OPTS */
873 return 0;
874 }
875
876 static void
set_divert(proxyspec_t * spec,int split)877 set_divert(proxyspec_t *spec, int split)
878 {
879 // The global divert option -n has precedence over the proxyspec Divert option
880 // Use split mode if no divert address is specified, even if the Divert option is used
881 // The Divert option in structured proxyspecs has precedence over the divert address option
882 // If the Divert option is not used in structured proxyspecs, use the global Divert option
883 if (split || !spec->divert_addrlen) {
884 opts_unset_divert(spec->opts);
885 }
886 }
887
888 /*
889 * Parse proxyspecs using a simple state machine.
890 */
891 int
proxyspec_parse(int * argc,char ** argv[],const char * natengine,global_t * global,const char * argv0,tmp_opts_t * tmp_opts)892 proxyspec_parse(int *argc, char **argv[], const char *natengine, global_t *global, const char *argv0, tmp_opts_t *tmp_opts)
893 {
894 proxyspec_t *spec = NULL;
895 char *addr = NULL;
896 int state = 0;
897 int af;
898
899 while ((*argc)--) {
900 switch (state) {
901 default:
902 case 0:
903 /* tcp | ssl | http | https | autossl | pop3 | pop3s | smtp | smtps */
904 spec = proxyspec_new(global, argv0, tmp_opts);
905 if (!spec)
906 return -1;
907 spec->next = global->spec;
908 global->spec = spec;
909
910 if (proxyspec_set_proto(spec, **argv) == -1)
911 return -1;
912 state++;
913 break;
914 case 1:
915 /* listenaddr */
916 addr = **argv;
917 state++;
918 break;
919 case 2:
920 /* listenport */
921 if ((af = proxyspec_set_listen_addr(spec, addr, **argv, natengine)) == -1)
922 return -1;
923 state++;
924 break;
925 case 3:
926 state++;
927 if (strstr(**argv, "up:")) {
928 char *dp = **argv + 3;
929 // @todo IPv6?
930 char *da = "127.0.0.1";
931 char *ra = "127.0.0.1";
932
933 // da and ra are optional, if both specified, da should come before ra
934 // Divert address
935 if (*argc && strstr(*((*argv) + 1), "ua:")) {
936 (*argv)++; (*argc)--;
937 da = **argv + 3;
938 }
939 // Return address
940 if (*argc && strstr(*((*argv) + 1), "ra:")) {
941 (*argv)++; (*argc)--;
942 ra = **argv + 3;
943 }
944
945 if (proxyspec_set_divert_addr(spec, da, dp) == -1)
946 return -1;
947 if (proxyspec_set_return_addr(spec, ra) == -1)
948 return -1;
949 break;
950 }
951 /* fall-through */
952 case 4:
953 /* [ natengine | dstaddr ] */
954 if (!strcmp(**argv, "tcp") ||
955 !strcmp(**argv, "ssl") ||
956 !strcmp(**argv, "http") ||
957 !strcmp(**argv, "https") ||
958 !strcmp(**argv, "autossl") ||
959 !strcmp(**argv, "pop3") ||
960 !strcmp(**argv, "pop3s") ||
961 !strcmp(**argv, "smtp") ||
962 !strcmp(**argv, "smtps")) {
963 /* implicit default natengine */
964 (*argv)--; (*argc)++; /* rewind */
965 state = 0;
966 } else
967 if (!strcmp(**argv, "sni")) {
968 state = 6;
969 } else
970 if (nat_exist(**argv)) {
971 /* natengine */
972 if (proxyspec_set_natengine(spec, natengine) == -1)
973 return -1;
974 state = 0;
975 } else {
976 /* explicit target address */
977 addr = **argv;
978 state++;
979 }
980 break;
981 case 5:
982 /* explicit target port */
983 if (proxyspec_set_target_addr(spec, addr, **argv, af) == -1)
984 return -1;
985 state = 0;
986 break;
987 case 6:
988 /* SNI dstport */
989 if (proxyspec_set_sni_port(spec, **argv) == -1)
990 return -1;
991 state = 0;
992 break;
993 }
994 (*argv)++;
995 }
996
997 if (state != 0 && state != 3 && state != 4) {
998 fprintf(stderr, "Incomplete proxyspec!\n");
999 return -1;
1000 }
1001
1002 // Empty line does not create new spec
1003 if (spec)
1004 set_divert(spec, tmp_opts->split);
1005
1006 return 0;
1007 }
1008
1009 char *
conn_opts_str(conn_opts_t * conn_opts)1010 conn_opts_str(conn_opts_t *conn_opts)
1011 {
1012 char *s;
1013
1014 if (!conn_opts) {
1015 s = strdup("");
1016 if (!s)
1017 return oom_return_na_null();
1018 return s;
1019 }
1020
1021 if (asprintf(&s, "conn opts: %s%s%s%s%s%s%s%s%s%s"
1022 #ifdef HAVE_SSLV2
1023 "%s"
1024 #endif /* HAVE_SSLV2 */
1025 #ifdef HAVE_SSLV3
1026 "%s"
1027 #endif /* HAVE_SSLV3 */
1028 #ifdef HAVE_TLSV10
1029 "%s"
1030 #endif /* HAVE_TLSV10 */
1031 #ifdef HAVE_TLSV11
1032 "%s"
1033 #endif /* HAVE_TLSV11 */
1034 #ifdef HAVE_TLSV12
1035 "%s"
1036 #endif /* HAVE_TLSV12 */
1037 #ifdef HAVE_TLSV13
1038 "%s"
1039 #endif /* HAVE_TLSV13 */
1040 "%s%s|%s|%s"
1041 #ifndef OPENSSL_NO_ECDH
1042 "|%s"
1043 #endif /* !OPENSSL_NO_ECDH */
1044 "|%s%s%s%s%s"
1045 #ifndef WITHOUT_USERAUTH
1046 "%s|%s|%d"
1047 #endif /* !WITHOUT_USERAUTH */
1048 "%s%s|%d",
1049 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20702000L)
1050 #ifdef HAVE_SSLV2
1051 (conn_opts->sslmethod == SSLv2_method) ? "ssl2" :
1052 #endif /* HAVE_SSLV2 */
1053 #ifdef HAVE_SSLV3
1054 (conn_opts->sslmethod == SSLv3_method) ? "ssl3" :
1055 #endif /* HAVE_SSLV3 */
1056 #ifdef HAVE_TLSV10
1057 (conn_opts->sslmethod == TLSv1_method) ? "tls10" :
1058 #endif /* HAVE_TLSV10 */
1059 #ifdef HAVE_TLSV11
1060 (conn_opts->sslmethod == TLSv1_1_method) ? "tls11" :
1061 #endif /* HAVE_TLSV11 */
1062 #ifdef HAVE_TLSV12
1063 (conn_opts->sslmethod == TLSv1_2_method) ? "tls12" :
1064 #endif /* HAVE_TLSV12 */
1065 /* There is no TLSv1_3_method defined,
1066 * since no ssl version < 0x10100000L supports it. */
1067 #else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
1068 #ifdef HAVE_SSLV3
1069 (conn_opts->sslversion == SSL3_VERSION) ? "ssl3" :
1070 #endif /* HAVE_SSLV3 */
1071 #ifdef HAVE_TLSV10
1072 (conn_opts->sslversion == TLS1_VERSION) ? "tls10" :
1073 #endif /* HAVE_TLSV10 */
1074 #ifdef HAVE_TLSV11
1075 (conn_opts->sslversion == TLS1_1_VERSION) ? "tls11" :
1076 #endif /* HAVE_TLSV11 */
1077 #ifdef HAVE_TLSV12
1078 (conn_opts->sslversion == TLS1_2_VERSION) ? "tls12" :
1079 #endif /* HAVE_TLSV12 */
1080 #ifdef HAVE_TLSV13
1081 (conn_opts->sslversion == TLS1_3_VERSION) ? "tls13" :
1082 #endif /* HAVE_TLSV13 */
1083 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
1084 "negotiate",
1085 #ifdef HAVE_SSLV2
1086 conn_opts->no_ssl2 ? " -ssl2" :
1087 #endif /* HAVE_SSLV2 */
1088 "",
1089 #ifdef HAVE_SSLV3
1090 conn_opts->no_ssl3 ? " -ssl3" :
1091 #endif /* HAVE_SSLV3 */
1092 "",
1093 #ifdef HAVE_TLSV10
1094 conn_opts->no_tls10 ? " -tls10" :
1095 #endif /* HAVE_TLSV10 */
1096 "",
1097 #ifdef HAVE_TLSV11
1098 conn_opts->no_tls11 ? " -tls11" :
1099 #endif /* HAVE_TLSV11 */
1100 "",
1101 #ifdef HAVE_TLSV12
1102 conn_opts->no_tls12 ? " -tls12" :
1103 #endif /* HAVE_TLSV12 */
1104 "",
1105 #ifdef HAVE_TLSV13
1106 conn_opts->no_tls13 ? " -tls13" :
1107 #endif /* HAVE_TLSV13 */
1108 "",
1109 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L)
1110 #ifdef HAVE_SSLV3
1111 (conn_opts->minsslversion == SSL3_VERSION) ? ">=ssl3" :
1112 #endif /* HAVE_SSLV3 */
1113 #ifdef HAVE_TLSV10
1114 (conn_opts->minsslversion == TLS1_VERSION) ? ">=tls10" :
1115 #endif /* HAVE_TLSV10 */
1116 #ifdef HAVE_TLSV11
1117 (conn_opts->minsslversion == TLS1_1_VERSION) ? ">=tls11" :
1118 #endif /* HAVE_TLSV11 */
1119 #ifdef HAVE_TLSV12
1120 (conn_opts->minsslversion == TLS1_2_VERSION) ? ">=tls12" :
1121 #endif /* HAVE_TLSV12 */
1122 #ifdef HAVE_TLSV13
1123 (conn_opts->minsslversion == TLS1_3_VERSION) ? ">=tls13" :
1124 #endif /* HAVE_TLSV13 */
1125 "",
1126 #ifdef HAVE_SSLV3
1127 (conn_opts->maxsslversion == SSL3_VERSION) ? "<=ssl3" :
1128 #endif /* HAVE_SSLV3 */
1129 #ifdef HAVE_TLSV10
1130 (conn_opts->maxsslversion == TLS1_VERSION) ? "<=tls10" :
1131 #endif /* HAVE_TLSV10 */
1132 #ifdef HAVE_TLSV11
1133 (conn_opts->maxsslversion == TLS1_1_VERSION) ? "<=tls11" :
1134 #endif /* HAVE_TLSV11 */
1135 #ifdef HAVE_TLSV12
1136 (conn_opts->maxsslversion == TLS1_2_VERSION) ? "<=tls12" :
1137 #endif /* HAVE_TLSV12 */
1138 #ifdef HAVE_TLSV13
1139 (conn_opts->maxsslversion == TLS1_3_VERSION) ? "<=tls13" :
1140 #endif /* HAVE_TLSV13 */
1141 "",
1142 #else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
1143 "", "",
1144 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
1145 (!conn_opts->sslcomp ? "|no sslcomp" : ""),
1146 #ifdef HAVE_SSLV2
1147 (conn_opts->no_ssl2 ? "|no_ssl2" : ""),
1148 #endif /* HAVE_SSLV2 */
1149 #ifdef HAVE_SSLV3
1150 (conn_opts->no_ssl3 ? "|no_ssl3" : ""),
1151 #endif /* HAVE_SSLV3 */
1152 #ifdef HAVE_TLSV10
1153 (conn_opts->no_tls10 ? "|no_tls10" : ""),
1154 #endif /* HAVE_TLSV10 */
1155 #ifdef HAVE_TLSV11
1156 (conn_opts->no_tls11 ? "|no_tls11" : ""),
1157 #endif /* HAVE_TLSV11 */
1158 #ifdef HAVE_TLSV12
1159 (conn_opts->no_tls12 ? "|no_tls12" : ""),
1160 #endif /* HAVE_TLSV12 */
1161 #ifdef HAVE_TLSV13
1162 (conn_opts->no_tls13 ? "|no_tls13" : ""),
1163 #endif /* HAVE_TLSV13 */
1164 (conn_opts->passthrough ? "|passthrough" : ""),
1165 (conn_opts->deny_ocsp ? "|deny_ocsp" : ""),
1166 (conn_opts->ciphers ? conn_opts->ciphers : "no ciphers"),
1167 (conn_opts->ciphersuites ? conn_opts->ciphersuites : "no ciphersuites"),
1168 #ifndef OPENSSL_NO_ECDH
1169 (conn_opts->ecdhcurve ? conn_opts->ecdhcurve : "no ecdhcurve"),
1170 #endif /* !OPENSSL_NO_ECDH */
1171 (conn_opts->leafcrlurl ? conn_opts->leafcrlurl : "no leafcrlurl"),
1172 (conn_opts->remove_http_accept_encoding ? "|remove_http_accept_encoding" : ""),
1173 (conn_opts->remove_http_referer ? "|remove_http_referer" : ""),
1174 (conn_opts->verify_peer ? "|verify_peer" : ""),
1175 (conn_opts->allow_wrong_host ? "|allow_wrong_host" : ""),
1176 #ifndef WITHOUT_USERAUTH
1177 (conn_opts->user_auth ? "|user_auth" : ""),
1178 (conn_opts->user_auth_url ? conn_opts->user_auth_url : "no user_auth_url"),
1179 conn_opts->user_timeout,
1180 #endif /* !WITHOUT_USERAUTH */
1181 (conn_opts->validate_proto ? "|validate_proto" : ""),
1182 (conn_opts->reconnect_ssl ? "|reconnect_ssl" : ""),
1183 conn_opts->max_http_header_size
1184 ) < 0) {
1185 return oom_return_na_null();
1186 }
1187 return s;
1188 }
1189
1190 static char *
opts_str(opts_t * opts,conn_opts_t * conn_opts)1191 opts_str(opts_t *opts, conn_opts_t *conn_opts)
1192 {
1193 char *s = NULL;
1194 char *copts_str = NULL;
1195 char *ms = NULL;
1196 char *frs = NULL;
1197 char *fs = NULL;
1198
1199 #ifndef WITHOUT_USERAUTH
1200 char *du = NULL;
1201 char *pu = NULL;
1202
1203 du = filter_userlist_str(opts->divertusers);
1204 if (!du)
1205 goto out;
1206
1207 pu = filter_userlist_str(opts->passusers);
1208 if (!pu)
1209 goto out;
1210 #endif /* !WITHOUT_USERAUTH */
1211
1212 copts_str = conn_opts_str(conn_opts);
1213 if (!copts_str)
1214 goto out;
1215
1216 ms = filter_macro_str(opts->macro);
1217 if (!ms)
1218 goto out;
1219
1220 frs = filter_rule_str(opts->filter_rules);
1221 if (!frs)
1222 goto out;
1223
1224 fs = filter_str(opts->filter);
1225 if (!fs)
1226 goto out;
1227
1228 if (asprintf(&s, "opts= %s\n%s"
1229 #ifndef WITHOUT_USERAUTH
1230 "|%s|%s"
1231 #endif /* !WITHOUT_USERAUTH */
1232 "%s%s%s%s%s%s",
1233 copts_str,
1234 (opts->divert ? "divert" : "split"),
1235 #ifndef WITHOUT_USERAUTH
1236 du,
1237 pu,
1238 #endif /* !WITHOUT_USERAUTH */
1239 strlen(ms) ? "\n" : "", ms,
1240 strlen(frs) ? "\n" : "", frs,
1241 (!strlen(frs) && strlen(fs)) ? "\n" : "", fs) < 0) {
1242 s = NULL;
1243 }
1244 out:
1245 #ifndef WITHOUT_USERAUTH
1246 if (du)
1247 free(du);
1248 if (pu)
1249 free(pu);
1250 #endif /* !WITHOUT_USERAUTH */
1251 if (copts_str)
1252 free(copts_str);
1253 if (ms)
1254 free(ms);
1255 if (frs)
1256 free(frs);
1257 if (fs)
1258 free(fs);
1259 return s;
1260 }
1261
1262 /*
1263 * Return text representation of proxy spec for display to the user.
1264 * Returned string must be freed by caller.
1265 */
1266 char *
proxyspec_str(proxyspec_t * spec)1267 proxyspec_str(proxyspec_t *spec)
1268 {
1269 char *s = NULL;
1270 char *lhbuf = NULL;
1271 char *lpbuf = NULL;
1272 char *cbuf = NULL;
1273 char *pdstbuf = NULL;
1274 char *csrcbuf = NULL;
1275 char *optsstr = NULL;
1276
1277 if (sys_sockaddr_str((struct sockaddr *)&spec->listen_addr,
1278 spec->listen_addrlen, &lhbuf, &lpbuf) != 0) {
1279 goto out;
1280 }
1281 if (spec->connect_addrlen) {
1282 char *chbuf, *cpbuf;
1283 if (sys_sockaddr_str((struct sockaddr *)&spec->connect_addr,
1284 spec->connect_addrlen,
1285 &chbuf, &cpbuf) != 0) {
1286 goto out;
1287 }
1288 int rv = asprintf(&cbuf, "\nconnect= [%s]:%s", chbuf, cpbuf);
1289 free(chbuf);
1290 free(cpbuf);
1291 if (rv < 0)
1292 goto out;
1293 }
1294 if (spec->divert_addrlen) {
1295 char *chbuf, *cpbuf;
1296 if (sys_sockaddr_str((struct sockaddr *)&spec->divert_addr,
1297 spec->divert_addrlen,
1298 &chbuf, &cpbuf) != 0) {
1299 goto out;
1300 }
1301 int rv = asprintf(&pdstbuf, "\ndivert addr= [%s]:%s", chbuf, cpbuf);
1302 free(chbuf);
1303 free(cpbuf);
1304 if (rv < 0)
1305 goto out;
1306 }
1307 if (spec->return_addrlen) {
1308 char *chbuf, *cpbuf;
1309 if (sys_sockaddr_str((struct sockaddr *)&spec->return_addr,
1310 spec->return_addrlen,
1311 &chbuf, &cpbuf) != 0) {
1312 goto out;
1313 }
1314 int rv = asprintf(&csrcbuf, "\nreturn addr= [%s]:%s", chbuf, cpbuf);
1315 free(chbuf);
1316 free(cpbuf);
1317 if (rv < 0)
1318 goto out;
1319 }
1320 if (spec->sni_port) {
1321 if (asprintf(&cbuf, "\nsni %i", spec->sni_port) < 0) {
1322 goto out;
1323 }
1324 }
1325 optsstr = opts_str(spec->opts, spec->conn_opts);
1326 if (!optsstr) {
1327 goto out;
1328 }
1329 if (asprintf(&s, "listen=[%s]:%s %s%s%s%s%s %s%s%s\n%s%s", lhbuf, lpbuf,
1330 (spec->ssl ? "ssl" : "tcp"),
1331 (spec->upgrade ? "|autossl" : ""),
1332 (spec->http ? "|http" : ""),
1333 (spec->pop3 ? "|pop3" : ""),
1334 (spec->smtp ? "|smtp" : ""),
1335 (spec->natengine ? spec->natengine : cbuf),
1336 STRORNONE(pdstbuf),
1337 STRORNONE(csrcbuf),
1338 optsstr,
1339 !spec->opts->divert && spec->divert_addrlen ? "\nWARNING: Divert address specified in split mode" : "") < 0) {
1340 s = NULL;
1341 }
1342 out:
1343 if (optsstr)
1344 free(optsstr);
1345 if (lhbuf)
1346 free(lhbuf);
1347 if (lpbuf)
1348 free(lpbuf);
1349 if (cbuf)
1350 free(cbuf);
1351 if (pdstbuf)
1352 free(pdstbuf);
1353 if (csrcbuf)
1354 free(csrcbuf);
1355 return s;
1356 }
1357
1358 int
opts_set_cacrt(conn_opts_t * conn_opts,const char * argv0,const char * optarg,tmp_opts_t * tmp_opts)1359 opts_set_cacrt(conn_opts_t *conn_opts, const char *argv0, const char *optarg, tmp_opts_t *tmp_opts)
1360 {
1361 if (tmp_opts) {
1362 if (tmp_opts->cacrt_str)
1363 free(tmp_opts->cacrt_str);
1364 tmp_opts->cacrt_str = strdup(optarg);
1365 if (!tmp_opts->cacrt_str)
1366 return oom_return(argv0);
1367 }
1368
1369 if (conn_opts->cacrt)
1370 X509_free(conn_opts->cacrt);
1371 conn_opts->cacrt = ssl_x509_load(optarg);
1372 if (!conn_opts->cacrt) {
1373 fprintf(stderr, "%s: error loading CA cert from '%s':\n",
1374 argv0, optarg);
1375 if (errno) {
1376 fprintf(stderr, "%s\n", strerror(errno));
1377 } else {
1378 ERR_print_errors_fp(stderr);
1379 }
1380 return -1;
1381 }
1382 ssl_x509_refcount_inc(conn_opts->cacrt);
1383 sk_X509_insert(conn_opts->chain, conn_opts->cacrt, 0);
1384 if (!conn_opts->cakey) {
1385 conn_opts->cakey = ssl_key_load(optarg);
1386 }
1387 #ifndef OPENSSL_NO_DH
1388 if (!conn_opts->dh) {
1389 conn_opts->dh = ssl_dh_load(optarg);
1390 }
1391 #endif /* !OPENSSL_NO_DH */
1392 #ifdef DEBUG_OPTS
1393 log_dbg_printf("CACert: %s\n", optarg);
1394 #endif /* DEBUG_OPTS */
1395 return 0;
1396 }
1397
1398 int
opts_set_cakey(conn_opts_t * conn_opts,const char * argv0,const char * optarg,tmp_opts_t * tmp_opts)1399 opts_set_cakey(conn_opts_t *conn_opts, const char *argv0, const char *optarg, tmp_opts_t *tmp_opts)
1400 {
1401 if (tmp_opts) {
1402 if (tmp_opts->cakey_str)
1403 free(tmp_opts->cakey_str);
1404 tmp_opts->cakey_str = strdup(optarg);
1405 if (!tmp_opts->cakey_str)
1406 return oom_return(argv0);
1407 }
1408
1409 if (conn_opts->cakey)
1410 EVP_PKEY_free(conn_opts->cakey);
1411 conn_opts->cakey = ssl_key_load(optarg);
1412 if (!conn_opts->cakey) {
1413 fprintf(stderr, "%s: error loading CA key from '%s':\n",
1414 argv0, optarg);
1415 if (errno) {
1416 fprintf(stderr, "%s\n", strerror(errno));
1417 } else {
1418 ERR_print_errors_fp(stderr);
1419 }
1420 return -1;
1421 }
1422 if (!conn_opts->cacrt) {
1423 conn_opts->cacrt = ssl_x509_load(optarg);
1424 if (conn_opts->cacrt) {
1425 ssl_x509_refcount_inc(conn_opts->cacrt);
1426 sk_X509_insert(conn_opts->chain, conn_opts->cacrt, 0);
1427 }
1428 }
1429 #ifndef OPENSSL_NO_DH
1430 if (!conn_opts->dh) {
1431 conn_opts->dh = ssl_dh_load(optarg);
1432 }
1433 #endif /* !OPENSSL_NO_DH */
1434 #ifdef DEBUG_OPTS
1435 log_dbg_printf("CAKey: %s\n", optarg);
1436 #endif /* DEBUG_OPTS */
1437 return 0;
1438 }
1439
1440 int
opts_set_chain(conn_opts_t * conn_opts,const char * argv0,const char * optarg,tmp_opts_t * tmp_opts)1441 opts_set_chain(conn_opts_t *conn_opts, const char *argv0, const char *optarg, tmp_opts_t *tmp_opts)
1442 {
1443 if (tmp_opts) {
1444 if (tmp_opts->chain_str)
1445 free(tmp_opts->chain_str);
1446 tmp_opts->chain_str = strdup(optarg);
1447 if (!tmp_opts->chain_str)
1448 return oom_return(argv0);
1449 }
1450
1451 if (ssl_x509chain_load(NULL, &conn_opts->chain, optarg) == -1) {
1452 fprintf(stderr, "%s: error loading chain from '%s':\n",
1453 argv0, optarg);
1454 if (errno) {
1455 fprintf(stderr, "%s\n", strerror(errno));
1456 } else {
1457 ERR_print_errors_fp(stderr);
1458 }
1459 return -1;
1460 }
1461 #ifdef DEBUG_OPTS
1462 log_dbg_printf("CAChain: %s\n", optarg);
1463 #endif /* DEBUG_OPTS */
1464 return 0;
1465 }
1466
1467 int
opts_set_leafcrlurl(conn_opts_t * conn_opts,const char * argv0,const char * optarg,tmp_opts_t * tmp_opts)1468 opts_set_leafcrlurl(conn_opts_t *conn_opts, const char *argv0, const char *optarg, tmp_opts_t *tmp_opts)
1469 {
1470 if (tmp_opts) {
1471 if (tmp_opts->leafcrlurl_str)
1472 free(tmp_opts->leafcrlurl_str);
1473 tmp_opts->leafcrlurl_str = strdup(optarg);
1474 if (!tmp_opts->leafcrlurl_str)
1475 return oom_return(argv0);
1476 }
1477
1478 if (conn_opts->leafcrlurl)
1479 free(conn_opts->leafcrlurl);
1480 conn_opts->leafcrlurl = strdup(optarg);
1481 if (!conn_opts->leafcrlurl)
1482 return oom_return(argv0);
1483 #ifdef DEBUG_OPTS
1484 log_dbg_printf("LeafCRLURL: %s\n", conn_opts->leafcrlurl);
1485 #endif /* DEBUG_OPTS */
1486 return 0;
1487 }
1488
1489 static int WUNRES
set_certgendir(global_t * global,const char * argv0,const char * optarg)1490 set_certgendir(global_t *global, const char *argv0, const char *optarg)
1491 {
1492 if (global->certgendir)
1493 free(global->certgendir);
1494 global->certgendir = strdup(optarg);
1495 if (!global->certgendir)
1496 return oom_return(argv0);
1497 return 0;
1498 }
1499
1500 void
opts_set_deny_ocsp(conn_opts_t * conn_opts)1501 opts_set_deny_ocsp(conn_opts_t *conn_opts)
1502 {
1503 conn_opts->deny_ocsp = 1;
1504 }
1505
1506 static void
opts_unset_deny_ocsp(conn_opts_t * conn_opts)1507 opts_unset_deny_ocsp(conn_opts_t *conn_opts)
1508 {
1509 conn_opts->deny_ocsp = 0;
1510 }
1511
1512 void
opts_set_passthrough(conn_opts_t * conn_opts)1513 opts_set_passthrough(conn_opts_t *conn_opts)
1514 {
1515 conn_opts->passthrough = 1;
1516 }
1517
1518 void
opts_unset_passthrough(conn_opts_t * conn_opts)1519 opts_unset_passthrough(conn_opts_t *conn_opts)
1520 {
1521 conn_opts->passthrough = 0;
1522 }
1523
1524 int
opts_set_clientcrt(conn_opts_t * conn_opts,const char * argv0,const char * optarg,tmp_opts_t * tmp_opts)1525 opts_set_clientcrt(conn_opts_t *conn_opts, const char *argv0, const char *optarg, tmp_opts_t *tmp_opts)
1526 {
1527 if (tmp_opts) {
1528 if (tmp_opts->clientcrt_str)
1529 free(tmp_opts->clientcrt_str);
1530 tmp_opts->clientcrt_str = strdup(optarg);
1531 if (!tmp_opts->clientcrt_str)
1532 return oom_return(argv0);
1533 }
1534
1535 if (conn_opts->clientcrt)
1536 X509_free(conn_opts->clientcrt);
1537 conn_opts->clientcrt = ssl_x509_load(optarg);
1538 if (!conn_opts->clientcrt) {
1539 fprintf(stderr, "%s: error loading client cert from '%s':\n",
1540 argv0, optarg);
1541 if (errno) {
1542 fprintf(stderr, "%s\n", strerror(errno));
1543 } else {
1544 ERR_print_errors_fp(stderr);
1545 }
1546 return -1;
1547 }
1548 #ifdef DEBUG_OPTS
1549 log_dbg_printf("ClientCert: %s\n", optarg);
1550 #endif /* DEBUG_OPTS */
1551 return 0;
1552 }
1553
1554 int
opts_set_clientkey(conn_opts_t * conn_opts,const char * argv0,const char * optarg,tmp_opts_t * tmp_opts)1555 opts_set_clientkey(conn_opts_t *conn_opts, const char *argv0, const char *optarg, tmp_opts_t *tmp_opts)
1556 {
1557 if (tmp_opts) {
1558 if (tmp_opts->clientkey_str)
1559 free(tmp_opts->clientkey_str);
1560 tmp_opts->clientkey_str = strdup(optarg);
1561 if (!tmp_opts->clientkey_str)
1562 return oom_return(argv0);
1563 }
1564
1565 if (conn_opts->clientkey)
1566 EVP_PKEY_free(conn_opts->clientkey);
1567 conn_opts->clientkey = ssl_key_load(optarg);
1568 if (!conn_opts->clientkey) {
1569 fprintf(stderr, "%s: error loading client key from '%s':\n",
1570 argv0, optarg);
1571 if (errno) {
1572 fprintf(stderr, "%s\n", strerror(errno));
1573 } else {
1574 ERR_print_errors_fp(stderr);
1575 }
1576 return -1;
1577 }
1578 #ifdef DEBUG_OPTS
1579 log_dbg_printf("ClientKey: %s\n", optarg);
1580 #endif /* DEBUG_OPTS */
1581 return 0;
1582 }
1583
1584 #ifndef OPENSSL_NO_DH
1585 int
opts_set_dh(conn_opts_t * conn_opts,const char * argv0,const char * optarg,tmp_opts_t * tmp_opts)1586 opts_set_dh(conn_opts_t *conn_opts, const char *argv0, const char *optarg, tmp_opts_t *tmp_opts)
1587 {
1588 if (tmp_opts) {
1589 if (tmp_opts->dh_str)
1590 free(tmp_opts->dh_str);
1591 tmp_opts->dh_str = strdup(optarg);
1592 if (!tmp_opts->dh_str)
1593 return oom_return(argv0);
1594 }
1595
1596 if (conn_opts->dh)
1597 DH_free(conn_opts->dh);
1598 conn_opts->dh = ssl_dh_load(optarg);
1599 if (!conn_opts->dh) {
1600 fprintf(stderr, "%s: error loading DH params from '%s':\n",
1601 argv0, optarg);
1602 if (errno) {
1603 fprintf(stderr, "%s\n", strerror(errno));
1604 } else {
1605 ERR_print_errors_fp(stderr);
1606 }
1607 return -1;
1608 }
1609 #ifdef DEBUG_OPTS
1610 log_dbg_printf("DHGroupParams: %s\n", optarg);
1611 #endif /* DEBUG_OPTS */
1612 return 0;
1613 }
1614 #endif /* !OPENSSL_NO_DH */
1615
1616 #ifndef OPENSSL_NO_ECDH
1617 int
opts_set_ecdhcurve(conn_opts_t * conn_opts,const char * argv0,const char * optarg)1618 opts_set_ecdhcurve(conn_opts_t *conn_opts, const char *argv0, const char *optarg)
1619 {
1620 EC_KEY *ec;
1621 if (conn_opts->ecdhcurve)
1622 free(conn_opts->ecdhcurve);
1623 if (!(ec = ssl_ec_by_name(optarg))) {
1624 fprintf(stderr, "%s: unknown curve '%s'\n", argv0, optarg);
1625 return -1;
1626 }
1627 EC_KEY_free(ec);
1628 conn_opts->ecdhcurve = strdup(optarg);
1629 if (!conn_opts->ecdhcurve)
1630 return oom_return(argv0);
1631 #ifdef DEBUG_OPTS
1632 log_dbg_printf("ECDHCurve: %s\n", conn_opts->ecdhcurve);
1633 #endif /* DEBUG_OPTS */
1634 return 0;
1635 }
1636 #endif /* !OPENSSL_NO_ECDH */
1637
1638 #ifdef SSL_OP_NO_COMPRESSION
1639 static void
opts_set_sslcomp(conn_opts_t * conn_opts)1640 opts_set_sslcomp(conn_opts_t *conn_opts)
1641 {
1642 conn_opts->sslcomp = 1;
1643 }
1644
1645 void
opts_unset_sslcomp(conn_opts_t * conn_opts)1646 opts_unset_sslcomp(conn_opts_t *conn_opts)
1647 {
1648 conn_opts->sslcomp = 0;
1649 }
1650 #endif /* SSL_OP_NO_COMPRESSION */
1651
1652 int
opts_set_ciphers(conn_opts_t * conn_opts,const char * argv0,const char * optarg)1653 opts_set_ciphers(conn_opts_t *conn_opts, const char *argv0, const char *optarg)
1654 {
1655 if (conn_opts->ciphers)
1656 free(conn_opts->ciphers);
1657 conn_opts->ciphers = strdup(optarg);
1658 if (!conn_opts->ciphers)
1659 return oom_return(argv0);
1660 #ifdef DEBUG_OPTS
1661 log_dbg_printf("Ciphers: %s\n", conn_opts->ciphers);
1662 #endif /* DEBUG_OPTS */
1663 return 0;
1664 }
1665
1666 int
opts_set_ciphersuites(conn_opts_t * conn_opts,const char * argv0,const char * optarg)1667 opts_set_ciphersuites(conn_opts_t *conn_opts, const char *argv0, const char *optarg)
1668 {
1669 if (conn_opts->ciphersuites)
1670 free(conn_opts->ciphersuites);
1671 conn_opts->ciphersuites = strdup(optarg);
1672 if (!conn_opts->ciphersuites)
1673 return oom_return(argv0);
1674 #ifdef DEBUG_OPTS
1675 log_dbg_printf("CipherSuites: %s\n", conn_opts->ciphersuites);
1676 #endif /* DEBUG_OPTS */
1677 return 0;
1678 }
1679
1680 /*
1681 * Parse SSL proto string in optarg and look up the corresponding SSL method.
1682 */
1683 int
opts_force_proto(conn_opts_t * conn_opts,const char * argv0,const char * optarg)1684 opts_force_proto(conn_opts_t *conn_opts, const char *argv0, const char *optarg)
1685 {
1686 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20702000L)
1687 if (conn_opts->sslmethod != SSLv23_method) {
1688 #else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
1689 if (conn_opts->sslversion) {
1690 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
1691 fprintf(stderr, "%s: overriding -r ssl version option\n", argv0);
1692 }
1693
1694 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20702000L)
1695 #ifdef HAVE_SSLV2
1696 if (!strcmp(optarg, "ssl2")) {
1697 conn_opts->sslmethod = SSLv2_method;
1698 } else
1699 #endif /* HAVE_SSLV2 */
1700 #ifdef HAVE_SSLV3
1701 if (!strcmp(optarg, "ssl3")) {
1702 conn_opts->sslmethod = SSLv3_method;
1703 } else
1704 #endif /* HAVE_SSLV3 */
1705 #ifdef HAVE_TLSV10
1706 if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
1707 conn_opts->sslmethod = TLSv1_method;
1708 } else
1709 #endif /* HAVE_TLSV10 */
1710 #ifdef HAVE_TLSV11
1711 if (!strcmp(optarg, "tls11")) {
1712 conn_opts->sslmethod = TLSv1_1_method;
1713 } else
1714 #endif /* HAVE_TLSV11 */
1715 #ifdef HAVE_TLSV12
1716 if (!strcmp(optarg, "tls12")) {
1717 conn_opts->sslmethod = TLSv1_2_method;
1718 } else
1719 #endif /* HAVE_TLSV12 */
1720 /* There is no TLSv1_3_method defined,
1721 * since no ssl version < 0x10100000L supports it. */
1722 #else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
1723 /*
1724 * Support for SSLv2 and the corresponding SSLv2_method(),
1725 * SSLv2_server_method() and SSLv2_client_method() functions were
1726 * removed in OpenSSL 1.1.0.
1727 */
1728 #ifdef HAVE_SSLV3
1729 if (!strcmp(optarg, "ssl3")) {
1730 conn_opts->sslversion = SSL3_VERSION;
1731 } else
1732 #endif /* HAVE_SSLV3 */
1733 #ifdef HAVE_TLSV10
1734 if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
1735 conn_opts->sslversion = TLS1_VERSION;
1736 } else
1737 #endif /* HAVE_TLSV10 */
1738 #ifdef HAVE_TLSV11
1739 if (!strcmp(optarg, "tls11")) {
1740 conn_opts->sslversion = TLS1_1_VERSION;
1741 } else
1742 #endif /* HAVE_TLSV11 */
1743 #ifdef HAVE_TLSV12
1744 if (!strcmp(optarg, "tls12")) {
1745 conn_opts->sslversion = TLS1_2_VERSION;
1746 } else
1747 #endif /* HAVE_TLSV12 */
1748 #ifdef HAVE_TLSV13
1749 if (!strcmp(optarg, "tls13")) {
1750 conn_opts->sslversion = TLS1_3_VERSION;
1751 } else
1752 #endif /* HAVE_TLSV13 */
1753 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
1754 {
1755 fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
1756 argv0, optarg);
1757 return -1;
1758 }
1759 #ifdef DEBUG_OPTS
1760 log_dbg_printf("ForceSSLProto: %s\n", optarg);
1761 #endif /* DEBUG_OPTS */
1762 return 0;
1763 }
1764
1765 /*
1766 * Parse SSL proto string in optarg and set the corresponding no_foo bit.
1767 * action: 1 for disable, 0 for enable.
1768 */
1769 int
1770 opts_disable_enable_proto(conn_opts_t *conn_opts, const char *argv0, const char *optarg, int action)
1771 {
1772 #ifdef HAVE_SSLV2
1773 if (!strcmp(optarg, "ssl2")) {
1774 conn_opts->no_ssl2 = action;
1775 } else
1776 #endif /* HAVE_SSLV2 */
1777 #ifdef HAVE_SSLV3
1778 if (!strcmp(optarg, "ssl3")) {
1779 conn_opts->no_ssl3 = action;
1780 } else
1781 #endif /* HAVE_SSLV3 */
1782 #ifdef HAVE_TLSV10
1783 if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
1784 conn_opts->no_tls10 = action;
1785 } else
1786 #endif /* HAVE_TLSV10 */
1787 #ifdef HAVE_TLSV11
1788 if (!strcmp(optarg, "tls11")) {
1789 conn_opts->no_tls11 = action;
1790 } else
1791 #endif /* HAVE_TLSV11 */
1792 #ifdef HAVE_TLSV12
1793 if (!strcmp(optarg, "tls12")) {
1794 conn_opts->no_tls12 = action;
1795 } else
1796 #endif /* HAVE_TLSV12 */
1797 #ifdef HAVE_TLSV13
1798 if (!strcmp(optarg, "tls13")) {
1799 conn_opts->no_tls13 = action;
1800 } else
1801 #endif /* HAVE_TLSV13 */
1802 {
1803 fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
1804 argv0, optarg);
1805 return -1;
1806 }
1807 #ifdef DEBUG_OPTS
1808 if (action)
1809 log_dbg_printf("DisableSSLProto: %s\n", optarg);
1810 else
1811 log_dbg_printf("EnableSSLProto: %s\n", optarg);
1812 #endif /* DEBUG_OPTS */
1813 return 0;
1814 }
1815
1816 static int WUNRES
1817 opts_set_min_proto(UNUSED conn_opts_t *conn_opts, const char *argv0, const char *optarg)
1818 {
1819 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L)
1820 #ifdef HAVE_SSLV3
1821 if (!strcmp(optarg, "ssl3")) {
1822 conn_opts->minsslversion = SSL3_VERSION;
1823 } else
1824 #endif /* HAVE_SSLV3 */
1825 #ifdef HAVE_TLSV10
1826 if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
1827 conn_opts->minsslversion = TLS1_VERSION;
1828 } else
1829 #endif /* HAVE_TLSV10 */
1830 #ifdef HAVE_TLSV11
1831 if (!strcmp(optarg, "tls11")) {
1832 conn_opts->minsslversion = TLS1_1_VERSION;
1833 } else
1834 #endif /* HAVE_TLSV11 */
1835 #ifdef HAVE_TLSV12
1836 if (!strcmp(optarg, "tls12")) {
1837 conn_opts->minsslversion = TLS1_2_VERSION;
1838 } else
1839 #endif /* HAVE_TLSV12 */
1840 #ifdef HAVE_TLSV13
1841 if (!strcmp(optarg, "tls13")) {
1842 conn_opts->minsslversion = TLS1_3_VERSION;
1843 } else
1844 #endif /* HAVE_TLSV13 */
1845 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
1846 {
1847 fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
1848 argv0, optarg);
1849 return -1;
1850 }
1851 #ifdef DEBUG_OPTS
1852 log_dbg_printf("MinSSLProto: %s\n", optarg);
1853 #endif /* DEBUG_OPTS */
1854 return 0;
1855 }
1856
1857 static int WUNRES
1858 opts_set_max_proto(UNUSED conn_opts_t *conn_opts, const char *argv0, const char *optarg)
1859 {
1860 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L)
1861 #ifdef HAVE_SSLV3
1862 if (!strcmp(optarg, "ssl3")) {
1863 conn_opts->maxsslversion = SSL3_VERSION;
1864 } else
1865 #endif /* HAVE_SSLV3 */
1866 #ifdef HAVE_TLSV10
1867 if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
1868 conn_opts->maxsslversion = TLS1_VERSION;
1869 } else
1870 #endif /* HAVE_TLSV10 */
1871 #ifdef HAVE_TLSV11
1872 if (!strcmp(optarg, "tls11")) {
1873 conn_opts->maxsslversion = TLS1_1_VERSION;
1874 } else
1875 #endif /* HAVE_TLSV11 */
1876 #ifdef HAVE_TLSV12
1877 if (!strcmp(optarg, "tls12")) {
1878 conn_opts->maxsslversion = TLS1_2_VERSION;
1879 } else
1880 #endif /* HAVE_TLSV12 */
1881 #ifdef HAVE_TLSV13
1882 if (!strcmp(optarg, "tls13")) {
1883 conn_opts->maxsslversion = TLS1_3_VERSION;
1884 } else
1885 #endif /* HAVE_TLSV13 */
1886 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
1887 {
1888 fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
1889 argv0, optarg);
1890 return -1;
1891 }
1892 #ifdef DEBUG_OPTS
1893 log_dbg_printf("MaxSSLProto: %s\n", optarg);
1894 #endif /* DEBUG_OPTS */
1895 return 0;
1896 }
1897
1898 static void
1899 opts_set_remove_http_accept_encoding(conn_opts_t *conn_opts)
1900 {
1901 conn_opts->remove_http_accept_encoding = 1;
1902 }
1903
1904 static void
1905 opts_unset_remove_http_accept_encoding(conn_opts_t *conn_opts)
1906 {
1907 conn_opts->remove_http_accept_encoding = 0;
1908 }
1909
1910 static void
1911 opts_set_remove_http_referer(conn_opts_t *conn_opts)
1912 {
1913 conn_opts->remove_http_referer = 1;
1914 }
1915
1916 static void
1917 opts_unset_remove_http_referer(conn_opts_t *conn_opts)
1918 {
1919 conn_opts->remove_http_referer = 0;
1920 }
1921
1922 static void
1923 opts_set_verify_peer(conn_opts_t *conn_opts)
1924 {
1925 conn_opts->verify_peer = 1;
1926 }
1927
1928 static void
1929 opts_unset_verify_peer(conn_opts_t *conn_opts)
1930 {
1931 conn_opts->verify_peer = 0;
1932 }
1933
1934 static void
1935 opts_set_allow_wrong_host(conn_opts_t *conn_opts)
1936 {
1937 conn_opts->allow_wrong_host = 1;
1938 }
1939
1940 static void
1941 opts_unset_allow_wrong_host(conn_opts_t *conn_opts)
1942 {
1943 conn_opts->allow_wrong_host = 0;
1944 }
1945
1946 #ifndef WITHOUT_USERAUTH
1947 static void
1948 opts_set_user_auth(UNUSED conn_opts_t *conn_opts)
1949 {
1950 #if defined(__OpenBSD__) || defined(__linux__)
1951 // Enable user auth on OpenBSD and Linux only
1952 conn_opts->user_auth = 1;
1953 #endif /* __OpenBSD__ || __linux__ */
1954 }
1955
1956 static void
1957 opts_unset_user_auth(conn_opts_t *conn_opts)
1958 {
1959 conn_opts->user_auth = 0;
1960 }
1961 #endif /* !WITHOUT_USERAUTH */
1962
1963 static void
1964 opts_set_validate_proto(conn_opts_t *conn_opts)
1965 {
1966 conn_opts->validate_proto = 1;
1967 }
1968
1969 static void
1970 opts_unset_validate_proto(conn_opts_t *conn_opts)
1971 {
1972 conn_opts->validate_proto = 0;
1973 }
1974
1975 int
1976 global_set_leafkey(global_t *global, const char *argv0, const char *optarg)
1977 {
1978 if (global->leafkey)
1979 EVP_PKEY_free(global->leafkey);
1980 global->leafkey = ssl_key_load(optarg);
1981 if (!global->leafkey) {
1982 fprintf(stderr, "%s: error loading leaf key from '%s':\n",
1983 argv0, optarg);
1984 if (errno) {
1985 fprintf(stderr, "%s\n", strerror(errno));
1986 } else {
1987 ERR_print_errors_fp(stderr);
1988 }
1989 return -1;
1990 }
1991 #ifndef OPENSSL_NO_DH
1992 if (!global->conn_opts->dh) {
1993 global->conn_opts->dh = ssl_dh_load(optarg);
1994 }
1995 #endif /* !OPENSSL_NO_DH */
1996 #ifdef DEBUG_OPTS
1997 log_dbg_printf("LeafKey: %s\n", optarg);
1998 #endif /* DEBUG_OPTS */
1999 return 0;
2000 }
2001
2002 #ifndef OPENSSL_NO_ENGINE
2003 int
2004 global_set_openssl_engine(global_t *global, const char *argv0, const char *optarg)
2005 {
2006 if (global->openssl_engine)
2007 free(global->openssl_engine);
2008 global->openssl_engine = strdup(optarg);
2009 if (!global->openssl_engine)
2010 return oom_return(argv0);
2011 #ifdef DEBUG_OPTS
2012 log_dbg_printf("OpenSSLEngine: %s\n", global->openssl_engine);
2013 #endif /* DEBUG_OPTS */
2014 return 0;
2015 }
2016 #endif /* !OPENSSL_NO_ENGINE */
2017
2018 int
2019 global_set_leafcertdir(global_t *global, const char *argv0, const char *optarg)
2020 {
2021 if (!sys_isdir(optarg)) {
2022 fprintf(stderr, "%s: '%s' is not a directory\n",
2023 argv0, optarg);
2024 return -1;
2025 }
2026 if (global->leafcertdir)
2027 free(global->leafcertdir);
2028 global->leafcertdir = strdup(optarg);
2029 if (!global->leafcertdir)
2030 return oom_return(argv0);
2031 #ifdef DEBUG_OPTS
2032 log_dbg_printf("LeafCertDir: %s\n", global->leafcertdir);
2033 #endif /* DEBUG_OPTS */
2034 return 0;
2035 }
2036
2037 int
2038 global_set_defaultleafcert(global_t *global, const char *argv0, const char *optarg)
2039 {
2040 if (global->defaultleafcert)
2041 cert_free(global->defaultleafcert);
2042 global->defaultleafcert = opts_load_cert_chain_key(optarg);
2043 if (!global->defaultleafcert) {
2044 fprintf(stderr, "%s: error loading default leaf cert/chain/key"
2045 " from '%s':\n", argv0, optarg);
2046 if (errno) {
2047 fprintf(stderr, "%s\n", strerror(errno));
2048 } else {
2049 ERR_print_errors_fp(stderr);
2050 }
2051 return -1;
2052 }
2053 #ifdef DEBUG_OPTS
2054 log_dbg_printf("DefaultLeafCert: %s\n", optarg);
2055 #endif /* DEBUG_OPTS */
2056 return 0;
2057 }
2058
2059 int
2060 global_set_certgendir_writegencerts(global_t *global, const char *argv0,
2061 const char *optarg)
2062 {
2063 global->certgen_writeall = 0;
2064 if (set_certgendir(global, argv0, optarg) == -1)
2065 return -1;
2066 #ifdef DEBUG_OPTS
2067 log_dbg_printf("WriteGenCertsDir: certgendir=%s, writeall=%u\n",
2068 global->certgendir, global->certgen_writeall);
2069 #endif /* DEBUG_OPTS */
2070 return 0;
2071 }
2072
2073 int
2074 global_set_certgendir_writeall(global_t *global, const char *argv0,
2075 const char *optarg)
2076 {
2077 global->certgen_writeall = 1;
2078 if (set_certgendir(global, argv0, optarg) == -1)
2079 return -1;
2080 #ifdef DEBUG_OPTS
2081 log_dbg_printf("WriteAllCertsDir: certgendir=%s, writeall=%u\n",
2082 global->certgendir, global->certgen_writeall);
2083 #endif /* DEBUG_OPTS */
2084 return 0;
2085 }
2086
2087 int
2088 global_set_user(global_t *global, const char *argv0, const char *optarg)
2089 {
2090 if (!sys_isuser(optarg)) {
2091 fprintf(stderr, "%s: '%s' is not an existing user\n",
2092 argv0, optarg);
2093 return -1;
2094 }
2095 if (global->dropuser)
2096 free(global->dropuser);
2097 global->dropuser = strdup(optarg);
2098 if (!global->dropuser)
2099 return oom_return(argv0);
2100 #ifdef DEBUG_OPTS
2101 log_dbg_printf("User: %s\n", global->dropuser);
2102 #endif /* DEBUG_OPTS */
2103 return 0;
2104 }
2105
2106 int
2107 global_set_group(global_t *global, const char *argv0, const char *optarg)
2108 {
2109 if (!sys_isgroup(optarg)) {
2110 fprintf(stderr, "%s: '%s' is not an existing group\n",
2111 argv0, optarg);
2112 return -1;
2113 }
2114 if (global->dropgroup)
2115 free(global->dropgroup);
2116 global->dropgroup = strdup(optarg);
2117 if (!global->dropgroup)
2118 return oom_return(argv0);
2119 #ifdef DEBUG_OPTS
2120 log_dbg_printf("Group: %s\n", global->dropgroup);
2121 #endif /* DEBUG_OPTS */
2122 return 0;
2123 }
2124
2125 int
2126 global_set_jaildir(global_t *global, const char *argv0, const char *optarg)
2127 {
2128 if (!sys_isdir(optarg)) {
2129 fprintf(stderr, "%s: '%s' is not a directory\n", argv0, optarg);
2130 return -1;
2131 }
2132 if (global->jaildir)
2133 free(global->jaildir);
2134 global->jaildir = realpath(optarg, NULL);
2135 if (!global->jaildir) {
2136 fprintf(stderr, "%s: Failed to realpath '%s': %s (%i)\n",
2137 argv0, optarg, strerror(errno), errno);
2138 return -1;
2139 }
2140 #ifdef DEBUG_OPTS
2141 log_dbg_printf("Chroot: %s\n", global->jaildir);
2142 #endif /* DEBUG_OPTS */
2143 return 0;
2144 }
2145
2146 int
2147 global_set_pidfile(global_t *global, const char *argv0, const char *optarg)
2148 {
2149 if (global->pidfile)
2150 free(global->pidfile);
2151 global->pidfile = strdup(optarg);
2152 if (!global->pidfile)
2153 return oom_return(argv0);
2154 #ifdef DEBUG_OPTS
2155 log_dbg_printf("PidFile: %s\n", global->pidfile);
2156 #endif /* DEBUG_OPTS */
2157 return 0;
2158 }
2159
2160 int
2161 global_set_connectlog(global_t *global, const char *argv0, const char *optarg)
2162 {
2163 if (global->connectlog)
2164 free(global->connectlog);
2165 if (!(global->connectlog = sys_realdir(optarg))) {
2166 if (errno == ENOENT) {
2167 fprintf(stderr, "Directory part of '%s' does not "
2168 "exist\n", optarg);
2169 return -1;
2170 } else {
2171 fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
2172 optarg, strerror(errno), errno);
2173 return oom_return(argv0);
2174 }
2175 }
2176 #ifdef DEBUG_OPTS
2177 log_dbg_printf("ConnectLog: %s\n", global->connectlog);
2178 #endif /* DEBUG_OPTS */
2179 return 0;
2180 }
2181
2182 int
2183 global_set_contentlog(global_t *global, const char *argv0, const char *optarg)
2184 {
2185 if (global->contentlog)
2186 free(global->contentlog);
2187 if (!(global->contentlog = sys_realdir(optarg))) {
2188 if (errno == ENOENT) {
2189 fprintf(stderr, "Directory part of '%s' does not "
2190 "exist\n", optarg);
2191 return -1;
2192 } else {
2193 fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
2194 optarg, strerror(errno), errno);
2195 return oom_return(argv0);
2196 }
2197 }
2198 global->contentlog_isdir = 0;
2199 global->contentlog_isspec = 0;
2200 #ifdef DEBUG_OPTS
2201 log_dbg_printf("ContentLog: %s\n", global->contentlog);
2202 #endif /* DEBUG_OPTS */
2203 return 0;
2204 }
2205
2206 int
2207 global_set_contentlogdir(global_t *global, const char *argv0, const char *optarg)
2208 {
2209 if (!sys_isdir(optarg)) {
2210 fprintf(stderr, "%s: '%s' is not a directory\n", argv0, optarg);
2211 return -1;
2212 }
2213 if (global->contentlog)
2214 free(global->contentlog);
2215 global->contentlog = realpath(optarg, NULL);
2216 if (!global->contentlog) {
2217 fprintf(stderr, "%s: Failed to realpath '%s': %s (%i)\n",
2218 argv0, optarg, strerror(errno), errno);
2219 return -1;
2220 }
2221 global->contentlog_isdir = 1;
2222 global->contentlog_isspec = 0;
2223 #ifdef DEBUG_OPTS
2224 log_dbg_printf("ContentLogDir: %s\n", global->contentlog);
2225 #endif /* DEBUG_OPTS */
2226 return 0;
2227 }
2228
2229 static int
2230 global_set_logbasedir(const char *argv0, const char *optarg,
2231 char **basedir, char **log)
2232 {
2233 char *lhs, *rhs, *p, *q;
2234 size_t n;
2235 if (*basedir)
2236 free(*basedir);
2237 if (*log)
2238 free(*log);
2239 if (log_content_split_pathspec(optarg, &lhs, &rhs) == -1) {
2240 fprintf(stderr, "%s: Failed to split '%s' in lhs/rhs:"
2241 " %s (%i)\n", argv0, optarg,
2242 strerror(errno), errno);
2243 return -1;
2244 }
2245 /* eliminate %% from lhs */
2246 for (p = q = lhs; *p; p++, q++) {
2247 if (q < p)
2248 *q = *p;
2249 if (*p == '%' && *(p+1) == '%')
2250 p++;
2251 }
2252 *q = '\0';
2253 /* all %% in lhs resolved to % */
2254 if (sys_mkpath(lhs, 0777) == -1) {
2255 fprintf(stderr, "%s: Failed to create '%s': %s (%i)\n",
2256 argv0, lhs, strerror(errno), errno);
2257 return -1;
2258 }
2259 *basedir = realpath(lhs, NULL);
2260 if (!*basedir) {
2261 fprintf(stderr, "%s: Failed to realpath '%s': %s (%i)\n",
2262 argv0, lhs, strerror(errno), errno);
2263 return -1;
2264 }
2265 /* count '%' in basedir */
2266 for (n = 0, p = *basedir;
2267 *p;
2268 p++) {
2269 if (*p == '%')
2270 n++;
2271 }
2272 free(lhs);
2273 n += strlen(*basedir);
2274 if (!(lhs = malloc(n + 1)))
2275 return oom_return(argv0);
2276 /* re-encoding % to %%, copying basedir to lhs */
2277 for (p = *basedir, q = lhs;
2278 *p;
2279 p++, q++) {
2280 *q = *p;
2281 if (*q == '%')
2282 *(++q) = '%';
2283 }
2284 *q = '\0';
2285 /* lhs contains encoded realpathed basedir */
2286 if (asprintf(log, "%s/%s", lhs, rhs) < 0)
2287 return oom_return(argv0);
2288 free(lhs);
2289 free(rhs);
2290 return 0;
2291 }
2292
2293 int
2294 global_set_contentlogpathspec(global_t *global, const char *argv0, const char *optarg)
2295 {
2296 if (global_set_logbasedir(argv0, optarg, &global->contentlog_basedir, &global->contentlog) == -1)
2297 return -1;
2298 global->contentlog_isdir = 0;
2299 global->contentlog_isspec = 1;
2300 #ifdef DEBUG_OPTS
2301 log_dbg_printf("ContentLogPathSpec: basedir=%s, %s\n",
2302 global->contentlog_basedir, global->contentlog);
2303 #endif /* DEBUG_OPTS */
2304 return 0;
2305 }
2306
2307 #ifdef HAVE_LOCAL_PROCINFO
2308 void
2309 global_set_lprocinfo(global_t *global)
2310 {
2311 global->lprocinfo = 1;
2312 }
2313
2314 void
2315 global_unset_lprocinfo(global_t *global)
2316 {
2317 global->lprocinfo = 0;
2318 }
2319 #endif /* HAVE_LOCAL_PROCINFO */
2320
2321 int
2322 global_set_masterkeylog(global_t *global, const char *argv0, const char *optarg)
2323 {
2324 if (global->masterkeylog)
2325 free(global->masterkeylog);
2326 if (!(global->masterkeylog = sys_realdir(optarg))) {
2327 if (errno == ENOENT) {
2328 fprintf(stderr, "Directory part of '%s' does not "
2329 "exist\n", optarg);
2330 return -1;
2331 } else {
2332 fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
2333 optarg, strerror(errno), errno);
2334 return oom_return(argv0);
2335 }
2336 }
2337 #ifdef DEBUG_OPTS
2338 log_dbg_printf("MasterKeyLog: %s\n", global->masterkeylog);
2339 #endif /* DEBUG_OPTS */
2340 return 0;
2341 }
2342
2343 int
2344 global_set_pcaplog(global_t *global, const char *argv0, const char *optarg)
2345 {
2346 if (global->pcaplog)
2347 free(global->pcaplog);
2348 if (!(global->pcaplog = sys_realdir(optarg))) {
2349 if (errno == ENOENT) {
2350 fprintf(stderr, "Directory part of '%s' does not "
2351 "exist\n", optarg);
2352 return -1;
2353 } else {
2354 fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
2355 optarg, strerror(errno), errno);
2356 return oom_return(argv0);
2357 }
2358 }
2359 global->pcaplog_isdir = 0;
2360 global->pcaplog_isspec = 0;
2361 #ifdef DEBUG_OPTS
2362 log_dbg_printf("PcapLog: %s\n", global->pcaplog);
2363 #endif /* DEBUG_OPTS */
2364 return 0;
2365 }
2366
2367 int
2368 global_set_pcaplogdir(global_t *global, const char *argv0, const char *optarg)
2369 {
2370 if (!sys_isdir(optarg)) {
2371 fprintf(stderr, "%s: '%s' is not a directory\n", argv0, optarg);
2372 return -1;
2373 }
2374 if (global->pcaplog)
2375 free(global->pcaplog);
2376 global->pcaplog = realpath(optarg, NULL);
2377 if (!global->pcaplog) {
2378 fprintf(stderr, "%s: Failed to realpath '%s': %s (%i)\n",
2379 argv0, optarg, strerror(errno), errno);
2380 return -1;
2381 }
2382 global->pcaplog_isdir = 1;
2383 global->pcaplog_isspec = 0;
2384 #ifdef DEBUG_OPTS
2385 log_dbg_printf("PcapLogDir: %s\n", global->pcaplog);
2386 #endif /* DEBUG_OPTS */
2387 return 0;
2388 }
2389
2390 int
2391 global_set_pcaplogpathspec(global_t *global, const char *argv0, const char *optarg)
2392 {
2393 if (global_set_logbasedir(argv0, optarg, &global->pcaplog_basedir, &global->pcaplog) == -1)
2394 return -1;
2395 global->pcaplog_isdir = 0;
2396 global->pcaplog_isspec = 1;
2397 #ifdef DEBUG_OPTS
2398 log_dbg_printf("PcapLogPathSpec: basedir=%s, %s\n",
2399 global->pcaplog_basedir, global->pcaplog);
2400 #endif /* DEBUG_OPTS */
2401 return 0;
2402 }
2403
2404 #ifndef WITHOUT_MIRROR
2405 int
2406 global_set_mirrorif(global_t *global, const char *argv0, const char *optarg)
2407 {
2408 if (global->mirrorif)
2409 free(global->mirrorif);
2410 global->mirrorif = strdup(optarg);
2411 if (!global->mirrorif)
2412 return oom_return(argv0);
2413 #ifdef DEBUG_OPTS
2414 log_dbg_printf("MirrorIf: %s\n", global->mirrorif);
2415 #endif /* DEBUG_OPTS */
2416 return 0;
2417 }
2418
2419 int
2420 global_set_mirrortarget(global_t *global, const char *argv0, const char *optarg)
2421 {
2422 if (global->mirrortarget)
2423 free(global->mirrortarget);
2424 global->mirrortarget = strdup(optarg);
2425 if (!global->mirrortarget)
2426 return oom_return(argv0);
2427 #ifdef DEBUG_OPTS
2428 log_dbg_printf("MirrorTarget: %s\n", global->mirrortarget);
2429 #endif /* DEBUG_OPTS */
2430 return 0;
2431 }
2432 #endif /* !WITHOUT_MIRROR */
2433
2434 void
2435 global_set_daemon(global_t *global)
2436 {
2437 global->detach = 1;
2438 }
2439
2440 void
2441 global_unset_daemon(global_t *global)
2442 {
2443 global->detach = 0;
2444 }
2445
2446 void
2447 global_set_debug(global_t *global)
2448 {
2449 log_dbg_mode(LOG_DBG_MODE_ERRLOG);
2450 global->debug = 1;
2451 }
2452
2453 void
2454 global_unset_debug(global_t *global)
2455 {
2456 log_dbg_mode(LOG_DBG_MODE_NONE);
2457 global->debug = 0;
2458 }
2459
2460 int
2461 global_set_debug_level(const char *optarg)
2462 {
2463 if (equal(optarg, "2")) {
2464 log_dbg_mode(LOG_DBG_MODE_FINE);
2465 } else if (equal(optarg, "3")) {
2466 log_dbg_mode(LOG_DBG_MODE_FINER);
2467 } else if (equal(optarg, "4")) {
2468 log_dbg_mode(LOG_DBG_MODE_FINEST);
2469 } else {
2470 fprintf(stderr, "Invalid DebugLevel '%s', use 2-4\n", optarg);
2471 return -1;
2472 }
2473 #ifdef DEBUG_OPTS
2474 log_dbg_printf("DebugLevel: %s\n", optarg);
2475 #endif /* DEBUG_OPTS */
2476 return 0;
2477 }
2478
2479 void
2480 global_set_statslog(global_t *global)
2481 {
2482 global->statslog = 1;
2483 }
2484
2485 void
2486 global_unset_statslog(global_t *global)
2487 {
2488 global->statslog = 0;
2489 }
2490
2491 #ifndef WITHOUT_USERAUTH
2492 static int WUNRES
2493 global_set_userdb_path(global_t *global, const char *argv0, const char *optarg)
2494 {
2495 FILE *fd = fopen(optarg, "r");
2496 if (!fd) {
2497 log_err_level_printf(LOG_CRIT, "Error opening UserDB file '%s': %s\n", optarg, strerror(errno));
2498 return -1;
2499 }
2500 fclose(fd);
2501
2502 if (global->userdb_path)
2503 free(global->userdb_path);
2504 global->userdb_path = strdup(optarg);
2505 if (!global->userdb_path)
2506 return oom_return(argv0);
2507 #ifdef DEBUG_OPTS
2508 log_dbg_printf("UserDBPath: %s\n", global->userdb_path);
2509 #endif /* DEBUG_OPTS */
2510 return 0;
2511 }
2512 #endif /* !WITHOUT_USERAUTH */
2513
2514 int
2515 is_yesno(const char *value)
2516 {
2517 if (equal(value, "yes"))
2518 return 1;
2519 else if (equal(value, "no"))
2520 return 0;
2521 return -1;
2522 }
2523
2524 int
2525 check_value_yesno(const char *value, const char *name, unsigned int line_num)
2526 {
2527 int rv;
2528 if ((rv = is_yesno(value)) == -1)
2529 fprintf(stderr, "Error in conf: Invalid '%s' value '%s' on line %d, use yes|no\n", name, value, line_num);
2530 return rv;
2531 }
2532
2533 int
2534 set_conn_opts_option(conn_opts_t *conn_opts, const char *argv0,
2535 const char *name, char *value, unsigned int line_num, tmp_opts_t *tmp_opts)
2536 {
2537 int yes;
2538
2539 if (!value || !strlen(value)) {
2540 fprintf(stderr, "Error in conf: No value assigned for %s on line %d\n", name, line_num);
2541 return -1;
2542 }
2543
2544 if (equal(name, "CACert")) {
2545 return opts_set_cacrt(conn_opts, argv0, value, tmp_opts);
2546 } else if (equal(name, "CAKey")) {
2547 return opts_set_cakey(conn_opts, argv0, value, tmp_opts);
2548 } else if (equal(name, "ClientCert")) {
2549 return opts_set_clientcrt(conn_opts, argv0, value, tmp_opts);
2550 } else if (equal(name, "ClientKey")) {
2551 return opts_set_clientkey(conn_opts, argv0, value, tmp_opts);
2552 } else if (equal(name, "CAChain")) {
2553 return opts_set_chain(conn_opts, argv0, value, tmp_opts);
2554 } else if (equal(name, "LeafCRLURL")) {
2555 return opts_set_leafcrlurl(conn_opts, argv0, value, tmp_opts);
2556 } else if (equal(name, "DenyOCSP")) {
2557 yes = check_value_yesno(value, "DenyOCSP", line_num);
2558 if (yes == -1)
2559 return -1;
2560 yes ? opts_set_deny_ocsp(conn_opts) : opts_unset_deny_ocsp(conn_opts);
2561 #ifdef DEBUG_OPTS
2562 log_dbg_printf("DenyOCSP: %u\n", conn_opts->deny_ocsp);
2563 #endif /* DEBUG_OPTS */
2564 } else if (equal(name, "Passthrough")) {
2565 yes = check_value_yesno(value, "Passthrough", line_num);
2566 if (yes == -1)
2567 return -1;
2568 yes ? opts_set_passthrough(conn_opts) : opts_unset_passthrough(conn_opts);
2569 #ifdef DEBUG_OPTS
2570 log_dbg_printf("Passthrough: %u\n", conn_opts->passthrough);
2571 #endif /* DEBUG_OPTS */
2572 #ifndef OPENSSL_NO_DH
2573 } else if (equal(name, "DHGroupParams")) {
2574 return opts_set_dh(conn_opts, argv0, value, tmp_opts);
2575 #endif /* !OPENSSL_NO_DH */
2576 #ifndef OPENSSL_NO_ECDH
2577 } else if (equal(name, "ECDHCurve")) {
2578 return opts_set_ecdhcurve(conn_opts, argv0, value);
2579 #endif /* !OPENSSL_NO_ECDH */
2580 #ifdef SSL_OP_NO_COMPRESSION
2581 } else if (equal(name, "SSLCompression")) {
2582 yes = check_value_yesno(value, "SSLCompression", line_num);
2583 if (yes == -1)
2584 return -1;
2585 yes ? opts_set_sslcomp(conn_opts) : opts_unset_sslcomp(conn_opts);
2586 #ifdef DEBUG_OPTS
2587 log_dbg_printf("SSLCompression: %u\n", conn_opts->sslcomp);
2588 #endif /* DEBUG_OPTS */
2589 #endif /* SSL_OP_NO_COMPRESSION */
2590 } else if (equal(name, "ForceSSLProto")) {
2591 return opts_force_proto(conn_opts, argv0, value);
2592 } else if (equal(name, "DisableSSLProto")) {
2593 return opts_disable_enable_proto(conn_opts, argv0, value, 1);
2594 } else if (equal(name, "EnableSSLProto")) {
2595 return opts_disable_enable_proto(conn_opts, argv0, value, 0);
2596 } else if (equal(name, "MinSSLProto")) {
2597 return opts_set_min_proto(conn_opts, argv0, value);
2598 } else if (equal(name, "MaxSSLProto")) {
2599 return opts_set_max_proto(conn_opts, argv0, value);
2600 } else if (equal(name, "Ciphers")) {
2601 return opts_set_ciphers(conn_opts, argv0, value);
2602 } else if (equal(name, "CipherSuites")) {
2603 return opts_set_ciphersuites(conn_opts, argv0, value);
2604 #ifndef WITHOUT_USERAUTH
2605 } else if (equal(name, "UserAuth")) {
2606 yes = check_value_yesno(value, "UserAuth", line_num);
2607 if (yes == -1)
2608 return -1;
2609 yes ? opts_set_user_auth(conn_opts) : opts_unset_user_auth(conn_opts);
2610 #ifdef DEBUG_OPTS
2611 log_dbg_printf("UserAuth: %u\n", conn_opts->user_auth);
2612 #endif /* DEBUG_OPTS */
2613 } else if (equal(name, "UserAuthURL")) {
2614 return opts_set_user_auth_url(conn_opts, argv0, value);
2615 } else if (equal(name, "UserTimeout")) {
2616 unsigned int i = atoi(value);
2617 if (i <= 86400) {
2618 conn_opts->user_timeout = i;
2619 } else {
2620 fprintf(stderr, "Invalid UserTimeout %s on line %d, use 0-86400\n", value, line_num);
2621 return -1;
2622 }
2623 #ifdef DEBUG_OPTS
2624 log_dbg_printf("UserTimeout: %u\n", conn_opts->user_timeout);
2625 #endif /* DEBUG_OPTS */
2626 #endif /* !WITHOUT_USERAUTH */
2627 } else if (equal(name, "ValidateProto")) {
2628 yes = check_value_yesno(value, "ValidateProto", line_num);
2629 if (yes == -1)
2630 return -1;
2631 yes ? opts_set_validate_proto(conn_opts) : opts_unset_validate_proto(conn_opts);
2632 #ifdef DEBUG_OPTS
2633 log_dbg_printf("ValidateProto: %u\n", conn_opts->validate_proto);
2634 #endif /* DEBUG_OPTS */
2635 } else if (equal(name, "MaxHTTPHeaderSize")) {
2636 unsigned int i = atoi(value);
2637 if (i >= 1024 && i <= 65536) {
2638 conn_opts->max_http_header_size = i;
2639 } else {
2640 fprintf(stderr, "Invalid MaxHTTPHeaderSize %s on line %d, use 1024-65536\n", value, line_num);
2641 return -1;
2642 }
2643 #ifdef DEBUG_OPTS
2644 log_dbg_printf("MaxHTTPHeaderSize: %u\n", conn_opts->max_http_header_size);
2645 #endif /* DEBUG_OPTS */
2646 } else if (equal(name, "VerifyPeer")) {
2647 yes = check_value_yesno(value, "VerifyPeer", line_num);
2648 if (yes == -1)
2649 return -1;
2650 yes ? opts_set_verify_peer(conn_opts) : opts_unset_verify_peer(conn_opts);
2651 #ifdef DEBUG_OPTS
2652 log_dbg_printf("VerifyPeer: %u\n", conn_opts->verify_peer);
2653 #endif /* DEBUG_OPTS */
2654 } else if (equal(name, "AllowWrongHost")) {
2655 yes = check_value_yesno(value, "AllowWrongHost", line_num);
2656 if (yes == -1)
2657 return -1;
2658 yes ? opts_set_allow_wrong_host(conn_opts) : opts_unset_allow_wrong_host(conn_opts);
2659 #ifdef DEBUG_OPTS
2660 log_dbg_printf("AllowWrongHost: %u\n", conn_opts->allow_wrong_host);
2661 #endif /* DEBUG_OPTS */
2662 } else if (equal(name, "RemoveHTTPAcceptEncoding")) {
2663 yes = check_value_yesno(value, "RemoveHTTPAcceptEncoding", line_num);
2664 if (yes == -1)
2665 return -1;
2666 yes ? opts_set_remove_http_accept_encoding(conn_opts) : opts_unset_remove_http_accept_encoding(conn_opts);
2667 #ifdef DEBUG_OPTS
2668 log_dbg_printf("RemoveHTTPAcceptEncoding: %u\n", conn_opts->remove_http_accept_encoding);
2669 #endif /* DEBUG_OPTS */
2670 } else if (equal(name, "RemoveHTTPReferer")) {
2671 yes = check_value_yesno(value, "RemoveHTTPReferer", line_num);
2672 if (yes == -1)
2673 return -1;
2674 yes ? opts_set_remove_http_referer(conn_opts) : opts_unset_remove_http_referer(conn_opts);
2675 #ifdef DEBUG_OPTS
2676 log_dbg_printf("RemoveHTTPReferer: %u\n", conn_opts->remove_http_referer);
2677 #endif /* DEBUG_OPTS */
2678 }
2679 else {
2680 // Unknown conn_opts option, but may not be an error, so return 1, instead of -1
2681 return 1;
2682 }
2683 return 0;
2684 }
2685
2686 /*
2687 * tmp_opts param is used to save certain opts, so that we can use them
2688 * to copy global opts to proxyspecs, or proxyspecs opts to struct filtering rules
2689 */
2690 static int
2691 set_option(opts_t *opts, conn_opts_t *conn_opts, const char *argv0,
2692 const char *name, char *value, char **natengine, FILE *f, unsigned int *line_num, tmp_opts_t *tmp_opts)
2693 {
2694 int yes;
2695
2696 if (!value || !strlen(value)) {
2697 fprintf(stderr, "Error in conf: No value assigned for %s on line %d\n", name, *line_num);
2698 return -1;
2699 }
2700
2701 if (equal(name, "NATEngine")) {
2702 if (*natengine)
2703 free(*natengine);
2704 *natengine = strdup(value);
2705 if (!*natengine)
2706 return oom_return(argv0);
2707 #ifdef DEBUG_OPTS
2708 log_dbg_printf("NATEngine: %s\n", *natengine);
2709 #endif /* DEBUG_OPTS */
2710 #ifndef WITHOUT_USERAUTH
2711 } else if (equal(name, "DivertUsers")) {
2712 return filter_userlist_set(value, *line_num, &opts->divertusers, "DivertUsers");
2713 } else if (equal(name, "PassUsers")) {
2714 return filter_userlist_set(value, *line_num, &opts->passusers, "PassUsers");
2715 #endif /* !WITHOUT_USERAUTH */
2716 } else if (equal(name, "PassSite")) {
2717 return filter_passsite_set(opts, conn_opts, value, *line_num);
2718 } else if (equal(name, "Define")) {
2719 return filter_macro_set(opts, value, *line_num);
2720 } else if (equal(name, "Split") || equal(name, "Pass") || equal(name, "Block") || equal(name, "Match")) {
2721 return filter_rule_set(opts, conn_opts, name, value, *line_num);
2722 } else if (equal(name, "Divert")) {
2723 yes = is_yesno(value);
2724 if (yes == -1)
2725 return filter_rule_set(opts, conn_opts, name, value, *line_num);
2726 else
2727 yes ? opts_set_divert(opts) : opts_unset_divert(opts);
2728 } else if (equal(name, "FilterRule") && equal(value, "{")) {
2729 #ifdef DEBUG_OPTS
2730 log_dbg_printf("FilterRule { on line %d\n", *line_num);
2731 #endif /* DEBUG_OPTS */
2732 return load_filterrule_struct(opts, conn_opts, argv0, line_num, f, tmp_opts);
2733 } else {
2734 int rv = set_conn_opts_option(conn_opts, argv0, name, value, *line_num, tmp_opts);
2735 if (rv == -1) {
2736 fprintf(stderr, "Error in conf: '%s' on line %d\n", name, *line_num);
2737 return -1;
2738 } else if (rv == 1) {
2739 fprintf(stderr, "Error in conf: Unknown option '%s' on line %d\n", name, *line_num);
2740 return -1;
2741 }
2742 }
2743 return 0;
2744 }
2745
2746 static int WUNRES
2747 set_proxyspec_option(proxyspec_t *spec, const char *argv0,
2748 const char *name, char *value, char **natengine, spec_addrs_t *spec_addrs, FILE *f, unsigned int *line_num, tmp_opts_t *proxyspec_tmp_opts)
2749 {
2750 // Closing brace '}' is the only option without a value
2751 // and only allowed in structured proxyspecs and filter rules
2752 if ((!value || !strlen(value)) && !equal(name, "}")) {
2753 fprintf(stderr, "Error in conf: No value assigned for %s on line %d\n", name, *line_num);
2754 return -1;
2755 }
2756
2757 if (equal(name, "Proto")) {
2758 if (proxyspec_set_proto(spec, value) == -1)
2759 return -1;
2760 }
2761 else if (equal(name, "Addr")) {
2762 spec_addrs->addr = strdup(value);
2763 if (!spec_addrs->addr)
2764 return oom_return(argv0);
2765 }
2766 else if (equal(name, "Port")) {
2767 if (spec_addrs->addr) {
2768 spec_addrs->af = proxyspec_set_listen_addr(spec, spec_addrs->addr, value, *natengine);
2769 } else {
2770 fprintf(stderr, "ProxySpec Port without Addr on line %d\n", *line_num);
2771 return -1;
2772 }
2773 }
2774 else if (equal(name, "DivertAddr")) {
2775 spec_addrs->divert_addr = strdup(value);
2776 if (!spec_addrs->divert_addr)
2777 return oom_return(argv0);
2778 }
2779 else if (equal(name, "DivertPort")) {
2780 if (spec_addrs->divert_addr) {
2781 if (proxyspec_set_divert_addr(spec, spec_addrs->divert_addr, value) == -1)
2782 return -1;
2783 } else {
2784 if (proxyspec_set_divert_addr(spec, "127.0.0.1", value) == -1)
2785 return -1;
2786 }
2787 }
2788 else if (equal(name, "ReturnAddr")) {
2789 if (proxyspec_set_return_addr(spec, value) == -1)
2790 return -1;
2791 }
2792 else if (equal(name, "TargetAddr")) {
2793 spec_addrs->target_addr = strdup(value);
2794 if (!spec_addrs->target_addr)
2795 return oom_return(argv0);
2796 }
2797 else if (equal(name, "TargetPort")) {
2798 if (spec_addrs->target_addr) {
2799 if (proxyspec_set_target_addr(spec, spec_addrs->target_addr, value, spec_addrs->af) == -1)
2800 return -1;
2801 } else {
2802 fprintf(stderr, "ProxySpec TargetPort without TargetAddr on line %d\n", *line_num);
2803 return -1;
2804 }
2805 }
2806 else if (equal(name, "SNIPort")) {
2807 if (proxyspec_set_sni_port(spec, value) == -1)
2808 return -1;
2809 }
2810 else if (equal(name, "NatEngine")) {
2811 if (proxyspec_set_natengine(spec, value) == -1)
2812 return -1;
2813 }
2814 else if (equal(name, "}")) {
2815 #ifdef DEBUG_OPTS
2816 log_dbg_printf("ProxySpec } on line %d\n", *line_num);
2817 #endif /* DEBUG_OPTS */
2818 if (!spec_addrs->addr || !spec_addrs->af) {
2819 fprintf(stderr, "Incomplete ProxySpec on line %d\n", *line_num);
2820 return -1;
2821 }
2822 // Return 2 to indicate the end of structured proxyspec
2823 return 2;
2824 }
2825 else {
2826 return set_option(spec->opts, spec->conn_opts, argv0, name, value, natengine, f, line_num, proxyspec_tmp_opts);
2827 }
2828 return 0;
2829 }
2830
2831 /*
2832 * Separator param is needed for command line options only.
2833 * Conf file option separator is ' ', on the command line is '='.
2834 * Allows multiple separators between name and value.
2835 */
2836 int
2837 get_name_value(char *name, char **value, const char sep, unsigned int line_num)
2838 {
2839 size_t len = strlen(name);
2840
2841 // Find end of name and null-terminate
2842 char *n = name;
2843 while (*n != '\0' && *n != ' ' && *n != '\t' && *n != '\r' && *n != '\n' && *n != sep)
2844 n++;
2845 *n = '\0';
2846
2847 size_t name_len = strlen(name);
2848
2849 if (!name_len) {
2850 fprintf(stderr, "Error in option: No option name on line %d\n", line_num);
2851 // Return empty value
2852 *value = name;
2853 return -1;
2854 }
2855
2856 if (len == name_len) {
2857 #ifdef DEBUG_OPTS
2858 log_dbg_printf("Warning in option: No option separator on line %d\n", line_num);
2859 #endif /* DEBUG_OPTS */
2860 // Return empty value
2861 *value = name + name_len;
2862 return 0;
2863 }
2864
2865 // Trim left of value (skip white space and sep until value)
2866 do n++;
2867 while (*n == ' ' || *n == '\t' || *n == '\r' || *n == '\n' || *n == sep);
2868
2869 *value = n;
2870
2871 size_t value_len = strlen(*value);
2872
2873 // Trim inline comment
2874 n = *value;
2875 while (*n) {
2876 if (*n == '#') {
2877 *n = '\0';
2878 value_len = strlen(*value);
2879 break;
2880 }
2881 n++;
2882 }
2883
2884 if (!value_len) {
2885 #ifdef DEBUG_OPTS
2886 log_dbg_printf("Warning in option: No option value on line %d\n", line_num);
2887 #endif /* DEBUG_OPTS */
2888 return 0;
2889 }
2890
2891 // Trim right of value
2892 n = *value + value_len - 1;
2893 while (*n == ' ' || *n == '\t' || *n == '\r' || *n == '\n' || *n == sep)
2894 n--;
2895 *(n + 1) = '\0';
2896
2897 return 0;
2898 }
2899
2900 #define MAX_TOKENS 8
2901
2902 static int WUNRES
2903 load_proxyspec_line(global_t *global, const char *argv0, char *value, char **natengine, unsigned int line_num, tmp_opts_t *global_tmp_opts)
2904 {
2905 /* Use MAX_TOKENS instead of computing the actual number of tokens in value */
2906 char **argv = malloc(sizeof(char *) * MAX_TOKENS);
2907 if (!argv)
2908 return oom_return(argv0);
2909 char **save_argv = argv;
2910 int argc = 0;
2911 char *p, *last = NULL;
2912
2913 for ((p = strtok_r(value, " ", &last));
2914 p;
2915 (p = strtok_r(NULL, " ", &last))) {
2916 /* Limit max # token */
2917 if (argc < MAX_TOKENS) {
2918 argv[argc++] = p;
2919 } else {
2920 fprintf(stderr, "Too many arguments in proxyspec on line %d\n", line_num);
2921 return -1;
2922 }
2923 }
2924
2925 if (proxyspec_parse(&argc, &argv, *natengine, global, argv0, global_tmp_opts) == -1) {
2926 fprintf(stderr, "Error in proxyspec on line %d\n", line_num);
2927 return -1;
2928 }
2929
2930 free(save_argv);
2931 return 0;
2932 }
2933
2934 int
2935 load_proxyspec_struct(global_t *global, const char *argv0, char **natengine, unsigned int *line_num, FILE *f, tmp_opts_t *global_tmp_opts)
2936 {
2937 int retval = -1;
2938 char *name, *value;
2939 char *line = NULL;
2940 size_t line_len;
2941
2942 proxyspec_t *spec = proxyspec_new(global, argv0, global_tmp_opts);
2943 if (!spec)
2944 return -1;
2945 spec->next = global->spec;
2946 global->spec = spec;
2947
2948 // Set the default return addr
2949 if (proxyspec_set_return_addr(spec, "127.0.0.1") == -1)
2950 return -1;
2951
2952 spec_addrs_t *spec_addrs = malloc(sizeof(spec_addrs_t));
2953 if (!spec_addrs)
2954 return oom_return(argv0);
2955 memset(spec_addrs, 0, sizeof(spec_addrs_t));
2956
2957 tmp_opts_t *proxyspec_tmp_opts = tmp_opts_copy(global_tmp_opts);
2958 if (!proxyspec_tmp_opts) {
2959 retval = -1;
2960 goto leave;
2961 }
2962
2963 int closing_brace = 0;
2964
2965 while (!feof(f) && !closing_brace) {
2966 if (getline(&line, &line_len, f) == -1) {
2967 break;
2968 }
2969 if (line == NULL) {
2970 fprintf(stderr, "Error in conf file: getline() returns NULL line after line %d\n", *line_num);
2971 goto leave;
2972 }
2973 (*line_num)++;
2974
2975 /* Skip white space */
2976 for (name = line; *name == ' ' || *name == '\t'; name++);
2977
2978 /* Skip comments and empty lines */
2979 if ((name[0] == '\0') || (name[0] == '#') || (name[0] == ';') ||
2980 (name[0] == '\r') || (name[0] == '\n')) {
2981 continue;
2982 }
2983
2984 retval = get_name_value(name, &value, ' ', *line_num);
2985 if (retval == 0) {
2986 retval = set_proxyspec_option(spec, argv0, name, value, natengine, spec_addrs, f, line_num, proxyspec_tmp_opts);
2987 }
2988 if (retval == -1) {
2989 goto leave;
2990 } else if (retval == 2) {
2991 closing_brace = 1;
2992 }
2993 free(line);
2994 line = NULL;
2995 }
2996
2997 if (!closing_brace) {
2998 fprintf(stderr, "Error in conf file: struct ProxySpec has no closing brace '}' after line %d\n", *line_num);
2999 retval = -1;
3000 goto leave;
3001 }
3002
3003 set_divert(spec, global_tmp_opts->split);
3004
3005 retval = 0;
3006 leave:
3007 if (line)
3008 free(line);
3009 spec_addrs_free(spec_addrs);
3010 if (proxyspec_tmp_opts)
3011 tmp_opts_free(proxyspec_tmp_opts);
3012 return retval;
3013 }
3014
3015 static int WUNRES
3016 global_set_open_files_limit(const char *value, unsigned int line_num)
3017 {
3018 unsigned int i = atoi(value);
3019 if (i >= 50 && i <= 10000) {
3020 struct rlimit rl;
3021 rl.rlim_cur = i;
3022 rl.rlim_max = i;
3023 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
3024 fprintf(stderr, "Failed setting OpenFilesLimit\n");
3025 if (errno) {
3026 fprintf(stderr, "%s\n", strerror(errno));
3027 } else {
3028 ERR_print_errors_fp(stderr);
3029 }
3030 return -1;
3031 }
3032 } else {
3033 fprintf(stderr, "Invalid OpenFilesLimit %s on line %d, use 50-10000\n", value, line_num);
3034 return -1;
3035 }
3036 #ifdef DEBUG_OPTS
3037 log_dbg_printf("OpenFilesLimit: %u\n", i);
3038 #endif /* DEBUG_OPTS */
3039 return 0;
3040 }
3041
3042
3043 static int
3044 opts_load_conffile(global_t *global, const char *argv0, char *conffile, char **natengine, tmp_opts_t *tmp_opts);
3045
3046 static int WUNRES
3047 set_global_option(global_t *global, const char *argv0,
3048 const char *name, char *value, char **natengine, unsigned int *line_num, FILE *f, tmp_opts_t *tmp_opts)
3049 {
3050 int yes;
3051
3052 if (!value || !strlen(value)) {
3053 fprintf(stderr, "Error in conf: No value assigned for %s on line %d\n", name, *line_num);
3054 return -1;
3055 }
3056
3057 if (equal(name, "LeafCertDir")) {
3058 return global_set_leafcertdir(global, argv0, value);
3059 } else if (equal(name, "DefaultLeafCert")) {
3060 return global_set_defaultleafcert(global, argv0, value);
3061 } else if (equal(name, "WriteGenCertsDir")) {
3062 return global_set_certgendir_writegencerts(global, argv0, value);
3063 } else if (equal(name, "WriteAllCertsDir")) {
3064 return global_set_certgendir_writeall(global, argv0, value);
3065 } else if (equal(name, "User")) {
3066 return global_set_user(global, argv0, value);
3067 } else if (equal(name, "Group")) {
3068 return global_set_group(global, argv0, value);
3069 } else if (equal(name, "Chroot")) {
3070 return global_set_jaildir(global, argv0, value);
3071 } else if (equal(name, "PidFile")) {
3072 return global_set_pidfile(global, argv0, value);
3073 } else if (equal(name, "ConnectLog")) {
3074 return global_set_connectlog(global, argv0, value);
3075 } else if (equal(name, "ContentLog")) {
3076 return global_set_contentlog(global, argv0, value);
3077 } else if (equal(name, "ContentLogDir")) {
3078 return global_set_contentlogdir(global, argv0, value);
3079 } else if (equal(name, "ContentLogPathSpec")) {
3080 return global_set_contentlogpathspec(global, argv0, value);
3081 #ifdef HAVE_LOCAL_PROCINFO
3082 } else if (equal(name, "LogProcInfo")) {
3083 yes = check_value_yesno(value, "LogProcInfo", *line_num);
3084 if (yes == -1)
3085 return -1;
3086 yes ? global_set_lprocinfo(global) : global_unset_lprocinfo(global);
3087 #ifdef DEBUG_OPTS
3088 log_dbg_printf("LogProcInfo: %u\n", global->lprocinfo);
3089 #endif /* DEBUG_OPTS */
3090 #endif /* HAVE_LOCAL_PROCINFO */
3091 } else if (equal(name, "MasterKeyLog")) {
3092 return global_set_masterkeylog(global, argv0, value);
3093 } else if (equal(name, "PcapLog")) {
3094 return global_set_pcaplog(global, argv0, value);
3095 } else if (equal(name, "PcapLogDir")) {
3096 return global_set_pcaplogdir(global, argv0, value);
3097 } else if (equal(name, "PcapLogPathSpec")) {
3098 return global_set_pcaplogpathspec(global, argv0, value);
3099 #ifndef WITHOUT_MIRROR
3100 } else if (equal(name, "MirrorIf")) {
3101 return global_set_mirrorif(global, argv0, value);
3102 } else if (equal(name, "MirrorTarget")) {
3103 return global_set_mirrortarget(global, argv0, value);
3104 #endif /* !WITHOUT_MIRROR */
3105 } else if (equal(name, "Daemon")) {
3106 yes = check_value_yesno(value, "Daemon", *line_num);
3107 if (yes == -1)
3108 return -1;
3109 yes ? global_set_daemon(global) : global_unset_daemon(global);
3110 #ifdef DEBUG_OPTS
3111 log_dbg_printf("Daemon: %u\n", global->detach);
3112 #endif /* DEBUG_OPTS */
3113 } else if (equal(name, "Debug")) {
3114 yes = check_value_yesno(value, "Debug", *line_num);
3115 if (yes == -1)
3116 return -1;
3117 yes ? global_set_debug(global) : global_unset_debug(global);
3118 #ifdef DEBUG_OPTS
3119 log_dbg_printf("Debug: %u\n", global->debug);
3120 #endif /* DEBUG_OPTS */
3121 } else if (equal(name, "DebugLevel")) {
3122 return global_set_debug_level(value);
3123 #ifndef WITHOUT_USERAUTH
3124 } else if (equal(name, "UserDBPath")) {
3125 return global_set_userdb_path(global, argv0, value);
3126 #endif /* !WITHOUT_USERAUTH */
3127 } else if (equal(name, "ProxySpec")) {
3128 if (equal(value, "{")) {
3129 #ifdef DEBUG_OPTS
3130 log_dbg_printf("ProxySpec { on line %d\n", *line_num);
3131 #endif /* DEBUG_OPTS */
3132 return load_proxyspec_struct(global, argv0, natengine, line_num, f, tmp_opts);
3133 } else {
3134 return load_proxyspec_line(global, argv0, value, natengine, *line_num, tmp_opts);
3135 }
3136 } else if (equal(name, "ConnIdleTimeout")) {
3137 unsigned int i = atoi(value);
3138 if (i >= 10 && i <= 3600) {
3139 global->conn_idle_timeout = i;
3140 } else {
3141 fprintf(stderr, "Invalid ConnIdleTimeout %s on line %d, use 10-3600\n", value, *line_num);
3142 return -1;
3143 }
3144 #ifdef DEBUG_OPTS
3145 log_dbg_printf("ConnIdleTimeout: %u\n", global->conn_idle_timeout);
3146 #endif /* DEBUG_OPTS */
3147 } else if (equal(name, "ExpiredConnCheckPeriod")) {
3148 unsigned int i = atoi(value);
3149 if (i >= 10 && i <= 60) {
3150 global->expired_conn_check_period = i;
3151 } else {
3152 fprintf(stderr, "Invalid ExpiredConnCheckPeriod %s on line %d, use 10-60\n", value, *line_num);
3153 return -1;
3154 }
3155 #ifdef DEBUG_OPTS
3156 log_dbg_printf("ExpiredConnCheckPeriod: %u\n", global->expired_conn_check_period);
3157 #endif /* DEBUG_OPTS */
3158 } else if (equal(name, "LogStats")) {
3159 yes = check_value_yesno(value, "LogStats", *line_num);
3160 if (yes == -1)
3161 return -1;
3162 yes ? global_set_statslog(global) : global_unset_statslog(global);
3163 #ifdef DEBUG_OPTS
3164 log_dbg_printf("LogStats: %u\n", global->statslog);
3165 #endif /* DEBUG_OPTS */
3166 } else if (equal(name, "StatsPeriod")) {
3167 unsigned int i = atoi(value);
3168 if (i >= 1 && i <= 10) {
3169 global->stats_period = i;
3170 } else {
3171 fprintf(stderr, "Invalid StatsPeriod %s on line %d, use 1-10\n", value, *line_num);
3172 return -1;
3173 }
3174 #ifdef DEBUG_OPTS
3175 log_dbg_printf("StatsPeriod: %u\n", global->stats_period);
3176 #endif /* DEBUG_OPTS */
3177 } else if (equal(name, "OpenFilesLimit")) {
3178 return global_set_open_files_limit(value, *line_num);
3179 } else if (equal(name, "LeafKey")) {
3180 return global_set_leafkey(global, argv0, value);
3181 } else if (equal(name, "LeafKeyRSABits")) {
3182 unsigned int i = atoi(value);
3183 if (i == 1024 || i == 2048 || i == 3072 || i == 4096) {
3184 global->leafkey_rsabits = i;
3185 } else {
3186 fprintf(stderr, "Invalid LeafKeyRSABits %s on line %d, use 1024|2048|3072|4096\n", value, *line_num);
3187 return -1;
3188 }
3189 #ifdef DEBUG_OPTS
3190 log_dbg_printf("LeafKeyRSABits: %u\n", global->leafkey_rsabits);
3191 #endif /* DEBUG_OPTS */
3192 #ifndef OPENSSL_NO_ENGINE
3193 } else if (equal(name, "OpenSSLEngine")) {
3194 return global_set_openssl_engine(global, argv0, value);
3195 #endif /* !OPENSSL_NO_ENGINE */
3196 } else if (equal(name, "Include")) {
3197 // Prevent infinitely recursive include files
3198 if (tmp_opts->include) {
3199 fprintf(stderr, "Include option not allowed in include files '%s' on line %d\n", value, *line_num);
3200 return -1;
3201 }
3202
3203 tmp_opts->include = 1;
3204 int retval = opts_load_conffile(global, argv0, value, natengine, tmp_opts);
3205 tmp_opts->include = 0;
3206
3207 if (retval == -1) {
3208 fprintf(stderr, "Error in include file '%s' on line %d\n", value, *line_num);
3209 }
3210 return retval;
3211 } else {
3212 return set_option(global->opts, global->conn_opts, argv0, name, value, natengine, f, line_num, tmp_opts);
3213 }
3214 return 0;
3215 }
3216
3217 int
3218 global_set_option(global_t *global, const char *argv0, const char *optarg,
3219 char **natengine, tmp_opts_t *tmp_opts)
3220 {
3221 char *name, *value;
3222 int retval = -1;
3223 char *line = strdup(optarg);
3224 if (!line)
3225 return oom_return(argv0);
3226
3227 /* White spaces possible before option name,
3228 * if the command line option is passed between the quotes */
3229 for (name = line; *name == ' ' || *name == '\t'; name++);
3230
3231 /* Command line option separator is '=' */
3232 retval = get_name_value(name, &value, '=', 0);
3233 if (retval == 0) {
3234 /* Line number param is for conf file, pass 0 for command line options */
3235 unsigned int line_num = 0;
3236 retval = set_global_option(global, argv0, name, value, natengine, &line_num, NULL, tmp_opts);
3237 }
3238
3239 if (line)
3240 free(line);
3241 return retval;
3242 }
3243
3244 static int WUNRES
3245 opts_load_conffile(global_t *global, const char *argv0, char *conffile, char **natengine, tmp_opts_t *tmp_opts)
3246 {
3247 int retval;
3248 unsigned int line_num;
3249 char *line, *name, *value;
3250 size_t line_len;
3251 FILE *f;
3252
3253 #ifdef DEBUG_OPTS
3254 log_dbg_printf("Conf file: %s\n", conffile);
3255 #endif /* DEBUG_OPTS */
3256
3257 f = fopen(conffile, "r");
3258 if (!f) {
3259 fprintf(stderr, "Error opening conf file '%s': %s\n", conffile, strerror(errno));
3260 return -1;
3261 }
3262
3263 line = NULL;
3264 line_num = 0;
3265 retval = -1;
3266 while (!feof(f)) {
3267 if (getline(&line, &line_len, f) == -1) {
3268 break;
3269 }
3270 if (line == NULL) {
3271 fprintf(stderr, "Error in conf file: getline() returns NULL line after line %d\n", line_num);
3272 goto leave;
3273 }
3274 line_num++;
3275
3276 /* Skip white space */
3277 for (name = line; *name == ' ' || *name == '\t'; name++);
3278
3279 /* Skip comments and empty lines */
3280 if ((name[0] == '\0') || (name[0] == '#') || (name[0] == ';') ||
3281 (name[0] == '\r') || (name[0] == '\n')) {
3282 continue;
3283 }
3284
3285 retval = get_name_value(name, &value, ' ', line_num);
3286 if (retval == 0) {
3287 retval = set_global_option(global, argv0, name, value, natengine, &line_num, f, tmp_opts);
3288 }
3289
3290 if (retval == -1) {
3291 goto leave;
3292 }
3293 free(line);
3294 line = NULL;
3295 }
3296
3297 leave:
3298 fclose(f);
3299 if (line)
3300 free(line);
3301 return retval;
3302 }
3303
3304 int
3305 global_load_conffile(global_t *global, const char *argv0, const char *optarg, char **natengine, tmp_opts_t *tmp_opts)
3306 {
3307 if (global->conffile)
3308 free(global->conffile);
3309 global->conffile = strdup(optarg);
3310 if (!global->conffile)
3311 return oom_return(argv0);
3312 int retval = opts_load_conffile(global, argv0, global->conffile, natengine, tmp_opts);
3313 if (retval == -1)
3314 fprintf(stderr, "Error in conf file '%s'\n", global->conffile);
3315 return retval;
3316 }
3317
3318 /* vim: set noet ft=c: */
3319