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