blob: 75af0e838bd0db06146e87584578e527c462fe24 [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>
Remi Tricot-Le Bretonc8d814e2022-12-20 11:11:17 +010043#include <haproxy/ssl_ocsp.h>
William Lallemanddad31052020-05-14 17:47:32 +020044
45
46/****************** Global Section Parsing ********************************************/
47
48static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +010049 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +020050 char **err)
51{
52 char *path;
53 struct dirent **de_list;
54 int i, n;
55 struct stat buf;
56 char *end;
57 char fp[MAXPATHLEN+1];
58
59 if (too_many_args(1, args, err, NULL))
60 return -1;
61
62 path = args[1];
63 if (*path == 0 || stat(path, &buf)) {
64 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
65 err && *err ? *err : "", args[0]);
66 return -1;
67 }
68 if (S_ISDIR(buf.st_mode) == 0) {
69 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
70 err && *err ? *err : "", args[0], path);
71 return -1;
72 }
73
74 /* strip trailing slashes, including first one */
75 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
76 *end = 0;
77 /* path already parsed? */
78 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
79 return 0;
80 /* overwrite old issuers_chain_path */
81 free(global_ssl.issuers_chain_path);
82 global_ssl.issuers_chain_path = strdup(path);
83 ssl_free_global_issuers();
84
85 n = scandir(path, &de_list, 0, alphasort);
86 if (n < 0) {
87 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
88 err && *err ? *err : "", args[0], path, strerror(errno));
89 return -1;
90 }
91 for (i = 0; i < n; i++) {
92 struct dirent *de = de_list[i];
93 BIO *in = NULL;
94 char *warn = NULL;
95
96 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
97 free(de);
98 if (stat(fp, &buf) != 0) {
99 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
100 goto next;
101 }
102 if (!S_ISREG(buf.st_mode))
103 goto next;
104
105 in = BIO_new(BIO_s_file());
106 if (in == NULL)
107 goto next;
108 if (BIO_read_filename(in, fp) <= 0)
109 goto next;
110 ssl_load_global_issuer_from_BIO(in, fp, &warn);
111 if (warn) {
112 ha_warning("%s", warn);
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100113 ha_free(&warn);
William Lallemanddad31052020-05-14 17:47:32 +0200114 }
115 next:
116 if (in)
117 BIO_free(in);
118 }
119 free(de_list);
120
121 return 0;
122}
123
William Lallemanddad31052020-05-14 17:47:32 +0200124/* parse the "ssl-mode-async" keyword in global section.
125 * Returns <0 on alert, >0 on warning, 0 on success.
126 */
127static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100128 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200129 char **err)
130{
Ilya Shipitsinbdec3ba2020-11-14 01:56:34 +0500131#ifdef SSL_MODE_ASYNC
William Lallemanddad31052020-05-14 17:47:32 +0200132 global_ssl.async = 1;
133 global.ssl_used_async_engines = nb_engines;
134 return 0;
135#else
136 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
137 return -1;
138#endif
139}
140
William Lallemandd7bfbe22022-04-11 18:41:24 +0200141#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +0200142/* parse the "ssl-engine" keyword in global section.
143 * Returns <0 on alert, >0 on warning, 0 on success.
144 */
145static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100146 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200147 char **err)
148{
149 char *algo;
150 int ret = -1;
151
152 if (*(args[1]) == 0) {
153 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
154 return ret;
155 }
156
157 if (*(args[2]) == 0) {
158 /* if no list of algorithms is given, it defaults to ALL */
159 algo = strdup("ALL");
160 goto add_engine;
161 }
162
163 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
164 if (strcmp(args[2], "algo") != 0) {
165 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
166 return ret;
167 }
168
169 if (*(args[3]) == 0) {
170 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
171 return ret;
172 }
173 algo = strdup(args[3]);
174
175add_engine:
176 if (ssl_init_single_engine(args[1], algo)==0) {
177 openssl_engines_initialized++;
178 ret = 0;
179 }
180 free(algo);
181 return ret;
182}
183#endif
184
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200185#ifdef HAVE_SSL_PROVIDERS
186/* parse the "ssl-propquery" keyword in global section.
187 * Returns <0 on alert, >0 on warning, 0 on success.
188 */
189static int ssl_parse_global_ssl_propquery(char **args, int section_type, struct proxy *curpx,
190 const struct proxy *defpx, const char *file, int line,
191 char **err)
192{
193 int ret = -1;
194
195 if (*(args[1]) == 0) {
196 memprintf(err, "global statement '%s' expects a property string as an argument.", args[0]);
197 return ret;
198 }
199
200 if (EVP_set_default_properties(NULL, args[1]))
201 ret = 0;
202
203 return ret;
204}
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +0200205
206/* parse the "ssl-provider" keyword in global section.
207 * Returns <0 on alert, >0 on warning, 0 on success.
208 */
209static int ssl_parse_global_ssl_provider(char **args, int section_type, struct proxy *curpx,
210 const struct proxy *defpx, const char *file, int line,
211 char **err)
212{
213 int ret = -1;
214
215 if (*(args[1]) == 0) {
216 memprintf(err, "global statement '%s' expects a valid engine provider name as an argument.", args[0]);
217 return ret;
218 }
219
220 if (ssl_init_provider(args[1]) == 0)
221 ret = 0;
222
223 return ret;
224}
Remi Tricot-Le Bretonccc03552022-05-17 15:18:37 +0200225
226/* parse the "ssl-provider-path" keyword in global section.
227 * Returns <0 on alert, >0 on warning, 0 on success.
228 */
229static int ssl_parse_global_ssl_provider_path(char **args, int section_type, struct proxy *curpx,
230 const struct proxy *defpx, const char *file, int line,
231 char **err)
232{
233 if (*(args[1]) == 0) {
234 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
235 return -1;
236 }
237
238 OSSL_PROVIDER_set_default_search_path(NULL, args[1]);
239
240 return 0;
241}
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200242#endif
243
William Lallemanddad31052020-05-14 17:47:32 +0200244/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
245 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
246 */
247static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100248 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200249 char **err)
250{
251 char **target;
252
253 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
254
255 if (too_many_args(1, args, err, NULL))
256 return -1;
257
258 if (*(args[1]) == 0) {
259 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
260 return -1;
261 }
262
263 free(*target);
264 *target = strdup(args[1]);
265 return 0;
266}
267
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500268#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200269/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
270 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
271 */
272static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100273 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200274 char **err)
275{
276 char **target;
277
278 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
279
280 if (too_many_args(1, args, err, NULL))
281 return -1;
282
283 if (*(args[1]) == 0) {
284 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
285 return -1;
286 }
287
288 free(*target);
289 *target = strdup(args[1]);
290 return 0;
291}
292#endif
293
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500294#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200295/*
296 * parse the "ssl-default-bind-curves" keyword in a global section.
297 * Returns <0 on alert, >0 on warning, 0 on success.
298 */
299static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100300 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200301 char **err)
302{
303 char **target;
304 target = &global_ssl.listen_default_curves;
305
306 if (too_many_args(1, args, err, NULL))
307 return -1;
308
309 if (*(args[1]) == 0) {
310 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
311 return -1;
312 }
313
314 free(*target);
315 *target = strdup(args[1]);
316 return 0;
317}
318#endif
319/* parse various global tune.ssl settings consisting in positive integers.
320 * Returns <0 on alert, >0 on warning, 0 on success.
321 */
322static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100323 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200324 char **err)
325{
326 int *target;
327
328 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
329 target = &global.tune.sslcachesize;
330 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
331 target = (int *)&global_ssl.max_record;
Thomas Prückl10243932022-04-27 13:04:54 +0200332 else if (strcmp(args[0], "tune.ssl.hard-maxrecord") == 0)
333 target = (int *)&global_ssl.hard_max_record;
William Lallemanddad31052020-05-14 17:47:32 +0200334 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
335 target = &global_ssl.ctx_cache;
336 else if (strcmp(args[0], "maxsslconn") == 0)
337 target = &global.maxsslconn;
Marcin Deranek310a2602021-07-13 19:04:24 +0200338 else if (strcmp(args[0], "tune.ssl.capture-buffer-size") == 0)
339 target = &global_ssl.capture_buffer_size;
340 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0) {
341 target = &global_ssl.capture_buffer_size;
342 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",
343 file, line, args[0]);
344 }
William Lallemanddad31052020-05-14 17:47:32 +0200345 else {
346 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
347 return -1;
348 }
349
350 if (too_many_args(1, args, err, NULL))
351 return -1;
352
353 if (*(args[1]) == 0) {
354 memprintf(err, "'%s' expects an integer argument.", args[0]);
355 return -1;
356 }
357
358 *target = atoi(args[1]);
359 if (*target < 0) {
360 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
361 return -1;
362 }
363 return 0;
364}
365
Marcin Deranek310a2602021-07-13 19:04:24 +0200366static int ssl_parse_global_capture_buffer(char **args, int section_type, struct proxy *curpx,
367 const struct proxy *defpx, const char *file, int line,
368 char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200369{
370 int ret;
371
372 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
373 if (ret != 0)
374 return ret;
375
376 if (pool_head_ssl_capture) {
377 memprintf(err, "'%s' is already configured.", args[0]);
378 return -1;
379 }
380
Marcin Deranek310a2602021-07-13 19:04:24 +0200381 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 +0200382 if (!pool_head_ssl_capture) {
383 memprintf(err, "Out of memory error.");
384 return -1;
385 }
386 return 0;
387}
388
William Lallemand7d42ef52020-07-06 11:41:30 +0200389/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200390#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200391static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100392 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200393 char **err)
394{
395
396 if (too_many_args(1, args, err, NULL))
397 return -1;
398
399 if (strcmp(args[1], "on") == 0)
400 global_ssl.keylog = 1;
401 else if (strcmp(args[1], "off") == 0)
402 global_ssl.keylog = 0;
403 else {
404 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
405 return -1;
406 }
407
408 if (pool_head_ssl_keylog) /* already configured */
409 return 0;
410
411 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
412 if (!pool_head_ssl_keylog) {
413 memprintf(err, "Out of memory error.");
414 return -1;
415 }
416
417 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
418 if (!pool_head_ssl_keylog_str) {
419 memprintf(err, "Out of memory error.");
420 return -1;
421 }
422
423 return 0;
424}
William Lallemand722180a2021-06-09 16:46:12 +0200425#else
426static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
427 const struct proxy *defpx, const char *file, int line,
428 char **err)
429{
430 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
431 return -1;
432}
William Lallemand7d42ef52020-07-06 11:41:30 +0200433#endif
434
William Lallemanddad31052020-05-14 17:47:32 +0200435/* parse "ssl.force-private-cache".
436 * Returns <0 on alert, >0 on warning, 0 on success.
437 */
438static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100439 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200440 char **err)
441{
442 if (too_many_args(0, args, err, NULL))
443 return -1;
444
445 global_ssl.private_cache = 1;
446 return 0;
447}
448
449/* parse "ssl.lifetime".
450 * Returns <0 on alert, >0 on warning, 0 on success.
451 */
452static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100453 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200454 char **err)
455{
456 const char *res;
457
458 if (too_many_args(1, args, err, NULL))
459 return -1;
460
461 if (*(args[1]) == 0) {
462 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
463 return -1;
464 }
465
466 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
467 if (res == PARSE_TIME_OVER) {
468 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
469 args[1], args[0]);
470 return -1;
471 }
472 else if (res == PARSE_TIME_UNDER) {
473 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
474 args[1], args[0]);
475 return -1;
476 }
477 else if (res) {
478 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
479 return -1;
480 }
481 return 0;
482}
483
484#ifndef OPENSSL_NO_DH
485/* parse "ssl-dh-param-file".
486 * Returns <0 on alert, >0 on warning, 0 on success.
487 */
488static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100489 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200490 char **err)
491{
492 if (too_many_args(1, args, err, NULL))
493 return -1;
494
495 if (*(args[1]) == 0) {
496 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
497 return -1;
498 }
499
500 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
501 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
502 return -1;
503 }
504 return 0;
505}
506
507/* parse "ssl.default-dh-param".
508 * Returns <0 on alert, >0 on warning, 0 on success.
509 */
510static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100511 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200512 char **err)
513{
514 if (too_many_args(1, args, err, NULL))
515 return -1;
516
517 if (*(args[1]) == 0) {
518 memprintf(err, "'%s' expects an integer argument.", args[0]);
519 return -1;
520 }
521
522 global_ssl.default_dh_param = atoi(args[1]);
523 if (global_ssl.default_dh_param < 1024) {
524 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
525 return -1;
526 }
527 return 0;
528}
529#endif
530
531
532/*
533 * parse "ssl-load-extra-files".
534 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
535 */
536static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100537 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200538 char **err)
539{
540 int i;
541 int gf = SSL_GF_NONE;
542
543 if (*(args[1]) == 0)
544 goto err_arg;
545
546 for (i = 1; *args[i]; i++) {
547
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100548 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200549 gf |= SSL_GF_BUNDLE;
550
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100551 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200552 gf |= SSL_GF_SCTL;
553
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100554 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200555 gf |= SSL_GF_OCSP;
556
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100557 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200558 gf |= SSL_GF_OCSP_ISSUER;
559
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100560 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200561 gf |= SSL_GF_KEY;
562
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100563 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200564 if (gf != SSL_GF_NONE)
565 goto err_alone;
566 gf = SSL_GF_NONE;
567 i++;
568 break;
569
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100570 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200571 if (gf != SSL_GF_NONE)
572 goto err_alone;
573 gf = SSL_GF_ALL;
574 i++;
575 break;
576 } else {
577 goto err_arg;
578 }
579 }
580 /* break from loop but there are still arguments */
581 if (*args[i])
582 goto err_alone;
583
584 global_ssl.extra_files = gf;
585
586 return 0;
587
588err_alone:
589 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
590 return -1;
591
592err_arg:
593 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
594 return -1;
595}
596
597
William Lallemand8e8581e2020-10-20 17:36:46 +0200598/* parse 'ssl-load-extra-del-ext */
599static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100600 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200601 char **err)
602{
603 global_ssl.extra_files_noext = 1;
604 return 0;
605}
606
Remi Tricot-Le Breton03c5fff2022-12-20 11:11:10 +0100607
William Lallemanddad31052020-05-14 17:47:32 +0200608/***************************** Bind keyword Parsing ********************************************/
609
610/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100611static 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 +0200612{
613 if (!*args[cur_arg + 1]) {
614 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
615 return ERR_ALERT | ERR_FATAL;
616 }
617
618 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
619 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
620 else
621 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
622
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200623 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200624 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
625 return ERR_ALERT | ERR_FATAL;
626 }
627 return 0;
628}
629
630/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100631static 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 +0200632{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100633 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200634}
635static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
636{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100637 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200638}
639
640/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100641static 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 +0200642{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100643 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200644}
645static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
646{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100647 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200648}
649
650/* parse the "ca-sign-file" bind keyword */
651static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
652{
653 if (!*args[cur_arg + 1]) {
654 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
655 return ERR_ALERT | ERR_FATAL;
656 }
657
658 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
659 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
660 else
661 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
662
663 return 0;
664}
665
666/* parse the "ca-sign-pass" bind keyword */
667static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
668{
669 if (!*args[cur_arg + 1]) {
670 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
671 return ERR_ALERT | ERR_FATAL;
672 }
673 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
674 return 0;
675}
676
677/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100678static 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 +0200679{
680 if (!*args[cur_arg + 1]) {
681 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
682 return ERR_ALERT | ERR_FATAL;
683 }
684
685 free(conf->ciphers);
686 conf->ciphers = strdup(args[cur_arg + 1]);
687 return 0;
688}
689static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
690{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100691 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200692}
693
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500694#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200695/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100696static 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 +0200697{
698 if (!*args[cur_arg + 1]) {
699 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
700 return ERR_ALERT | ERR_FATAL;
701 }
702
703 free(conf->ciphersuites);
704 conf->ciphersuites = strdup(args[cur_arg + 1]);
705 return 0;
706}
707static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
708{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100709 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200710}
711#endif
712
713/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
714static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
715{
716 char path[MAXPATHLEN];
717
718 if (!*args[cur_arg + 1]) {
719 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
720 return ERR_ALERT | ERR_FATAL;
721 }
722
723 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
Willy Tarreau393e42a2022-05-09 10:31:28 +0200724 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
725 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
William Lallemanddad31052020-05-14 17:47:32 +0200726 memprintf(err, "'%s' : path too long", args[cur_arg]);
727 return ERR_ALERT | ERR_FATAL;
728 }
William Lallemanddad31052020-05-14 17:47:32 +0200729 return ssl_sock_load_cert(path, conf, err);
730 }
731
732 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
733}
734
735/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
736static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
737{
738 int err_code;
739
740 if (!*args[cur_arg + 1]) {
741 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
742 return ERR_ALERT | ERR_FATAL;
743 }
744
745 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
746 if (err_code)
747 memprintf(err, "'%s' : %s", args[cur_arg], *err);
748
749 return err_code;
750}
751
752/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100753static 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 +0200754{
755#ifndef X509_V_FLAG_CRL_CHECK
756 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
757 return ERR_ALERT | ERR_FATAL;
758#else
759 if (!*args[cur_arg + 1]) {
760 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
761 return ERR_ALERT | ERR_FATAL;
762 }
763
764 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
765 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
766 else
767 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
768
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200769 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200770 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
771 return ERR_ALERT | ERR_FATAL;
772 }
773 return 0;
774#endif
775}
776static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
777{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100778 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200779}
780
781/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100782static 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 +0200783{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500784#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200785 if (!*args[cur_arg + 1]) {
786 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
787 return ERR_ALERT | ERR_FATAL;
788 }
789 conf->curves = strdup(args[cur_arg + 1]);
790 return 0;
791#else
792 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
793 return ERR_ALERT | ERR_FATAL;
794#endif
795}
796static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
797{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100798 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200799}
800
801/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100802static 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 +0200803{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500804#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200805 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
806 return ERR_ALERT | ERR_FATAL;
807#elif defined(OPENSSL_NO_ECDH)
808 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
809 return ERR_ALERT | ERR_FATAL;
810#else
811 if (!*args[cur_arg + 1]) {
812 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
813 return ERR_ALERT | ERR_FATAL;
814 }
815
816 conf->ecdhe = strdup(args[cur_arg + 1]);
817
818 return 0;
819#endif
820}
821static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
822{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100823 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200824}
825
826/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
827static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
828{
829 int code;
William Lallemand960fb742022-11-03 16:31:50 +0100830 char *s1 = NULL, *s2 = NULL;
831 char *token = NULL;
William Lallemanddad31052020-05-14 17:47:32 +0200832 char *p = args[cur_arg + 1];
William Lallemand960fb742022-11-03 16:31:50 +0100833 char *str;
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100834 unsigned long long *ignerr = conf->crt_ignerr_bitfield;
William Lallemanddad31052020-05-14 17:47:32 +0200835
836 if (!*p) {
837 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
838 return ERR_ALERT | ERR_FATAL;
839 }
840
841 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100842 ignerr = conf->ca_ignerr_bitfield;
William Lallemanddad31052020-05-14 17:47:32 +0200843
844 if (strcmp(p, "all") == 0) {
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100845 cert_ignerr_bitfield_set_all(ignerr);
William Lallemanddad31052020-05-14 17:47:32 +0200846 return 0;
847 }
848
William Lallemandf813dab2022-11-14 11:36:11 +0100849 /* copy the string to be able to dump the complete one in case of
850 * error, because strtok_r is writing \0 inside. */
851 str = strdup(p);
852 if (!str) {
853 memprintf(err, "'%s' : Could not allocate memory", args[cur_arg]);
854 return ERR_ALERT | ERR_FATAL;
855 }
856
William Lallemand960fb742022-11-03 16:31:50 +0100857 s1 = str;
858 while ((token = strtok_r(s1, ",", &s2))) {
859 s1 = NULL;
William Lallemand960fb742022-11-03 16:31:50 +0100860 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);
Willy Tarreauc57fb3b2022-12-29 11:11:02 +01001019 if (!conf->npn_str) {
1020 memprintf(err, "out of memory");
1021 return ERR_ALERT | ERR_FATAL;
1022 }
1023
William Lallemanddad31052020-05-14 17:47:32 +02001024 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
1025
1026 /* replace commas with the name length */
1027 p1 = conf->npn_str;
1028 p2 = p1 + 1;
1029 while (1) {
1030 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
1031 if (!p2)
1032 p2 = p1 + 1 + strlen(p1 + 1);
1033
1034 if (p2 - (p1 + 1) > 255) {
1035 *p2 = '\0';
1036 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
1037 return ERR_ALERT | ERR_FATAL;
1038 }
1039
1040 *p1 = p2 - (p1 + 1);
1041 p1 = p2;
1042
1043 if (!*p2)
1044 break;
1045
1046 *(p2++) = '\0';
1047 }
1048 return 0;
1049#else
1050 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
1051 return ERR_ALERT | ERR_FATAL;
1052#endif
1053}
1054
1055static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1056{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001057 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001058}
1059
1060
1061/* Parses a alpn string and converts it to the right format for the SSL api */
1062int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
1063{
1064 char *p1, *p2, *alpn = NULL;
1065 int len, ret = 0;
1066
1067 *alpn_str = NULL;
1068 *alpn_len = 0;
1069
1070 if (!*arg) {
1071 memprintf(err, "missing the comma-delimited ALPN protocol suite");
1072 goto error;
1073 }
1074
1075 /* the ALPN string is built as a suite of (<len> <name>)*,
1076 * so we reuse each comma to store the next <len> and need
1077 * one more for the end of the string.
1078 */
1079 len = strlen(arg) + 1;
1080 alpn = calloc(1, len+1);
1081 if (!alpn) {
1082 memprintf(err, "'%s' : out of memory", arg);
1083 goto error;
1084 }
1085 memcpy(alpn+1, arg, len);
1086
1087 /* replace commas with the name length */
1088 p1 = alpn;
1089 p2 = p1 + 1;
1090 while (1) {
1091 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1092 if (!p2)
1093 p2 = p1 + 1 + strlen(p1 + 1);
1094
1095 if (p2 - (p1 + 1) > 255) {
1096 *p2 = '\0';
1097 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1098 goto error;
1099 }
1100
1101 *p1 = p2 - (p1 + 1);
1102 p1 = p2;
1103
1104 if (!*p2)
1105 break;
1106
1107 *(p2++) = '\0';
1108 }
1109
1110 *alpn_str = alpn;
1111 *alpn_len = len;
1112
1113 out:
1114 return ret;
1115
1116 error:
1117 free(alpn);
1118 ret = ERR_ALERT | ERR_FATAL;
1119 goto out;
1120}
1121
1122/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001123static 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 +02001124{
1125#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1126 int ret;
1127
1128 free(conf->alpn_str);
1129
1130 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1131 if (ret)
1132 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1133 return ret;
1134#else
1135 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1136 return ERR_ALERT | ERR_FATAL;
1137#endif
1138}
1139
1140static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1141{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001142 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001143}
1144
1145/* parse the "ssl" bind keyword */
1146static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1147{
Willy Tarreau11ba4042022-05-20 15:56:32 +02001148 conf->options |= BC_O_USE_SSL;
William Lallemanddad31052020-05-14 17:47:32 +02001149
1150 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1151 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001152#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001153 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1154 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1155#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001156#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001157 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1158 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1159#endif
1160 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1161 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1162 if (!conf->ssl_conf.ssl_methods.min)
1163 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1164 if (!conf->ssl_conf.ssl_methods.max)
1165 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1166
1167 return 0;
1168}
1169
1170/* parse the "prefer-client-ciphers" bind keyword */
1171static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1172{
1173 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1174 return 0;
1175}
1176
1177/* parse the "generate-certificates" bind keyword */
1178static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1179{
1180#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau1ea6e6a2022-05-20 16:03:18 +02001181 conf->options |= BC_O_GENERATE_CERTS;
William Lallemanddad31052020-05-14 17:47:32 +02001182#else
1183 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1184 err && *err ? *err : "");
1185#endif
1186 return 0;
1187}
1188
1189/* parse the "strict-sni" bind keyword */
1190static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1191{
1192 conf->strict_sni = 1;
1193 return 0;
1194}
1195
1196/* parse the "tls-ticket-keys" bind keyword */
1197static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1198{
1199#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1200 FILE *f = NULL;
1201 int i = 0;
1202 char thisline[LINESIZE];
1203 struct tls_keys_ref *keys_ref = NULL;
1204
1205 if (!*args[cur_arg + 1]) {
1206 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1207 goto fail;
1208 }
1209
1210 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1211 if (keys_ref) {
1212 keys_ref->refcount++;
1213 conf->keys_ref = keys_ref;
1214 return 0;
1215 }
1216
1217 keys_ref = calloc(1, sizeof(*keys_ref));
1218 if (!keys_ref) {
1219 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1220 goto fail;
1221 }
1222
1223 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1224 if (!keys_ref->tlskeys) {
1225 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1226 goto fail;
1227 }
1228
1229 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1230 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1231 goto fail;
1232 }
1233
1234 keys_ref->filename = strdup(args[cur_arg + 1]);
1235 if (!keys_ref->filename) {
1236 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1237 goto fail;
1238 }
1239
1240 keys_ref->key_size_bits = 0;
1241 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1242 int len = strlen(thisline);
1243 int dec_size;
1244
1245 /* Strip newline characters from the end */
1246 if(thisline[len - 1] == '\n')
1247 thisline[--len] = 0;
1248
1249 if(thisline[len - 1] == '\r')
1250 thisline[--len] = 0;
1251
1252 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1253 if (dec_size < 0) {
1254 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1255 goto fail;
1256 }
1257 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1258 keys_ref->key_size_bits = 128;
1259 }
1260 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1261 keys_ref->key_size_bits = 256;
1262 }
1263 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1264 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1265 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1266 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1267 goto fail;
1268 }
1269 i++;
1270 }
1271
1272 if (i < TLS_TICKETS_NO) {
1273 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1274 goto fail;
1275 }
1276
1277 fclose(f);
1278
1279 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1280 i -= 2;
1281 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1282 keys_ref->unique_id = -1;
1283 keys_ref->refcount = 1;
1284 HA_RWLOCK_INIT(&keys_ref->lock);
1285 conf->keys_ref = keys_ref;
1286
Willy Tarreau2b718102021-04-21 07:32:39 +02001287 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001288
1289 return 0;
1290
1291 fail:
1292 if (f)
1293 fclose(f);
1294 if (keys_ref) {
1295 free(keys_ref->filename);
1296 free(keys_ref->tlskeys);
1297 free(keys_ref);
1298 }
1299 return ERR_ALERT | ERR_FATAL;
1300
1301#else
1302 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1303 return ERR_ALERT | ERR_FATAL;
1304#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1305}
1306
1307/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001308static 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 +02001309{
1310 if (!*args[cur_arg + 1]) {
1311 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1312 return ERR_ALERT | ERR_FATAL;
1313 }
1314
1315 if (strcmp(args[cur_arg + 1], "none") == 0)
1316 conf->verify = SSL_SOCK_VERIFY_NONE;
1317 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1318 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1319 else if (strcmp(args[cur_arg + 1], "required") == 0)
1320 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1321 else {
1322 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1323 args[cur_arg], args[cur_arg + 1]);
1324 return ERR_ALERT | ERR_FATAL;
1325 }
1326
1327 return 0;
1328}
1329static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1330{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001331 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001332}
1333
1334/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001335static 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 +02001336{
1337 conf->no_ca_names = 1;
1338 return 0;
1339}
1340static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1341{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001342 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001343}
1344
Remi Tricot-Le Breton03c5fff2022-12-20 11:11:10 +01001345
1346static int ssl_bind_parse_ocsp_update(char **args, int cur_arg, struct proxy *px,
1347 struct ssl_bind_conf *ssl_conf, int from_cli, char **err)
1348{
1349 if (!*args[cur_arg + 1]) {
1350 memprintf(err, "'%s' : expecting <on|off>", args[cur_arg]);
1351 return ERR_ALERT | ERR_FATAL;
1352 }
1353
1354 if (strcmp(args[cur_arg + 1], "on") == 0)
1355 ssl_conf->ocsp_update = SSL_SOCK_OCSP_UPDATE_ON;
1356 else if (strcmp(args[cur_arg + 1], "off") == 0)
1357 ssl_conf->ocsp_update = SSL_SOCK_OCSP_UPDATE_OFF;
1358 else {
1359 memprintf(err, "'%s' : expecting <on|off>", args[cur_arg]);
1360 return ERR_ALERT | ERR_FATAL;
1361 }
1362
Remi Tricot-Le Bretonaff82772022-12-20 11:11:14 +01001363 if (ssl_conf->ocsp_update == SSL_SOCK_OCSP_UPDATE_ON) {
1364 /* We might need to create the main ocsp update task */
1365 int ret = ssl_create_ocsp_update_task(err);
1366 if (ret)
1367 return ret;
1368 }
1369
Remi Tricot-Le Breton03c5fff2022-12-20 11:11:10 +01001370 return 0;
1371}
1372
1373
William Lallemanddad31052020-05-14 17:47:32 +02001374/***************************** "server" keywords Parsing ********************************************/
1375
1376/* parse the "npn" bind keyword */
1377static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1378{
1379#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1380 char *p1, *p2;
1381
1382 if (!*args[*cur_arg + 1]) {
1383 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1384 return ERR_ALERT | ERR_FATAL;
1385 }
1386
1387 free(newsrv->ssl_ctx.npn_str);
1388
1389 /* the NPN string is built as a suite of (<len> <name>)*,
1390 * so we reuse each comma to store the next <len> and need
1391 * one more for the end of the string.
1392 */
1393 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1394 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001395 if (!newsrv->ssl_ctx.npn_str) {
1396 memprintf(err, "out of memory");
1397 return ERR_ALERT | ERR_FATAL;
1398 }
1399
William Lallemanddad31052020-05-14 17:47:32 +02001400 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1401 newsrv->ssl_ctx.npn_len);
1402
1403 /* replace commas with the name length */
1404 p1 = newsrv->ssl_ctx.npn_str;
1405 p2 = p1 + 1;
1406 while (1) {
1407 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1408 newsrv->ssl_ctx.npn_len - (p1 + 1));
1409 if (!p2)
1410 p2 = p1 + 1 + strlen(p1 + 1);
1411
1412 if (p2 - (p1 + 1) > 255) {
1413 *p2 = '\0';
1414 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1415 return ERR_ALERT | ERR_FATAL;
1416 }
1417
1418 *p1 = p2 - (p1 + 1);
1419 p1 = p2;
1420
1421 if (!*p2)
1422 break;
1423
1424 *(p2++) = '\0';
1425 }
1426 return 0;
1427#else
1428 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1429 return ERR_ALERT | ERR_FATAL;
1430#endif
1431}
1432
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001433#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1434static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1435{
1436 free(*out_alpn_str);
1437 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1438}
1439#endif
1440
1441/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001442static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1443{
1444#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001445 int ret = parse_alpn(args[*cur_arg + 1],
1446 &newsrv->ssl_ctx.alpn_str,
1447 &newsrv->ssl_ctx.alpn_len, err);
1448 if (ret)
1449 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1450 return ret;
1451#else
1452 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1453 return ERR_ALERT | ERR_FATAL;
1454#endif
1455}
William Lallemanddad31052020-05-14 17:47:32 +02001456
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001457/* parse the "check-alpn" server keyword */
1458static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1459{
1460#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1461 int ret = parse_alpn(args[*cur_arg + 1],
1462 &newsrv->check.alpn_str,
1463 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001464 if (ret)
1465 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1466 return ret;
1467#else
1468 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1469 return ERR_ALERT | ERR_FATAL;
1470#endif
1471}
1472
1473/* parse the "ca-file" server keyword */
1474static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1475{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001476 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1477
William Lallemanddad31052020-05-14 17:47:32 +02001478 if (!*args[*cur_arg + 1]) {
1479 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1480 return ERR_ALERT | ERR_FATAL;
1481 }
1482
1483 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1484 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1485 else
1486 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1487
Amaury Denoyelle48255022021-05-19 09:46:59 +02001488 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001489 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1490 return ERR_ALERT | ERR_FATAL;
1491 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001492
William Lallemanddad31052020-05-14 17:47:32 +02001493 return 0;
1494}
1495
1496/* parse the "check-sni" server keyword */
1497static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1498{
1499 if (!*args[*cur_arg + 1]) {
1500 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1501 return ERR_ALERT | ERR_FATAL;
1502 }
1503
1504 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1505 if (!newsrv->check.sni) {
1506 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1507 return ERR_ALERT | ERR_FATAL;
1508 }
1509 return 0;
1510
1511}
1512
William Dauchyfc52f522020-11-14 19:25:32 +01001513/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001514static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001515{
William Dauchyfc52f522020-11-14 19:25:32 +01001516 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1517 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001518#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001519 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001520 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001521 if (!s->ssl_ctx.ciphersuites)
1522 return 1;
1523 }
William Lallemanddad31052020-05-14 17:47:32 +02001524#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001525 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1526 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1527
1528 if (!s->ssl_ctx.methods.min)
1529 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001530
William Dauchyfc52f522020-11-14 19:25:32 +01001531 if (!s->ssl_ctx.methods.max)
1532 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001533
1534 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001535}
1536
1537/* parse the "check-ssl" server keyword */
1538static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1539{
1540 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001541 if (ssl_sock_init_srv(newsrv)) {
1542 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1543 return ERR_ALERT | ERR_FATAL;
1544 }
1545
William Lallemanddad31052020-05-14 17:47:32 +02001546 return 0;
1547}
1548
1549/* parse the "ciphers" server keyword */
1550static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1551{
1552 if (!*args[*cur_arg + 1]) {
1553 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1554 return ERR_ALERT | ERR_FATAL;
1555 }
1556
1557 free(newsrv->ssl_ctx.ciphers);
1558 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001559
1560 if (!newsrv->ssl_ctx.ciphers) {
1561 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1562 return ERR_ALERT | ERR_FATAL;
1563 }
1564
William Lallemanddad31052020-05-14 17:47:32 +02001565 return 0;
1566}
1567
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001568#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001569/* parse the "ciphersuites" server keyword */
1570static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1571{
1572 if (!*args[*cur_arg + 1]) {
1573 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1574 return ERR_ALERT | ERR_FATAL;
1575 }
1576
1577 free(newsrv->ssl_ctx.ciphersuites);
1578 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001579
1580 if (!newsrv->ssl_ctx.ciphersuites) {
1581 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1582 return ERR_ALERT | ERR_FATAL;
1583 }
1584
William Lallemanddad31052020-05-14 17:47:32 +02001585 return 0;
1586}
1587#endif
1588
1589/* parse the "crl-file" server keyword */
1590static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1591{
1592#ifndef X509_V_FLAG_CRL_CHECK
1593 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1594 return ERR_ALERT | ERR_FATAL;
1595#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001596 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1597
William Lallemanddad31052020-05-14 17:47:32 +02001598 if (!*args[*cur_arg + 1]) {
1599 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1600 return ERR_ALERT | ERR_FATAL;
1601 }
1602
1603 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1604 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1605 else
1606 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1607
Amaury Denoyellefde82602021-06-14 10:10:32 +02001608 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001609 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1610 return ERR_ALERT | ERR_FATAL;
1611 }
1612 return 0;
1613#endif
1614}
1615
1616/* parse the "crt" server keyword */
1617static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1618{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001619
William Lallemanddad31052020-05-14 17:47:32 +02001620 if (!*args[*cur_arg + 1]) {
1621 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1622 return ERR_ALERT | ERR_FATAL;
1623 }
1624
1625 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001626 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001627 else
William Lallemand2c776f12021-12-28 18:47:17 +01001628 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001629
William Lallemand2c776f12021-12-28 18:47:17 +01001630 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001631}
1632
1633/* parse the "no-check-ssl" server keyword */
1634static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1635{
1636 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001637 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001638 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1639 return 0;
1640}
1641
1642/* parse the "no-send-proxy-v2-ssl" server keyword */
1643static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1644{
1645 newsrv->pp_opts &= ~SRV_PP_V2;
1646 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1647 return 0;
1648}
1649
1650/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1651static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1652{
1653 newsrv->pp_opts &= ~SRV_PP_V2;
1654 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1655 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1656 return 0;
1657}
1658
1659/* parse the "no-ssl" server keyword */
1660static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1661{
William Dauchyf6370442020-11-14 19:25:33 +01001662 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001663 if (newsrv->use_ssl == 1) {
1664 if (ssl_sock_init_srv(newsrv)) {
1665 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1666 return ERR_ALERT | ERR_FATAL;
1667 }
1668 }
William Dauchyf6370442020-11-14 19:25:33 +01001669 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001670 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001671 }
William Lallemanddad31052020-05-14 17:47:32 +02001672 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001673 return 0;
1674}
1675
1676/* parse the "allow-0rtt" server keyword */
1677static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1678{
1679 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1680 return 0;
1681}
1682
1683/* parse the "no-ssl-reuse" server keyword */
1684static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1685{
1686 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1687 return 0;
1688}
1689
1690/* parse the "no-tls-tickets" server keyword */
1691static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1692{
1693 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1694 return 0;
1695}
1696/* parse the "send-proxy-v2-ssl" server keyword */
1697static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1698{
1699 newsrv->pp_opts |= SRV_PP_V2;
1700 newsrv->pp_opts |= SRV_PP_V2_SSL;
1701 return 0;
1702}
1703
1704/* parse the "send-proxy-v2-ssl-cn" server keyword */
1705static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1706{
1707 newsrv->pp_opts |= SRV_PP_V2;
1708 newsrv->pp_opts |= SRV_PP_V2_SSL;
1709 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1710 return 0;
1711}
1712
1713/* parse the "sni" server keyword */
1714static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1715{
1716#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1717 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1718 return ERR_ALERT | ERR_FATAL;
1719#else
1720 char *arg;
1721
1722 arg = args[*cur_arg + 1];
1723 if (!*arg) {
1724 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1725 return ERR_ALERT | ERR_FATAL;
1726 }
1727
1728 free(newsrv->sni_expr);
1729 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001730 if (!newsrv->sni_expr) {
1731 memprintf(err, "out of memory");
1732 return ERR_ALERT | ERR_FATAL;
1733 }
William Lallemanddad31052020-05-14 17:47:32 +02001734
1735 return 0;
1736#endif
1737}
1738
1739/* parse the "ssl" server keyword */
1740static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1741{
1742 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001743 if (ssl_sock_init_srv(newsrv)) {
1744 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1745 return ERR_ALERT | ERR_FATAL;
1746 }
1747
William Lallemanddad31052020-05-14 17:47:32 +02001748 return 0;
1749}
1750
1751/* parse the "ssl-reuse" server keyword */
1752static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1753{
1754 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1755 return 0;
1756}
1757
1758/* parse the "tls-tickets" server keyword */
1759static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1760{
1761 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1762 return 0;
1763}
1764
1765/* parse the "verify" server keyword */
1766static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1767{
1768 if (!*args[*cur_arg + 1]) {
1769 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1770 return ERR_ALERT | ERR_FATAL;
1771 }
1772
1773 if (strcmp(args[*cur_arg + 1], "none") == 0)
1774 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1775 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1776 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1777 else {
1778 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1779 args[*cur_arg], args[*cur_arg + 1]);
1780 return ERR_ALERT | ERR_FATAL;
1781 }
1782
1783 return 0;
1784}
1785
1786/* parse the "verifyhost" server keyword */
1787static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1788{
1789 if (!*args[*cur_arg + 1]) {
1790 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1791 return ERR_ALERT | ERR_FATAL;
1792 }
1793
1794 free(newsrv->ssl_ctx.verify_host);
1795 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1796
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001797 if (!newsrv->ssl_ctx.verify_host) {
1798 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1799 return ERR_ALERT | ERR_FATAL;
1800 }
1801
William Lallemanddad31052020-05-14 17:47:32 +02001802 return 0;
1803}
1804
1805/* parse the "ssl-default-bind-options" keyword in global section */
1806static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001807 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001808 char **err) {
1809 int i = 1;
1810
1811 if (*(args[i]) == 0) {
1812 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1813 return -1;
1814 }
1815 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001816 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001817 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001818 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001819 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001820 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001821 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1822 i++;
1823 else {
1824 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1825 return -1;
1826 }
1827 }
1828 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1829 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1830 return -1;
1831 }
1832 i++;
1833 }
1834 return 0;
1835}
1836
1837/* parse the "ssl-default-server-options" keyword in global section */
1838static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001839 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001840 char **err) {
1841 int i = 1;
1842
1843 if (*(args[i]) == 0) {
1844 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1845 return -1;
1846 }
1847 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001848 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001849 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001850 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001851 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1852 i++;
1853 else {
1854 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1855 return -1;
1856 }
1857 }
1858 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1859 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1860 return -1;
1861 }
1862 i++;
1863 }
1864 return 0;
1865}
1866
1867/* parse the "ca-base" / "crt-base" keywords in global section.
1868 * Returns <0 on alert, >0 on warning, 0 on success.
1869 */
1870static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001871 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001872 char **err)
1873{
1874 char **target;
1875
1876 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1877
1878 if (too_many_args(1, args, err, NULL))
1879 return -1;
1880
1881 if (*target) {
1882 memprintf(err, "'%s' already specified.", args[0]);
1883 return -1;
1884 }
1885
1886 if (*(args[1]) == 0) {
1887 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1888 return -1;
1889 }
1890 *target = strdup(args[1]);
1891 return 0;
1892}
1893
1894/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1895static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001896 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001897 char **err)
1898{
William Lallemand9a1d8392020-08-10 17:28:23 +02001899#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001900 global_ssl.skip_self_issued_ca = 1;
1901 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001902#else
1903 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1904 return -1;
1905#endif
William Lallemanddad31052020-05-14 17:47:32 +02001906}
1907
1908
1909
1910
1911
1912/* Note: must not be declared <const> as its list will be overwritten.
1913 * Please take care of keeping this list alphabetically sorted, doing so helps
1914 * all code contributors.
1915 * Optional keywords are also declared with a NULL ->parse() function so that
1916 * the config parser can report an appropriate error when a known keyword was
1917 * not enabled.
1918 */
1919
1920/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1921 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1922struct ssl_bind_kw ssl_bind_kws[] = {
1923 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1924 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1925 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1926 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1927 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001928#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001929 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1930#endif
1931 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1932 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1933 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1934 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1935 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1936 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1937 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1938 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
Remi Tricot-Le Breton03c5fff2022-12-20 11:11:10 +01001939 { "ocsp-update", ssl_bind_parse_ocsp_update, 1 }, /* ocsp update mode (on or off) */
William Lallemanddad31052020-05-14 17:47:32 +02001940 { NULL, NULL, 0 },
1941};
1942
1943/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1944
1945static struct bind_kw_list bind_kws = { "SSL", { }, {
1946 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1947 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1948 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1949 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1950 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1951 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1952 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1953 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001954#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001955 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1956#endif
1957 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1958 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1959 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1960 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1961 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1962 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1963 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1964 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1965 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1966 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1967 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1968 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1969 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1970 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1971 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1972 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1973 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1974 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1975 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1976 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1977 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1978 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1979 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1980 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1981 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1982 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1983 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1984 { NULL, NULL, 0 },
1985}};
1986
1987INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1988
1989/* Note: must not be declared <const> as its list will be overwritten.
1990 * Please take care of keeping this list alphabetically sorted, doing so helps
1991 * all code contributors.
1992 * Optional keywords are also declared with a NULL ->parse() function so that
1993 * the config parser can report an appropriate error when a known keyword was
1994 * not enabled.
1995 */
1996static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001997 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1998 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001999 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02002000 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
2001 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
2002 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002003 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05002004#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002005 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02002006#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02002007 { "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 +02002008 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002009 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
2010 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
2011 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
2012 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
2013 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01002014 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
2015 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
2016 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
2017 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002018 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
2019 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
2020 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
2021 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
2022 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
2023 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
2024 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
2025 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
2026 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
2027 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
2028 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02002029 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002030 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
2031 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01002032 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002033 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
2034 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
2035 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02002036 { NULL, NULL, 0, 0 },
2037}};
2038
2039INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
2040
2041static struct cfg_kw_list cfg_kws = {ILH, {
2042 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
2043 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
2044 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
2045 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
2046 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
2047 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
2048#ifndef OPENSSL_NO_DH
2049 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
2050#endif
2051 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
William Lallemandd7bfbe22022-04-11 18:41:24 +02002052#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +02002053 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
2054#endif
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002055#ifdef HAVE_SSL_PROVIDERS
2056 { CFG_GLOBAL, "ssl-propquery", ssl_parse_global_ssl_propquery },
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +02002057 { CFG_GLOBAL, "ssl-provider", ssl_parse_global_ssl_provider },
Remi Tricot-Le Bretonccc03552022-05-17 15:18:37 +02002058 { CFG_GLOBAL, "ssl-provider-path", ssl_parse_global_ssl_provider_path },
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002059#endif
William Lallemanddad31052020-05-14 17:47:32 +02002060 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
2061 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
2062#ifndef OPENSSL_NO_DH
2063 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
2064#endif
2065 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
2066 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
2067 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
Thomas Prückl10243932022-04-27 13:04:54 +02002068 { CFG_GLOBAL, "tune.ssl.hard-maxrecord", ssl_parse_global_int },
William Lallemanddad31052020-05-14 17:47:32 +02002069 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02002070 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
2071 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02002072 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02002073 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
2074 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05002075#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02002076 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
2077#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05002078#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02002079 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
2080 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
2081#endif
2082 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02002083 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02002084 { 0, NULL, NULL },
2085}};
2086
2087INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);