blob: 654b0204123f351595a4215f288c07db4ca7d2db [file] [log] [blame]
William Lallemanddad31052020-05-14 17:47:32 +02001/*
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
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020034#include <haproxy/api.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020035#include <haproxy/base64.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020036#include <haproxy/cfgparse.h>
Willy Tarreau213e9902020-06-04 14:58:24 +020037#include <haproxy/listener.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +020038#include <haproxy/openssl-compat.h>
Willy Tarreau209108d2020-06-04 20:30:20 +020039#include <haproxy/ssl_sock.h>
Willy Tarreaucc81eca2021-05-08 12:54:42 +020040#include <haproxy/tools.h>
William Lallemanddad31052020-05-14 17:47:32 +020041
42
43/****************** Global Section Parsing ********************************************/
44
45static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +010046 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +020047 char **err)
48{
49 char *path;
50 struct dirent **de_list;
51 int i, n;
52 struct stat buf;
53 char *end;
54 char fp[MAXPATHLEN+1];
55
56 if (too_many_args(1, args, err, NULL))
57 return -1;
58
59 path = args[1];
60 if (*path == 0 || stat(path, &buf)) {
61 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
62 err && *err ? *err : "", args[0]);
63 return -1;
64 }
65 if (S_ISDIR(buf.st_mode) == 0) {
66 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
67 err && *err ? *err : "", args[0], path);
68 return -1;
69 }
70
71 /* strip trailing slashes, including first one */
72 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
73 *end = 0;
74 /* path already parsed? */
75 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
76 return 0;
77 /* overwrite old issuers_chain_path */
78 free(global_ssl.issuers_chain_path);
79 global_ssl.issuers_chain_path = strdup(path);
80 ssl_free_global_issuers();
81
82 n = scandir(path, &de_list, 0, alphasort);
83 if (n < 0) {
84 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
85 err && *err ? *err : "", args[0], path, strerror(errno));
86 return -1;
87 }
88 for (i = 0; i < n; i++) {
89 struct dirent *de = de_list[i];
90 BIO *in = NULL;
91 char *warn = NULL;
92
93 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
94 free(de);
95 if (stat(fp, &buf) != 0) {
96 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
97 goto next;
98 }
99 if (!S_ISREG(buf.st_mode))
100 goto next;
101
102 in = BIO_new(BIO_s_file());
103 if (in == NULL)
104 goto next;
105 if (BIO_read_filename(in, fp) <= 0)
106 goto next;
107 ssl_load_global_issuer_from_BIO(in, fp, &warn);
108 if (warn) {
109 ha_warning("%s", warn);
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100110 ha_free(&warn);
William Lallemanddad31052020-05-14 17:47:32 +0200111 }
112 next:
113 if (in)
114 BIO_free(in);
115 }
116 free(de_list);
117
118 return 0;
119}
120
William Lallemanddad31052020-05-14 17:47:32 +0200121/* parse the "ssl-mode-async" keyword in global section.
122 * Returns <0 on alert, >0 on warning, 0 on success.
123 */
124static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100125 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200126 char **err)
127{
Ilya Shipitsinbdec3ba2020-11-14 01:56:34 +0500128#ifdef SSL_MODE_ASYNC
William Lallemanddad31052020-05-14 17:47:32 +0200129 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
William Lallemand5520d6f2020-05-18 13:42:49 +0200138#ifndef OPENSSL_NO_ENGINE
William Lallemanddad31052020-05-14 17:47:32 +0200139/* parse the "ssl-engine" keyword in global section.
140 * Returns <0 on alert, >0 on warning, 0 on success.
141 */
142static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100143 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200144 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
172add_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 */
185static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100186 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200187 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
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500206#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200207/* 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 */
210static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100211 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200212 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
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500232#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200233/*
234 * parse the "ssl-default-bind-curves" keyword in a global section.
235 * Returns <0 on alert, >0 on warning, 0 on success.
236 */
237static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100238 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200239 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 */
260static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100261 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200262 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
297static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100298 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200299 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
William Lallemand7d42ef52020-07-06 11:41:30 +0200320/* init the SSLKEYLOGFILE pool */
William Lallemandca5cf0a2021-06-09 16:46:12 +0200321#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200322static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100323 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200324 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}
William Lallemandca5cf0a2021-06-09 16:46:12 +0200356#else
357static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
358 const 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}
William Lallemand7d42ef52020-07-06 11:41:30 +0200364#endif
365
William Lallemanddad31052020-05-14 17:47:32 +0200366/* parse "ssl.force-private-cache".
367 * Returns <0 on alert, >0 on warning, 0 on success.
368 */
369static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100370 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200371 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 */
383static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100384 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200385 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 */
419static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100420 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200421 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 */
441static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100442 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200443 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 */
467static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100468 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200469 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
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100479 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200480 gf |= SSL_GF_BUNDLE;
481
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100482 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200483 gf |= SSL_GF_SCTL;
484
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100485 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200486 gf |= SSL_GF_OCSP;
487
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100488 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200489 gf |= SSL_GF_OCSP_ISSUER;
490
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100491 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200492 gf |= SSL_GF_KEY;
493
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100494 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200495 if (gf != SSL_GF_NONE)
496 goto err_alone;
497 gf = SSL_GF_NONE;
498 i++;
499 break;
500
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100501 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200502 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
519err_alone:
520 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
521 return -1;
522
523err_arg:
524 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
525 return -1;
526}
527
528
William Lallemand8e8581e2020-10-20 17:36:46 +0200529/* parse 'ssl-load-extra-del-ext */
530static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100531 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200532 char **err)
533{
534 global_ssl.extra_files_noext = 1;
535 return 0;
536}
537
William Lallemanddad31052020-05-14 17:47:32 +0200538/***************************** Bind keyword Parsing ********************************************/
539
540/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100541static int ssl_bind_parse_ca_file_common(char **args, int cur_arg, char **ca_file_p, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200542{
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
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100553 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli)) {
William Lallemanddad31052020-05-14 17:47:32 +0200554 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 */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100561static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200562{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100563 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200564}
565static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
566{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100567 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200568}
569
570/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100571static 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)
William Lallemanddad31052020-05-14 17:47:32 +0200572{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100573 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200574}
575static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
576{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100577 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200578}
579
580/* parse the "ca-sign-file" bind keyword */
581static 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 */
597static 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 */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100608static int ssl_bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200609{
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}
619static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
620{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100621 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200622}
623
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500624#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200625/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100626static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200627{
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}
637static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
638{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100639 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200640}
641#endif
642
643/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
644static 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) {
Willy Tarreau326a8662022-05-09 10:31:28 +0200654 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
655 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
William Lallemanddad31052020-05-14 17:47:32 +0200656 memprintf(err, "'%s' : path too long", args[cur_arg]);
657 return ERR_ALERT | ERR_FATAL;
658 }
William Lallemanddad31052020-05-14 17:47:32 +0200659 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>. */
666static 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 */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100683static int ssl_bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200684{
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
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100699 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli)) {
William Lallemanddad31052020-05-14 17:47:32 +0200700 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}
706static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
707{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100708 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200709}
710
711/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100712static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200713{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500714#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200715 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}
726static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
727{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100728 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200729}
730
731/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100732static int ssl_bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200733{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500734#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200735 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}
751static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
752{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100753 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200754}
755
756/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
757static 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" */
793static 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++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100801 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200802 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100803 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200804 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100805 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200806 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100807 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200808 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100809 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200810 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
825static 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
830static 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" */
836static 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++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100845 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200846 v = i;
847 if (!v) {
848 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
849 return ERR_ALERT | ERR_FATAL;
850 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100851 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200852 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100853 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200854 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
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100862static 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)
William Lallemanddad31052020-05-14 17:47:32 +0200863{
William Lallemand8177ad92020-05-20 16:49:02 +0200864 int ret;
865
William Lallemanddad31052020-05-14 17:47:32 +0200866#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
William Lallemand8177ad92020-05-20 16:49:02 +0200869 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
870 if (ret != ERR_NONE)
871 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200872
William Lallemand8177ad92020-05-20 16:49:02 +0200873 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
874 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
875
876 return ret;
877}
William Lallemanddad31052020-05-14 17:47:32 +0200878static 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
883static 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 */
889static 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 */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100896static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200897{
898 conf->early_data = 1;
899 return 0;
900}
901
902static 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 */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100909static int ssl_bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200910{
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
958static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
959{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100960 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200961}
962
963
964/* Parses a alpn string and converts it to the right format for the SSL api */
965int 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 */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001026static int ssl_bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +02001027{
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
1043static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1044{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001045 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001046}
1047
1048/* parse the "ssl" bind keyword */
1049static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1050{
Frédéric Lécaillee50afbd2020-11-23 11:33:12 +01001051 /* Do not change the xprt for QUIC. */
1052 if (conf->xprt != xprt_get(XPRT_QUIC))
1053 conf->xprt = &ssl_sock;
William Lallemanddad31052020-05-14 17:47:32 +02001054 conf->is_ssl = 1;
1055
1056 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1057 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001058#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001059 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1060 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1061#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001062#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001063 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1064 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1065#endif
1066 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1067 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1068 if (!conf->ssl_conf.ssl_methods.min)
1069 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1070 if (!conf->ssl_conf.ssl_methods.max)
1071 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1072
1073 return 0;
1074}
1075
1076/* parse the "prefer-client-ciphers" bind keyword */
1077static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1078{
1079 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1080 return 0;
1081}
1082
1083/* parse the "generate-certificates" bind keyword */
1084static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1085{
1086#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1087 conf->generate_certs = 1;
1088#else
1089 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1090 err && *err ? *err : "");
1091#endif
1092 return 0;
1093}
1094
1095/* parse the "strict-sni" bind keyword */
1096static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1097{
1098 conf->strict_sni = 1;
1099 return 0;
1100}
1101
1102/* parse the "tls-ticket-keys" bind keyword */
1103static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1104{
1105#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1106 FILE *f = NULL;
1107 int i = 0;
1108 char thisline[LINESIZE];
1109 struct tls_keys_ref *keys_ref = NULL;
1110
1111 if (!*args[cur_arg + 1]) {
1112 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1113 goto fail;
1114 }
1115
1116 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1117 if (keys_ref) {
1118 keys_ref->refcount++;
1119 conf->keys_ref = keys_ref;
1120 return 0;
1121 }
1122
1123 keys_ref = calloc(1, sizeof(*keys_ref));
1124 if (!keys_ref) {
1125 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1126 goto fail;
1127 }
1128
1129 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1130 if (!keys_ref->tlskeys) {
1131 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1132 goto fail;
1133 }
1134
1135 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1136 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1137 goto fail;
1138 }
1139
1140 keys_ref->filename = strdup(args[cur_arg + 1]);
1141 if (!keys_ref->filename) {
1142 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1143 goto fail;
1144 }
1145
1146 keys_ref->key_size_bits = 0;
1147 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1148 int len = strlen(thisline);
1149 int dec_size;
1150
1151 /* Strip newline characters from the end */
1152 if(thisline[len - 1] == '\n')
1153 thisline[--len] = 0;
1154
1155 if(thisline[len - 1] == '\r')
1156 thisline[--len] = 0;
1157
1158 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1159 if (dec_size < 0) {
1160 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1161 goto fail;
1162 }
1163 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1164 keys_ref->key_size_bits = 128;
1165 }
1166 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1167 keys_ref->key_size_bits = 256;
1168 }
1169 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1170 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1171 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1172 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1173 goto fail;
1174 }
1175 i++;
1176 }
1177
1178 if (i < TLS_TICKETS_NO) {
1179 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1180 goto fail;
1181 }
1182
1183 fclose(f);
1184
1185 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1186 i -= 2;
1187 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1188 keys_ref->unique_id = -1;
1189 keys_ref->refcount = 1;
1190 HA_RWLOCK_INIT(&keys_ref->lock);
1191 conf->keys_ref = keys_ref;
1192
Willy Tarreau2b718102021-04-21 07:32:39 +02001193 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001194
1195 return 0;
1196
1197 fail:
1198 if (f)
1199 fclose(f);
1200 if (keys_ref) {
1201 free(keys_ref->filename);
1202 free(keys_ref->tlskeys);
1203 free(keys_ref);
1204 }
1205 return ERR_ALERT | ERR_FATAL;
1206
1207#else
1208 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1209 return ERR_ALERT | ERR_FATAL;
1210#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1211}
1212
1213/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001214static int ssl_bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
William Lallemanddad31052020-05-14 17:47:32 +02001215{
1216 if (!*args[cur_arg + 1]) {
1217 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1218 return ERR_ALERT | ERR_FATAL;
1219 }
1220
1221 if (strcmp(args[cur_arg + 1], "none") == 0)
1222 conf->verify = SSL_SOCK_VERIFY_NONE;
1223 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1224 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1225 else if (strcmp(args[cur_arg + 1], "required") == 0)
1226 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1227 else {
1228 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1229 args[cur_arg], args[cur_arg + 1]);
1230 return ERR_ALERT | ERR_FATAL;
1231 }
1232
1233 return 0;
1234}
1235static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1236{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001237 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001238}
1239
1240/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001241static 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)
William Lallemanddad31052020-05-14 17:47:32 +02001242{
1243 conf->no_ca_names = 1;
1244 return 0;
1245}
1246static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1247{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001248 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001249}
1250
1251/***************************** "server" keywords Parsing ********************************************/
1252
1253/* parse the "npn" bind keyword */
1254static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1255{
1256#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1257 char *p1, *p2;
1258
1259 if (!*args[*cur_arg + 1]) {
1260 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1261 return ERR_ALERT | ERR_FATAL;
1262 }
1263
1264 free(newsrv->ssl_ctx.npn_str);
1265
1266 /* the NPN string is built as a suite of (<len> <name>)*,
1267 * so we reuse each comma to store the next <len> and need
1268 * one more for the end of the string.
1269 */
1270 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1271 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
1272 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1273 newsrv->ssl_ctx.npn_len);
1274
1275 /* replace commas with the name length */
1276 p1 = newsrv->ssl_ctx.npn_str;
1277 p2 = p1 + 1;
1278 while (1) {
1279 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1280 newsrv->ssl_ctx.npn_len - (p1 + 1));
1281 if (!p2)
1282 p2 = p1 + 1 + strlen(p1 + 1);
1283
1284 if (p2 - (p1 + 1) > 255) {
1285 *p2 = '\0';
1286 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1287 return ERR_ALERT | ERR_FATAL;
1288 }
1289
1290 *p1 = p2 - (p1 + 1);
1291 p1 = p2;
1292
1293 if (!*p2)
1294 break;
1295
1296 *(p2++) = '\0';
1297 }
1298 return 0;
1299#else
1300 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1301 return ERR_ALERT | ERR_FATAL;
1302#endif
1303}
1304
1305/* parse the "alpn" or the "check-alpn" server keyword */
1306static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1307{
1308#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1309 char **alpn_str;
1310 int *alpn_len;
1311 int ret;
1312
1313 if (*args[*cur_arg] == 'c') {
1314 alpn_str = &newsrv->check.alpn_str;
1315 alpn_len = &newsrv->check.alpn_len;
1316 } else {
1317 alpn_str = &newsrv->ssl_ctx.alpn_str;
1318 alpn_len = &newsrv->ssl_ctx.alpn_len;
1319
1320 }
1321
1322 free(*alpn_str);
1323 ret = ssl_sock_parse_alpn(args[*cur_arg + 1], alpn_str, alpn_len, err);
1324 if (ret)
1325 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1326 return ret;
1327#else
1328 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1329 return ERR_ALERT | ERR_FATAL;
1330#endif
1331}
1332
1333/* parse the "ca-file" server keyword */
1334static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1335{
1336 if (!*args[*cur_arg + 1]) {
1337 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1338 return ERR_ALERT | ERR_FATAL;
1339 }
1340
1341 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1342 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1343 else
1344 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1345
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001346 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, 1)) {
William Lallemanddad31052020-05-14 17:47:32 +02001347 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1348 return ERR_ALERT | ERR_FATAL;
1349 }
1350 return 0;
1351}
1352
1353/* parse the "check-sni" server keyword */
1354static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1355{
1356 if (!*args[*cur_arg + 1]) {
1357 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1358 return ERR_ALERT | ERR_FATAL;
1359 }
1360
1361 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1362 if (!newsrv->check.sni) {
1363 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1364 return ERR_ALERT | ERR_FATAL;
1365 }
1366 return 0;
1367
1368}
1369
William Dauchyfc52f522020-11-14 19:25:32 +01001370/* common function to init ssl_ctx */
1371static void ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001372{
William Dauchyfc52f522020-11-14 19:25:32 +01001373 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1374 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001375#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Dauchyfc52f522020-11-14 19:25:32 +01001376 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites)
1377 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
William Lallemanddad31052020-05-14 17:47:32 +02001378#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001379 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1380 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1381
1382 if (!s->ssl_ctx.methods.min)
1383 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001384
William Dauchyfc52f522020-11-14 19:25:32 +01001385 if (!s->ssl_ctx.methods.max)
1386 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
1387}
1388
1389/* parse the "check-ssl" server keyword */
1390static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1391{
1392 newsrv->check.use_ssl = 1;
1393 ssl_sock_init_srv(newsrv);
William Lallemanddad31052020-05-14 17:47:32 +02001394 return 0;
1395}
1396
1397/* parse the "ciphers" server keyword */
1398static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1399{
1400 if (!*args[*cur_arg + 1]) {
1401 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1402 return ERR_ALERT | ERR_FATAL;
1403 }
1404
1405 free(newsrv->ssl_ctx.ciphers);
1406 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
1407 return 0;
1408}
1409
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001410#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001411/* parse the "ciphersuites" server keyword */
1412static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1413{
1414 if (!*args[*cur_arg + 1]) {
1415 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1416 return ERR_ALERT | ERR_FATAL;
1417 }
1418
1419 free(newsrv->ssl_ctx.ciphersuites);
1420 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
1421 return 0;
1422}
1423#endif
1424
1425/* parse the "crl-file" server keyword */
1426static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1427{
1428#ifndef X509_V_FLAG_CRL_CHECK
1429 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1430 return ERR_ALERT | ERR_FATAL;
1431#else
1432 if (!*args[*cur_arg + 1]) {
1433 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1434 return ERR_ALERT | ERR_FATAL;
1435 }
1436
1437 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1438 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1439 else
1440 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1441
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001442 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, 1)) {
William Lallemanddad31052020-05-14 17:47:32 +02001443 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1444 return ERR_ALERT | ERR_FATAL;
1445 }
1446 return 0;
1447#endif
1448}
1449
1450/* parse the "crt" server keyword */
1451static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1452{
1453 if (!*args[*cur_arg + 1]) {
1454 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1455 return ERR_ALERT | ERR_FATAL;
1456 }
1457
1458 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand6338b7d2021-12-28 18:47:17 +01001459 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001460 else
William Lallemand6338b7d2021-12-28 18:47:17 +01001461 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001462
William Lallemand6338b7d2021-12-28 18:47:17 +01001463 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001464}
1465
1466/* parse the "no-check-ssl" server keyword */
1467static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1468{
1469 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001470 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001471 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1472 return 0;
1473}
1474
1475/* parse the "no-send-proxy-v2-ssl" server keyword */
1476static int srv_parse_no_send_proxy_ssl(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 return 0;
1481}
1482
1483/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1484static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1485{
1486 newsrv->pp_opts &= ~SRV_PP_V2;
1487 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1488 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1489 return 0;
1490}
1491
1492/* parse the "no-ssl" server keyword */
1493static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1494{
William Dauchyf6370442020-11-14 19:25:33 +01001495 /* if default-server have use_ssl, prepare ssl settings */
1496 if (newsrv->use_ssl == 1)
1497 ssl_sock_init_srv(newsrv);
1498 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001499 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001500 }
William Lallemanddad31052020-05-14 17:47:32 +02001501 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001502 return 0;
1503}
1504
1505/* parse the "allow-0rtt" server keyword */
1506static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1507{
1508 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1509 return 0;
1510}
1511
1512/* parse the "no-ssl-reuse" server keyword */
1513static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1514{
1515 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1516 return 0;
1517}
1518
1519/* parse the "no-tls-tickets" server keyword */
1520static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1521{
1522 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1523 return 0;
1524}
1525/* parse the "send-proxy-v2-ssl" server keyword */
1526static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1527{
1528 newsrv->pp_opts |= SRV_PP_V2;
1529 newsrv->pp_opts |= SRV_PP_V2_SSL;
1530 return 0;
1531}
1532
1533/* parse the "send-proxy-v2-ssl-cn" server keyword */
1534static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1535{
1536 newsrv->pp_opts |= SRV_PP_V2;
1537 newsrv->pp_opts |= SRV_PP_V2_SSL;
1538 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1539 return 0;
1540}
1541
1542/* parse the "sni" server keyword */
1543static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1544{
1545#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1546 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1547 return ERR_ALERT | ERR_FATAL;
1548#else
1549 char *arg;
1550
1551 arg = args[*cur_arg + 1];
1552 if (!*arg) {
1553 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1554 return ERR_ALERT | ERR_FATAL;
1555 }
1556
1557 free(newsrv->sni_expr);
1558 newsrv->sni_expr = strdup(arg);
1559
1560 return 0;
1561#endif
1562}
1563
1564/* parse the "ssl" server keyword */
1565static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1566{
1567 newsrv->use_ssl = 1;
William Dauchyfc52f522020-11-14 19:25:32 +01001568 ssl_sock_init_srv(newsrv);
William Lallemanddad31052020-05-14 17:47:32 +02001569 return 0;
1570}
1571
1572/* parse the "ssl-reuse" server keyword */
1573static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1574{
1575 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1576 return 0;
1577}
1578
1579/* parse the "tls-tickets" server keyword */
1580static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1581{
1582 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1583 return 0;
1584}
1585
1586/* parse the "verify" server keyword */
1587static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1588{
1589 if (!*args[*cur_arg + 1]) {
1590 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1591 return ERR_ALERT | ERR_FATAL;
1592 }
1593
1594 if (strcmp(args[*cur_arg + 1], "none") == 0)
1595 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1596 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1597 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1598 else {
1599 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1600 args[*cur_arg], args[*cur_arg + 1]);
1601 return ERR_ALERT | ERR_FATAL;
1602 }
1603
1604 return 0;
1605}
1606
1607/* parse the "verifyhost" server keyword */
1608static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1609{
1610 if (!*args[*cur_arg + 1]) {
1611 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1612 return ERR_ALERT | ERR_FATAL;
1613 }
1614
1615 free(newsrv->ssl_ctx.verify_host);
1616 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1617
1618 return 0;
1619}
1620
1621/* parse the "ssl-default-bind-options" keyword in global section */
1622static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001623 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001624 char **err) {
1625 int i = 1;
1626
1627 if (*(args[i]) == 0) {
1628 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1629 return -1;
1630 }
1631 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001632 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001633 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001634 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001635 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001636 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001637 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1638 i++;
1639 else {
1640 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1641 return -1;
1642 }
1643 }
1644 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1645 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1646 return -1;
1647 }
1648 i++;
1649 }
1650 return 0;
1651}
1652
1653/* parse the "ssl-default-server-options" keyword in global section */
1654static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001655 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001656 char **err) {
1657 int i = 1;
1658
1659 if (*(args[i]) == 0) {
1660 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1661 return -1;
1662 }
1663 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001664 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001665 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001666 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001667 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1668 i++;
1669 else {
1670 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1671 return -1;
1672 }
1673 }
1674 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1675 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1676 return -1;
1677 }
1678 i++;
1679 }
1680 return 0;
1681}
1682
1683/* parse the "ca-base" / "crt-base" keywords in global section.
1684 * Returns <0 on alert, >0 on warning, 0 on success.
1685 */
1686static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001687 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001688 char **err)
1689{
1690 char **target;
1691
1692 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1693
1694 if (too_many_args(1, args, err, NULL))
1695 return -1;
1696
1697 if (*target) {
1698 memprintf(err, "'%s' already specified.", args[0]);
1699 return -1;
1700 }
1701
1702 if (*(args[1]) == 0) {
1703 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1704 return -1;
1705 }
1706 *target = strdup(args[1]);
1707 return 0;
1708}
1709
1710/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1711static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001712 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001713 char **err)
1714{
William Lallemand9a1d8392020-08-10 17:28:23 +02001715#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001716 global_ssl.skip_self_issued_ca = 1;
1717 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001718#else
1719 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1720 return -1;
1721#endif
William Lallemanddad31052020-05-14 17:47:32 +02001722}
1723
1724
1725
1726
1727
1728/* Note: must not be declared <const> as its list will be overwritten.
1729 * Please take care of keeping this list alphabetically sorted, doing so helps
1730 * all code contributors.
1731 * Optional keywords are also declared with a NULL ->parse() function so that
1732 * the config parser can report an appropriate error when a known keyword was
1733 * not enabled.
1734 */
1735
1736/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1737 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1738struct ssl_bind_kw ssl_bind_kws[] = {
1739 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1740 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1741 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1742 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1743 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001744#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001745 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1746#endif
1747 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1748 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1749 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1750 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1751 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1752 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1753 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1754 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1755 { NULL, NULL, 0 },
1756};
1757
1758/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1759
1760static struct bind_kw_list bind_kws = { "SSL", { }, {
1761 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1762 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1763 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1764 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1765 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1766 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1767 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1768 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001769#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001770 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1771#endif
1772 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1773 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1774 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1775 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1776 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1777 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1778 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1779 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1780 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1781 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1782 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1783 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1784 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1785 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1786 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1787 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1788 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1789 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1790 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1791 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1792 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1793 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1794 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1795 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1796 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1797 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1798 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1799 { NULL, NULL, 0 },
1800}};
1801
1802INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1803
1804/* Note: must not be declared <const> as its list will be overwritten.
1805 * Please take care of keeping this list alphabetically sorted, doing so helps
1806 * all code contributors.
1807 * Optional keywords are also declared with a NULL ->parse() function so that
1808 * the config parser can report an appropriate error when a known keyword was
1809 * not enabled.
1810 */
1811static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001812 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 0 }, /* Allow using early data on this server */
1813 { "alpn", srv_parse_alpn, 1, 1, 0 }, /* Set ALPN supported protocols */
1814 { "ca-file", srv_parse_ca_file, 1, 1, 0 }, /* set CAfile to process verify server cert */
1815 { "check-alpn", srv_parse_alpn, 1, 1, 0 }, /* Set ALPN used for checks */
1816 { "check-sni", srv_parse_check_sni, 1, 1, 0 }, /* set SNI */
1817 { "check-ssl", srv_parse_check_ssl, 0, 1, 0 }, /* enable SSL for health checks */
1818 { "ciphers", srv_parse_ciphers, 1, 1, 0 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001819#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001820 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 0 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001821#endif
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001822 { "crl-file", srv_parse_crl_file, 1, 1, 0 }, /* set certificate revocation list file use on server cert verify */
1823 { "crt", srv_parse_crt, 1, 1, 0 }, /* set client certificate */
1824 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 0 }, /* force SSLv3 */
1825 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 0 }, /* force TLSv10 */
1826 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 0 }, /* force TLSv11 */
1827 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 0 }, /* force TLSv12 */
1828 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 0 }, /* force TLSv13 */
1829 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1830 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1831 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1832 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
1833 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 0 }, /* disable session reuse */
1834 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 0 }, /* disable SSLv3 */
1835 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 0 }, /* disable TLSv10 */
1836 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 0 }, /* disable TLSv11 */
1837 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 0 }, /* disable TLSv12 */
1838 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 0 }, /* disable TLSv13 */
1839 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 0 }, /* disable session resumption tickets */
1840 { "npn", srv_parse_npn, 1, 1, 0 }, /* Set NPN supported protocols */
1841 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 0 }, /* send PROXY protocol header v2 with SSL info */
1842 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 0 }, /* send PROXY protocol header v2 with CN */
1843 { "sni", srv_parse_sni, 1, 1, 0 }, /* send SNI extension */
1844 { "ssl", srv_parse_ssl, 0, 1, 0 }, /* enable SSL processing */
1845 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 0 }, /* minimum version */
1846 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 0 }, /* maximum version */
1847 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
1848 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 0 }, /* enable session resumption tickets */
1849 { "verify", srv_parse_verify, 1, 1, 0 }, /* set SSL verify method */
1850 { "verifyhost", srv_parse_verifyhost, 1, 1, 0 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001851 { NULL, NULL, 0, 0 },
1852}};
1853
1854INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1855
1856static struct cfg_kw_list cfg_kws = {ILH, {
1857 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1858 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1859 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1860 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1861 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1862 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1863#ifndef OPENSSL_NO_DH
1864 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1865#endif
1866 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
1867#ifndef OPENSSL_NO_ENGINE
1868 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1869#endif
1870 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1871 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1872#ifndef OPENSSL_NO_DH
1873 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1874#endif
1875 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
1876 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1877 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
1878 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
1879 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
William Lallemand7d42ef52020-07-06 11:41:30 +02001880 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02001881 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1882 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001883#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001884 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
1885#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001886#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001887 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
1888 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
1889#endif
1890 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02001891 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02001892 { 0, NULL, NULL },
1893}};
1894
1895INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);