1 /*
2  *
3  * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
4  * Copyright (C) 2020 HAProxy Technologies, William Lallemand <wlallemand@haproxy.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  *
11  *
12  * Configuration parsing for SSL.
13  * This file is split in 3 parts:
14  * - global section parsing
15  * - bind keyword parsing
16  * - server keyword parsing
17  *
18  *  Please insert the new keywords at the right place
19  */
20 
21 #define _GNU_SOURCE
22 #include <ctype.h>
23 #include <dirent.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 
34 #include <haproxy/api.h>
35 #include <haproxy/base64.h>
36 #include <haproxy/cfgparse.h>
37 #include <haproxy/listener.h>
38 #include <haproxy/openssl-compat.h>
39 #include <haproxy/ssl_sock.h>
40 
41 
42 /****************** Global Section Parsing ********************************************/
43 
ssl_load_global_issuers_from_path(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)44 static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
45 					      struct proxy *defpx, const char *file, int line,
46 					      char **err)
47 {
48 	char *path;
49 	struct dirent **de_list;
50 	int i, n;
51 	struct stat buf;
52 	char *end;
53 	char fp[MAXPATHLEN+1];
54 
55 	if (too_many_args(1, args, err, NULL))
56 		return -1;
57 
58 	path = args[1];
59 	if (*path == 0 || stat(path, &buf)) {
60 		memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
61 			  err && *err ? *err : "", args[0]);
62 		return -1;
63 	}
64 	if (S_ISDIR(buf.st_mode) == 0) {
65 		memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
66 			  err && *err ? *err : "", args[0], path);
67 		return -1;
68 	}
69 
70 	/* strip trailing slashes, including first one */
71 	for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
72 		*end = 0;
73 	/* path already parsed? */
74 	if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
75 		return 0;
76 	/* overwrite old issuers_chain_path */
77 	free(global_ssl.issuers_chain_path);
78 	global_ssl.issuers_chain_path = strdup(path);
79 	ssl_free_global_issuers();
80 
81 	n = scandir(path, &de_list, 0, alphasort);
82 	if (n < 0) {
83 		memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
84 			  err && *err ? *err : "", args[0], path, strerror(errno));
85 		return -1;
86 	}
87 	for (i = 0; i < n; i++) {
88 		struct dirent *de = de_list[i];
89 		BIO *in = NULL;
90 		char *warn = NULL;
91 
92 		snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
93 		free(de);
94 		if (stat(fp, &buf) != 0) {
95 			ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
96 			goto next;
97 		}
98 		if (!S_ISREG(buf.st_mode))
99 			goto next;
100 
101 		in = BIO_new(BIO_s_file());
102 		if (in == NULL)
103 			goto next;
104 		if (BIO_read_filename(in, fp) <= 0)
105 			goto next;
106 		ssl_load_global_issuer_from_BIO(in, fp, &warn);
107 		if (warn) {
108 			ha_warning("%s", warn);
109 			free(warn);
110 			warn = NULL;
111 		}
112 	next:
113 		if (in)
114 			BIO_free(in);
115 	}
116 	free(de_list);
117 
118 	return 0;
119 }
120 
121 /* parse the "ssl-mode-async" keyword in global section.
122  * Returns <0 on alert, >0 on warning, 0 on success.
123  */
ssl_parse_global_ssl_async(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)124 static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
125                                        struct proxy *defpx, const char *file, int line,
126                                        char **err)
127 {
128 #if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
129 	global_ssl.async = 1;
130 	global.ssl_used_async_engines = nb_engines;
131 	return 0;
132 #else
133 	memprintf(err, "'%s': openssl library does not support async mode", args[0]);
134 	return -1;
135 #endif
136 }
137 
138 #ifndef OPENSSL_NO_ENGINE
139 /* parse the "ssl-engine" keyword in global section.
140  * Returns <0 on alert, >0 on warning, 0 on success.
141  */
ssl_parse_global_ssl_engine(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)142 static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
143                                        struct proxy *defpx, const char *file, int line,
144                                        char **err)
145 {
146 	char *algo;
147 	int ret = -1;
148 
149 	if (*(args[1]) == 0) {
150 		memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
151 		return ret;
152 	}
153 
154 	if (*(args[2]) == 0) {
155 		/* if no list of algorithms is given, it defaults to ALL */
156 		algo = strdup("ALL");
157 		goto add_engine;
158 	}
159 
160 	/* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
161 	if (strcmp(args[2], "algo") != 0) {
162 		memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
163 		return ret;
164 	}
165 
166 	if (*(args[3]) == 0) {
167 		memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
168 		return ret;
169 	}
170 	algo = strdup(args[3]);
171 
172 add_engine:
173 	if (ssl_init_single_engine(args[1], algo)==0) {
174 		openssl_engines_initialized++;
175 		ret = 0;
176 	}
177 	free(algo);
178 	return ret;
179 }
180 #endif
181 
182 /* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
183  * in global section. Returns <0 on alert, >0 on warning, 0 on success.
184  */
ssl_parse_global_ciphers(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)185 static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
186                                     struct proxy *defpx, const char *file, int line,
187                                     char **err)
188 {
189 	char **target;
190 
191 	target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
192 
193 	if (too_many_args(1, args, err, NULL))
194 		return -1;
195 
196 	if (*(args[1]) == 0) {
197 		memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
198 		return -1;
199 	}
200 
201 	free(*target);
202 	*target = strdup(args[1]);
203 	return 0;
204 }
205 
206 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
207 /* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
208  * in global section. Returns <0 on alert, >0 on warning, 0 on success.
209  */
ssl_parse_global_ciphersuites(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)210 static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
211                                     struct proxy *defpx, const char *file, int line,
212                                     char **err)
213 {
214 	char **target;
215 
216 	target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
217 
218 	if (too_many_args(1, args, err, NULL))
219 		return -1;
220 
221 	if (*(args[1]) == 0) {
222 		memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
223 		return -1;
224 	}
225 
226 	free(*target);
227 	*target = strdup(args[1]);
228 	return 0;
229 }
230 #endif
231 
232 #if defined(SSL_CTX_set1_curves_list)
233 /*
234  * parse the "ssl-default-bind-curves" keyword in a global section.
235  * Returns <0 on alert, >0 on warning, 0 on success.
236  */
ssl_parse_global_curves(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)237 static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
238                                    struct proxy *defpx, const char *file, int line,
239 				   char **err)
240 {
241 	char **target;
242 	target = &global_ssl.listen_default_curves;
243 
244 	if (too_many_args(1, args, err, NULL))
245 		return -1;
246 
247 	if (*(args[1]) == 0) {
248 		memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
249 		return -1;
250 	}
251 
252 	free(*target);
253 	*target = strdup(args[1]);
254 	return 0;
255 }
256 #endif
257 /* parse various global tune.ssl settings consisting in positive integers.
258  * Returns <0 on alert, >0 on warning, 0 on success.
259  */
ssl_parse_global_int(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)260 static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
261                                 struct proxy *defpx, const char *file, int line,
262                                 char **err)
263 {
264 	int *target;
265 
266 	if (strcmp(args[0], "tune.ssl.cachesize") == 0)
267 		target = &global.tune.sslcachesize;
268 	else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
269 		target = (int *)&global_ssl.max_record;
270 	else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
271 		target = &global_ssl.ctx_cache;
272 	else if (strcmp(args[0], "maxsslconn") == 0)
273 		target = &global.maxsslconn;
274 	else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
275 		target = &global_ssl.capture_cipherlist;
276 	else {
277 		memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
278 		return -1;
279 	}
280 
281 	if (too_many_args(1, args, err, NULL))
282 		return -1;
283 
284 	if (*(args[1]) == 0) {
285 		memprintf(err, "'%s' expects an integer argument.", args[0]);
286 		return -1;
287 	}
288 
289 	*target = atoi(args[1]);
290 	if (*target < 0) {
291 		memprintf(err, "'%s' expects a positive numeric value.", args[0]);
292 		return -1;
293 	}
294 	return 0;
295 }
296 
ssl_parse_global_capture_cipherlist(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)297 static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
298                                                struct proxy *defpx, const char *file, int line,
299                                                char **err)
300 {
301 	int ret;
302 
303 	ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
304 	if (ret != 0)
305 		return ret;
306 
307 	if (pool_head_ssl_capture) {
308 		memprintf(err, "'%s' is already configured.", args[0]);
309 		return -1;
310 	}
311 
312 	pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
313 	if (!pool_head_ssl_capture) {
314 		memprintf(err, "Out of memory error.");
315 		return -1;
316 	}
317 	return 0;
318 }
319 
320 /* init the SSLKEYLOGFILE pool */
321 #ifdef HAVE_SSL_KEYLOG
ssl_parse_global_keylog(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)322 static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
323                                        struct proxy *defpx, const char *file, int line,
324                                        char **err)
325 {
326 
327 	if (too_many_args(1, args, err, NULL))
328 		return -1;
329 
330 	if (strcmp(args[1], "on") == 0)
331 		global_ssl.keylog = 1;
332 	else if (strcmp(args[1], "off") == 0)
333 		global_ssl.keylog = 0;
334 	else {
335 		memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
336 		return -1;
337 	}
338 
339 	if (pool_head_ssl_keylog) /* already configured */
340 		return 0;
341 
342 	pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
343 	if (!pool_head_ssl_keylog) {
344 		memprintf(err, "Out of memory error.");
345 		return -1;
346 	}
347 
348 	pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
349 	if (!pool_head_ssl_keylog_str) {
350 		memprintf(err, "Out of memory error.");
351 		return -1;
352 	}
353 
354 	return 0;
355 }
356 #else
ssl_parse_global_keylog(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)357 static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
358                                        struct proxy *defpx, const char *file, int line,
359                                        char **err)
360 {
361 	memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
362 	return -1;
363 }
364 #endif
365 
366 /* parse "ssl.force-private-cache".
367  * Returns <0 on alert, >0 on warning, 0 on success.
368  */
ssl_parse_global_private_cache(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)369 static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
370                                           struct proxy *defpx, const char *file, int line,
371                                           char **err)
372 {
373 	if (too_many_args(0, args, err, NULL))
374 		return -1;
375 
376 	global_ssl.private_cache = 1;
377 	return 0;
378 }
379 
380 /* parse "ssl.lifetime".
381  * Returns <0 on alert, >0 on warning, 0 on success.
382  */
ssl_parse_global_lifetime(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)383 static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
384                                      struct proxy *defpx, const char *file, int line,
385                                      char **err)
386 {
387 	const char *res;
388 
389 	if (too_many_args(1, args, err, NULL))
390 		return -1;
391 
392 	if (*(args[1]) == 0) {
393 		memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
394 		return -1;
395 	}
396 
397 	res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
398 	if (res == PARSE_TIME_OVER) {
399 		memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
400 			  args[1], args[0]);
401 		return -1;
402 	}
403 	else if (res == PARSE_TIME_UNDER) {
404 		memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
405 			  args[1], args[0]);
406 		return -1;
407 	}
408 	else if (res) {
409 		memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
410 		return -1;
411 	}
412 	return 0;
413 }
414 
415 #ifndef OPENSSL_NO_DH
416 /* parse "ssl-dh-param-file".
417  * Returns <0 on alert, >0 on warning, 0 on success.
418  */
ssl_parse_global_dh_param_file(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)419 static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
420                                        struct proxy *defpx, const char *file, int line,
421                                        char **err)
422 {
423 	if (too_many_args(1, args, err, NULL))
424 		return -1;
425 
426 	if (*(args[1]) == 0) {
427 		memprintf(err, "'%s' expects a file path as an argument.", args[0]);
428 		return -1;
429 	}
430 
431 	if (ssl_sock_load_global_dh_param_from_file(args[1])) {
432 		memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
433 		return -1;
434 	}
435 	return 0;
436 }
437 
438 /* parse "ssl.default-dh-param".
439  * Returns <0 on alert, >0 on warning, 0 on success.
440  */
ssl_parse_global_default_dh(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)441 static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
442                                        struct proxy *defpx, const char *file, int line,
443                                        char **err)
444 {
445 	if (too_many_args(1, args, err, NULL))
446 		return -1;
447 
448 	if (*(args[1]) == 0) {
449 		memprintf(err, "'%s' expects an integer argument.", args[0]);
450 		return -1;
451 	}
452 
453 	global_ssl.default_dh_param = atoi(args[1]);
454 	if (global_ssl.default_dh_param < 1024) {
455 		memprintf(err, "'%s' expects a value >= 1024.", args[0]);
456 		return -1;
457 	}
458 	return 0;
459 }
460 #endif
461 
462 
463 /*
464  * parse "ssl-load-extra-files".
465  * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
466  */
ssl_parse_global_extra_files(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)467 static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
468                                        struct proxy *defpx, const char *file, int line,
469                                        char **err)
470 {
471 	int i;
472 	int gf = SSL_GF_NONE;
473 
474 	if (*(args[1]) == 0)
475 		goto err_arg;
476 
477 	for (i = 1; *args[i]; i++) {
478 
479 		if (!strcmp("bundle", args[i])) {
480 			gf |= SSL_GF_BUNDLE;
481 
482 		} else if (!strcmp("sctl", args[i])) {
483 			gf |= SSL_GF_SCTL;
484 
485 		} else if (!strcmp("ocsp", args[i])){
486 			gf |= SSL_GF_OCSP;
487 
488 		} else if (!strcmp("issuer", args[i])){
489 			gf |= SSL_GF_OCSP_ISSUER;
490 
491 		} else if (!strcmp("key", args[i])) {
492 			gf |= SSL_GF_KEY;
493 
494 		} else if (!strcmp("none", args[i])) {
495 			if (gf != SSL_GF_NONE)
496 				goto err_alone;
497 			gf = SSL_GF_NONE;
498 			i++;
499 			break;
500 
501 		} else if (!strcmp("all", args[i])) {
502 			if (gf != SSL_GF_NONE)
503 				goto err_alone;
504 			gf = SSL_GF_ALL;
505 			i++;
506 			break;
507 		} else {
508 			goto err_arg;
509 		}
510 	}
511 	/* break from loop but there are still arguments */
512 	if (*args[i])
513 		goto err_alone;
514 
515 	global_ssl.extra_files = gf;
516 
517 	return 0;
518 
519 err_alone:
520 	memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
521 	return -1;
522 
523 err_arg:
524 	memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
525 	return -1;
526 }
527 
528 
529 /* parse 'ssl-load-extra-del-ext */
ssl_parse_global_extra_noext(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)530 static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
531                                        struct proxy *defpx, const char *file, int line,
532                                        char **err)
533 {
534 	global_ssl.extra_files_noext = 1;
535 	return 0;
536 }
537 
538 /***************************** Bind keyword Parsing ********************************************/
539 
540 /* for ca-file and ca-verify-file */
ssl_bind_parse_ca_file_common(char ** args,int cur_arg,char ** ca_file_p,int from_cli,char ** err)541 static int ssl_bind_parse_ca_file_common(char **args, int cur_arg, char **ca_file_p, int from_cli, char **err)
542 {
543 	if (!*args[cur_arg + 1]) {
544 		memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
545 		return ERR_ALERT | ERR_FATAL;
546 	}
547 
548 	if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
549 		memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
550 	else
551 		memprintf(ca_file_p, "%s", args[cur_arg + 1]);
552 
553 	if (!ssl_store_load_locations_file(*ca_file_p, !from_cli)) {
554 		memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
555 		return ERR_ALERT | ERR_FATAL;
556 	}
557 	return 0;
558 }
559 
560 /* parse the "ca-file" bind keyword */
ssl_bind_parse_ca_file(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)561 static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
562 {
563 	return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
564 }
bind_parse_ca_file(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)565 static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
566 {
567 	return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
568 }
569 
570 /* parse the "ca-verify-file" bind keyword */
ssl_bind_parse_ca_verify_file(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)571 static int ssl_bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
572 {
573 	return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
574 }
bind_parse_ca_verify_file(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)575 static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
576 {
577 	return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
578 }
579 
580 /* parse the "ca-sign-file" bind keyword */
bind_parse_ca_sign_file(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)581 static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
582 {
583 	if (!*args[cur_arg + 1]) {
584 		memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
585 		return ERR_ALERT | ERR_FATAL;
586 	}
587 
588 	if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
589 		memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
590 	else
591 		memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
592 
593 	return 0;
594 }
595 
596 /* parse the "ca-sign-pass" bind keyword */
bind_parse_ca_sign_pass(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)597 static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
598 {
599 	if (!*args[cur_arg + 1]) {
600 		memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
601 		return ERR_ALERT | ERR_FATAL;
602 	}
603 	memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
604 	return 0;
605 }
606 
607 /* parse the "ciphers" bind keyword */
ssl_bind_parse_ciphers(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)608 static int ssl_bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
609 {
610 	if (!*args[cur_arg + 1]) {
611 		memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
612 		return ERR_ALERT | ERR_FATAL;
613 	}
614 
615 	free(conf->ciphers);
616 	conf->ciphers = strdup(args[cur_arg + 1]);
617 	return 0;
618 }
bind_parse_ciphers(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)619 static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
620 {
621 	return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
622 }
623 
624 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
625 /* parse the "ciphersuites" bind keyword */
ssl_bind_parse_ciphersuites(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)626 static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
627 {
628 	if (!*args[cur_arg + 1]) {
629 		memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
630 		return ERR_ALERT | ERR_FATAL;
631 	}
632 
633 	free(conf->ciphersuites);
634 	conf->ciphersuites = strdup(args[cur_arg + 1]);
635 	return 0;
636 }
bind_parse_ciphersuites(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)637 static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
638 {
639 	return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
640 }
641 #endif
642 
643 /* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
bind_parse_crt(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)644 static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
645 {
646 	char path[MAXPATHLEN];
647 
648 	if (!*args[cur_arg + 1]) {
649 		memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
650 		return ERR_ALERT | ERR_FATAL;
651 	}
652 
653 	if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
654 		if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
655 			memprintf(err, "'%s' : path too long", args[cur_arg]);
656 			return ERR_ALERT | ERR_FATAL;
657 		}
658 		snprintf(path, sizeof(path), "%s/%s",  global_ssl.crt_base, args[cur_arg + 1]);
659 		return ssl_sock_load_cert(path, conf, err);
660 	}
661 
662 	return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
663 }
664 
665 /* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
bind_parse_crt_list(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)666 static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
667 {
668 	int err_code;
669 
670 	if (!*args[cur_arg + 1]) {
671 		memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
672 		return ERR_ALERT | ERR_FATAL;
673 	}
674 
675 	err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
676 	if (err_code)
677 		memprintf(err, "'%s' : %s", args[cur_arg], *err);
678 
679 	return err_code;
680 }
681 
682 /* parse the "crl-file" bind keyword */
ssl_bind_parse_crl_file(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)683 static int ssl_bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
684 {
685 #ifndef X509_V_FLAG_CRL_CHECK
686 	memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
687 	return ERR_ALERT | ERR_FATAL;
688 #else
689 	if (!*args[cur_arg + 1]) {
690 		memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
691 		return ERR_ALERT | ERR_FATAL;
692 	}
693 
694 	if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
695 		memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
696 	else
697 		memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
698 
699 	if (!ssl_store_load_locations_file(conf->crl_file, !from_cli)) {
700 		memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
701 		return ERR_ALERT | ERR_FATAL;
702 	}
703 	return 0;
704 #endif
705 }
bind_parse_crl_file(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)706 static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
707 {
708 	return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
709 }
710 
711 /* parse the "curves" bind keyword keyword */
ssl_bind_parse_curves(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)712 static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
713 {
714 #if defined(SSL_CTX_set1_curves_list)
715 	if (!*args[cur_arg + 1]) {
716 		memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
717 		return ERR_ALERT | ERR_FATAL;
718 	}
719 	conf->curves = strdup(args[cur_arg + 1]);
720 	return 0;
721 #else
722 	memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
723 	return ERR_ALERT | ERR_FATAL;
724 #endif
725 }
bind_parse_curves(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)726 static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
727 {
728 	return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
729 }
730 
731 /* parse the "ecdhe" bind keyword keyword */
ssl_bind_parse_ecdhe(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)732 static int ssl_bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
733 {
734 #if !defined(SSL_CTX_set_tmp_ecdh)
735 	memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
736 	return ERR_ALERT | ERR_FATAL;
737 #elif defined(OPENSSL_NO_ECDH)
738 	memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
739 	return ERR_ALERT | ERR_FATAL;
740 #else
741 	if (!*args[cur_arg + 1]) {
742 		memprintf(err, "'%s' : missing named curve", args[cur_arg]);
743 		return ERR_ALERT | ERR_FATAL;
744 	}
745 
746 	conf->ecdhe = strdup(args[cur_arg + 1]);
747 
748 	return 0;
749 #endif
750 }
bind_parse_ecdhe(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)751 static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
752 {
753 	return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
754 }
755 
756 /* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
bind_parse_ignore_err(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)757 static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
758 {
759 	int code;
760 	char *p = args[cur_arg + 1];
761 	unsigned long long *ignerr = &conf->crt_ignerr;
762 
763 	if (!*p) {
764 		memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
765 		return ERR_ALERT | ERR_FATAL;
766 	}
767 
768 	if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
769 		ignerr = &conf->ca_ignerr;
770 
771 	if (strcmp(p, "all") == 0) {
772 		*ignerr = ~0ULL;
773 		return 0;
774 	}
775 
776 	while (p) {
777 		code = atoi(p);
778 		if ((code <= 0) || (code > 63)) {
779 			memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
780 			          args[cur_arg], code, args[cur_arg + 1]);
781 			return ERR_ALERT | ERR_FATAL;
782 		}
783 		*ignerr |= 1ULL << code;
784 		p = strchr(p, ',');
785 		if (p)
786 			p++;
787 	}
788 
789 	return 0;
790 }
791 
792 /* parse tls_method_options "no-xxx" and "force-xxx" */
parse_tls_method_options(char * arg,struct tls_version_filter * methods,char ** err)793 static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
794 {
795 	uint16_t v;
796 	char *p;
797 	p = strchr(arg, '-');
798 	if (!p)
799 		goto fail;
800 	p++;
801 	if (!strcmp(p, "sslv3"))
802 		v = CONF_SSLV3;
803 	else if (!strcmp(p, "tlsv10"))
804 		v = CONF_TLSV10;
805 	else if (!strcmp(p, "tlsv11"))
806 		v = CONF_TLSV11;
807 	else if (!strcmp(p, "tlsv12"))
808 		v = CONF_TLSV12;
809 	else if (!strcmp(p, "tlsv13"))
810 		v = CONF_TLSV13;
811 	else
812 		goto fail;
813 	if (!strncmp(arg, "no-", 3))
814 		methods->flags |= methodVersions[v].flag;
815 	else if (!strncmp(arg, "force-", 6))
816 		methods->min = methods->max = v;
817 	else
818 		goto fail;
819 	return 0;
820  fail:
821 	memprintf(err, "'%s' : option not implemented", arg);
822 	return ERR_ALERT | ERR_FATAL;
823 }
824 
bind_parse_tls_method_options(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)825 static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
826 {
827 	return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
828 }
829 
srv_parse_tls_method_options(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)830 static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
831 {
832 	return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
833 }
834 
835 /* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
parse_tls_method_minmax(char ** args,int cur_arg,struct tls_version_filter * methods,char ** err)836 static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
837 {
838 	uint16_t i, v = 0;
839 	char *argv = args[cur_arg + 1];
840 	if (!*argv) {
841 		memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
842 		return ERR_ALERT | ERR_FATAL;
843 	}
844 	for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
845 		if (!strcmp(argv, methodVersions[i].name))
846 			v = i;
847 	if (!v) {
848 		memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
849 		return ERR_ALERT | ERR_FATAL;
850 	}
851 	if (!strcmp("ssl-min-ver", args[cur_arg]))
852 		methods->min = v;
853 	else if (!strcmp("ssl-max-ver", args[cur_arg]))
854 		methods->max = v;
855 	else {
856 		memprintf(err, "'%s' : option not implemented", args[cur_arg]);
857 		return ERR_ALERT | ERR_FATAL;
858 	}
859 	return 0;
860 }
861 
ssl_bind_parse_tls_method_minmax(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)862 static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
863 {
864 	int ret;
865 
866 #if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
867 	ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
868 #endif
869 	ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
870 	if (ret != ERR_NONE)
871 		return ret;
872 
873 	conf->ssl_methods.min = conf->ssl_methods_cfg.min;
874 	conf->ssl_methods.max = conf->ssl_methods_cfg.max;
875 
876 	return ret;
877 }
bind_parse_tls_method_minmax(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)878 static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
879 {
880 	return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
881 }
882 
srv_parse_tls_method_minmax(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)883 static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
884 {
885 	return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
886 }
887 
888 /* parse the "no-tls-tickets" bind keyword */
bind_parse_no_tls_tickets(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)889 static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
890 {
891 	conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
892 	return 0;
893 }
894 
895 /* parse the "allow-0rtt" bind keyword */
ssl_bind_parse_allow_0rtt(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)896 static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
897 {
898 	conf->early_data = 1;
899 	return 0;
900 }
901 
bind_parse_allow_0rtt(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)902 static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
903 {
904 	conf->ssl_conf.early_data = 1;
905 	return 0;
906 }
907 
908 /* parse the "npn" bind keyword */
ssl_bind_parse_npn(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)909 static int ssl_bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
910 {
911 #if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
912 	char *p1, *p2;
913 
914 	if (!*args[cur_arg + 1]) {
915 		memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
916 		return ERR_ALERT | ERR_FATAL;
917 	}
918 
919 	free(conf->npn_str);
920 
921 	/* the NPN string is built as a suite of (<len> <name>)*,
922 	 * so we reuse each comma to store the next <len> and need
923 	 * one more for the end of the string.
924 	 */
925 	conf->npn_len = strlen(args[cur_arg + 1]) + 1;
926 	conf->npn_str = calloc(1, conf->npn_len + 1);
927 	memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
928 
929 	/* replace commas with the name length */
930 	p1 = conf->npn_str;
931 	p2 = p1 + 1;
932 	while (1) {
933 		p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
934 		if (!p2)
935 			p2 = p1 + 1 + strlen(p1 + 1);
936 
937 		if (p2 - (p1 + 1) > 255) {
938 			*p2 = '\0';
939 			memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
940 			return ERR_ALERT | ERR_FATAL;
941 		}
942 
943 		*p1 = p2 - (p1 + 1);
944 		p1 = p2;
945 
946 		if (!*p2)
947 			break;
948 
949 		*(p2++) = '\0';
950 	}
951 	return 0;
952 #else
953 	memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
954 	return ERR_ALERT | ERR_FATAL;
955 #endif
956 }
957 
bind_parse_npn(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)958 static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
959 {
960 	return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
961 }
962 
963 
964 /* Parses a alpn string and converts it to the right format for the SSL api */
ssl_sock_parse_alpn(char * arg,char ** alpn_str,int * alpn_len,char ** err)965 int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
966 {
967 	char *p1, *p2, *alpn = NULL;
968 	int len, ret = 0;
969 
970 	*alpn_str = NULL;
971 	*alpn_len = 0;
972 
973 	if (!*arg) {
974 		memprintf(err, "missing the comma-delimited ALPN protocol suite");
975 		goto error;
976 	}
977 
978 	/* the ALPN string is built as a suite of (<len> <name>)*,
979 	 * so we reuse each comma to store the next <len> and need
980 	 * one more for the end of the string.
981 	 */
982 	len  = strlen(arg) + 1;
983 	alpn = calloc(1, len+1);
984 	if (!alpn) {
985 		memprintf(err, "'%s' : out of memory", arg);
986 		goto error;
987 	}
988 	memcpy(alpn+1, arg, len);
989 
990 	/* replace commas with the name length */
991 	p1 = alpn;
992 	p2 = p1 + 1;
993 	while (1) {
994 		p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
995 		if (!p2)
996 			p2 = p1 + 1 + strlen(p1 + 1);
997 
998 		if (p2 - (p1 + 1) > 255) {
999 			*p2 = '\0';
1000 			memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1001 			goto error;
1002 		}
1003 
1004 		*p1 = p2 - (p1 + 1);
1005 		p1 = p2;
1006 
1007 		if (!*p2)
1008 			break;
1009 
1010 		*(p2++) = '\0';
1011 	}
1012 
1013 	*alpn_str = alpn;
1014 	*alpn_len = len;
1015 
1016   out:
1017 	return ret;
1018 
1019   error:
1020 	free(alpn);
1021 	ret = ERR_ALERT | ERR_FATAL;
1022 	goto out;
1023 }
1024 
1025 /* parse the "alpn" bind keyword */
ssl_bind_parse_alpn(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)1026 static int ssl_bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
1027 {
1028 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1029 	int ret;
1030 
1031 	free(conf->alpn_str);
1032 
1033 	ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1034 	if (ret)
1035 		memprintf(err, "'%s' : %s", args[cur_arg], *err);
1036 	return ret;
1037 #else
1038 	memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1039 	return ERR_ALERT | ERR_FATAL;
1040 #endif
1041 }
1042 
bind_parse_alpn(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1043 static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1044 {
1045 	return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
1046 }
1047 
1048 /* parse the "ssl" bind keyword */
bind_parse_ssl(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1049 static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1050 {
1051 	conf->xprt = &ssl_sock;
1052 	conf->is_ssl = 1;
1053 
1054 	if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1055 		conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
1056 #if defined(SSL_CTX_set1_curves_list)
1057 	if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1058 		conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1059 #endif
1060 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1061 	if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1062 		conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1063 #endif
1064 	conf->ssl_options |= global_ssl.listen_default_ssloptions;
1065 	conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1066 	if (!conf->ssl_conf.ssl_methods.min)
1067 		conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1068 	if (!conf->ssl_conf.ssl_methods.max)
1069 		conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1070 
1071 	return 0;
1072 }
1073 
1074 /* parse the "prefer-client-ciphers" bind keyword */
bind_parse_pcc(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1075 static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1076 {
1077         conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1078         return 0;
1079 }
1080 
1081 /* parse the "generate-certificates" bind keyword */
bind_parse_generate_certs(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1082 static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1083 {
1084 #if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1085 	conf->generate_certs = 1;
1086 #else
1087 	memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1088 		  err && *err ? *err : "");
1089 #endif
1090 	return 0;
1091 }
1092 
1093 /* parse the "strict-sni" bind keyword */
bind_parse_strict_sni(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1094 static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1095 {
1096 	conf->strict_sni = 1;
1097 	return 0;
1098 }
1099 
1100 /* parse the "tls-ticket-keys" bind keyword */
bind_parse_tls_ticket_keys(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1101 static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1102 {
1103 #if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1104 	FILE *f = NULL;
1105 	int i = 0;
1106 	char thisline[LINESIZE];
1107 	struct tls_keys_ref *keys_ref = NULL;
1108 
1109 	if (!*args[cur_arg + 1]) {
1110 		memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1111 		goto fail;
1112 	}
1113 
1114 	keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1115 	if (keys_ref) {
1116 		keys_ref->refcount++;
1117 		conf->keys_ref = keys_ref;
1118 		return 0;
1119 	}
1120 
1121 	keys_ref = calloc(1, sizeof(*keys_ref));
1122 	if (!keys_ref) {
1123 		memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1124 		goto fail;
1125 	}
1126 
1127 	keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1128 	if (!keys_ref->tlskeys) {
1129 		memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1130 		goto fail;
1131 	}
1132 
1133 	if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1134 		memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1135 		goto fail;
1136 	}
1137 
1138 	keys_ref->filename = strdup(args[cur_arg + 1]);
1139 	if (!keys_ref->filename) {
1140 		memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1141 		goto fail;
1142 	}
1143 
1144 	keys_ref->key_size_bits = 0;
1145 	while (fgets(thisline, sizeof(thisline), f) != NULL) {
1146 		int len = strlen(thisline);
1147 		int dec_size;
1148 
1149 		/* Strip newline characters from the end */
1150 		if(thisline[len - 1] == '\n')
1151 			thisline[--len] = 0;
1152 
1153 		if(thisline[len - 1] == '\r')
1154 			thisline[--len] = 0;
1155 
1156 		dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1157 		if (dec_size < 0) {
1158 			memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1159 			goto fail;
1160 		}
1161 		else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1162 			keys_ref->key_size_bits = 128;
1163 		}
1164 		else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1165 			keys_ref->key_size_bits = 256;
1166 		}
1167 		else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1168 			 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1169 			 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1170 			memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1171 			goto fail;
1172 		}
1173 		i++;
1174 	}
1175 
1176 	if (i < TLS_TICKETS_NO) {
1177 		memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1178 		goto fail;
1179 	}
1180 
1181 	fclose(f);
1182 
1183 	/* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1184 	i -= 2;
1185 	keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1186 	keys_ref->unique_id = -1;
1187 	keys_ref->refcount = 1;
1188 	HA_RWLOCK_INIT(&keys_ref->lock);
1189 	conf->keys_ref = keys_ref;
1190 
1191 	LIST_ADD(&tlskeys_reference, &keys_ref->list);
1192 
1193 	return 0;
1194 
1195   fail:
1196 	if (f)
1197 		fclose(f);
1198 	if (keys_ref) {
1199 		free(keys_ref->filename);
1200 		free(keys_ref->tlskeys);
1201 		free(keys_ref);
1202 	}
1203 	return ERR_ALERT | ERR_FATAL;
1204 
1205 #else
1206 	memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1207 	return ERR_ALERT | ERR_FATAL;
1208 #endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1209 }
1210 
1211 /* parse the "verify" bind keyword */
ssl_bind_parse_verify(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)1212 static int ssl_bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
1213 {
1214 	if (!*args[cur_arg + 1]) {
1215 		memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1216 		return ERR_ALERT | ERR_FATAL;
1217 	}
1218 
1219 	if (strcmp(args[cur_arg + 1], "none") == 0)
1220 		conf->verify = SSL_SOCK_VERIFY_NONE;
1221 	else if (strcmp(args[cur_arg + 1], "optional") == 0)
1222 		conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1223 	else if (strcmp(args[cur_arg + 1], "required") == 0)
1224 		conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1225 	else {
1226 		memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1227 		          args[cur_arg], args[cur_arg + 1]);
1228 		return ERR_ALERT | ERR_FATAL;
1229 	}
1230 
1231 	return 0;
1232 }
bind_parse_verify(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1233 static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1234 {
1235 	return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
1236 }
1237 
1238 /* parse the "no-ca-names" bind keyword */
ssl_bind_parse_no_ca_names(char ** args,int cur_arg,struct proxy * px,struct ssl_bind_conf * conf,int from_cli,char ** err)1239 static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
1240 {
1241 	conf->no_ca_names = 1;
1242 	return 0;
1243 }
bind_parse_no_ca_names(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1244 static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1245 {
1246 	return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
1247 }
1248 
1249 /***************************** "server" keywords Parsing ********************************************/
1250 
1251 /* parse the "npn" bind keyword */
srv_parse_npn(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1252 static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1253 {
1254 #if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1255 	char *p1, *p2;
1256 
1257 	if (!*args[*cur_arg + 1]) {
1258 		memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1259 		return ERR_ALERT | ERR_FATAL;
1260 	}
1261 
1262 	free(newsrv->ssl_ctx.npn_str);
1263 
1264 	/* the NPN string is built as a suite of (<len> <name>)*,
1265 	 * so we reuse each comma to store the next <len> and need
1266 	 * one more for the end of the string.
1267 	 */
1268 	newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1269 	newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
1270 	memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1271 	    newsrv->ssl_ctx.npn_len);
1272 
1273 	/* replace commas with the name length */
1274 	p1 = newsrv->ssl_ctx.npn_str;
1275 	p2 = p1 + 1;
1276 	while (1) {
1277 		p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1278 		    newsrv->ssl_ctx.npn_len - (p1 + 1));
1279 		if (!p2)
1280 			p2 = p1 + 1 + strlen(p1 + 1);
1281 
1282 		if (p2 - (p1 + 1) > 255) {
1283 			*p2 = '\0';
1284 			memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1285 			return ERR_ALERT | ERR_FATAL;
1286 		}
1287 
1288 		*p1 = p2 - (p1 + 1);
1289 		p1 = p2;
1290 
1291 		if (!*p2)
1292 			break;
1293 
1294 		*(p2++) = '\0';
1295 	}
1296 	return 0;
1297 #else
1298 	memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1299 	return ERR_ALERT | ERR_FATAL;
1300 #endif
1301 }
1302 
1303 /* parse the "alpn" or the "check-alpn" server keyword */
srv_parse_alpn(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1304 static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1305 {
1306 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1307 	char **alpn_str;
1308 	int *alpn_len;
1309 	int ret;
1310 
1311 	if (*args[*cur_arg] == 'c') {
1312 		alpn_str = &newsrv->check.alpn_str;
1313 		alpn_len = &newsrv->check.alpn_len;
1314 	} else {
1315 		alpn_str = &newsrv->ssl_ctx.alpn_str;
1316 		alpn_len = &newsrv->ssl_ctx.alpn_len;
1317 
1318 	}
1319 
1320 	free(*alpn_str);
1321 	ret = ssl_sock_parse_alpn(args[*cur_arg + 1], alpn_str, alpn_len, err);
1322 	if (ret)
1323 		memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1324 	return ret;
1325 #else
1326 	memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1327 	return ERR_ALERT | ERR_FATAL;
1328 #endif
1329 }
1330 
1331 /* parse the "ca-file" server keyword */
srv_parse_ca_file(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1332 static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1333 {
1334 	if (!*args[*cur_arg + 1]) {
1335 		memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1336 		return ERR_ALERT | ERR_FATAL;
1337 	}
1338 
1339 	if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1340 		memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1341 	else
1342 		memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1343 
1344 	if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, 1)) {
1345 		memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1346 		return ERR_ALERT | ERR_FATAL;
1347 	}
1348 	return 0;
1349 }
1350 
1351 /* parse the "check-sni" server keyword */
srv_parse_check_sni(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1352 static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1353 {
1354 	if (!*args[*cur_arg + 1]) {
1355 		memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1356 		return ERR_ALERT | ERR_FATAL;
1357 	}
1358 
1359 	newsrv->check.sni = strdup(args[*cur_arg + 1]);
1360 	if (!newsrv->check.sni) {
1361 		memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1362 		return ERR_ALERT | ERR_FATAL;
1363 	}
1364 	return 0;
1365 
1366 }
1367 
1368 /* parse the "check-ssl" server keyword */
srv_parse_check_ssl(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1369 static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1370 {
1371 	newsrv->check.use_ssl = 1;
1372 	if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
1373 		newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
1374 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1375 	if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
1376 		newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
1377 #endif
1378 	newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1379 	newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1380 	if (!newsrv->ssl_ctx.methods.min)
1381 		newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
1382 	if (!newsrv->ssl_ctx.methods.max)
1383 		newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
1384 
1385 	return 0;
1386 }
1387 
1388 /* parse the "ciphers" server keyword */
srv_parse_ciphers(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1389 static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1390 {
1391 	if (!*args[*cur_arg + 1]) {
1392 		memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1393 		return ERR_ALERT | ERR_FATAL;
1394 	}
1395 
1396 	free(newsrv->ssl_ctx.ciphers);
1397 	newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
1398 	return 0;
1399 }
1400 
1401 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1402 /* parse the "ciphersuites" server keyword */
srv_parse_ciphersuites(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1403 static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1404 {
1405 	if (!*args[*cur_arg + 1]) {
1406 		memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1407 		return ERR_ALERT | ERR_FATAL;
1408 	}
1409 
1410 	free(newsrv->ssl_ctx.ciphersuites);
1411 	newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
1412 	return 0;
1413 }
1414 #endif
1415 
1416 /* parse the "crl-file" server keyword */
srv_parse_crl_file(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1417 static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1418 {
1419 #ifndef X509_V_FLAG_CRL_CHECK
1420 	memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1421 	return ERR_ALERT | ERR_FATAL;
1422 #else
1423 	if (!*args[*cur_arg + 1]) {
1424 		memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1425 		return ERR_ALERT | ERR_FATAL;
1426 	}
1427 
1428 	if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1429 		memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1430 	else
1431 		memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1432 
1433 	if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, 1)) {
1434 		memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1435 		return ERR_ALERT | ERR_FATAL;
1436 	}
1437 	return 0;
1438 #endif
1439 }
1440 
1441 /* parse the "crt" server keyword */
srv_parse_crt(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1442 static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1443 {
1444 	if (!*args[*cur_arg + 1]) {
1445 		memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1446 		return ERR_ALERT | ERR_FATAL;
1447 	}
1448 
1449 	if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
1450 		memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
1451 	else
1452 		memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
1453 
1454 	return 0;
1455 }
1456 
1457 /* parse the "no-check-ssl" server keyword */
srv_parse_no_check_ssl(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1458 static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1459 {
1460 	newsrv->check.use_ssl = -1;
1461 	free(newsrv->ssl_ctx.ciphers);
1462 	newsrv->ssl_ctx.ciphers = NULL;
1463 	newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1464 	return 0;
1465 }
1466 
1467 /* parse the "no-send-proxy-v2-ssl" server keyword */
srv_parse_no_send_proxy_ssl(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1468 static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1469 {
1470 	newsrv->pp_opts &= ~SRV_PP_V2;
1471 	newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1472 	return 0;
1473 }
1474 
1475 /* parse the "no-send-proxy-v2-ssl-cn" server keyword */
srv_parse_no_send_proxy_cn(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1476 static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1477 {
1478 	newsrv->pp_opts &= ~SRV_PP_V2;
1479 	newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1480 	newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1481 	return 0;
1482 }
1483 
1484 /* parse the "no-ssl" server keyword */
srv_parse_no_ssl(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1485 static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1486 {
1487 	newsrv->use_ssl = -1;
1488 	free(newsrv->ssl_ctx.ciphers);
1489 	newsrv->ssl_ctx.ciphers = NULL;
1490 	return 0;
1491 }
1492 
1493 /* parse the "allow-0rtt" server keyword */
srv_parse_allow_0rtt(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1494 static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1495 {
1496 	newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1497 	return 0;
1498 }
1499 
1500 /* parse the "no-ssl-reuse" server keyword */
srv_parse_no_ssl_reuse(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1501 static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1502 {
1503 	newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1504 	return 0;
1505 }
1506 
1507 /* parse the "no-tls-tickets" server keyword */
srv_parse_no_tls_tickets(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1508 static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1509 {
1510 	newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1511 	return 0;
1512 }
1513 /* parse the "send-proxy-v2-ssl" server keyword */
srv_parse_send_proxy_ssl(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1514 static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1515 {
1516 	newsrv->pp_opts |= SRV_PP_V2;
1517 	newsrv->pp_opts |= SRV_PP_V2_SSL;
1518 	return 0;
1519 }
1520 
1521 /* parse the "send-proxy-v2-ssl-cn" server keyword */
srv_parse_send_proxy_cn(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1522 static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1523 {
1524 	newsrv->pp_opts |= SRV_PP_V2;
1525 	newsrv->pp_opts |= SRV_PP_V2_SSL;
1526 	newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1527 	return 0;
1528 }
1529 
1530 /* parse the "sni" server keyword */
srv_parse_sni(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1531 static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1532 {
1533 #ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1534 	memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1535 	return ERR_ALERT | ERR_FATAL;
1536 #else
1537 	char *arg;
1538 
1539 	arg = args[*cur_arg + 1];
1540 	if (!*arg) {
1541 		memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1542 		return ERR_ALERT | ERR_FATAL;
1543 	}
1544 
1545 	free(newsrv->sni_expr);
1546 	newsrv->sni_expr = strdup(arg);
1547 
1548 	return 0;
1549 #endif
1550 }
1551 
1552 /* parse the "ssl" server keyword */
srv_parse_ssl(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1553 static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1554 {
1555 	newsrv->use_ssl = 1;
1556 	if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
1557 		newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
1558 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1559 	if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
1560 		newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
1561 #endif
1562 	newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1563 	newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1564 
1565 	if (!newsrv->ssl_ctx.methods.min)
1566 		newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
1567 
1568 	if (!newsrv->ssl_ctx.methods.max)
1569 		newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
1570 
1571 
1572 	return 0;
1573 }
1574 
1575 /* parse the "ssl-reuse" server keyword */
srv_parse_ssl_reuse(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1576 static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1577 {
1578 	newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1579 	return 0;
1580 }
1581 
1582 /* parse the "tls-tickets" server keyword */
srv_parse_tls_tickets(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1583 static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1584 {
1585 	newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1586 	return 0;
1587 }
1588 
1589 /* parse the "verify" server keyword */
srv_parse_verify(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1590 static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1591 {
1592 	if (!*args[*cur_arg + 1]) {
1593 		memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1594 		return ERR_ALERT | ERR_FATAL;
1595 	}
1596 
1597 	if (strcmp(args[*cur_arg + 1], "none") == 0)
1598 		newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1599 	else if (strcmp(args[*cur_arg + 1], "required") == 0)
1600 		newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1601 	else {
1602 		memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1603 		          args[*cur_arg], args[*cur_arg + 1]);
1604 		return ERR_ALERT | ERR_FATAL;
1605 	}
1606 
1607 	return 0;
1608 }
1609 
1610 /* parse the "verifyhost" server keyword */
srv_parse_verifyhost(char ** args,int * cur_arg,struct proxy * px,struct server * newsrv,char ** err)1611 static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1612 {
1613 	if (!*args[*cur_arg + 1]) {
1614 		memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1615 		return ERR_ALERT | ERR_FATAL;
1616 	}
1617 
1618 	free(newsrv->ssl_ctx.verify_host);
1619 	newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1620 
1621 	return 0;
1622 }
1623 
1624 /* parse the "ssl-default-bind-options" keyword in global section */
ssl_parse_default_bind_options(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)1625 static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
1626                                           struct proxy *defpx, const char *file, int line,
1627                                           char **err) {
1628 	int i = 1;
1629 
1630 	if (*(args[i]) == 0) {
1631 		memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1632 		return -1;
1633 	}
1634 	while (*(args[i])) {
1635 		if (!strcmp(args[i], "no-tls-tickets"))
1636 			global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
1637 		else if (!strcmp(args[i], "prefer-client-ciphers"))
1638 			global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
1639 		else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
1640 			if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1641 				i++;
1642 			else {
1643 				memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1644 				return -1;
1645 			}
1646 		}
1647 		else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1648 			memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1649 			return -1;
1650 		}
1651 		i++;
1652 	}
1653 	return 0;
1654 }
1655 
1656 /* parse the "ssl-default-server-options" keyword in global section */
ssl_parse_default_server_options(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)1657 static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
1658                                             struct proxy *defpx, const char *file, int line,
1659                                             char **err) {
1660 	int i = 1;
1661 
1662 	if (*(args[i]) == 0) {
1663 		memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1664 		return -1;
1665 	}
1666 	while (*(args[i])) {
1667 		if (!strcmp(args[i], "no-tls-tickets"))
1668 			global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
1669 		else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
1670 			if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1671 				i++;
1672 			else {
1673 				memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1674 				return -1;
1675 			}
1676 		}
1677 		else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1678 			memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1679 			return -1;
1680 		}
1681 		i++;
1682 	}
1683 	return 0;
1684 }
1685 
1686 /* parse the "ca-base" / "crt-base" keywords in global section.
1687  * Returns <0 on alert, >0 on warning, 0 on success.
1688  */
ssl_parse_global_ca_crt_base(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)1689 static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
1690                                         struct proxy *defpx, const char *file, int line,
1691                                         char **err)
1692 {
1693 	char **target;
1694 
1695 	target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1696 
1697 	if (too_many_args(1, args, err, NULL))
1698 		return -1;
1699 
1700 	if (*target) {
1701 		memprintf(err, "'%s' already specified.", args[0]);
1702 		return -1;
1703 	}
1704 
1705 	if (*(args[1]) == 0) {
1706 		memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1707 		return -1;
1708 	}
1709 	*target = strdup(args[1]);
1710 	return 0;
1711 }
1712 
1713 /* parse the "ssl-skip-self-issued-ca" keyword in global section.  */
ssl_parse_skip_self_issued_ca(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)1714 static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
1715 					 struct proxy *defpx, const char *file, int line,
1716 					 char **err)
1717 {
1718 #ifdef SSL_CTX_build_cert_chain
1719 	global_ssl.skip_self_issued_ca = 1;
1720 	return 0;
1721 #else
1722 	memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1723 	return -1;
1724 #endif
1725 }
1726 
1727 
1728 
1729 
1730 
1731 /* Note: must not be declared <const> as its list will be overwritten.
1732  * Please take care of keeping this list alphabetically sorted, doing so helps
1733  * all code contributors.
1734  * Optional keywords are also declared with a NULL ->parse() function so that
1735  * the config parser can report an appropriate error when a known keyword was
1736  * not enabled.
1737  */
1738 
1739 /* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1740  * with their proxy argument NULL and must only fill the ssl_bind_conf */
1741 struct ssl_bind_kw ssl_bind_kws[] = {
1742 	{ "allow-0rtt",            ssl_bind_parse_allow_0rtt,       0 }, /* allow 0-RTT */
1743 	{ "alpn",                  ssl_bind_parse_alpn,             1 }, /* set ALPN supported protocols */
1744 	{ "ca-file",               ssl_bind_parse_ca_file,          1 }, /* set CAfile to process ca-names and verify on client cert */
1745 	{ "ca-verify-file",        ssl_bind_parse_ca_verify_file,   1 }, /* set CAverify file to process verify on client cert */
1746 	{ "ciphers",               ssl_bind_parse_ciphers,          1 }, /* set SSL cipher suite */
1747 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1748 	{ "ciphersuites",          ssl_bind_parse_ciphersuites,     1 }, /* set TLS 1.3 cipher suite */
1749 #endif
1750 	{ "crl-file",              ssl_bind_parse_crl_file,         1 }, /* set certificate revocation list file use on client cert verify */
1751 	{ "curves",                ssl_bind_parse_curves,           1 }, /* set SSL curve suite */
1752 	{ "ecdhe",                 ssl_bind_parse_ecdhe,            1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1753 	{ "no-ca-names",           ssl_bind_parse_no_ca_names,      0 }, /* do not send ca names to clients (ca_file related) */
1754 	{ "npn",                   ssl_bind_parse_npn,              1 }, /* set NPN supported protocols */
1755 	{ "ssl-min-ver",           ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1756 	{ "ssl-max-ver",           ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1757 	{ "verify",                ssl_bind_parse_verify,           1 }, /* set SSL verify method */
1758 	{ NULL, NULL, 0 },
1759 };
1760 
1761 /* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1762 
1763 static struct bind_kw_list bind_kws = { "SSL", { }, {
1764 	{ "allow-0rtt",            bind_parse_allow_0rtt,         0 }, /* Allow 0RTT */
1765 	{ "alpn",                  bind_parse_alpn,               1 }, /* set ALPN supported protocols */
1766 	{ "ca-file",               bind_parse_ca_file,            1 }, /* set CAfile to process ca-names and verify on client cert */
1767 	{ "ca-verify-file",        bind_parse_ca_verify_file,     1 }, /* set CAverify file to process verify on client cert */
1768 	{ "ca-ignore-err",         bind_parse_ignore_err,         1 }, /* set error IDs to ignore on verify depth > 0 */
1769 	{ "ca-sign-file",          bind_parse_ca_sign_file,       1 }, /* set CAFile used to generate and sign server certs */
1770 	{ "ca-sign-pass",          bind_parse_ca_sign_pass,       1 }, /* set CAKey passphrase */
1771 	{ "ciphers",               bind_parse_ciphers,            1 }, /* set SSL cipher suite */
1772 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1773 	{ "ciphersuites",          bind_parse_ciphersuites,       1 }, /* set TLS 1.3 cipher suite */
1774 #endif
1775 	{ "crl-file",              bind_parse_crl_file,           1 }, /* set certificate revocation list file use on client cert verify */
1776 	{ "crt",                   bind_parse_crt,                1 }, /* load SSL certificates from this location */
1777 	{ "crt-ignore-err",        bind_parse_ignore_err,         1 }, /* set error IDs to ignore on verify depth == 0 */
1778 	{ "crt-list",              bind_parse_crt_list,           1 }, /* load a list of crt from this location */
1779 	{ "curves",                bind_parse_curves,             1 }, /* set SSL curve suite */
1780 	{ "ecdhe",                 bind_parse_ecdhe,              1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1781 	{ "force-sslv3",           bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1782 	{ "force-tlsv10",          bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1783 	{ "force-tlsv11",          bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1784 	{ "force-tlsv12",          bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1785 	{ "force-tlsv13",          bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1786 	{ "generate-certificates", bind_parse_generate_certs,     0 }, /* enable the server certificates generation */
1787 	{ "no-ca-names",           bind_parse_no_ca_names,        0 }, /* do not send ca names to clients (ca_file related) */
1788 	{ "no-sslv3",              bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1789 	{ "no-tlsv10",             bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1790 	{ "no-tlsv11",             bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1791 	{ "no-tlsv12",             bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1792 	{ "no-tlsv13",             bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1793 	{ "no-tls-tickets",        bind_parse_no_tls_tickets,     0 }, /* disable session resumption tickets */
1794 	{ "ssl",                   bind_parse_ssl,                0 }, /* enable SSL processing */
1795 	{ "ssl-min-ver",           bind_parse_tls_method_minmax,  1 }, /* minimum version */
1796 	{ "ssl-max-ver",           bind_parse_tls_method_minmax,  1 }, /* maximum version */
1797 	{ "strict-sni",            bind_parse_strict_sni,         0 }, /* refuse negotiation if sni doesn't match a certificate */
1798 	{ "tls-ticket-keys",       bind_parse_tls_ticket_keys,    1 }, /* set file to load TLS ticket keys from */
1799 	{ "verify",                bind_parse_verify,             1 }, /* set SSL verify method */
1800 	{ "npn",                   bind_parse_npn,                1 }, /* set NPN supported protocols */
1801 	{ "prefer-client-ciphers", bind_parse_pcc,                0 }, /* prefer client ciphers */
1802 	{ NULL, NULL, 0 },
1803 }};
1804 
1805 INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1806 
1807 /* Note: must not be declared <const> as its list will be overwritten.
1808  * Please take care of keeping this list alphabetically sorted, doing so helps
1809  * all code contributors.
1810  * Optional keywords are also declared with a NULL ->parse() function so that
1811  * the config parser can report an appropriate error when a known keyword was
1812  * not enabled.
1813  */
1814 static struct srv_kw_list srv_kws = { "SSL", { }, {
1815 	{ "allow-0rtt",              srv_parse_allow_0rtt,         0, 1 }, /* Allow using early data on this server */
1816 	{ "alpn",                    srv_parse_alpn,               1, 1 }, /* Set ALPN supported protocols */
1817 	{ "ca-file",                 srv_parse_ca_file,            1, 1 }, /* set CAfile to process verify server cert */
1818 	{ "check-alpn",              srv_parse_alpn,               1, 1 }, /* Set ALPN used for checks */
1819 	{ "check-sni",               srv_parse_check_sni,          1, 1 }, /* set SNI */
1820 	{ "check-ssl",               srv_parse_check_ssl,          0, 1 }, /* enable SSL for health checks */
1821 	{ "ciphers",                 srv_parse_ciphers,            1, 1 }, /* select the cipher suite */
1822 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1823 	{ "ciphersuites",            srv_parse_ciphersuites,       1, 1 }, /* select the cipher suite */
1824 #endif
1825 	{ "crl-file",                srv_parse_crl_file,           1, 1 }, /* set certificate revocation list file use on server cert verify */
1826 	{ "crt",                     srv_parse_crt,                1, 1 }, /* set client certificate */
1827 	{ "force-sslv3",             srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
1828 	{ "force-tlsv10",            srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
1829 	{ "force-tlsv11",            srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
1830 	{ "force-tlsv12",            srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
1831 	{ "force-tlsv13",            srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
1832 	{ "no-check-ssl",            srv_parse_no_check_ssl,       0, 1 }, /* disable SSL for health checks */
1833 	{ "no-send-proxy-v2-ssl",    srv_parse_no_send_proxy_ssl,  0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
1834 	{ "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn,   0, 1 }, /* do not send PROXY protocol header v2 with CN */
1835 	{ "no-ssl",                  srv_parse_no_ssl,             0, 1 }, /* disable SSL processing */
1836 	{ "no-ssl-reuse",            srv_parse_no_ssl_reuse,       0, 1 }, /* disable session reuse */
1837 	{ "no-sslv3",                srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
1838 	{ "no-tlsv10",               srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
1839 	{ "no-tlsv11",               srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
1840 	{ "no-tlsv12",               srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
1841 	{ "no-tlsv13",               srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
1842 	{ "no-tls-tickets",          srv_parse_no_tls_tickets,     0, 1 }, /* disable session resumption tickets */
1843 	{ "npn",                     srv_parse_npn,                1, 1 }, /* Set NPN supported protocols */
1844 	{ "send-proxy-v2-ssl",       srv_parse_send_proxy_ssl,     0, 1 }, /* send PROXY protocol header v2 with SSL info */
1845 	{ "send-proxy-v2-ssl-cn",    srv_parse_send_proxy_cn,      0, 1 }, /* send PROXY protocol header v2 with CN */
1846 	{ "sni",                     srv_parse_sni,                1, 1 }, /* send SNI extension */
1847 	{ "ssl",                     srv_parse_ssl,                0, 1 }, /* enable SSL processing */
1848 	{ "ssl-min-ver",             srv_parse_tls_method_minmax,  1, 1 }, /* minimum version */
1849 	{ "ssl-max-ver",             srv_parse_tls_method_minmax,  1, 1 }, /* maximum version */
1850 	{ "ssl-reuse",               srv_parse_ssl_reuse,          0, 1 }, /* enable session reuse */
1851 	{ "tls-tickets",             srv_parse_tls_tickets,        0, 1 }, /* enable session resumption tickets */
1852 	{ "verify",                  srv_parse_verify,             1, 1 }, /* set SSL verify method */
1853 	{ "verifyhost",              srv_parse_verifyhost,         1, 1 }, /* require that SSL cert verifies for hostname */
1854 	{ NULL, NULL, 0, 0 },
1855 }};
1856 
1857 INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1858 
1859 static struct cfg_kw_list cfg_kws = {ILH, {
1860 	{ CFG_GLOBAL, "ca-base",  ssl_parse_global_ca_crt_base },
1861 	{ CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1862 	{ CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1863 	{ CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1864 	{ CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1865 	{ CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1866 #ifndef OPENSSL_NO_DH
1867 	{ CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1868 #endif
1869 	{ CFG_GLOBAL, "ssl-mode-async",  ssl_parse_global_ssl_async },
1870 #ifndef OPENSSL_NO_ENGINE
1871 	{ CFG_GLOBAL, "ssl-engine",  ssl_parse_global_ssl_engine },
1872 #endif
1873 	{ CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1874 	{ CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1875 #ifndef OPENSSL_NO_DH
1876 	{ CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1877 #endif
1878 	{ CFG_GLOBAL, "tune.ssl.force-private-cache",  ssl_parse_global_private_cache },
1879 	{ CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1880 	{ CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
1881 	{ CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
1882 	{ CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
1883 	{ CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
1884 	{ CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1885 	{ CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
1886 #if defined(SSL_CTX_set1_curves_list)
1887 	{ CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
1888 #endif
1889 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1890 	{ CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
1891 	{ CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
1892 #endif
1893 	{ CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
1894 	{ CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
1895 	{ 0, NULL, NULL },
1896 }};
1897 
1898 INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
1899