blob: d9e93e44071da5d22a9f63a991e3f0946b6d648e [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
839 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100840 ignerr = conf->ca_ignerr_bitfield;
William Lallemanddad31052020-05-14 17:47:32 +0200841
842 if (strcmp(p, "all") == 0) {
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100843 cert_ignerr_bitfield_set_all(ignerr);
William Lallemanddad31052020-05-14 17:47:32 +0200844 return 0;
845 }
846
William Lallemandf813dab2022-11-14 11:36:11 +0100847 /* copy the string to be able to dump the complete one in case of
848 * error, because strtok_r is writing \0 inside. */
849 str = strdup(p);
850 if (!str) {
851 memprintf(err, "'%s' : Could not allocate memory", args[cur_arg]);
852 return ERR_ALERT | ERR_FATAL;
853 }
854
William Lallemand960fb742022-11-03 16:31:50 +0100855 s1 = str;
856 while ((token = strtok_r(s1, ",", &s2))) {
857 s1 = NULL;
William Lallemand960fb742022-11-03 16:31:50 +0100858 if (isdigit((int)*token)) {
859 code = atoi(token);
860 if ((code <= 0) || (code > SSL_MAX_VFY_ERROR_CODE)) {
861 memprintf(err, "'%s' : ID '%d' out of range (1..%d) in error IDs list '%s'",
862 args[cur_arg], code, SSL_MAX_VFY_ERROR_CODE, args[cur_arg + 1]);
863 free(str);
864 return ERR_ALERT | ERR_FATAL;
865 }
866 } else {
867 code = x509_v_err_str_to_int(token);
868 if (code < 0) {
869 memprintf(err, "'%s' : error constant '%s' unknown in error IDs list '%s'",
870 args[cur_arg], token, args[cur_arg + 1]);
871 free(str);
872 return ERR_ALERT | ERR_FATAL;
873 }
William Lallemanddad31052020-05-14 17:47:32 +0200874 }
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100875 cert_ignerr_bitfield_set(ignerr, code);
William Lallemanddad31052020-05-14 17:47:32 +0200876 }
877
William Lallemand960fb742022-11-03 16:31:50 +0100878 free(str);
William Lallemanddad31052020-05-14 17:47:32 +0200879 return 0;
880}
881
882/* parse tls_method_options "no-xxx" and "force-xxx" */
883static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
884{
885 uint16_t v;
886 char *p;
887 p = strchr(arg, '-');
888 if (!p)
889 goto fail;
890 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100891 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200892 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100893 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200894 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100895 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200896 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100897 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200898 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100899 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200900 v = CONF_TLSV13;
901 else
902 goto fail;
903 if (!strncmp(arg, "no-", 3))
904 methods->flags |= methodVersions[v].flag;
905 else if (!strncmp(arg, "force-", 6))
906 methods->min = methods->max = v;
907 else
908 goto fail;
909 return 0;
910 fail:
911 memprintf(err, "'%s' : option not implemented", arg);
912 return ERR_ALERT | ERR_FATAL;
913}
914
915static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
916{
917 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
918}
919
920static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
921{
922 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
923}
924
925/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
926static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
927{
928 uint16_t i, v = 0;
929 char *argv = args[cur_arg + 1];
930 if (!*argv) {
931 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
932 return ERR_ALERT | ERR_FATAL;
933 }
934 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100935 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200936 v = i;
937 if (!v) {
938 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
939 return ERR_ALERT | ERR_FATAL;
940 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100941 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200942 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100943 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200944 methods->max = v;
945 else {
946 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
947 return ERR_ALERT | ERR_FATAL;
948 }
949 return 0;
950}
951
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100952static 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 +0200953{
William Lallemand8177ad92020-05-20 16:49:02 +0200954 int ret;
955
William Lallemanddad31052020-05-14 17:47:32 +0200956#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
957 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
958#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200959 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
960 if (ret != ERR_NONE)
961 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200962
William Lallemand8177ad92020-05-20 16:49:02 +0200963 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
964 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
965
966 return ret;
967}
William Lallemanddad31052020-05-14 17:47:32 +0200968static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
969{
970 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
971}
972
973static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
974{
975 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
976}
977
978/* parse the "no-tls-tickets" bind keyword */
979static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
980{
981 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
982 return 0;
983}
984
985/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100986static 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 +0200987{
988 conf->early_data = 1;
989 return 0;
990}
991
992static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
993{
994 conf->ssl_conf.early_data = 1;
995 return 0;
996}
997
998/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100999static 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 +02001000{
1001#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1002 char *p1, *p2;
1003
1004 if (!*args[cur_arg + 1]) {
1005 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
1006 return ERR_ALERT | ERR_FATAL;
1007 }
1008
1009 free(conf->npn_str);
1010
1011 /* the NPN string is built as a suite of (<len> <name>)*,
1012 * so we reuse each comma to store the next <len> and need
1013 * one more for the end of the string.
1014 */
1015 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
1016 conf->npn_str = calloc(1, conf->npn_len + 1);
1017 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
1018
1019 /* replace commas with the name length */
1020 p1 = conf->npn_str;
1021 p2 = p1 + 1;
1022 while (1) {
1023 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
1024 if (!p2)
1025 p2 = p1 + 1 + strlen(p1 + 1);
1026
1027 if (p2 - (p1 + 1) > 255) {
1028 *p2 = '\0';
1029 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
1030 return ERR_ALERT | ERR_FATAL;
1031 }
1032
1033 *p1 = p2 - (p1 + 1);
1034 p1 = p2;
1035
1036 if (!*p2)
1037 break;
1038
1039 *(p2++) = '\0';
1040 }
1041 return 0;
1042#else
1043 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
1044 return ERR_ALERT | ERR_FATAL;
1045#endif
1046}
1047
1048static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1049{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001050 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001051}
1052
1053
1054/* Parses a alpn string and converts it to the right format for the SSL api */
1055int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
1056{
1057 char *p1, *p2, *alpn = NULL;
1058 int len, ret = 0;
1059
1060 *alpn_str = NULL;
1061 *alpn_len = 0;
1062
1063 if (!*arg) {
1064 memprintf(err, "missing the comma-delimited ALPN protocol suite");
1065 goto error;
1066 }
1067
1068 /* the ALPN string is built as a suite of (<len> <name>)*,
1069 * so we reuse each comma to store the next <len> and need
1070 * one more for the end of the string.
1071 */
1072 len = strlen(arg) + 1;
1073 alpn = calloc(1, len+1);
1074 if (!alpn) {
1075 memprintf(err, "'%s' : out of memory", arg);
1076 goto error;
1077 }
1078 memcpy(alpn+1, arg, len);
1079
1080 /* replace commas with the name length */
1081 p1 = alpn;
1082 p2 = p1 + 1;
1083 while (1) {
1084 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1085 if (!p2)
1086 p2 = p1 + 1 + strlen(p1 + 1);
1087
1088 if (p2 - (p1 + 1) > 255) {
1089 *p2 = '\0';
1090 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1091 goto error;
1092 }
1093
1094 *p1 = p2 - (p1 + 1);
1095 p1 = p2;
1096
1097 if (!*p2)
1098 break;
1099
1100 *(p2++) = '\0';
1101 }
1102
1103 *alpn_str = alpn;
1104 *alpn_len = len;
1105
1106 out:
1107 return ret;
1108
1109 error:
1110 free(alpn);
1111 ret = ERR_ALERT | ERR_FATAL;
1112 goto out;
1113}
1114
1115/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001116static 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 +02001117{
1118#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1119 int ret;
1120
1121 free(conf->alpn_str);
1122
1123 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1124 if (ret)
1125 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1126 return ret;
1127#else
1128 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1129 return ERR_ALERT | ERR_FATAL;
1130#endif
1131}
1132
1133static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1134{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001135 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001136}
1137
1138/* parse the "ssl" bind keyword */
1139static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1140{
Willy Tarreau11ba4042022-05-20 15:56:32 +02001141 conf->options |= BC_O_USE_SSL;
William Lallemanddad31052020-05-14 17:47:32 +02001142
1143 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1144 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001145#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001146 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1147 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1148#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001149#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001150 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1151 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1152#endif
1153 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1154 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1155 if (!conf->ssl_conf.ssl_methods.min)
1156 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1157 if (!conf->ssl_conf.ssl_methods.max)
1158 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1159
1160 return 0;
1161}
1162
1163/* parse the "prefer-client-ciphers" bind keyword */
1164static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1165{
1166 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1167 return 0;
1168}
1169
1170/* parse the "generate-certificates" bind keyword */
1171static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1172{
1173#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau1ea6e6a2022-05-20 16:03:18 +02001174 conf->options |= BC_O_GENERATE_CERTS;
William Lallemanddad31052020-05-14 17:47:32 +02001175#else
1176 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1177 err && *err ? *err : "");
1178#endif
1179 return 0;
1180}
1181
1182/* parse the "strict-sni" bind keyword */
1183static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1184{
1185 conf->strict_sni = 1;
1186 return 0;
1187}
1188
1189/* parse the "tls-ticket-keys" bind keyword */
1190static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1191{
1192#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1193 FILE *f = NULL;
1194 int i = 0;
1195 char thisline[LINESIZE];
1196 struct tls_keys_ref *keys_ref = NULL;
1197
1198 if (!*args[cur_arg + 1]) {
1199 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1200 goto fail;
1201 }
1202
1203 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1204 if (keys_ref) {
1205 keys_ref->refcount++;
1206 conf->keys_ref = keys_ref;
1207 return 0;
1208 }
1209
1210 keys_ref = calloc(1, sizeof(*keys_ref));
1211 if (!keys_ref) {
1212 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1213 goto fail;
1214 }
1215
1216 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1217 if (!keys_ref->tlskeys) {
1218 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1219 goto fail;
1220 }
1221
1222 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1223 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1224 goto fail;
1225 }
1226
1227 keys_ref->filename = strdup(args[cur_arg + 1]);
1228 if (!keys_ref->filename) {
1229 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1230 goto fail;
1231 }
1232
1233 keys_ref->key_size_bits = 0;
1234 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1235 int len = strlen(thisline);
1236 int dec_size;
1237
1238 /* Strip newline characters from the end */
1239 if(thisline[len - 1] == '\n')
1240 thisline[--len] = 0;
1241
1242 if(thisline[len - 1] == '\r')
1243 thisline[--len] = 0;
1244
1245 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1246 if (dec_size < 0) {
1247 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1248 goto fail;
1249 }
1250 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1251 keys_ref->key_size_bits = 128;
1252 }
1253 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1254 keys_ref->key_size_bits = 256;
1255 }
1256 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1257 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1258 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1259 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1260 goto fail;
1261 }
1262 i++;
1263 }
1264
1265 if (i < TLS_TICKETS_NO) {
1266 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1267 goto fail;
1268 }
1269
1270 fclose(f);
1271
1272 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1273 i -= 2;
1274 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1275 keys_ref->unique_id = -1;
1276 keys_ref->refcount = 1;
1277 HA_RWLOCK_INIT(&keys_ref->lock);
1278 conf->keys_ref = keys_ref;
1279
Willy Tarreau2b718102021-04-21 07:32:39 +02001280 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001281
1282 return 0;
1283
1284 fail:
1285 if (f)
1286 fclose(f);
1287 if (keys_ref) {
1288 free(keys_ref->filename);
1289 free(keys_ref->tlskeys);
1290 free(keys_ref);
1291 }
1292 return ERR_ALERT | ERR_FATAL;
1293
1294#else
1295 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1296 return ERR_ALERT | ERR_FATAL;
1297#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1298}
1299
1300/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001301static 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 +02001302{
1303 if (!*args[cur_arg + 1]) {
1304 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1305 return ERR_ALERT | ERR_FATAL;
1306 }
1307
1308 if (strcmp(args[cur_arg + 1], "none") == 0)
1309 conf->verify = SSL_SOCK_VERIFY_NONE;
1310 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1311 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1312 else if (strcmp(args[cur_arg + 1], "required") == 0)
1313 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1314 else {
1315 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1316 args[cur_arg], args[cur_arg + 1]);
1317 return ERR_ALERT | ERR_FATAL;
1318 }
1319
1320 return 0;
1321}
1322static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1323{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001324 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001325}
1326
1327/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001328static 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 +02001329{
1330 conf->no_ca_names = 1;
1331 return 0;
1332}
1333static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1334{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001335 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001336}
1337
1338/***************************** "server" keywords Parsing ********************************************/
1339
1340/* parse the "npn" bind keyword */
1341static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1342{
1343#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1344 char *p1, *p2;
1345
1346 if (!*args[*cur_arg + 1]) {
1347 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1348 return ERR_ALERT | ERR_FATAL;
1349 }
1350
1351 free(newsrv->ssl_ctx.npn_str);
1352
1353 /* the NPN string is built as a suite of (<len> <name>)*,
1354 * so we reuse each comma to store the next <len> and need
1355 * one more for the end of the string.
1356 */
1357 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1358 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001359 if (!newsrv->ssl_ctx.npn_str) {
1360 memprintf(err, "out of memory");
1361 return ERR_ALERT | ERR_FATAL;
1362 }
1363
William Lallemanddad31052020-05-14 17:47:32 +02001364 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1365 newsrv->ssl_ctx.npn_len);
1366
1367 /* replace commas with the name length */
1368 p1 = newsrv->ssl_ctx.npn_str;
1369 p2 = p1 + 1;
1370 while (1) {
1371 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1372 newsrv->ssl_ctx.npn_len - (p1 + 1));
1373 if (!p2)
1374 p2 = p1 + 1 + strlen(p1 + 1);
1375
1376 if (p2 - (p1 + 1) > 255) {
1377 *p2 = '\0';
1378 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1379 return ERR_ALERT | ERR_FATAL;
1380 }
1381
1382 *p1 = p2 - (p1 + 1);
1383 p1 = p2;
1384
1385 if (!*p2)
1386 break;
1387
1388 *(p2++) = '\0';
1389 }
1390 return 0;
1391#else
1392 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1393 return ERR_ALERT | ERR_FATAL;
1394#endif
1395}
1396
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001397#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1398static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1399{
1400 free(*out_alpn_str);
1401 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1402}
1403#endif
1404
1405/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001406static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1407{
1408#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001409 int ret = parse_alpn(args[*cur_arg + 1],
1410 &newsrv->ssl_ctx.alpn_str,
1411 &newsrv->ssl_ctx.alpn_len, err);
1412 if (ret)
1413 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1414 return ret;
1415#else
1416 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1417 return ERR_ALERT | ERR_FATAL;
1418#endif
1419}
William Lallemanddad31052020-05-14 17:47:32 +02001420
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001421/* parse the "check-alpn" server keyword */
1422static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1423{
1424#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1425 int ret = parse_alpn(args[*cur_arg + 1],
1426 &newsrv->check.alpn_str,
1427 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001428 if (ret)
1429 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1430 return ret;
1431#else
1432 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1433 return ERR_ALERT | ERR_FATAL;
1434#endif
1435}
1436
1437/* parse the "ca-file" server keyword */
1438static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1439{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001440 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1441
William Lallemanddad31052020-05-14 17:47:32 +02001442 if (!*args[*cur_arg + 1]) {
1443 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1444 return ERR_ALERT | ERR_FATAL;
1445 }
1446
1447 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1448 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1449 else
1450 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1451
Amaury Denoyelle48255022021-05-19 09:46:59 +02001452 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001453 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1454 return ERR_ALERT | ERR_FATAL;
1455 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001456
William Lallemanddad31052020-05-14 17:47:32 +02001457 return 0;
1458}
1459
1460/* parse the "check-sni" server keyword */
1461static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1462{
1463 if (!*args[*cur_arg + 1]) {
1464 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1465 return ERR_ALERT | ERR_FATAL;
1466 }
1467
1468 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1469 if (!newsrv->check.sni) {
1470 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1471 return ERR_ALERT | ERR_FATAL;
1472 }
1473 return 0;
1474
1475}
1476
William Dauchyfc52f522020-11-14 19:25:32 +01001477/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001478static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001479{
William Dauchyfc52f522020-11-14 19:25:32 +01001480 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1481 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001482#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001483 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001484 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001485 if (!s->ssl_ctx.ciphersuites)
1486 return 1;
1487 }
William Lallemanddad31052020-05-14 17:47:32 +02001488#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001489 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1490 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1491
1492 if (!s->ssl_ctx.methods.min)
1493 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001494
William Dauchyfc52f522020-11-14 19:25:32 +01001495 if (!s->ssl_ctx.methods.max)
1496 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001497
1498 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001499}
1500
1501/* parse the "check-ssl" server keyword */
1502static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1503{
1504 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001505 if (ssl_sock_init_srv(newsrv)) {
1506 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1507 return ERR_ALERT | ERR_FATAL;
1508 }
1509
William Lallemanddad31052020-05-14 17:47:32 +02001510 return 0;
1511}
1512
1513/* parse the "ciphers" server keyword */
1514static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1515{
1516 if (!*args[*cur_arg + 1]) {
1517 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1518 return ERR_ALERT | ERR_FATAL;
1519 }
1520
1521 free(newsrv->ssl_ctx.ciphers);
1522 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001523
1524 if (!newsrv->ssl_ctx.ciphers) {
1525 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1526 return ERR_ALERT | ERR_FATAL;
1527 }
1528
William Lallemanddad31052020-05-14 17:47:32 +02001529 return 0;
1530}
1531
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001532#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001533/* parse the "ciphersuites" server keyword */
1534static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1535{
1536 if (!*args[*cur_arg + 1]) {
1537 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1538 return ERR_ALERT | ERR_FATAL;
1539 }
1540
1541 free(newsrv->ssl_ctx.ciphersuites);
1542 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001543
1544 if (!newsrv->ssl_ctx.ciphersuites) {
1545 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1546 return ERR_ALERT | ERR_FATAL;
1547 }
1548
William Lallemanddad31052020-05-14 17:47:32 +02001549 return 0;
1550}
1551#endif
1552
1553/* parse the "crl-file" server keyword */
1554static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1555{
1556#ifndef X509_V_FLAG_CRL_CHECK
1557 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1558 return ERR_ALERT | ERR_FATAL;
1559#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001560 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1561
William Lallemanddad31052020-05-14 17:47:32 +02001562 if (!*args[*cur_arg + 1]) {
1563 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1564 return ERR_ALERT | ERR_FATAL;
1565 }
1566
1567 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1568 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1569 else
1570 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1571
Amaury Denoyellefde82602021-06-14 10:10:32 +02001572 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001573 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1574 return ERR_ALERT | ERR_FATAL;
1575 }
1576 return 0;
1577#endif
1578}
1579
1580/* parse the "crt" server keyword */
1581static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1582{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001583
William Lallemanddad31052020-05-14 17:47:32 +02001584 if (!*args[*cur_arg + 1]) {
1585 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1586 return ERR_ALERT | ERR_FATAL;
1587 }
1588
1589 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001590 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001591 else
William Lallemand2c776f12021-12-28 18:47:17 +01001592 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001593
William Lallemand2c776f12021-12-28 18:47:17 +01001594 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001595}
1596
1597/* parse the "no-check-ssl" server keyword */
1598static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1599{
1600 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001601 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001602 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1603 return 0;
1604}
1605
1606/* parse the "no-send-proxy-v2-ssl" server keyword */
1607static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1608{
1609 newsrv->pp_opts &= ~SRV_PP_V2;
1610 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1611 return 0;
1612}
1613
1614/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1615static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1616{
1617 newsrv->pp_opts &= ~SRV_PP_V2;
1618 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1619 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1620 return 0;
1621}
1622
1623/* parse the "no-ssl" server keyword */
1624static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1625{
William Dauchyf6370442020-11-14 19:25:33 +01001626 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001627 if (newsrv->use_ssl == 1) {
1628 if (ssl_sock_init_srv(newsrv)) {
1629 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1630 return ERR_ALERT | ERR_FATAL;
1631 }
1632 }
William Dauchyf6370442020-11-14 19:25:33 +01001633 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001634 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001635 }
William Lallemanddad31052020-05-14 17:47:32 +02001636 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001637 return 0;
1638}
1639
1640/* parse the "allow-0rtt" server keyword */
1641static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1642{
1643 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1644 return 0;
1645}
1646
1647/* parse the "no-ssl-reuse" server keyword */
1648static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1649{
1650 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1651 return 0;
1652}
1653
1654/* parse the "no-tls-tickets" server keyword */
1655static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1656{
1657 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1658 return 0;
1659}
1660/* parse the "send-proxy-v2-ssl" server keyword */
1661static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1662{
1663 newsrv->pp_opts |= SRV_PP_V2;
1664 newsrv->pp_opts |= SRV_PP_V2_SSL;
1665 return 0;
1666}
1667
1668/* parse the "send-proxy-v2-ssl-cn" server keyword */
1669static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1670{
1671 newsrv->pp_opts |= SRV_PP_V2;
1672 newsrv->pp_opts |= SRV_PP_V2_SSL;
1673 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1674 return 0;
1675}
1676
1677/* parse the "sni" server keyword */
1678static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1679{
1680#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1681 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1682 return ERR_ALERT | ERR_FATAL;
1683#else
1684 char *arg;
1685
1686 arg = args[*cur_arg + 1];
1687 if (!*arg) {
1688 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1689 return ERR_ALERT | ERR_FATAL;
1690 }
1691
1692 free(newsrv->sni_expr);
1693 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001694 if (!newsrv->sni_expr) {
1695 memprintf(err, "out of memory");
1696 return ERR_ALERT | ERR_FATAL;
1697 }
William Lallemanddad31052020-05-14 17:47:32 +02001698
1699 return 0;
1700#endif
1701}
1702
1703/* parse the "ssl" server keyword */
1704static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1705{
1706 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001707 if (ssl_sock_init_srv(newsrv)) {
1708 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1709 return ERR_ALERT | ERR_FATAL;
1710 }
1711
William Lallemanddad31052020-05-14 17:47:32 +02001712 return 0;
1713}
1714
1715/* parse the "ssl-reuse" server keyword */
1716static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1717{
1718 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1719 return 0;
1720}
1721
1722/* parse the "tls-tickets" server keyword */
1723static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1724{
1725 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1726 return 0;
1727}
1728
1729/* parse the "verify" server keyword */
1730static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1731{
1732 if (!*args[*cur_arg + 1]) {
1733 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1734 return ERR_ALERT | ERR_FATAL;
1735 }
1736
1737 if (strcmp(args[*cur_arg + 1], "none") == 0)
1738 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1739 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1740 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1741 else {
1742 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1743 args[*cur_arg], args[*cur_arg + 1]);
1744 return ERR_ALERT | ERR_FATAL;
1745 }
1746
1747 return 0;
1748}
1749
1750/* parse the "verifyhost" server keyword */
1751static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1752{
1753 if (!*args[*cur_arg + 1]) {
1754 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1755 return ERR_ALERT | ERR_FATAL;
1756 }
1757
1758 free(newsrv->ssl_ctx.verify_host);
1759 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1760
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001761 if (!newsrv->ssl_ctx.verify_host) {
1762 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1763 return ERR_ALERT | ERR_FATAL;
1764 }
1765
William Lallemanddad31052020-05-14 17:47:32 +02001766 return 0;
1767}
1768
1769/* parse the "ssl-default-bind-options" keyword in global section */
1770static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001771 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001772 char **err) {
1773 int i = 1;
1774
1775 if (*(args[i]) == 0) {
1776 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1777 return -1;
1778 }
1779 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001780 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001781 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001782 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001783 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001784 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001785 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1786 i++;
1787 else {
1788 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1789 return -1;
1790 }
1791 }
1792 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1793 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1794 return -1;
1795 }
1796 i++;
1797 }
1798 return 0;
1799}
1800
1801/* parse the "ssl-default-server-options" keyword in global section */
1802static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001803 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001804 char **err) {
1805 int i = 1;
1806
1807 if (*(args[i]) == 0) {
1808 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1809 return -1;
1810 }
1811 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001812 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001813 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001814 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001815 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1816 i++;
1817 else {
1818 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1819 return -1;
1820 }
1821 }
1822 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1823 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1824 return -1;
1825 }
1826 i++;
1827 }
1828 return 0;
1829}
1830
1831/* parse the "ca-base" / "crt-base" keywords in global section.
1832 * Returns <0 on alert, >0 on warning, 0 on success.
1833 */
1834static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001835 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001836 char **err)
1837{
1838 char **target;
1839
1840 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1841
1842 if (too_many_args(1, args, err, NULL))
1843 return -1;
1844
1845 if (*target) {
1846 memprintf(err, "'%s' already specified.", args[0]);
1847 return -1;
1848 }
1849
1850 if (*(args[1]) == 0) {
1851 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1852 return -1;
1853 }
1854 *target = strdup(args[1]);
1855 return 0;
1856}
1857
1858/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1859static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001860 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001861 char **err)
1862{
William Lallemand9a1d8392020-08-10 17:28:23 +02001863#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001864 global_ssl.skip_self_issued_ca = 1;
1865 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001866#else
1867 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1868 return -1;
1869#endif
William Lallemanddad31052020-05-14 17:47:32 +02001870}
1871
1872
1873
1874
1875
1876/* Note: must not be declared <const> as its list will be overwritten.
1877 * Please take care of keeping this list alphabetically sorted, doing so helps
1878 * all code contributors.
1879 * Optional keywords are also declared with a NULL ->parse() function so that
1880 * the config parser can report an appropriate error when a known keyword was
1881 * not enabled.
1882 */
1883
1884/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1885 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1886struct ssl_bind_kw ssl_bind_kws[] = {
1887 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1888 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1889 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1890 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1891 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001892#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001893 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1894#endif
1895 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1896 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1897 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1898 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1899 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1900 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1901 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1902 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1903 { NULL, NULL, 0 },
1904};
1905
1906/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1907
1908static struct bind_kw_list bind_kws = { "SSL", { }, {
1909 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1910 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1911 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1912 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1913 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1914 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1915 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1916 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001917#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001918 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1919#endif
1920 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1921 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1922 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1923 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1924 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1925 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1926 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1927 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1928 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1929 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1930 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1931 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1932 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1933 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1934 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1935 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1936 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1937 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1938 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1939 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1940 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1941 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1942 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1943 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1944 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1945 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1946 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1947 { NULL, NULL, 0 },
1948}};
1949
1950INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1951
1952/* Note: must not be declared <const> as its list will be overwritten.
1953 * Please take care of keeping this list alphabetically sorted, doing so helps
1954 * all code contributors.
1955 * Optional keywords are also declared with a NULL ->parse() function so that
1956 * the config parser can report an appropriate error when a known keyword was
1957 * not enabled.
1958 */
1959static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001960 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1961 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001962 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001963 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1964 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1965 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001966 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001967#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001968 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001969#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001970 { "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 +02001971 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001972 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1973 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1974 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1975 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1976 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001977 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1978 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1979 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1980 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001981 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1982 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1983 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1984 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1985 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1986 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1987 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1988 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1989 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1990 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1991 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001992 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001993 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1994 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001995 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001996 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1997 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
1998 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001999 { NULL, NULL, 0, 0 },
2000}};
2001
2002INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
2003
2004static struct cfg_kw_list cfg_kws = {ILH, {
2005 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
2006 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
2007 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
2008 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
2009 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
2010 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
2011#ifndef OPENSSL_NO_DH
2012 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
2013#endif
2014 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
William Lallemandd7bfbe22022-04-11 18:41:24 +02002015#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +02002016 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
2017#endif
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002018#ifdef HAVE_SSL_PROVIDERS
2019 { CFG_GLOBAL, "ssl-propquery", ssl_parse_global_ssl_propquery },
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +02002020 { CFG_GLOBAL, "ssl-provider", ssl_parse_global_ssl_provider },
Remi Tricot-Le Bretonccc03552022-05-17 15:18:37 +02002021 { CFG_GLOBAL, "ssl-provider-path", ssl_parse_global_ssl_provider_path },
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002022#endif
William Lallemanddad31052020-05-14 17:47:32 +02002023 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
2024 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
2025#ifndef OPENSSL_NO_DH
2026 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
2027#endif
2028 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
2029 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
2030 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
Thomas Prückl10243932022-04-27 13:04:54 +02002031 { CFG_GLOBAL, "tune.ssl.hard-maxrecord", ssl_parse_global_int },
William Lallemanddad31052020-05-14 17:47:32 +02002032 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02002033 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
2034 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02002035 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02002036 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
2037 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05002038#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02002039 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
2040#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05002041#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02002042 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
2043 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
2044#endif
2045 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02002046 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02002047 { 0, NULL, NULL },
2048}};
2049
2050INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);