blob: 7cee13db039d384ec5ece9500241cc2dfe910f49 [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>
William Lallemanddad31052020-05-14 17:47:32 +020025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include <sys/stat.h>
31#include <sys/types.h>
32
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020033#include <haproxy/api.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020034#include <haproxy/base64.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020035#include <haproxy/cfgparse.h>
Willy Tarreau0d1dd0e2021-10-06 19:00:49 +020036#include <haproxy/errors.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>
William Lallemand960fb742022-11-03 16:31:50 +010040#include <haproxy/ssl_utils.h>
Willy Tarreaucc81eca2021-05-08 12:54:42 +020041#include <haproxy/tools.h>
Remi Tricot-Le Bretonaf8820a2021-04-13 10:10:37 +020042#include <haproxy/ssl_ckch.h>
William Lallemanddad31052020-05-14 17:47:32 +020043
44
45/****************** Global Section Parsing ********************************************/
46
47static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +010048 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +020049 char **err)
50{
51 char *path;
52 struct dirent **de_list;
53 int i, n;
54 struct stat buf;
55 char *end;
56 char fp[MAXPATHLEN+1];
57
58 if (too_many_args(1, args, err, NULL))
59 return -1;
60
61 path = args[1];
62 if (*path == 0 || stat(path, &buf)) {
63 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
64 err && *err ? *err : "", args[0]);
65 return -1;
66 }
67 if (S_ISDIR(buf.st_mode) == 0) {
68 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
69 err && *err ? *err : "", args[0], path);
70 return -1;
71 }
72
73 /* strip trailing slashes, including first one */
74 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
75 *end = 0;
76 /* path already parsed? */
77 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
78 return 0;
79 /* overwrite old issuers_chain_path */
80 free(global_ssl.issuers_chain_path);
81 global_ssl.issuers_chain_path = strdup(path);
82 ssl_free_global_issuers();
83
84 n = scandir(path, &de_list, 0, alphasort);
85 if (n < 0) {
86 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
87 err && *err ? *err : "", args[0], path, strerror(errno));
88 return -1;
89 }
90 for (i = 0; i < n; i++) {
91 struct dirent *de = de_list[i];
92 BIO *in = NULL;
93 char *warn = NULL;
94
95 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
96 free(de);
97 if (stat(fp, &buf) != 0) {
98 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
99 goto next;
100 }
101 if (!S_ISREG(buf.st_mode))
102 goto next;
103
104 in = BIO_new(BIO_s_file());
105 if (in == NULL)
106 goto next;
107 if (BIO_read_filename(in, fp) <= 0)
108 goto next;
109 ssl_load_global_issuer_from_BIO(in, fp, &warn);
110 if (warn) {
111 ha_warning("%s", warn);
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100112 ha_free(&warn);
William Lallemanddad31052020-05-14 17:47:32 +0200113 }
114 next:
115 if (in)
116 BIO_free(in);
117 }
118 free(de_list);
119
120 return 0;
121}
122
William Lallemanddad31052020-05-14 17:47:32 +0200123/* parse the "ssl-mode-async" keyword in global section.
124 * Returns <0 on alert, >0 on warning, 0 on success.
125 */
126static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100127 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200128 char **err)
129{
Ilya Shipitsinbdec3ba2020-11-14 01:56:34 +0500130#ifdef SSL_MODE_ASYNC
William Lallemanddad31052020-05-14 17:47:32 +0200131 global_ssl.async = 1;
132 global.ssl_used_async_engines = nb_engines;
133 return 0;
134#else
135 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
136 return -1;
137#endif
138}
139
William Lallemandd7bfbe22022-04-11 18:41:24 +0200140#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +0200141/* parse the "ssl-engine" keyword in global section.
142 * Returns <0 on alert, >0 on warning, 0 on success.
143 */
144static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100145 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200146 char **err)
147{
148 char *algo;
149 int ret = -1;
150
151 if (*(args[1]) == 0) {
152 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
153 return ret;
154 }
155
156 if (*(args[2]) == 0) {
157 /* if no list of algorithms is given, it defaults to ALL */
158 algo = strdup("ALL");
159 goto add_engine;
160 }
161
162 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
163 if (strcmp(args[2], "algo") != 0) {
164 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
165 return ret;
166 }
167
168 if (*(args[3]) == 0) {
169 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
170 return ret;
171 }
172 algo = strdup(args[3]);
173
174add_engine:
175 if (ssl_init_single_engine(args[1], algo)==0) {
176 openssl_engines_initialized++;
177 ret = 0;
178 }
179 free(algo);
180 return ret;
181}
182#endif
183
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200184#ifdef HAVE_SSL_PROVIDERS
185/* parse the "ssl-propquery" keyword in global section.
186 * Returns <0 on alert, >0 on warning, 0 on success.
187 */
188static int ssl_parse_global_ssl_propquery(char **args, int section_type, struct proxy *curpx,
189 const struct proxy *defpx, const char *file, int line,
190 char **err)
191{
192 int ret = -1;
193
194 if (*(args[1]) == 0) {
195 memprintf(err, "global statement '%s' expects a property string as an argument.", args[0]);
196 return ret;
197 }
198
199 if (EVP_set_default_properties(NULL, args[1]))
200 ret = 0;
201
202 return ret;
203}
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +0200204
205/* parse the "ssl-provider" keyword in global section.
206 * Returns <0 on alert, >0 on warning, 0 on success.
207 */
208static int ssl_parse_global_ssl_provider(char **args, int section_type, struct proxy *curpx,
209 const struct proxy *defpx, const char *file, int line,
210 char **err)
211{
212 int ret = -1;
213
214 if (*(args[1]) == 0) {
215 memprintf(err, "global statement '%s' expects a valid engine provider name as an argument.", args[0]);
216 return ret;
217 }
218
219 if (ssl_init_provider(args[1]) == 0)
220 ret = 0;
221
222 return ret;
223}
Remi Tricot-Le Bretonccc03552022-05-17 15:18:37 +0200224
225/* parse the "ssl-provider-path" keyword in global section.
226 * Returns <0 on alert, >0 on warning, 0 on success.
227 */
228static int ssl_parse_global_ssl_provider_path(char **args, int section_type, struct proxy *curpx,
229 const struct proxy *defpx, const char *file, int line,
230 char **err)
231{
232 if (*(args[1]) == 0) {
233 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
234 return -1;
235 }
236
237 OSSL_PROVIDER_set_default_search_path(NULL, args[1]);
238
239 return 0;
240}
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200241#endif
242
William Lallemanddad31052020-05-14 17:47:32 +0200243/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
244 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
245 */
246static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100247 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200248 char **err)
249{
250 char **target;
251
252 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
253
254 if (too_many_args(1, args, err, NULL))
255 return -1;
256
257 if (*(args[1]) == 0) {
258 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
259 return -1;
260 }
261
262 free(*target);
263 *target = strdup(args[1]);
264 return 0;
265}
266
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500267#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200268/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
269 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
270 */
271static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100272 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200273 char **err)
274{
275 char **target;
276
277 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
278
279 if (too_many_args(1, args, err, NULL))
280 return -1;
281
282 if (*(args[1]) == 0) {
283 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
284 return -1;
285 }
286
287 free(*target);
288 *target = strdup(args[1]);
289 return 0;
290}
291#endif
292
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500293#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200294/*
295 * parse the "ssl-default-bind-curves" keyword in a global section.
296 * Returns <0 on alert, >0 on warning, 0 on success.
297 */
298static int ssl_parse_global_curves(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 char **target;
303 target = &global_ssl.listen_default_curves;
304
305 if (too_many_args(1, args, err, NULL))
306 return -1;
307
308 if (*(args[1]) == 0) {
309 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
310 return -1;
311 }
312
313 free(*target);
314 *target = strdup(args[1]);
315 return 0;
316}
317#endif
318/* parse various global tune.ssl settings consisting in positive integers.
319 * Returns <0 on alert, >0 on warning, 0 on success.
320 */
321static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100322 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200323 char **err)
324{
325 int *target;
326
327 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
328 target = &global.tune.sslcachesize;
329 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
330 target = (int *)&global_ssl.max_record;
Thomas Prückl10243932022-04-27 13:04:54 +0200331 else if (strcmp(args[0], "tune.ssl.hard-maxrecord") == 0)
332 target = (int *)&global_ssl.hard_max_record;
William Lallemanddad31052020-05-14 17:47:32 +0200333 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
334 target = &global_ssl.ctx_cache;
335 else if (strcmp(args[0], "maxsslconn") == 0)
336 target = &global.maxsslconn;
Marcin Deranek310a2602021-07-13 19:04:24 +0200337 else if (strcmp(args[0], "tune.ssl.capture-buffer-size") == 0)
338 target = &global_ssl.capture_buffer_size;
339 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0) {
340 target = &global_ssl.capture_buffer_size;
341 ha_warning("parsing [%s:%d]: '%s' is deprecated and will be removed in version 2.7. Please use 'tune.ssl.capture-buffer-size' instead.\n",
342 file, line, args[0]);
343 }
William Lallemanddad31052020-05-14 17:47:32 +0200344 else {
345 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
346 return -1;
347 }
348
349 if (too_many_args(1, args, err, NULL))
350 return -1;
351
352 if (*(args[1]) == 0) {
353 memprintf(err, "'%s' expects an integer argument.", args[0]);
354 return -1;
355 }
356
357 *target = atoi(args[1]);
358 if (*target < 0) {
359 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
360 return -1;
361 }
362 return 0;
363}
364
Marcin Deranek310a2602021-07-13 19:04:24 +0200365static int ssl_parse_global_capture_buffer(char **args, int section_type, struct proxy *curpx,
366 const struct proxy *defpx, const char *file, int line,
367 char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200368{
369 int ret;
370
371 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
372 if (ret != 0)
373 return ret;
374
375 if (pool_head_ssl_capture) {
376 memprintf(err, "'%s' is already configured.", args[0]);
377 return -1;
378 }
379
Marcin Deranek310a2602021-07-13 19:04:24 +0200380 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_buffer_size, MEM_F_SHARED);
William Lallemanddad31052020-05-14 17:47:32 +0200381 if (!pool_head_ssl_capture) {
382 memprintf(err, "Out of memory error.");
383 return -1;
384 }
385 return 0;
386}
387
William Lallemand7d42ef52020-07-06 11:41:30 +0200388/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200389#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200390static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100391 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200392 char **err)
393{
394
395 if (too_many_args(1, args, err, NULL))
396 return -1;
397
398 if (strcmp(args[1], "on") == 0)
399 global_ssl.keylog = 1;
400 else if (strcmp(args[1], "off") == 0)
401 global_ssl.keylog = 0;
402 else {
403 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
404 return -1;
405 }
406
407 if (pool_head_ssl_keylog) /* already configured */
408 return 0;
409
410 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
411 if (!pool_head_ssl_keylog) {
412 memprintf(err, "Out of memory error.");
413 return -1;
414 }
415
416 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
417 if (!pool_head_ssl_keylog_str) {
418 memprintf(err, "Out of memory error.");
419 return -1;
420 }
421
422 return 0;
423}
William Lallemand722180a2021-06-09 16:46:12 +0200424#else
425static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
426 const struct proxy *defpx, const char *file, int line,
427 char **err)
428{
429 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
430 return -1;
431}
William Lallemand7d42ef52020-07-06 11:41:30 +0200432#endif
433
William Lallemanddad31052020-05-14 17:47:32 +0200434/* parse "ssl.force-private-cache".
435 * Returns <0 on alert, >0 on warning, 0 on success.
436 */
437static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100438 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200439 char **err)
440{
441 if (too_many_args(0, args, err, NULL))
442 return -1;
443
444 global_ssl.private_cache = 1;
445 return 0;
446}
447
448/* parse "ssl.lifetime".
449 * Returns <0 on alert, >0 on warning, 0 on success.
450 */
451static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100452 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200453 char **err)
454{
455 const char *res;
456
457 if (too_many_args(1, args, err, NULL))
458 return -1;
459
460 if (*(args[1]) == 0) {
461 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
462 return -1;
463 }
464
465 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
466 if (res == PARSE_TIME_OVER) {
467 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
468 args[1], args[0]);
469 return -1;
470 }
471 else if (res == PARSE_TIME_UNDER) {
472 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
473 args[1], args[0]);
474 return -1;
475 }
476 else if (res) {
477 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
478 return -1;
479 }
480 return 0;
481}
482
483#ifndef OPENSSL_NO_DH
484/* parse "ssl-dh-param-file".
485 * Returns <0 on alert, >0 on warning, 0 on success.
486 */
487static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100488 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200489 char **err)
490{
491 if (too_many_args(1, args, err, NULL))
492 return -1;
493
494 if (*(args[1]) == 0) {
495 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
496 return -1;
497 }
498
499 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
500 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
501 return -1;
502 }
503 return 0;
504}
505
506/* parse "ssl.default-dh-param".
507 * Returns <0 on alert, >0 on warning, 0 on success.
508 */
509static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100510 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200511 char **err)
512{
513 if (too_many_args(1, args, err, NULL))
514 return -1;
515
516 if (*(args[1]) == 0) {
517 memprintf(err, "'%s' expects an integer argument.", args[0]);
518 return -1;
519 }
520
521 global_ssl.default_dh_param = atoi(args[1]);
522 if (global_ssl.default_dh_param < 1024) {
523 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
524 return -1;
525 }
526 return 0;
527}
528#endif
529
530
531/*
532 * parse "ssl-load-extra-files".
533 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
534 */
535static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100536 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200537 char **err)
538{
539 int i;
540 int gf = SSL_GF_NONE;
541
542 if (*(args[1]) == 0)
543 goto err_arg;
544
545 for (i = 1; *args[i]; i++) {
546
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100547 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200548 gf |= SSL_GF_BUNDLE;
549
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100550 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200551 gf |= SSL_GF_SCTL;
552
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100553 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200554 gf |= SSL_GF_OCSP;
555
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100556 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200557 gf |= SSL_GF_OCSP_ISSUER;
558
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100559 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200560 gf |= SSL_GF_KEY;
561
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100562 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200563 if (gf != SSL_GF_NONE)
564 goto err_alone;
565 gf = SSL_GF_NONE;
566 i++;
567 break;
568
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100569 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200570 if (gf != SSL_GF_NONE)
571 goto err_alone;
572 gf = SSL_GF_ALL;
573 i++;
574 break;
575 } else {
576 goto err_arg;
577 }
578 }
579 /* break from loop but there are still arguments */
580 if (*args[i])
581 goto err_alone;
582
583 global_ssl.extra_files = gf;
584
585 return 0;
586
587err_alone:
588 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
589 return -1;
590
591err_arg:
592 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
593 return -1;
594}
595
596
William Lallemand8e8581e2020-10-20 17:36:46 +0200597/* parse 'ssl-load-extra-del-ext */
598static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100599 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200600 char **err)
601{
602 global_ssl.extra_files_noext = 1;
603 return 0;
604}
605
William Lallemanddad31052020-05-14 17:47:32 +0200606/***************************** Bind keyword Parsing ********************************************/
607
608/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100609static 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 +0200610{
611 if (!*args[cur_arg + 1]) {
612 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
613 return ERR_ALERT | ERR_FATAL;
614 }
615
616 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
617 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
618 else
619 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
620
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200621 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200622 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
623 return ERR_ALERT | ERR_FATAL;
624 }
625 return 0;
626}
627
628/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100629static 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 +0200630{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100631 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200632}
633static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
634{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100635 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200636}
637
638/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100639static 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 +0200640{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100641 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200642}
643static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
644{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100645 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200646}
647
648/* parse the "ca-sign-file" bind keyword */
649static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
650{
651 if (!*args[cur_arg + 1]) {
652 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
653 return ERR_ALERT | ERR_FATAL;
654 }
655
656 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
657 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
658 else
659 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
660
661 return 0;
662}
663
664/* parse the "ca-sign-pass" bind keyword */
665static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
666{
667 if (!*args[cur_arg + 1]) {
668 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
669 return ERR_ALERT | ERR_FATAL;
670 }
671 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
672 return 0;
673}
674
675/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100676static 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 +0200677{
678 if (!*args[cur_arg + 1]) {
679 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
680 return ERR_ALERT | ERR_FATAL;
681 }
682
683 free(conf->ciphers);
684 conf->ciphers = strdup(args[cur_arg + 1]);
685 return 0;
686}
687static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
688{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100689 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200690}
691
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500692#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200693/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100694static 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 +0200695{
696 if (!*args[cur_arg + 1]) {
697 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
698 return ERR_ALERT | ERR_FATAL;
699 }
700
701 free(conf->ciphersuites);
702 conf->ciphersuites = strdup(args[cur_arg + 1]);
703 return 0;
704}
705static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
706{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100707 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200708}
709#endif
710
711/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
712static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
713{
714 char path[MAXPATHLEN];
715
716 if (!*args[cur_arg + 1]) {
717 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
718 return ERR_ALERT | ERR_FATAL;
719 }
720
721 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
Willy Tarreau393e42a2022-05-09 10:31:28 +0200722 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
723 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
William Lallemanddad31052020-05-14 17:47:32 +0200724 memprintf(err, "'%s' : path too long", args[cur_arg]);
725 return ERR_ALERT | ERR_FATAL;
726 }
William Lallemanddad31052020-05-14 17:47:32 +0200727 return ssl_sock_load_cert(path, conf, err);
728 }
729
730 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
731}
732
733/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
734static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
735{
736 int err_code;
737
738 if (!*args[cur_arg + 1]) {
739 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
740 return ERR_ALERT | ERR_FATAL;
741 }
742
743 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
744 if (err_code)
745 memprintf(err, "'%s' : %s", args[cur_arg], *err);
746
747 return err_code;
748}
749
750/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100751static 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 +0200752{
753#ifndef X509_V_FLAG_CRL_CHECK
754 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
755 return ERR_ALERT | ERR_FATAL;
756#else
757 if (!*args[cur_arg + 1]) {
758 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
759 return ERR_ALERT | ERR_FATAL;
760 }
761
762 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
763 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
764 else
765 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
766
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200767 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200768 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
769 return ERR_ALERT | ERR_FATAL;
770 }
771 return 0;
772#endif
773}
774static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
775{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100776 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200777}
778
779/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100780static 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 +0200781{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500782#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200783 if (!*args[cur_arg + 1]) {
784 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
785 return ERR_ALERT | ERR_FATAL;
786 }
787 conf->curves = strdup(args[cur_arg + 1]);
788 return 0;
789#else
790 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
791 return ERR_ALERT | ERR_FATAL;
792#endif
793}
794static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
795{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100796 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200797}
798
799/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100800static 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 +0200801{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500802#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200803 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
804 return ERR_ALERT | ERR_FATAL;
805#elif defined(OPENSSL_NO_ECDH)
806 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
807 return ERR_ALERT | ERR_FATAL;
808#else
809 if (!*args[cur_arg + 1]) {
810 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
811 return ERR_ALERT | ERR_FATAL;
812 }
813
814 conf->ecdhe = strdup(args[cur_arg + 1]);
815
816 return 0;
817#endif
818}
819static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
820{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100821 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200822}
823
824/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
825static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
826{
827 int code;
William Lallemand960fb742022-11-03 16:31:50 +0100828 char *s1 = NULL, *s2 = NULL;
829 char *token = NULL;
William Lallemanddad31052020-05-14 17:47:32 +0200830 char *p = args[cur_arg + 1];
William Lallemand960fb742022-11-03 16:31:50 +0100831 char *str;
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100832 unsigned long long *ignerr = conf->crt_ignerr_bitfield;
William Lallemanddad31052020-05-14 17:47:32 +0200833
834 if (!*p) {
835 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
836 return ERR_ALERT | ERR_FATAL;
837 }
838
William Lallemand960fb742022-11-03 16:31:50 +0100839 /* copy the string to be able to dump the complete one in case of
840 * error, because strtok_r is writing \0 inside. */
841 str = strdup(p);
842 if (!str) {
843 memprintf(err, "'%s' : Could not allocate memory", args[cur_arg]);
844 return ERR_ALERT | ERR_FATAL;
845
846 }
847
William Lallemanddad31052020-05-14 17:47:32 +0200848 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100849 ignerr = conf->ca_ignerr_bitfield;
William Lallemanddad31052020-05-14 17:47:32 +0200850
851 if (strcmp(p, "all") == 0) {
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100852 cert_ignerr_bitfield_set_all(ignerr);
William Lallemanddad31052020-05-14 17:47:32 +0200853 return 0;
854 }
855
William Lallemand960fb742022-11-03 16:31:50 +0100856 s1 = str;
857 while ((token = strtok_r(s1, ",", &s2))) {
858 s1 = NULL;
859 printf("token: %s\n", token);
860 if (isdigit((int)*token)) {
861 code = atoi(token);
862 if ((code <= 0) || (code > SSL_MAX_VFY_ERROR_CODE)) {
863 memprintf(err, "'%s' : ID '%d' out of range (1..%d) in error IDs list '%s'",
864 args[cur_arg], code, SSL_MAX_VFY_ERROR_CODE, args[cur_arg + 1]);
865 free(str);
866 return ERR_ALERT | ERR_FATAL;
867 }
868 } else {
869 code = x509_v_err_str_to_int(token);
870 if (code < 0) {
871 memprintf(err, "'%s' : error constant '%s' unknown in error IDs list '%s'",
872 args[cur_arg], token, args[cur_arg + 1]);
873 free(str);
874 return ERR_ALERT | ERR_FATAL;
875 }
William Lallemanddad31052020-05-14 17:47:32 +0200876 }
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100877 cert_ignerr_bitfield_set(ignerr, code);
William Lallemanddad31052020-05-14 17:47:32 +0200878 }
879
William Lallemand960fb742022-11-03 16:31:50 +0100880 free(str);
William Lallemanddad31052020-05-14 17:47:32 +0200881 return 0;
882}
883
884/* parse tls_method_options "no-xxx" and "force-xxx" */
885static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
886{
887 uint16_t v;
888 char *p;
889 p = strchr(arg, '-');
890 if (!p)
891 goto fail;
892 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100893 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200894 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100895 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200896 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100897 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200898 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100899 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200900 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100901 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200902 v = CONF_TLSV13;
903 else
904 goto fail;
905 if (!strncmp(arg, "no-", 3))
906 methods->flags |= methodVersions[v].flag;
907 else if (!strncmp(arg, "force-", 6))
908 methods->min = methods->max = v;
909 else
910 goto fail;
911 return 0;
912 fail:
913 memprintf(err, "'%s' : option not implemented", arg);
914 return ERR_ALERT | ERR_FATAL;
915}
916
917static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
918{
919 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
920}
921
922static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
923{
924 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
925}
926
927/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
928static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
929{
930 uint16_t i, v = 0;
931 char *argv = args[cur_arg + 1];
932 if (!*argv) {
933 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
934 return ERR_ALERT | ERR_FATAL;
935 }
936 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100937 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200938 v = i;
939 if (!v) {
940 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
941 return ERR_ALERT | ERR_FATAL;
942 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100943 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200944 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100945 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200946 methods->max = v;
947 else {
948 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
949 return ERR_ALERT | ERR_FATAL;
950 }
951 return 0;
952}
953
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100954static 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 +0200955{
William Lallemand8177ad92020-05-20 16:49:02 +0200956 int ret;
957
William Lallemanddad31052020-05-14 17:47:32 +0200958#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
959 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
960#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200961 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
962 if (ret != ERR_NONE)
963 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200964
William Lallemand8177ad92020-05-20 16:49:02 +0200965 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
966 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
967
968 return ret;
969}
William Lallemanddad31052020-05-14 17:47:32 +0200970static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
971{
972 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
973}
974
975static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
976{
977 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
978}
979
980/* parse the "no-tls-tickets" bind keyword */
981static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
982{
983 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
984 return 0;
985}
986
987/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100988static 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 +0200989{
990 conf->early_data = 1;
991 return 0;
992}
993
994static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
995{
996 conf->ssl_conf.early_data = 1;
997 return 0;
998}
999
1000/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001001static 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 +02001002{
1003#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1004 char *p1, *p2;
1005
1006 if (!*args[cur_arg + 1]) {
1007 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
1008 return ERR_ALERT | ERR_FATAL;
1009 }
1010
1011 free(conf->npn_str);
1012
1013 /* the NPN string is built as a suite of (<len> <name>)*,
1014 * so we reuse each comma to store the next <len> and need
1015 * one more for the end of the string.
1016 */
1017 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
1018 conf->npn_str = calloc(1, conf->npn_len + 1);
1019 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
1020
1021 /* replace commas with the name length */
1022 p1 = conf->npn_str;
1023 p2 = p1 + 1;
1024 while (1) {
1025 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
1026 if (!p2)
1027 p2 = p1 + 1 + strlen(p1 + 1);
1028
1029 if (p2 - (p1 + 1) > 255) {
1030 *p2 = '\0';
1031 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
1032 return ERR_ALERT | ERR_FATAL;
1033 }
1034
1035 *p1 = p2 - (p1 + 1);
1036 p1 = p2;
1037
1038 if (!*p2)
1039 break;
1040
1041 *(p2++) = '\0';
1042 }
1043 return 0;
1044#else
1045 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
1046 return ERR_ALERT | ERR_FATAL;
1047#endif
1048}
1049
1050static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1051{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001052 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001053}
1054
1055
1056/* Parses a alpn string and converts it to the right format for the SSL api */
1057int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
1058{
1059 char *p1, *p2, *alpn = NULL;
1060 int len, ret = 0;
1061
1062 *alpn_str = NULL;
1063 *alpn_len = 0;
1064
1065 if (!*arg) {
1066 memprintf(err, "missing the comma-delimited ALPN protocol suite");
1067 goto error;
1068 }
1069
1070 /* the ALPN string is built as a suite of (<len> <name>)*,
1071 * so we reuse each comma to store the next <len> and need
1072 * one more for the end of the string.
1073 */
1074 len = strlen(arg) + 1;
1075 alpn = calloc(1, len+1);
1076 if (!alpn) {
1077 memprintf(err, "'%s' : out of memory", arg);
1078 goto error;
1079 }
1080 memcpy(alpn+1, arg, len);
1081
1082 /* replace commas with the name length */
1083 p1 = alpn;
1084 p2 = p1 + 1;
1085 while (1) {
1086 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1087 if (!p2)
1088 p2 = p1 + 1 + strlen(p1 + 1);
1089
1090 if (p2 - (p1 + 1) > 255) {
1091 *p2 = '\0';
1092 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1093 goto error;
1094 }
1095
1096 *p1 = p2 - (p1 + 1);
1097 p1 = p2;
1098
1099 if (!*p2)
1100 break;
1101
1102 *(p2++) = '\0';
1103 }
1104
1105 *alpn_str = alpn;
1106 *alpn_len = len;
1107
1108 out:
1109 return ret;
1110
1111 error:
1112 free(alpn);
1113 ret = ERR_ALERT | ERR_FATAL;
1114 goto out;
1115}
1116
1117/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001118static 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 +02001119{
1120#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1121 int ret;
1122
1123 free(conf->alpn_str);
1124
1125 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1126 if (ret)
1127 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1128 return ret;
1129#else
1130 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1131 return ERR_ALERT | ERR_FATAL;
1132#endif
1133}
1134
1135static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1136{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001137 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001138}
1139
1140/* parse the "ssl" bind keyword */
1141static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1142{
Willy Tarreau11ba4042022-05-20 15:56:32 +02001143 conf->options |= BC_O_USE_SSL;
William Lallemanddad31052020-05-14 17:47:32 +02001144
1145 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1146 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001147#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001148 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1149 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1150#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001151#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001152 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1153 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1154#endif
1155 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1156 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1157 if (!conf->ssl_conf.ssl_methods.min)
1158 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1159 if (!conf->ssl_conf.ssl_methods.max)
1160 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1161
1162 return 0;
1163}
1164
1165/* parse the "prefer-client-ciphers" bind keyword */
1166static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1167{
1168 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1169 return 0;
1170}
1171
1172/* parse the "generate-certificates" bind keyword */
1173static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1174{
1175#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau1ea6e6a2022-05-20 16:03:18 +02001176 conf->options |= BC_O_GENERATE_CERTS;
William Lallemanddad31052020-05-14 17:47:32 +02001177#else
1178 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1179 err && *err ? *err : "");
1180#endif
1181 return 0;
1182}
1183
1184/* parse the "strict-sni" bind keyword */
1185static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1186{
1187 conf->strict_sni = 1;
1188 return 0;
1189}
1190
1191/* parse the "tls-ticket-keys" bind keyword */
1192static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1193{
1194#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1195 FILE *f = NULL;
1196 int i = 0;
1197 char thisline[LINESIZE];
1198 struct tls_keys_ref *keys_ref = NULL;
1199
1200 if (!*args[cur_arg + 1]) {
1201 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1202 goto fail;
1203 }
1204
1205 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1206 if (keys_ref) {
1207 keys_ref->refcount++;
1208 conf->keys_ref = keys_ref;
1209 return 0;
1210 }
1211
1212 keys_ref = calloc(1, sizeof(*keys_ref));
1213 if (!keys_ref) {
1214 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1215 goto fail;
1216 }
1217
1218 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1219 if (!keys_ref->tlskeys) {
1220 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1221 goto fail;
1222 }
1223
1224 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1225 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1226 goto fail;
1227 }
1228
1229 keys_ref->filename = strdup(args[cur_arg + 1]);
1230 if (!keys_ref->filename) {
1231 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1232 goto fail;
1233 }
1234
1235 keys_ref->key_size_bits = 0;
1236 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1237 int len = strlen(thisline);
1238 int dec_size;
1239
1240 /* Strip newline characters from the end */
1241 if(thisline[len - 1] == '\n')
1242 thisline[--len] = 0;
1243
1244 if(thisline[len - 1] == '\r')
1245 thisline[--len] = 0;
1246
1247 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1248 if (dec_size < 0) {
1249 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1250 goto fail;
1251 }
1252 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1253 keys_ref->key_size_bits = 128;
1254 }
1255 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1256 keys_ref->key_size_bits = 256;
1257 }
1258 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1259 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1260 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1261 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1262 goto fail;
1263 }
1264 i++;
1265 }
1266
1267 if (i < TLS_TICKETS_NO) {
1268 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1269 goto fail;
1270 }
1271
1272 fclose(f);
1273
1274 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1275 i -= 2;
1276 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1277 keys_ref->unique_id = -1;
1278 keys_ref->refcount = 1;
1279 HA_RWLOCK_INIT(&keys_ref->lock);
1280 conf->keys_ref = keys_ref;
1281
Willy Tarreau2b718102021-04-21 07:32:39 +02001282 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001283
1284 return 0;
1285
1286 fail:
1287 if (f)
1288 fclose(f);
1289 if (keys_ref) {
1290 free(keys_ref->filename);
1291 free(keys_ref->tlskeys);
1292 free(keys_ref);
1293 }
1294 return ERR_ALERT | ERR_FATAL;
1295
1296#else
1297 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1298 return ERR_ALERT | ERR_FATAL;
1299#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1300}
1301
1302/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001303static 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 +02001304{
1305 if (!*args[cur_arg + 1]) {
1306 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1307 return ERR_ALERT | ERR_FATAL;
1308 }
1309
1310 if (strcmp(args[cur_arg + 1], "none") == 0)
1311 conf->verify = SSL_SOCK_VERIFY_NONE;
1312 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1313 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1314 else if (strcmp(args[cur_arg + 1], "required") == 0)
1315 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1316 else {
1317 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1318 args[cur_arg], args[cur_arg + 1]);
1319 return ERR_ALERT | ERR_FATAL;
1320 }
1321
1322 return 0;
1323}
1324static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1325{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001326 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001327}
1328
1329/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001330static 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 +02001331{
1332 conf->no_ca_names = 1;
1333 return 0;
1334}
1335static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1336{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001337 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001338}
1339
1340/***************************** "server" keywords Parsing ********************************************/
1341
1342/* parse the "npn" bind keyword */
1343static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1344{
1345#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1346 char *p1, *p2;
1347
1348 if (!*args[*cur_arg + 1]) {
1349 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1350 return ERR_ALERT | ERR_FATAL;
1351 }
1352
1353 free(newsrv->ssl_ctx.npn_str);
1354
1355 /* the NPN string is built as a suite of (<len> <name>)*,
1356 * so we reuse each comma to store the next <len> and need
1357 * one more for the end of the string.
1358 */
1359 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1360 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001361 if (!newsrv->ssl_ctx.npn_str) {
1362 memprintf(err, "out of memory");
1363 return ERR_ALERT | ERR_FATAL;
1364 }
1365
William Lallemanddad31052020-05-14 17:47:32 +02001366 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1367 newsrv->ssl_ctx.npn_len);
1368
1369 /* replace commas with the name length */
1370 p1 = newsrv->ssl_ctx.npn_str;
1371 p2 = p1 + 1;
1372 while (1) {
1373 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1374 newsrv->ssl_ctx.npn_len - (p1 + 1));
1375 if (!p2)
1376 p2 = p1 + 1 + strlen(p1 + 1);
1377
1378 if (p2 - (p1 + 1) > 255) {
1379 *p2 = '\0';
1380 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1381 return ERR_ALERT | ERR_FATAL;
1382 }
1383
1384 *p1 = p2 - (p1 + 1);
1385 p1 = p2;
1386
1387 if (!*p2)
1388 break;
1389
1390 *(p2++) = '\0';
1391 }
1392 return 0;
1393#else
1394 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1395 return ERR_ALERT | ERR_FATAL;
1396#endif
1397}
1398
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001399#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1400static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1401{
1402 free(*out_alpn_str);
1403 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1404}
1405#endif
1406
1407/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001408static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1409{
1410#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001411 int ret = parse_alpn(args[*cur_arg + 1],
1412 &newsrv->ssl_ctx.alpn_str,
1413 &newsrv->ssl_ctx.alpn_len, err);
1414 if (ret)
1415 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1416 return ret;
1417#else
1418 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1419 return ERR_ALERT | ERR_FATAL;
1420#endif
1421}
William Lallemanddad31052020-05-14 17:47:32 +02001422
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001423/* parse the "check-alpn" server keyword */
1424static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1425{
1426#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1427 int ret = parse_alpn(args[*cur_arg + 1],
1428 &newsrv->check.alpn_str,
1429 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001430 if (ret)
1431 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1432 return ret;
1433#else
1434 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1435 return ERR_ALERT | ERR_FATAL;
1436#endif
1437}
1438
1439/* parse the "ca-file" server keyword */
1440static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1441{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001442 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1443
William Lallemanddad31052020-05-14 17:47:32 +02001444 if (!*args[*cur_arg + 1]) {
1445 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1446 return ERR_ALERT | ERR_FATAL;
1447 }
1448
1449 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1450 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1451 else
1452 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1453
Amaury Denoyelle48255022021-05-19 09:46:59 +02001454 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001455 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1456 return ERR_ALERT | ERR_FATAL;
1457 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001458
William Lallemanddad31052020-05-14 17:47:32 +02001459 return 0;
1460}
1461
1462/* parse the "check-sni" server keyword */
1463static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1464{
1465 if (!*args[*cur_arg + 1]) {
1466 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1467 return ERR_ALERT | ERR_FATAL;
1468 }
1469
1470 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1471 if (!newsrv->check.sni) {
1472 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1473 return ERR_ALERT | ERR_FATAL;
1474 }
1475 return 0;
1476
1477}
1478
William Dauchyfc52f522020-11-14 19:25:32 +01001479/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001480static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001481{
William Dauchyfc52f522020-11-14 19:25:32 +01001482 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1483 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001484#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001485 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001486 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001487 if (!s->ssl_ctx.ciphersuites)
1488 return 1;
1489 }
William Lallemanddad31052020-05-14 17:47:32 +02001490#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001491 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1492 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1493
1494 if (!s->ssl_ctx.methods.min)
1495 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001496
William Dauchyfc52f522020-11-14 19:25:32 +01001497 if (!s->ssl_ctx.methods.max)
1498 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001499
1500 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001501}
1502
1503/* parse the "check-ssl" server keyword */
1504static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1505{
1506 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001507 if (ssl_sock_init_srv(newsrv)) {
1508 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1509 return ERR_ALERT | ERR_FATAL;
1510 }
1511
William Lallemanddad31052020-05-14 17:47:32 +02001512 return 0;
1513}
1514
1515/* parse the "ciphers" server keyword */
1516static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1517{
1518 if (!*args[*cur_arg + 1]) {
1519 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1520 return ERR_ALERT | ERR_FATAL;
1521 }
1522
1523 free(newsrv->ssl_ctx.ciphers);
1524 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001525
1526 if (!newsrv->ssl_ctx.ciphers) {
1527 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1528 return ERR_ALERT | ERR_FATAL;
1529 }
1530
William Lallemanddad31052020-05-14 17:47:32 +02001531 return 0;
1532}
1533
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001534#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001535/* parse the "ciphersuites" server keyword */
1536static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1537{
1538 if (!*args[*cur_arg + 1]) {
1539 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1540 return ERR_ALERT | ERR_FATAL;
1541 }
1542
1543 free(newsrv->ssl_ctx.ciphersuites);
1544 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001545
1546 if (!newsrv->ssl_ctx.ciphersuites) {
1547 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1548 return ERR_ALERT | ERR_FATAL;
1549 }
1550
William Lallemanddad31052020-05-14 17:47:32 +02001551 return 0;
1552}
1553#endif
1554
1555/* parse the "crl-file" server keyword */
1556static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1557{
1558#ifndef X509_V_FLAG_CRL_CHECK
1559 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1560 return ERR_ALERT | ERR_FATAL;
1561#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001562 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1563
William Lallemanddad31052020-05-14 17:47:32 +02001564 if (!*args[*cur_arg + 1]) {
1565 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1566 return ERR_ALERT | ERR_FATAL;
1567 }
1568
1569 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1570 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1571 else
1572 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1573
Amaury Denoyellefde82602021-06-14 10:10:32 +02001574 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001575 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1576 return ERR_ALERT | ERR_FATAL;
1577 }
1578 return 0;
1579#endif
1580}
1581
1582/* parse the "crt" server keyword */
1583static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1584{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001585
William Lallemanddad31052020-05-14 17:47:32 +02001586 if (!*args[*cur_arg + 1]) {
1587 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1588 return ERR_ALERT | ERR_FATAL;
1589 }
1590
1591 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001592 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001593 else
William Lallemand2c776f12021-12-28 18:47:17 +01001594 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001595
William Lallemand2c776f12021-12-28 18:47:17 +01001596 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001597}
1598
1599/* parse the "no-check-ssl" server keyword */
1600static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1601{
1602 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001603 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001604 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1605 return 0;
1606}
1607
1608/* parse the "no-send-proxy-v2-ssl" server keyword */
1609static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1610{
1611 newsrv->pp_opts &= ~SRV_PP_V2;
1612 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1613 return 0;
1614}
1615
1616/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1617static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1618{
1619 newsrv->pp_opts &= ~SRV_PP_V2;
1620 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1621 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1622 return 0;
1623}
1624
1625/* parse the "no-ssl" server keyword */
1626static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1627{
William Dauchyf6370442020-11-14 19:25:33 +01001628 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001629 if (newsrv->use_ssl == 1) {
1630 if (ssl_sock_init_srv(newsrv)) {
1631 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1632 return ERR_ALERT | ERR_FATAL;
1633 }
1634 }
William Dauchyf6370442020-11-14 19:25:33 +01001635 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001636 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001637 }
William Lallemanddad31052020-05-14 17:47:32 +02001638 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001639 return 0;
1640}
1641
1642/* parse the "allow-0rtt" server keyword */
1643static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1644{
1645 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1646 return 0;
1647}
1648
1649/* parse the "no-ssl-reuse" server keyword */
1650static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1651{
1652 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1653 return 0;
1654}
1655
1656/* parse the "no-tls-tickets" server keyword */
1657static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1658{
1659 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1660 return 0;
1661}
1662/* parse the "send-proxy-v2-ssl" server keyword */
1663static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1664{
1665 newsrv->pp_opts |= SRV_PP_V2;
1666 newsrv->pp_opts |= SRV_PP_V2_SSL;
1667 return 0;
1668}
1669
1670/* parse the "send-proxy-v2-ssl-cn" server keyword */
1671static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1672{
1673 newsrv->pp_opts |= SRV_PP_V2;
1674 newsrv->pp_opts |= SRV_PP_V2_SSL;
1675 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1676 return 0;
1677}
1678
1679/* parse the "sni" server keyword */
1680static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1681{
1682#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1683 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1684 return ERR_ALERT | ERR_FATAL;
1685#else
1686 char *arg;
1687
1688 arg = args[*cur_arg + 1];
1689 if (!*arg) {
1690 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1691 return ERR_ALERT | ERR_FATAL;
1692 }
1693
1694 free(newsrv->sni_expr);
1695 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001696 if (!newsrv->sni_expr) {
1697 memprintf(err, "out of memory");
1698 return ERR_ALERT | ERR_FATAL;
1699 }
William Lallemanddad31052020-05-14 17:47:32 +02001700
1701 return 0;
1702#endif
1703}
1704
1705/* parse the "ssl" server keyword */
1706static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1707{
1708 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001709 if (ssl_sock_init_srv(newsrv)) {
1710 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1711 return ERR_ALERT | ERR_FATAL;
1712 }
1713
William Lallemanddad31052020-05-14 17:47:32 +02001714 return 0;
1715}
1716
1717/* parse the "ssl-reuse" server keyword */
1718static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1719{
1720 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1721 return 0;
1722}
1723
1724/* parse the "tls-tickets" server keyword */
1725static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1726{
1727 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1728 return 0;
1729}
1730
1731/* parse the "verify" server keyword */
1732static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1733{
1734 if (!*args[*cur_arg + 1]) {
1735 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1736 return ERR_ALERT | ERR_FATAL;
1737 }
1738
1739 if (strcmp(args[*cur_arg + 1], "none") == 0)
1740 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1741 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1742 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1743 else {
1744 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1745 args[*cur_arg], args[*cur_arg + 1]);
1746 return ERR_ALERT | ERR_FATAL;
1747 }
1748
1749 return 0;
1750}
1751
1752/* parse the "verifyhost" server keyword */
1753static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1754{
1755 if (!*args[*cur_arg + 1]) {
1756 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1757 return ERR_ALERT | ERR_FATAL;
1758 }
1759
1760 free(newsrv->ssl_ctx.verify_host);
1761 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1762
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001763 if (!newsrv->ssl_ctx.verify_host) {
1764 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1765 return ERR_ALERT | ERR_FATAL;
1766 }
1767
William Lallemanddad31052020-05-14 17:47:32 +02001768 return 0;
1769}
1770
1771/* parse the "ssl-default-bind-options" keyword in global section */
1772static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001773 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001774 char **err) {
1775 int i = 1;
1776
1777 if (*(args[i]) == 0) {
1778 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1779 return -1;
1780 }
1781 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001782 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001783 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001784 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001785 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001786 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001787 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1788 i++;
1789 else {
1790 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1791 return -1;
1792 }
1793 }
1794 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1795 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1796 return -1;
1797 }
1798 i++;
1799 }
1800 return 0;
1801}
1802
1803/* parse the "ssl-default-server-options" keyword in global section */
1804static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001805 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001806 char **err) {
1807 int i = 1;
1808
1809 if (*(args[i]) == 0) {
1810 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1811 return -1;
1812 }
1813 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001814 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001815 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001816 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001817 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1818 i++;
1819 else {
1820 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1821 return -1;
1822 }
1823 }
1824 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1825 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1826 return -1;
1827 }
1828 i++;
1829 }
1830 return 0;
1831}
1832
1833/* parse the "ca-base" / "crt-base" keywords in global section.
1834 * Returns <0 on alert, >0 on warning, 0 on success.
1835 */
1836static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001837 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001838 char **err)
1839{
1840 char **target;
1841
1842 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1843
1844 if (too_many_args(1, args, err, NULL))
1845 return -1;
1846
1847 if (*target) {
1848 memprintf(err, "'%s' already specified.", args[0]);
1849 return -1;
1850 }
1851
1852 if (*(args[1]) == 0) {
1853 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1854 return -1;
1855 }
1856 *target = strdup(args[1]);
1857 return 0;
1858}
1859
1860/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1861static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001862 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001863 char **err)
1864{
William Lallemand9a1d8392020-08-10 17:28:23 +02001865#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001866 global_ssl.skip_self_issued_ca = 1;
1867 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001868#else
1869 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1870 return -1;
1871#endif
William Lallemanddad31052020-05-14 17:47:32 +02001872}
1873
1874
1875
1876
1877
1878/* Note: must not be declared <const> as its list will be overwritten.
1879 * Please take care of keeping this list alphabetically sorted, doing so helps
1880 * all code contributors.
1881 * Optional keywords are also declared with a NULL ->parse() function so that
1882 * the config parser can report an appropriate error when a known keyword was
1883 * not enabled.
1884 */
1885
1886/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1887 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1888struct ssl_bind_kw ssl_bind_kws[] = {
1889 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1890 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1891 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1892 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1893 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001894#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001895 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1896#endif
1897 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1898 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1899 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1900 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1901 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1902 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1903 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1904 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1905 { NULL, NULL, 0 },
1906};
1907
1908/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1909
1910static struct bind_kw_list bind_kws = { "SSL", { }, {
1911 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1912 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1913 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1914 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1915 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1916 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1917 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1918 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001919#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001920 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1921#endif
1922 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1923 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1924 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1925 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1926 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1927 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1928 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1929 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1930 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1931 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1932 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1933 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1934 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1935 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1936 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1937 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1938 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1939 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1940 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1941 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1942 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1943 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1944 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1945 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1946 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1947 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1948 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1949 { NULL, NULL, 0 },
1950}};
1951
1952INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1953
1954/* Note: must not be declared <const> as its list will be overwritten.
1955 * Please take care of keeping this list alphabetically sorted, doing so helps
1956 * all code contributors.
1957 * Optional keywords are also declared with a NULL ->parse() function so that
1958 * the config parser can report an appropriate error when a known keyword was
1959 * not enabled.
1960 */
1961static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001962 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1963 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001964 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001965 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1966 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1967 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001968 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001969#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001970 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001971#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001972 { "crl-file", srv_parse_crl_file, 1, 1, 1 }, /* set certificate revocation list file use on server cert verify */
Amaury Denoyelle93be21e2021-05-21 16:22:53 +02001973 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001974 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1975 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1976 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1977 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1978 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001979 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1980 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1981 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1982 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001983 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1984 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1985 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1986 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1987 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1988 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1989 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1990 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1991 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1992 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1993 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001994 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001995 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1996 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001997 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001998 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1999 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
2000 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02002001 { NULL, NULL, 0, 0 },
2002}};
2003
2004INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
2005
2006static struct cfg_kw_list cfg_kws = {ILH, {
2007 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
2008 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
2009 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
2010 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
2011 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
2012 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
2013#ifndef OPENSSL_NO_DH
2014 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
2015#endif
2016 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
William Lallemandd7bfbe22022-04-11 18:41:24 +02002017#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +02002018 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
2019#endif
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002020#ifdef HAVE_SSL_PROVIDERS
2021 { CFG_GLOBAL, "ssl-propquery", ssl_parse_global_ssl_propquery },
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +02002022 { CFG_GLOBAL, "ssl-provider", ssl_parse_global_ssl_provider },
Remi Tricot-Le Bretonccc03552022-05-17 15:18:37 +02002023 { CFG_GLOBAL, "ssl-provider-path", ssl_parse_global_ssl_provider_path },
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002024#endif
William Lallemanddad31052020-05-14 17:47:32 +02002025 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
2026 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
2027#ifndef OPENSSL_NO_DH
2028 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
2029#endif
2030 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
2031 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
2032 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
Thomas Prückl10243932022-04-27 13:04:54 +02002033 { CFG_GLOBAL, "tune.ssl.hard-maxrecord", ssl_parse_global_int },
William Lallemanddad31052020-05-14 17:47:32 +02002034 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02002035 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
2036 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02002037 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02002038 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
2039 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05002040#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02002041 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
2042#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05002043#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02002044 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
2045 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
2046#endif
2047 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02002048 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02002049 { 0, NULL, NULL },
2050}};
2051
2052INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);