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