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