blob: fad0828f2edeb16c9bfc5d792381d4a7c4781eda [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>
Willy Tarreaucc81eca2021-05-08 12:54:42 +020040#include <haproxy/tools.h>
Remi Tricot-Le Bretonaf8820a2021-04-13 10:10:37 +020041#include <haproxy/ssl_ckch.h>
William Lallemanddad31052020-05-14 17:47:32 +020042
43
44/****************** Global Section Parsing ********************************************/
45
46static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +010047 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +020048 char **err)
49{
50 char *path;
51 struct dirent **de_list;
52 int i, n;
53 struct stat buf;
54 char *end;
55 char fp[MAXPATHLEN+1];
56
57 if (too_many_args(1, args, err, NULL))
58 return -1;
59
60 path = args[1];
61 if (*path == 0 || stat(path, &buf)) {
62 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
63 err && *err ? *err : "", args[0]);
64 return -1;
65 }
66 if (S_ISDIR(buf.st_mode) == 0) {
67 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
68 err && *err ? *err : "", args[0], path);
69 return -1;
70 }
71
72 /* strip trailing slashes, including first one */
73 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
74 *end = 0;
75 /* path already parsed? */
76 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
77 return 0;
78 /* overwrite old issuers_chain_path */
79 free(global_ssl.issuers_chain_path);
80 global_ssl.issuers_chain_path = strdup(path);
81 ssl_free_global_issuers();
82
83 n = scandir(path, &de_list, 0, alphasort);
84 if (n < 0) {
85 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
86 err && *err ? *err : "", args[0], path, strerror(errno));
87 return -1;
88 }
89 for (i = 0; i < n; i++) {
90 struct dirent *de = de_list[i];
91 BIO *in = NULL;
92 char *warn = NULL;
93
94 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
95 free(de);
96 if (stat(fp, &buf) != 0) {
97 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
98 goto next;
99 }
100 if (!S_ISREG(buf.st_mode))
101 goto next;
102
103 in = BIO_new(BIO_s_file());
104 if (in == NULL)
105 goto next;
106 if (BIO_read_filename(in, fp) <= 0)
107 goto next;
108 ssl_load_global_issuer_from_BIO(in, fp, &warn);
109 if (warn) {
110 ha_warning("%s", warn);
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100111 ha_free(&warn);
William Lallemanddad31052020-05-14 17:47:32 +0200112 }
113 next:
114 if (in)
115 BIO_free(in);
116 }
117 free(de_list);
118
119 return 0;
120}
121
William Lallemanddad31052020-05-14 17:47:32 +0200122/* parse the "ssl-mode-async" keyword in global section.
123 * Returns <0 on alert, >0 on warning, 0 on success.
124 */
125static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100126 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200127 char **err)
128{
Ilya Shipitsinbdec3ba2020-11-14 01:56:34 +0500129#ifdef SSL_MODE_ASYNC
William Lallemanddad31052020-05-14 17:47:32 +0200130 global_ssl.async = 1;
131 global.ssl_used_async_engines = nb_engines;
132 return 0;
133#else
134 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
135 return -1;
136#endif
137}
138
William Lallemandd7bfbe22022-04-11 18:41:24 +0200139#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +0200140/* parse the "ssl-engine" keyword in global section.
141 * Returns <0 on alert, >0 on warning, 0 on success.
142 */
143static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100144 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200145 char **err)
146{
147 char *algo;
148 int ret = -1;
149
150 if (*(args[1]) == 0) {
151 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
152 return ret;
153 }
154
155 if (*(args[2]) == 0) {
156 /* if no list of algorithms is given, it defaults to ALL */
157 algo = strdup("ALL");
158 goto add_engine;
159 }
160
161 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
162 if (strcmp(args[2], "algo") != 0) {
163 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
164 return ret;
165 }
166
167 if (*(args[3]) == 0) {
168 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
169 return ret;
170 }
171 algo = strdup(args[3]);
172
173add_engine:
174 if (ssl_init_single_engine(args[1], algo)==0) {
175 openssl_engines_initialized++;
176 ret = 0;
177 }
178 free(algo);
179 return ret;
180}
181#endif
182
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200183#ifdef HAVE_SSL_PROVIDERS
184/* parse the "ssl-propquery" keyword in global section.
185 * Returns <0 on alert, >0 on warning, 0 on success.
186 */
187static int ssl_parse_global_ssl_propquery(char **args, int section_type, struct proxy *curpx,
188 const struct proxy *defpx, const char *file, int line,
189 char **err)
190{
191 int ret = -1;
192
193 if (*(args[1]) == 0) {
194 memprintf(err, "global statement '%s' expects a property string as an argument.", args[0]);
195 return ret;
196 }
197
198 if (EVP_set_default_properties(NULL, args[1]))
199 ret = 0;
200
201 return ret;
202}
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +0200203
204/* parse the "ssl-provider" keyword in global section.
205 * Returns <0 on alert, >0 on warning, 0 on success.
206 */
207static int ssl_parse_global_ssl_provider(char **args, int section_type, struct proxy *curpx,
208 const struct proxy *defpx, const char *file, int line,
209 char **err)
210{
211 int ret = -1;
212
213 if (*(args[1]) == 0) {
214 memprintf(err, "global statement '%s' expects a valid engine provider name as an argument.", args[0]);
215 return ret;
216 }
217
218 if (ssl_init_provider(args[1]) == 0)
219 ret = 0;
220
221 return ret;
222}
Remi Tricot-Le Bretonccc03552022-05-17 15:18:37 +0200223
224/* parse the "ssl-provider-path" keyword in global section.
225 * Returns <0 on alert, >0 on warning, 0 on success.
226 */
227static int ssl_parse_global_ssl_provider_path(char **args, int section_type, struct proxy *curpx,
228 const struct proxy *defpx, const char *file, int line,
229 char **err)
230{
231 if (*(args[1]) == 0) {
232 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
233 return -1;
234 }
235
236 OSSL_PROVIDER_set_default_search_path(NULL, args[1]);
237
238 return 0;
239}
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200240#endif
241
William Lallemanddad31052020-05-14 17:47:32 +0200242/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
243 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
244 */
245static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100246 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200247 char **err)
248{
249 char **target;
250
251 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
252
253 if (too_many_args(1, args, err, NULL))
254 return -1;
255
256 if (*(args[1]) == 0) {
257 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
258 return -1;
259 }
260
261 free(*target);
262 *target = strdup(args[1]);
263 return 0;
264}
265
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500266#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200267/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
268 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
269 */
270static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100271 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200272 char **err)
273{
274 char **target;
275
276 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
277
278 if (too_many_args(1, args, err, NULL))
279 return -1;
280
281 if (*(args[1]) == 0) {
282 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
283 return -1;
284 }
285
286 free(*target);
287 *target = strdup(args[1]);
288 return 0;
289}
290#endif
291
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500292#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200293/*
294 * parse the "ssl-default-bind-curves" keyword in a global section.
295 * Returns <0 on alert, >0 on warning, 0 on success.
296 */
297static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100298 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200299 char **err)
300{
301 char **target;
302 target = &global_ssl.listen_default_curves;
303
304 if (too_many_args(1, args, err, NULL))
305 return -1;
306
307 if (*(args[1]) == 0) {
308 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
309 return -1;
310 }
311
312 free(*target);
313 *target = strdup(args[1]);
314 return 0;
315}
316#endif
317/* parse various global tune.ssl settings consisting in positive integers.
318 * Returns <0 on alert, >0 on warning, 0 on success.
319 */
320static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100321 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200322 char **err)
323{
324 int *target;
325
326 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
327 target = &global.tune.sslcachesize;
328 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
329 target = (int *)&global_ssl.max_record;
Thomas Prückl10243932022-04-27 13:04:54 +0200330 else if (strcmp(args[0], "tune.ssl.hard-maxrecord") == 0)
331 target = (int *)&global_ssl.hard_max_record;
William Lallemanddad31052020-05-14 17:47:32 +0200332 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
333 target = &global_ssl.ctx_cache;
334 else if (strcmp(args[0], "maxsslconn") == 0)
335 target = &global.maxsslconn;
Marcin Deranek310a2602021-07-13 19:04:24 +0200336 else if (strcmp(args[0], "tune.ssl.capture-buffer-size") == 0)
337 target = &global_ssl.capture_buffer_size;
338 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0) {
339 target = &global_ssl.capture_buffer_size;
340 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",
341 file, line, args[0]);
342 }
William Lallemanddad31052020-05-14 17:47:32 +0200343 else {
344 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
345 return -1;
346 }
347
348 if (too_many_args(1, args, err, NULL))
349 return -1;
350
351 if (*(args[1]) == 0) {
352 memprintf(err, "'%s' expects an integer argument.", args[0]);
353 return -1;
354 }
355
356 *target = atoi(args[1]);
357 if (*target < 0) {
358 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
359 return -1;
360 }
361 return 0;
362}
363
Marcin Deranek310a2602021-07-13 19:04:24 +0200364static int ssl_parse_global_capture_buffer(char **args, int section_type, struct proxy *curpx,
365 const struct proxy *defpx, const char *file, int line,
366 char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200367{
368 int ret;
369
370 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
371 if (ret != 0)
372 return ret;
373
374 if (pool_head_ssl_capture) {
375 memprintf(err, "'%s' is already configured.", args[0]);
376 return -1;
377 }
378
Marcin Deranek310a2602021-07-13 19:04:24 +0200379 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 +0200380 if (!pool_head_ssl_capture) {
381 memprintf(err, "Out of memory error.");
382 return -1;
383 }
384 return 0;
385}
386
William Lallemand7d42ef52020-07-06 11:41:30 +0200387/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200388#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200389static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100390 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200391 char **err)
392{
393
394 if (too_many_args(1, args, err, NULL))
395 return -1;
396
397 if (strcmp(args[1], "on") == 0)
398 global_ssl.keylog = 1;
399 else if (strcmp(args[1], "off") == 0)
400 global_ssl.keylog = 0;
401 else {
402 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
403 return -1;
404 }
405
406 if (pool_head_ssl_keylog) /* already configured */
407 return 0;
408
409 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
410 if (!pool_head_ssl_keylog) {
411 memprintf(err, "Out of memory error.");
412 return -1;
413 }
414
415 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
416 if (!pool_head_ssl_keylog_str) {
417 memprintf(err, "Out of memory error.");
418 return -1;
419 }
420
421 return 0;
422}
William Lallemand722180a2021-06-09 16:46:12 +0200423#else
424static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
425 const struct proxy *defpx, const char *file, int line,
426 char **err)
427{
428 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
429 return -1;
430}
William Lallemand7d42ef52020-07-06 11:41:30 +0200431#endif
432
William Lallemanddad31052020-05-14 17:47:32 +0200433/* parse "ssl.force-private-cache".
434 * Returns <0 on alert, >0 on warning, 0 on success.
435 */
436static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100437 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200438 char **err)
439{
440 if (too_many_args(0, args, err, NULL))
441 return -1;
442
443 global_ssl.private_cache = 1;
444 return 0;
445}
446
447/* parse "ssl.lifetime".
448 * Returns <0 on alert, >0 on warning, 0 on success.
449 */
450static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100451 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200452 char **err)
453{
454 const char *res;
455
456 if (too_many_args(1, args, err, NULL))
457 return -1;
458
459 if (*(args[1]) == 0) {
460 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
461 return -1;
462 }
463
464 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
465 if (res == PARSE_TIME_OVER) {
466 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
467 args[1], args[0]);
468 return -1;
469 }
470 else if (res == PARSE_TIME_UNDER) {
471 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
472 args[1], args[0]);
473 return -1;
474 }
475 else if (res) {
476 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
477 return -1;
478 }
479 return 0;
480}
481
482#ifndef OPENSSL_NO_DH
483/* parse "ssl-dh-param-file".
484 * Returns <0 on alert, >0 on warning, 0 on success.
485 */
486static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100487 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200488 char **err)
489{
490 if (too_many_args(1, args, err, NULL))
491 return -1;
492
493 if (*(args[1]) == 0) {
494 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
495 return -1;
496 }
497
498 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
499 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
500 return -1;
501 }
502 return 0;
503}
504
505/* parse "ssl.default-dh-param".
506 * Returns <0 on alert, >0 on warning, 0 on success.
507 */
508static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100509 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200510 char **err)
511{
512 if (too_many_args(1, args, err, NULL))
513 return -1;
514
515 if (*(args[1]) == 0) {
516 memprintf(err, "'%s' expects an integer argument.", args[0]);
517 return -1;
518 }
519
520 global_ssl.default_dh_param = atoi(args[1]);
521 if (global_ssl.default_dh_param < 1024) {
522 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
523 return -1;
524 }
525 return 0;
526}
527#endif
528
529
530/*
531 * parse "ssl-load-extra-files".
532 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
533 */
534static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100535 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200536 char **err)
537{
538 int i;
539 int gf = SSL_GF_NONE;
540
541 if (*(args[1]) == 0)
542 goto err_arg;
543
544 for (i = 1; *args[i]; i++) {
545
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100546 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200547 gf |= SSL_GF_BUNDLE;
548
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100549 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200550 gf |= SSL_GF_SCTL;
551
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100552 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200553 gf |= SSL_GF_OCSP;
554
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100555 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200556 gf |= SSL_GF_OCSP_ISSUER;
557
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100558 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200559 gf |= SSL_GF_KEY;
560
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100561 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200562 if (gf != SSL_GF_NONE)
563 goto err_alone;
564 gf = SSL_GF_NONE;
565 i++;
566 break;
567
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100568 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200569 if (gf != SSL_GF_NONE)
570 goto err_alone;
571 gf = SSL_GF_ALL;
572 i++;
573 break;
574 } else {
575 goto err_arg;
576 }
577 }
578 /* break from loop but there are still arguments */
579 if (*args[i])
580 goto err_alone;
581
582 global_ssl.extra_files = gf;
583
584 return 0;
585
586err_alone:
587 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
588 return -1;
589
590err_arg:
591 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
592 return -1;
593}
594
595
William Lallemand8e8581e2020-10-20 17:36:46 +0200596/* parse 'ssl-load-extra-del-ext */
597static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100598 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200599 char **err)
600{
601 global_ssl.extra_files_noext = 1;
602 return 0;
603}
604
William Lallemanddad31052020-05-14 17:47:32 +0200605/***************************** Bind keyword Parsing ********************************************/
606
607/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100608static 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 +0200609{
610 if (!*args[cur_arg + 1]) {
611 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
612 return ERR_ALERT | ERR_FATAL;
613 }
614
615 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
616 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
617 else
618 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
619
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200620 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200621 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
622 return ERR_ALERT | ERR_FATAL;
623 }
624 return 0;
625}
626
627/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100628static 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 +0200629{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100630 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200631}
632static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
633{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100634 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200635}
636
637/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100638static 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 +0200639{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100640 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200641}
642static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
643{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100644 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200645}
646
647/* parse the "ca-sign-file" bind keyword */
648static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
649{
650 if (!*args[cur_arg + 1]) {
651 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
652 return ERR_ALERT | ERR_FATAL;
653 }
654
655 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
656 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
657 else
658 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
659
660 return 0;
661}
662
663/* parse the "ca-sign-pass" bind keyword */
664static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
665{
666 if (!*args[cur_arg + 1]) {
667 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
668 return ERR_ALERT | ERR_FATAL;
669 }
670 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
671 return 0;
672}
673
674/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100675static 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 +0200676{
677 if (!*args[cur_arg + 1]) {
678 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
679 return ERR_ALERT | ERR_FATAL;
680 }
681
682 free(conf->ciphers);
683 conf->ciphers = strdup(args[cur_arg + 1]);
684 return 0;
685}
686static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
687{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100688 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200689}
690
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500691#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200692/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100693static 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 +0200694{
695 if (!*args[cur_arg + 1]) {
696 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
697 return ERR_ALERT | ERR_FATAL;
698 }
699
700 free(conf->ciphersuites);
701 conf->ciphersuites = strdup(args[cur_arg + 1]);
702 return 0;
703}
704static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
705{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100706 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200707}
708#endif
709
710/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
711static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
712{
713 char path[MAXPATHLEN];
714
715 if (!*args[cur_arg + 1]) {
716 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
717 return ERR_ALERT | ERR_FATAL;
718 }
719
720 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
Willy Tarreau393e42a2022-05-09 10:31:28 +0200721 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
722 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
William Lallemanddad31052020-05-14 17:47:32 +0200723 memprintf(err, "'%s' : path too long", args[cur_arg]);
724 return ERR_ALERT | ERR_FATAL;
725 }
William Lallemanddad31052020-05-14 17:47:32 +0200726 return ssl_sock_load_cert(path, conf, err);
727 }
728
729 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
730}
731
732/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
733static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
734{
735 int err_code;
736
737 if (!*args[cur_arg + 1]) {
738 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
739 return ERR_ALERT | ERR_FATAL;
740 }
741
742 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
743 if (err_code)
744 memprintf(err, "'%s' : %s", args[cur_arg], *err);
745
746 return err_code;
747}
748
749/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100750static 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 +0200751{
752#ifndef X509_V_FLAG_CRL_CHECK
753 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
754 return ERR_ALERT | ERR_FATAL;
755#else
756 if (!*args[cur_arg + 1]) {
757 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
758 return ERR_ALERT | ERR_FATAL;
759 }
760
761 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
762 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
763 else
764 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
765
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200766 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200767 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
768 return ERR_ALERT | ERR_FATAL;
769 }
770 return 0;
771#endif
772}
773static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
774{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100775 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200776}
777
778/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100779static 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 +0200780{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500781#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200782 if (!*args[cur_arg + 1]) {
783 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
784 return ERR_ALERT | ERR_FATAL;
785 }
786 conf->curves = strdup(args[cur_arg + 1]);
787 return 0;
788#else
789 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
790 return ERR_ALERT | ERR_FATAL;
791#endif
792}
793static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
794{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100795 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200796}
797
798/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100799static 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 +0200800{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500801#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200802 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
803 return ERR_ALERT | ERR_FATAL;
804#elif defined(OPENSSL_NO_ECDH)
805 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
806 return ERR_ALERT | ERR_FATAL;
807#else
808 if (!*args[cur_arg + 1]) {
809 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
810 return ERR_ALERT | ERR_FATAL;
811 }
812
813 conf->ecdhe = strdup(args[cur_arg + 1]);
814
815 return 0;
816#endif
817}
818static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
819{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100820 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200821}
822
823/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
824static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
825{
826 int code;
827 char *p = args[cur_arg + 1];
828 unsigned long long *ignerr = &conf->crt_ignerr;
829
830 if (!*p) {
831 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
832 return ERR_ALERT | ERR_FATAL;
833 }
834
835 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
836 ignerr = &conf->ca_ignerr;
837
838 if (strcmp(p, "all") == 0) {
839 *ignerr = ~0ULL;
840 return 0;
841 }
842
843 while (p) {
844 code = atoi(p);
845 if ((code <= 0) || (code > 63)) {
846 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
847 args[cur_arg], code, args[cur_arg + 1]);
848 return ERR_ALERT | ERR_FATAL;
849 }
850 *ignerr |= 1ULL << code;
851 p = strchr(p, ',');
852 if (p)
853 p++;
854 }
855
856 return 0;
857}
858
859/* parse tls_method_options "no-xxx" and "force-xxx" */
860static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
861{
862 uint16_t v;
863 char *p;
864 p = strchr(arg, '-');
865 if (!p)
866 goto fail;
867 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100868 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200869 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100870 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200871 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100872 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200873 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100874 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200875 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100876 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200877 v = CONF_TLSV13;
878 else
879 goto fail;
880 if (!strncmp(arg, "no-", 3))
881 methods->flags |= methodVersions[v].flag;
882 else if (!strncmp(arg, "force-", 6))
883 methods->min = methods->max = v;
884 else
885 goto fail;
886 return 0;
887 fail:
888 memprintf(err, "'%s' : option not implemented", arg);
889 return ERR_ALERT | ERR_FATAL;
890}
891
892static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
893{
894 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
895}
896
897static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
898{
899 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
900}
901
902/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
903static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
904{
905 uint16_t i, v = 0;
906 char *argv = args[cur_arg + 1];
907 if (!*argv) {
908 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
909 return ERR_ALERT | ERR_FATAL;
910 }
911 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100912 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200913 v = i;
914 if (!v) {
915 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
916 return ERR_ALERT | ERR_FATAL;
917 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100918 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200919 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100920 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200921 methods->max = v;
922 else {
923 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
924 return ERR_ALERT | ERR_FATAL;
925 }
926 return 0;
927}
928
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100929static 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 +0200930{
William Lallemand8177ad92020-05-20 16:49:02 +0200931 int ret;
932
William Lallemanddad31052020-05-14 17:47:32 +0200933#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
934 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
935#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200936 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
937 if (ret != ERR_NONE)
938 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200939
William Lallemand8177ad92020-05-20 16:49:02 +0200940 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
941 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
942
943 return ret;
944}
William Lallemanddad31052020-05-14 17:47:32 +0200945static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
946{
947 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
948}
949
950static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
951{
952 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
953}
954
955/* parse the "no-tls-tickets" bind keyword */
956static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
957{
958 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
959 return 0;
960}
961
962/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100963static 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 +0200964{
965 conf->early_data = 1;
966 return 0;
967}
968
969static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
970{
971 conf->ssl_conf.early_data = 1;
972 return 0;
973}
974
975/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100976static 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 +0200977{
978#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
979 char *p1, *p2;
980
981 if (!*args[cur_arg + 1]) {
982 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
983 return ERR_ALERT | ERR_FATAL;
984 }
985
986 free(conf->npn_str);
987
988 /* the NPN string is built as a suite of (<len> <name>)*,
989 * so we reuse each comma to store the next <len> and need
990 * one more for the end of the string.
991 */
992 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
993 conf->npn_str = calloc(1, conf->npn_len + 1);
994 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
995
996 /* replace commas with the name length */
997 p1 = conf->npn_str;
998 p2 = p1 + 1;
999 while (1) {
1000 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
1001 if (!p2)
1002 p2 = p1 + 1 + strlen(p1 + 1);
1003
1004 if (p2 - (p1 + 1) > 255) {
1005 *p2 = '\0';
1006 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
1007 return ERR_ALERT | ERR_FATAL;
1008 }
1009
1010 *p1 = p2 - (p1 + 1);
1011 p1 = p2;
1012
1013 if (!*p2)
1014 break;
1015
1016 *(p2++) = '\0';
1017 }
1018 return 0;
1019#else
1020 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
1021 return ERR_ALERT | ERR_FATAL;
1022#endif
1023}
1024
1025static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1026{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001027 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001028}
1029
1030
1031/* Parses a alpn string and converts it to the right format for the SSL api */
1032int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
1033{
1034 char *p1, *p2, *alpn = NULL;
1035 int len, ret = 0;
1036
1037 *alpn_str = NULL;
1038 *alpn_len = 0;
1039
1040 if (!*arg) {
1041 memprintf(err, "missing the comma-delimited ALPN protocol suite");
1042 goto error;
1043 }
1044
1045 /* the ALPN string is built as a suite of (<len> <name>)*,
1046 * so we reuse each comma to store the next <len> and need
1047 * one more for the end of the string.
1048 */
1049 len = strlen(arg) + 1;
1050 alpn = calloc(1, len+1);
1051 if (!alpn) {
1052 memprintf(err, "'%s' : out of memory", arg);
1053 goto error;
1054 }
1055 memcpy(alpn+1, arg, len);
1056
1057 /* replace commas with the name length */
1058 p1 = alpn;
1059 p2 = p1 + 1;
1060 while (1) {
1061 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1062 if (!p2)
1063 p2 = p1 + 1 + strlen(p1 + 1);
1064
1065 if (p2 - (p1 + 1) > 255) {
1066 *p2 = '\0';
1067 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1068 goto error;
1069 }
1070
1071 *p1 = p2 - (p1 + 1);
1072 p1 = p2;
1073
1074 if (!*p2)
1075 break;
1076
1077 *(p2++) = '\0';
1078 }
1079
1080 *alpn_str = alpn;
1081 *alpn_len = len;
1082
1083 out:
1084 return ret;
1085
1086 error:
1087 free(alpn);
1088 ret = ERR_ALERT | ERR_FATAL;
1089 goto out;
1090}
1091
1092/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001093static 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 +02001094{
1095#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1096 int ret;
1097
1098 free(conf->alpn_str);
1099
1100 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1101 if (ret)
1102 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1103 return ret;
1104#else
1105 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1106 return ERR_ALERT | ERR_FATAL;
1107#endif
1108}
1109
1110static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1111{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001112 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001113}
1114
1115/* parse the "ssl" bind keyword */
1116static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1117{
Frédéric Lécaillee50afbd2020-11-23 11:33:12 +01001118 /* Do not change the xprt for QUIC. */
1119 if (conf->xprt != xprt_get(XPRT_QUIC))
1120 conf->xprt = &ssl_sock;
Willy Tarreau11ba4042022-05-20 15:56:32 +02001121 conf->options |= BC_O_USE_SSL;
William Lallemanddad31052020-05-14 17:47:32 +02001122
1123 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1124 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001125#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001126 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1127 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1128#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001129#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001130 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1131 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1132#endif
1133 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1134 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1135 if (!conf->ssl_conf.ssl_methods.min)
1136 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1137 if (!conf->ssl_conf.ssl_methods.max)
1138 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1139
1140 return 0;
1141}
1142
1143/* parse the "prefer-client-ciphers" bind keyword */
1144static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1145{
1146 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1147 return 0;
1148}
1149
1150/* parse the "generate-certificates" bind keyword */
1151static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1152{
1153#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau1ea6e6a2022-05-20 16:03:18 +02001154 conf->options |= BC_O_GENERATE_CERTS;
William Lallemanddad31052020-05-14 17:47:32 +02001155#else
1156 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1157 err && *err ? *err : "");
1158#endif
1159 return 0;
1160}
1161
1162/* parse the "strict-sni" bind keyword */
1163static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1164{
1165 conf->strict_sni = 1;
1166 return 0;
1167}
1168
1169/* parse the "tls-ticket-keys" bind keyword */
1170static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1171{
1172#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1173 FILE *f = NULL;
1174 int i = 0;
1175 char thisline[LINESIZE];
1176 struct tls_keys_ref *keys_ref = NULL;
1177
1178 if (!*args[cur_arg + 1]) {
1179 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1180 goto fail;
1181 }
1182
1183 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1184 if (keys_ref) {
1185 keys_ref->refcount++;
1186 conf->keys_ref = keys_ref;
1187 return 0;
1188 }
1189
1190 keys_ref = calloc(1, sizeof(*keys_ref));
1191 if (!keys_ref) {
1192 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1193 goto fail;
1194 }
1195
1196 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1197 if (!keys_ref->tlskeys) {
1198 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1199 goto fail;
1200 }
1201
1202 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1203 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1204 goto fail;
1205 }
1206
1207 keys_ref->filename = strdup(args[cur_arg + 1]);
1208 if (!keys_ref->filename) {
1209 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1210 goto fail;
1211 }
1212
1213 keys_ref->key_size_bits = 0;
1214 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1215 int len = strlen(thisline);
1216 int dec_size;
1217
1218 /* Strip newline characters from the end */
1219 if(thisline[len - 1] == '\n')
1220 thisline[--len] = 0;
1221
1222 if(thisline[len - 1] == '\r')
1223 thisline[--len] = 0;
1224
1225 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1226 if (dec_size < 0) {
1227 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1228 goto fail;
1229 }
1230 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1231 keys_ref->key_size_bits = 128;
1232 }
1233 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1234 keys_ref->key_size_bits = 256;
1235 }
1236 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1237 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1238 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1239 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1240 goto fail;
1241 }
1242 i++;
1243 }
1244
1245 if (i < TLS_TICKETS_NO) {
1246 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1247 goto fail;
1248 }
1249
1250 fclose(f);
1251
1252 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1253 i -= 2;
1254 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1255 keys_ref->unique_id = -1;
1256 keys_ref->refcount = 1;
1257 HA_RWLOCK_INIT(&keys_ref->lock);
1258 conf->keys_ref = keys_ref;
1259
Willy Tarreau2b718102021-04-21 07:32:39 +02001260 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001261
1262 return 0;
1263
1264 fail:
1265 if (f)
1266 fclose(f);
1267 if (keys_ref) {
1268 free(keys_ref->filename);
1269 free(keys_ref->tlskeys);
1270 free(keys_ref);
1271 }
1272 return ERR_ALERT | ERR_FATAL;
1273
1274#else
1275 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1276 return ERR_ALERT | ERR_FATAL;
1277#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1278}
1279
1280/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001281static 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 +02001282{
1283 if (!*args[cur_arg + 1]) {
1284 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1285 return ERR_ALERT | ERR_FATAL;
1286 }
1287
1288 if (strcmp(args[cur_arg + 1], "none") == 0)
1289 conf->verify = SSL_SOCK_VERIFY_NONE;
1290 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1291 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1292 else if (strcmp(args[cur_arg + 1], "required") == 0)
1293 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1294 else {
1295 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1296 args[cur_arg], args[cur_arg + 1]);
1297 return ERR_ALERT | ERR_FATAL;
1298 }
1299
1300 return 0;
1301}
1302static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1303{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001304 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001305}
1306
1307/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001308static 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 +02001309{
1310 conf->no_ca_names = 1;
1311 return 0;
1312}
1313static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1314{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001315 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001316}
1317
1318/***************************** "server" keywords Parsing ********************************************/
1319
1320/* parse the "npn" bind keyword */
1321static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1322{
1323#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1324 char *p1, *p2;
1325
1326 if (!*args[*cur_arg + 1]) {
1327 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1328 return ERR_ALERT | ERR_FATAL;
1329 }
1330
1331 free(newsrv->ssl_ctx.npn_str);
1332
1333 /* the NPN string is built as a suite of (<len> <name>)*,
1334 * so we reuse each comma to store the next <len> and need
1335 * one more for the end of the string.
1336 */
1337 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1338 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001339 if (!newsrv->ssl_ctx.npn_str) {
1340 memprintf(err, "out of memory");
1341 return ERR_ALERT | ERR_FATAL;
1342 }
1343
William Lallemanddad31052020-05-14 17:47:32 +02001344 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1345 newsrv->ssl_ctx.npn_len);
1346
1347 /* replace commas with the name length */
1348 p1 = newsrv->ssl_ctx.npn_str;
1349 p2 = p1 + 1;
1350 while (1) {
1351 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1352 newsrv->ssl_ctx.npn_len - (p1 + 1));
1353 if (!p2)
1354 p2 = p1 + 1 + strlen(p1 + 1);
1355
1356 if (p2 - (p1 + 1) > 255) {
1357 *p2 = '\0';
1358 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1359 return ERR_ALERT | ERR_FATAL;
1360 }
1361
1362 *p1 = p2 - (p1 + 1);
1363 p1 = p2;
1364
1365 if (!*p2)
1366 break;
1367
1368 *(p2++) = '\0';
1369 }
1370 return 0;
1371#else
1372 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1373 return ERR_ALERT | ERR_FATAL;
1374#endif
1375}
1376
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001377#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1378static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1379{
1380 free(*out_alpn_str);
1381 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1382}
1383#endif
1384
1385/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001386static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1387{
1388#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001389 int ret = parse_alpn(args[*cur_arg + 1],
1390 &newsrv->ssl_ctx.alpn_str,
1391 &newsrv->ssl_ctx.alpn_len, err);
1392 if (ret)
1393 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1394 return ret;
1395#else
1396 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1397 return ERR_ALERT | ERR_FATAL;
1398#endif
1399}
William Lallemanddad31052020-05-14 17:47:32 +02001400
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001401/* parse the "check-alpn" server keyword */
1402static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1403{
1404#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1405 int ret = parse_alpn(args[*cur_arg + 1],
1406 &newsrv->check.alpn_str,
1407 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001408 if (ret)
1409 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1410 return ret;
1411#else
1412 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1413 return ERR_ALERT | ERR_FATAL;
1414#endif
1415}
1416
1417/* parse the "ca-file" server keyword */
1418static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1419{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001420 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1421
William Lallemanddad31052020-05-14 17:47:32 +02001422 if (!*args[*cur_arg + 1]) {
1423 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1424 return ERR_ALERT | ERR_FATAL;
1425 }
1426
1427 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1428 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1429 else
1430 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1431
Amaury Denoyelle48255022021-05-19 09:46:59 +02001432 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001433 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1434 return ERR_ALERT | ERR_FATAL;
1435 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001436
William Lallemanddad31052020-05-14 17:47:32 +02001437 return 0;
1438}
1439
1440/* parse the "check-sni" server keyword */
1441static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1442{
1443 if (!*args[*cur_arg + 1]) {
1444 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1445 return ERR_ALERT | ERR_FATAL;
1446 }
1447
1448 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1449 if (!newsrv->check.sni) {
1450 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1451 return ERR_ALERT | ERR_FATAL;
1452 }
1453 return 0;
1454
1455}
1456
William Dauchyfc52f522020-11-14 19:25:32 +01001457/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001458static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001459{
William Dauchyfc52f522020-11-14 19:25:32 +01001460 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1461 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001462#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001463 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001464 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001465 if (!s->ssl_ctx.ciphersuites)
1466 return 1;
1467 }
William Lallemanddad31052020-05-14 17:47:32 +02001468#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001469 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1470 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1471
1472 if (!s->ssl_ctx.methods.min)
1473 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001474
William Dauchyfc52f522020-11-14 19:25:32 +01001475 if (!s->ssl_ctx.methods.max)
1476 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001477
1478 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001479}
1480
1481/* parse the "check-ssl" server keyword */
1482static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1483{
1484 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001485 if (ssl_sock_init_srv(newsrv)) {
1486 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1487 return ERR_ALERT | ERR_FATAL;
1488 }
1489
William Lallemanddad31052020-05-14 17:47:32 +02001490 return 0;
1491}
1492
1493/* parse the "ciphers" server keyword */
1494static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1495{
1496 if (!*args[*cur_arg + 1]) {
1497 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1498 return ERR_ALERT | ERR_FATAL;
1499 }
1500
1501 free(newsrv->ssl_ctx.ciphers);
1502 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001503
1504 if (!newsrv->ssl_ctx.ciphers) {
1505 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1506 return ERR_ALERT | ERR_FATAL;
1507 }
1508
William Lallemanddad31052020-05-14 17:47:32 +02001509 return 0;
1510}
1511
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001512#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001513/* parse the "ciphersuites" server keyword */
1514static int srv_parse_ciphersuites(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.ciphersuites);
1522 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001523
1524 if (!newsrv->ssl_ctx.ciphersuites) {
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#endif
1532
1533/* parse the "crl-file" server keyword */
1534static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1535{
1536#ifndef X509_V_FLAG_CRL_CHECK
1537 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1538 return ERR_ALERT | ERR_FATAL;
1539#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001540 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1541
William Lallemanddad31052020-05-14 17:47:32 +02001542 if (!*args[*cur_arg + 1]) {
1543 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1544 return ERR_ALERT | ERR_FATAL;
1545 }
1546
1547 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1548 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1549 else
1550 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1551
Amaury Denoyellefde82602021-06-14 10:10:32 +02001552 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001553 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1554 return ERR_ALERT | ERR_FATAL;
1555 }
1556 return 0;
1557#endif
1558}
1559
1560/* parse the "crt" server keyword */
1561static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1562{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001563
William Lallemanddad31052020-05-14 17:47:32 +02001564 if (!*args[*cur_arg + 1]) {
1565 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1566 return ERR_ALERT | ERR_FATAL;
1567 }
1568
1569 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001570 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001571 else
William Lallemand2c776f12021-12-28 18:47:17 +01001572 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001573
William Lallemand2c776f12021-12-28 18:47:17 +01001574 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001575}
1576
1577/* parse the "no-check-ssl" server keyword */
1578static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1579{
1580 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001581 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001582 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1583 return 0;
1584}
1585
1586/* parse the "no-send-proxy-v2-ssl" server keyword */
1587static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1588{
1589 newsrv->pp_opts &= ~SRV_PP_V2;
1590 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1591 return 0;
1592}
1593
1594/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1595static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1596{
1597 newsrv->pp_opts &= ~SRV_PP_V2;
1598 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1599 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1600 return 0;
1601}
1602
1603/* parse the "no-ssl" server keyword */
1604static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1605{
William Dauchyf6370442020-11-14 19:25:33 +01001606 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001607 if (newsrv->use_ssl == 1) {
1608 if (ssl_sock_init_srv(newsrv)) {
1609 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1610 return ERR_ALERT | ERR_FATAL;
1611 }
1612 }
William Dauchyf6370442020-11-14 19:25:33 +01001613 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001614 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001615 }
William Lallemanddad31052020-05-14 17:47:32 +02001616 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001617 return 0;
1618}
1619
1620/* parse the "allow-0rtt" server keyword */
1621static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1622{
1623 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1624 return 0;
1625}
1626
1627/* parse the "no-ssl-reuse" server keyword */
1628static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1629{
1630 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1631 return 0;
1632}
1633
1634/* parse the "no-tls-tickets" server keyword */
1635static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1636{
1637 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1638 return 0;
1639}
1640/* parse the "send-proxy-v2-ssl" server keyword */
1641static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1642{
1643 newsrv->pp_opts |= SRV_PP_V2;
1644 newsrv->pp_opts |= SRV_PP_V2_SSL;
1645 return 0;
1646}
1647
1648/* parse the "send-proxy-v2-ssl-cn" server keyword */
1649static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1650{
1651 newsrv->pp_opts |= SRV_PP_V2;
1652 newsrv->pp_opts |= SRV_PP_V2_SSL;
1653 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1654 return 0;
1655}
1656
1657/* parse the "sni" server keyword */
1658static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1659{
1660#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1661 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1662 return ERR_ALERT | ERR_FATAL;
1663#else
1664 char *arg;
1665
1666 arg = args[*cur_arg + 1];
1667 if (!*arg) {
1668 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1669 return ERR_ALERT | ERR_FATAL;
1670 }
1671
1672 free(newsrv->sni_expr);
1673 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001674 if (!newsrv->sni_expr) {
1675 memprintf(err, "out of memory");
1676 return ERR_ALERT | ERR_FATAL;
1677 }
William Lallemanddad31052020-05-14 17:47:32 +02001678
1679 return 0;
1680#endif
1681}
1682
1683/* parse the "ssl" server keyword */
1684static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1685{
1686 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001687 if (ssl_sock_init_srv(newsrv)) {
1688 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1689 return ERR_ALERT | ERR_FATAL;
1690 }
1691
William Lallemanddad31052020-05-14 17:47:32 +02001692 return 0;
1693}
1694
1695/* parse the "ssl-reuse" server keyword */
1696static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1697{
1698 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1699 return 0;
1700}
1701
1702/* parse the "tls-tickets" server keyword */
1703static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1704{
1705 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1706 return 0;
1707}
1708
1709/* parse the "verify" server keyword */
1710static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1711{
1712 if (!*args[*cur_arg + 1]) {
1713 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1714 return ERR_ALERT | ERR_FATAL;
1715 }
1716
1717 if (strcmp(args[*cur_arg + 1], "none") == 0)
1718 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1719 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1720 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1721 else {
1722 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1723 args[*cur_arg], args[*cur_arg + 1]);
1724 return ERR_ALERT | ERR_FATAL;
1725 }
1726
1727 return 0;
1728}
1729
1730/* parse the "verifyhost" server keyword */
1731static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1732{
1733 if (!*args[*cur_arg + 1]) {
1734 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1735 return ERR_ALERT | ERR_FATAL;
1736 }
1737
1738 free(newsrv->ssl_ctx.verify_host);
1739 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1740
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001741 if (!newsrv->ssl_ctx.verify_host) {
1742 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1743 return ERR_ALERT | ERR_FATAL;
1744 }
1745
William Lallemanddad31052020-05-14 17:47:32 +02001746 return 0;
1747}
1748
1749/* parse the "ssl-default-bind-options" keyword in global section */
1750static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001751 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001752 char **err) {
1753 int i = 1;
1754
1755 if (*(args[i]) == 0) {
1756 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1757 return -1;
1758 }
1759 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001760 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001761 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001762 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001763 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001764 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001765 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1766 i++;
1767 else {
1768 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1769 return -1;
1770 }
1771 }
1772 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1773 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1774 return -1;
1775 }
1776 i++;
1777 }
1778 return 0;
1779}
1780
1781/* parse the "ssl-default-server-options" keyword in global section */
1782static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001783 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001784 char **err) {
1785 int i = 1;
1786
1787 if (*(args[i]) == 0) {
1788 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1789 return -1;
1790 }
1791 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001792 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001793 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001794 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001795 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1796 i++;
1797 else {
1798 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1799 return -1;
1800 }
1801 }
1802 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1803 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1804 return -1;
1805 }
1806 i++;
1807 }
1808 return 0;
1809}
1810
1811/* parse the "ca-base" / "crt-base" keywords in global section.
1812 * Returns <0 on alert, >0 on warning, 0 on success.
1813 */
1814static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001815 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001816 char **err)
1817{
1818 char **target;
1819
1820 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1821
1822 if (too_many_args(1, args, err, NULL))
1823 return -1;
1824
1825 if (*target) {
1826 memprintf(err, "'%s' already specified.", args[0]);
1827 return -1;
1828 }
1829
1830 if (*(args[1]) == 0) {
1831 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1832 return -1;
1833 }
1834 *target = strdup(args[1]);
1835 return 0;
1836}
1837
1838/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1839static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001840 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001841 char **err)
1842{
William Lallemand9a1d8392020-08-10 17:28:23 +02001843#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001844 global_ssl.skip_self_issued_ca = 1;
1845 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001846#else
1847 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1848 return -1;
1849#endif
William Lallemanddad31052020-05-14 17:47:32 +02001850}
1851
1852
1853
1854
1855
1856/* Note: must not be declared <const> as its list will be overwritten.
1857 * Please take care of keeping this list alphabetically sorted, doing so helps
1858 * all code contributors.
1859 * Optional keywords are also declared with a NULL ->parse() function so that
1860 * the config parser can report an appropriate error when a known keyword was
1861 * not enabled.
1862 */
1863
1864/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1865 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1866struct ssl_bind_kw ssl_bind_kws[] = {
1867 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1868 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1869 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1870 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1871 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001872#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001873 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1874#endif
1875 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1876 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1877 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1878 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1879 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1880 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1881 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1882 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1883 { NULL, NULL, 0 },
1884};
1885
1886/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1887
1888static struct bind_kw_list bind_kws = { "SSL", { }, {
1889 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1890 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1891 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1892 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1893 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1894 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1895 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1896 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001897#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001898 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1899#endif
1900 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1901 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1902 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1903 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1904 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1905 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1906 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1907 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1908 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1909 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1910 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1911 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1912 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1913 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1914 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1915 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1916 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1917 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1918 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1919 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1920 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1921 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1922 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1923 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1924 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1925 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1926 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1927 { NULL, NULL, 0 },
1928}};
1929
1930INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1931
1932/* Note: must not be declared <const> as its list will be overwritten.
1933 * Please take care of keeping this list alphabetically sorted, doing so helps
1934 * all code contributors.
1935 * Optional keywords are also declared with a NULL ->parse() function so that
1936 * the config parser can report an appropriate error when a known keyword was
1937 * not enabled.
1938 */
1939static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001940 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1941 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001942 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001943 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1944 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1945 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001946 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001947#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001948 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001949#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001950 { "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 +02001951 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001952 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1953 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1954 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1955 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1956 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001957 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1958 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1959 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1960 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001961 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1962 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1963 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1964 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1965 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1966 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1967 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1968 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1969 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1970 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1971 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001972 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001973 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1974 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001975 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001976 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1977 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
1978 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001979 { NULL, NULL, 0, 0 },
1980}};
1981
1982INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1983
1984static struct cfg_kw_list cfg_kws = {ILH, {
1985 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1986 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1987 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1988 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1989 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1990 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1991#ifndef OPENSSL_NO_DH
1992 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1993#endif
1994 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
William Lallemandd7bfbe22022-04-11 18:41:24 +02001995#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +02001996 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1997#endif
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02001998#ifdef HAVE_SSL_PROVIDERS
1999 { CFG_GLOBAL, "ssl-propquery", ssl_parse_global_ssl_propquery },
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +02002000 { CFG_GLOBAL, "ssl-provider", ssl_parse_global_ssl_provider },
Remi Tricot-Le Bretonccc03552022-05-17 15:18:37 +02002001 { CFG_GLOBAL, "ssl-provider-path", ssl_parse_global_ssl_provider_path },
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002002#endif
William Lallemanddad31052020-05-14 17:47:32 +02002003 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
2004 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
2005#ifndef OPENSSL_NO_DH
2006 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
2007#endif
2008 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
2009 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
2010 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
Thomas Prückl10243932022-04-27 13:04:54 +02002011 { CFG_GLOBAL, "tune.ssl.hard-maxrecord", ssl_parse_global_int },
William Lallemanddad31052020-05-14 17:47:32 +02002012 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02002013 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
2014 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02002015 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02002016 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
2017 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05002018#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02002019 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
2020#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05002021#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02002022 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
2023 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
2024#endif
2025 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02002026 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02002027 { 0, NULL, NULL },
2028}};
2029
2030INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);