blob: f4a5214605df7bf76bc693e6144f8ac95abb746e [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
Remi Tricot-Le Breton03c5fff2022-12-20 11:11:10 +0100606
William Lallemanddad31052020-05-14 17:47:32 +0200607/***************************** Bind keyword Parsing ********************************************/
608
609/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100610static 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 +0200611{
612 if (!*args[cur_arg + 1]) {
613 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
614 return ERR_ALERT | ERR_FATAL;
615 }
616
617 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
618 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
619 else
620 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
621
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200622 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200623 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
624 return ERR_ALERT | ERR_FATAL;
625 }
626 return 0;
627}
628
629/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100630static 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 +0200631{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100632 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200633}
634static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
635{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100636 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200637}
638
639/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100640static 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 +0200641{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100642 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200643}
644static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
645{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100646 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200647}
648
649/* parse the "ca-sign-file" bind keyword */
650static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
651{
652 if (!*args[cur_arg + 1]) {
653 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
654 return ERR_ALERT | ERR_FATAL;
655 }
656
657 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
658 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
659 else
660 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
661
662 return 0;
663}
664
665/* parse the "ca-sign-pass" bind keyword */
666static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
667{
668 if (!*args[cur_arg + 1]) {
669 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
670 return ERR_ALERT | ERR_FATAL;
671 }
672 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
673 return 0;
674}
675
676/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100677static 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 +0200678{
679 if (!*args[cur_arg + 1]) {
680 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
681 return ERR_ALERT | ERR_FATAL;
682 }
683
684 free(conf->ciphers);
685 conf->ciphers = strdup(args[cur_arg + 1]);
686 return 0;
687}
688static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
689{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100690 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200691}
692
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500693#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200694/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100695static 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 +0200696{
697 if (!*args[cur_arg + 1]) {
698 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
699 return ERR_ALERT | ERR_FATAL;
700 }
701
702 free(conf->ciphersuites);
703 conf->ciphersuites = strdup(args[cur_arg + 1]);
704 return 0;
705}
706static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
707{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100708 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200709}
710#endif
711
712/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
713static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
714{
715 char path[MAXPATHLEN];
716
717 if (!*args[cur_arg + 1]) {
718 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
719 return ERR_ALERT | ERR_FATAL;
720 }
721
722 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
Willy Tarreau393e42a2022-05-09 10:31:28 +0200723 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
724 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
William Lallemanddad31052020-05-14 17:47:32 +0200725 memprintf(err, "'%s' : path too long", args[cur_arg]);
726 return ERR_ALERT | ERR_FATAL;
727 }
William Lallemanddad31052020-05-14 17:47:32 +0200728 return ssl_sock_load_cert(path, conf, err);
729 }
730
731 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
732}
733
734/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
735static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
736{
737 int err_code;
738
739 if (!*args[cur_arg + 1]) {
740 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
741 return ERR_ALERT | ERR_FATAL;
742 }
743
744 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
745 if (err_code)
746 memprintf(err, "'%s' : %s", args[cur_arg], *err);
747
748 return err_code;
749}
750
751/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100752static 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 +0200753{
754#ifndef X509_V_FLAG_CRL_CHECK
755 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
756 return ERR_ALERT | ERR_FATAL;
757#else
758 if (!*args[cur_arg + 1]) {
759 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
760 return ERR_ALERT | ERR_FATAL;
761 }
762
763 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
764 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
765 else
766 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
767
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200768 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200769 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
770 return ERR_ALERT | ERR_FATAL;
771 }
772 return 0;
773#endif
774}
775static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
776{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100777 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200778}
779
780/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100781static 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 +0200782{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500783#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200784 if (!*args[cur_arg + 1]) {
785 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
786 return ERR_ALERT | ERR_FATAL;
787 }
788 conf->curves = strdup(args[cur_arg + 1]);
789 return 0;
790#else
791 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
792 return ERR_ALERT | ERR_FATAL;
793#endif
794}
795static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
796{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100797 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200798}
799
800/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100801static 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 +0200802{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500803#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200804 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
805 return ERR_ALERT | ERR_FATAL;
806#elif defined(OPENSSL_NO_ECDH)
807 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
808 return ERR_ALERT | ERR_FATAL;
809#else
810 if (!*args[cur_arg + 1]) {
811 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
812 return ERR_ALERT | ERR_FATAL;
813 }
814
815 conf->ecdhe = strdup(args[cur_arg + 1]);
816
817 return 0;
818#endif
819}
820static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
821{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100822 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200823}
824
825/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
826static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
827{
828 int code;
William Lallemand960fb742022-11-03 16:31:50 +0100829 char *s1 = NULL, *s2 = NULL;
830 char *token = NULL;
William Lallemanddad31052020-05-14 17:47:32 +0200831 char *p = args[cur_arg + 1];
William Lallemand960fb742022-11-03 16:31:50 +0100832 char *str;
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100833 unsigned long long *ignerr = conf->crt_ignerr_bitfield;
William Lallemanddad31052020-05-14 17:47:32 +0200834
835 if (!*p) {
836 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
837 return ERR_ALERT | ERR_FATAL;
838 }
839
840 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100841 ignerr = conf->ca_ignerr_bitfield;
William Lallemanddad31052020-05-14 17:47:32 +0200842
843 if (strcmp(p, "all") == 0) {
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100844 cert_ignerr_bitfield_set_all(ignerr);
William Lallemanddad31052020-05-14 17:47:32 +0200845 return 0;
846 }
847
William Lallemandf813dab2022-11-14 11:36:11 +0100848 /* copy the string to be able to dump the complete one in case of
849 * error, because strtok_r is writing \0 inside. */
850 str = strdup(p);
851 if (!str) {
852 memprintf(err, "'%s' : Could not allocate memory", args[cur_arg]);
853 return ERR_ALERT | ERR_FATAL;
854 }
855
William Lallemand960fb742022-11-03 16:31:50 +0100856 s1 = str;
857 while ((token = strtok_r(s1, ",", &s2))) {
858 s1 = NULL;
William Lallemand960fb742022-11-03 16:31:50 +0100859 if (isdigit((int)*token)) {
860 code = atoi(token);
861 if ((code <= 0) || (code > SSL_MAX_VFY_ERROR_CODE)) {
862 memprintf(err, "'%s' : ID '%d' out of range (1..%d) in error IDs list '%s'",
863 args[cur_arg], code, SSL_MAX_VFY_ERROR_CODE, args[cur_arg + 1]);
864 free(str);
865 return ERR_ALERT | ERR_FATAL;
866 }
867 } else {
868 code = x509_v_err_str_to_int(token);
869 if (code < 0) {
870 memprintf(err, "'%s' : error constant '%s' unknown in error IDs list '%s'",
871 args[cur_arg], token, args[cur_arg + 1]);
872 free(str);
873 return ERR_ALERT | ERR_FATAL;
874 }
William Lallemanddad31052020-05-14 17:47:32 +0200875 }
Remi Tricot-Le Breton9b259822022-11-10 10:48:58 +0100876 cert_ignerr_bitfield_set(ignerr, code);
William Lallemanddad31052020-05-14 17:47:32 +0200877 }
878
William Lallemand960fb742022-11-03 16:31:50 +0100879 free(str);
William Lallemanddad31052020-05-14 17:47:32 +0200880 return 0;
881}
882
883/* parse tls_method_options "no-xxx" and "force-xxx" */
884static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
885{
886 uint16_t v;
887 char *p;
888 p = strchr(arg, '-');
889 if (!p)
890 goto fail;
891 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100892 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200893 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100894 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200895 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100896 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200897 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100898 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200899 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100900 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200901 v = CONF_TLSV13;
902 else
903 goto fail;
904 if (!strncmp(arg, "no-", 3))
905 methods->flags |= methodVersions[v].flag;
906 else if (!strncmp(arg, "force-", 6))
907 methods->min = methods->max = v;
908 else
909 goto fail;
910 return 0;
911 fail:
912 memprintf(err, "'%s' : option not implemented", arg);
913 return ERR_ALERT | ERR_FATAL;
914}
915
916static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
917{
918 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
919}
920
921static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
922{
923 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
924}
925
926/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
927static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
928{
929 uint16_t i, v = 0;
930 char *argv = args[cur_arg + 1];
931 if (!*argv) {
932 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
933 return ERR_ALERT | ERR_FATAL;
934 }
935 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100936 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200937 v = i;
938 if (!v) {
939 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
940 return ERR_ALERT | ERR_FATAL;
941 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100942 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200943 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100944 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200945 methods->max = v;
946 else {
947 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
948 return ERR_ALERT | ERR_FATAL;
949 }
950 return 0;
951}
952
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100953static 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 +0200954{
William Lallemand8177ad92020-05-20 16:49:02 +0200955 int ret;
956
William Lallemanddad31052020-05-14 17:47:32 +0200957#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
958 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
959#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200960 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
961 if (ret != ERR_NONE)
962 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200963
William Lallemand8177ad92020-05-20 16:49:02 +0200964 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
965 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
966
967 return ret;
968}
William Lallemanddad31052020-05-14 17:47:32 +0200969static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
970{
971 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
972}
973
974static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
975{
976 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
977}
978
979/* parse the "no-tls-tickets" bind keyword */
980static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
981{
982 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
983 return 0;
984}
985
986/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100987static 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 +0200988{
989 conf->early_data = 1;
990 return 0;
991}
992
993static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
994{
995 conf->ssl_conf.early_data = 1;
996 return 0;
997}
998
999/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001000static 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 +02001001{
1002#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1003 char *p1, *p2;
1004
1005 if (!*args[cur_arg + 1]) {
1006 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
1007 return ERR_ALERT | ERR_FATAL;
1008 }
1009
1010 free(conf->npn_str);
1011
1012 /* the NPN string is built as a suite of (<len> <name>)*,
1013 * so we reuse each comma to store the next <len> and need
1014 * one more for the end of the string.
1015 */
1016 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
1017 conf->npn_str = calloc(1, conf->npn_len + 1);
1018 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
1019
1020 /* replace commas with the name length */
1021 p1 = conf->npn_str;
1022 p2 = p1 + 1;
1023 while (1) {
1024 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
1025 if (!p2)
1026 p2 = p1 + 1 + strlen(p1 + 1);
1027
1028 if (p2 - (p1 + 1) > 255) {
1029 *p2 = '\0';
1030 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
1031 return ERR_ALERT | ERR_FATAL;
1032 }
1033
1034 *p1 = p2 - (p1 + 1);
1035 p1 = p2;
1036
1037 if (!*p2)
1038 break;
1039
1040 *(p2++) = '\0';
1041 }
1042 return 0;
1043#else
1044 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
1045 return ERR_ALERT | ERR_FATAL;
1046#endif
1047}
1048
1049static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1050{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001051 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001052}
1053
1054
1055/* Parses a alpn string and converts it to the right format for the SSL api */
1056int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
1057{
1058 char *p1, *p2, *alpn = NULL;
1059 int len, ret = 0;
1060
1061 *alpn_str = NULL;
1062 *alpn_len = 0;
1063
1064 if (!*arg) {
1065 memprintf(err, "missing the comma-delimited ALPN protocol suite");
1066 goto error;
1067 }
1068
1069 /* the ALPN string is built as a suite of (<len> <name>)*,
1070 * so we reuse each comma to store the next <len> and need
1071 * one more for the end of the string.
1072 */
1073 len = strlen(arg) + 1;
1074 alpn = calloc(1, len+1);
1075 if (!alpn) {
1076 memprintf(err, "'%s' : out of memory", arg);
1077 goto error;
1078 }
1079 memcpy(alpn+1, arg, len);
1080
1081 /* replace commas with the name length */
1082 p1 = alpn;
1083 p2 = p1 + 1;
1084 while (1) {
1085 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1086 if (!p2)
1087 p2 = p1 + 1 + strlen(p1 + 1);
1088
1089 if (p2 - (p1 + 1) > 255) {
1090 *p2 = '\0';
1091 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1092 goto error;
1093 }
1094
1095 *p1 = p2 - (p1 + 1);
1096 p1 = p2;
1097
1098 if (!*p2)
1099 break;
1100
1101 *(p2++) = '\0';
1102 }
1103
1104 *alpn_str = alpn;
1105 *alpn_len = len;
1106
1107 out:
1108 return ret;
1109
1110 error:
1111 free(alpn);
1112 ret = ERR_ALERT | ERR_FATAL;
1113 goto out;
1114}
1115
1116/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001117static 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 +02001118{
1119#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1120 int ret;
1121
1122 free(conf->alpn_str);
1123
1124 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1125 if (ret)
1126 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1127 return ret;
1128#else
1129 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1130 return ERR_ALERT | ERR_FATAL;
1131#endif
1132}
1133
1134static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1135{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001136 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001137}
1138
1139/* parse the "ssl" bind keyword */
1140static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1141{
Willy Tarreau11ba4042022-05-20 15:56:32 +02001142 conf->options |= BC_O_USE_SSL;
William Lallemanddad31052020-05-14 17:47:32 +02001143
1144 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1145 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001146#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001147 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1148 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1149#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001150#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001151 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1152 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1153#endif
1154 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1155 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1156 if (!conf->ssl_conf.ssl_methods.min)
1157 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1158 if (!conf->ssl_conf.ssl_methods.max)
1159 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1160
1161 return 0;
1162}
1163
1164/* parse the "prefer-client-ciphers" bind keyword */
1165static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1166{
1167 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1168 return 0;
1169}
1170
1171/* parse the "generate-certificates" bind keyword */
1172static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1173{
1174#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau1ea6e6a2022-05-20 16:03:18 +02001175 conf->options |= BC_O_GENERATE_CERTS;
William Lallemanddad31052020-05-14 17:47:32 +02001176#else
1177 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1178 err && *err ? *err : "");
1179#endif
1180 return 0;
1181}
1182
1183/* parse the "strict-sni" bind keyword */
1184static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1185{
1186 conf->strict_sni = 1;
1187 return 0;
1188}
1189
1190/* parse the "tls-ticket-keys" bind keyword */
1191static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1192{
1193#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1194 FILE *f = NULL;
1195 int i = 0;
1196 char thisline[LINESIZE];
1197 struct tls_keys_ref *keys_ref = NULL;
1198
1199 if (!*args[cur_arg + 1]) {
1200 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1201 goto fail;
1202 }
1203
1204 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1205 if (keys_ref) {
1206 keys_ref->refcount++;
1207 conf->keys_ref = keys_ref;
1208 return 0;
1209 }
1210
1211 keys_ref = calloc(1, sizeof(*keys_ref));
1212 if (!keys_ref) {
1213 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1214 goto fail;
1215 }
1216
1217 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1218 if (!keys_ref->tlskeys) {
1219 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1220 goto fail;
1221 }
1222
1223 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1224 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1225 goto fail;
1226 }
1227
1228 keys_ref->filename = strdup(args[cur_arg + 1]);
1229 if (!keys_ref->filename) {
1230 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1231 goto fail;
1232 }
1233
1234 keys_ref->key_size_bits = 0;
1235 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1236 int len = strlen(thisline);
1237 int dec_size;
1238
1239 /* Strip newline characters from the end */
1240 if(thisline[len - 1] == '\n')
1241 thisline[--len] = 0;
1242
1243 if(thisline[len - 1] == '\r')
1244 thisline[--len] = 0;
1245
1246 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1247 if (dec_size < 0) {
1248 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1249 goto fail;
1250 }
1251 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1252 keys_ref->key_size_bits = 128;
1253 }
1254 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1255 keys_ref->key_size_bits = 256;
1256 }
1257 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1258 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1259 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1260 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1261 goto fail;
1262 }
1263 i++;
1264 }
1265
1266 if (i < TLS_TICKETS_NO) {
1267 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1268 goto fail;
1269 }
1270
1271 fclose(f);
1272
1273 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1274 i -= 2;
1275 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1276 keys_ref->unique_id = -1;
1277 keys_ref->refcount = 1;
1278 HA_RWLOCK_INIT(&keys_ref->lock);
1279 conf->keys_ref = keys_ref;
1280
Willy Tarreau2b718102021-04-21 07:32:39 +02001281 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001282
1283 return 0;
1284
1285 fail:
1286 if (f)
1287 fclose(f);
1288 if (keys_ref) {
1289 free(keys_ref->filename);
1290 free(keys_ref->tlskeys);
1291 free(keys_ref);
1292 }
1293 return ERR_ALERT | ERR_FATAL;
1294
1295#else
1296 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1297 return ERR_ALERT | ERR_FATAL;
1298#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1299}
1300
1301/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001302static 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 +02001303{
1304 if (!*args[cur_arg + 1]) {
1305 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1306 return ERR_ALERT | ERR_FATAL;
1307 }
1308
1309 if (strcmp(args[cur_arg + 1], "none") == 0)
1310 conf->verify = SSL_SOCK_VERIFY_NONE;
1311 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1312 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1313 else if (strcmp(args[cur_arg + 1], "required") == 0)
1314 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1315 else {
1316 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1317 args[cur_arg], args[cur_arg + 1]);
1318 return ERR_ALERT | ERR_FATAL;
1319 }
1320
1321 return 0;
1322}
1323static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1324{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001325 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001326}
1327
1328/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001329static 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 +02001330{
1331 conf->no_ca_names = 1;
1332 return 0;
1333}
1334static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1335{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001336 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001337}
1338
Remi Tricot-Le Breton03c5fff2022-12-20 11:11:10 +01001339
1340static int ssl_bind_parse_ocsp_update(char **args, int cur_arg, struct proxy *px,
1341 struct ssl_bind_conf *ssl_conf, int from_cli, char **err)
1342{
1343 if (!*args[cur_arg + 1]) {
1344 memprintf(err, "'%s' : expecting <on|off>", args[cur_arg]);
1345 return ERR_ALERT | ERR_FATAL;
1346 }
1347
1348 if (strcmp(args[cur_arg + 1], "on") == 0)
1349 ssl_conf->ocsp_update = SSL_SOCK_OCSP_UPDATE_ON;
1350 else if (strcmp(args[cur_arg + 1], "off") == 0)
1351 ssl_conf->ocsp_update = SSL_SOCK_OCSP_UPDATE_OFF;
1352 else {
1353 memprintf(err, "'%s' : expecting <on|off>", args[cur_arg]);
1354 return ERR_ALERT | ERR_FATAL;
1355 }
1356
Remi Tricot-Le Bretonaff82772022-12-20 11:11:14 +01001357 if (ssl_conf->ocsp_update == SSL_SOCK_OCSP_UPDATE_ON) {
1358 /* We might need to create the main ocsp update task */
1359 int ret = ssl_create_ocsp_update_task(err);
1360 if (ret)
1361 return ret;
1362 }
1363
Remi Tricot-Le Breton03c5fff2022-12-20 11:11:10 +01001364 return 0;
1365}
1366
1367
William Lallemanddad31052020-05-14 17:47:32 +02001368/***************************** "server" keywords Parsing ********************************************/
1369
1370/* parse the "npn" bind keyword */
1371static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1372{
1373#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1374 char *p1, *p2;
1375
1376 if (!*args[*cur_arg + 1]) {
1377 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1378 return ERR_ALERT | ERR_FATAL;
1379 }
1380
1381 free(newsrv->ssl_ctx.npn_str);
1382
1383 /* the NPN string is built as a suite of (<len> <name>)*,
1384 * so we reuse each comma to store the next <len> and need
1385 * one more for the end of the string.
1386 */
1387 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1388 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001389 if (!newsrv->ssl_ctx.npn_str) {
1390 memprintf(err, "out of memory");
1391 return ERR_ALERT | ERR_FATAL;
1392 }
1393
William Lallemanddad31052020-05-14 17:47:32 +02001394 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1395 newsrv->ssl_ctx.npn_len);
1396
1397 /* replace commas with the name length */
1398 p1 = newsrv->ssl_ctx.npn_str;
1399 p2 = p1 + 1;
1400 while (1) {
1401 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1402 newsrv->ssl_ctx.npn_len - (p1 + 1));
1403 if (!p2)
1404 p2 = p1 + 1 + strlen(p1 + 1);
1405
1406 if (p2 - (p1 + 1) > 255) {
1407 *p2 = '\0';
1408 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1409 return ERR_ALERT | ERR_FATAL;
1410 }
1411
1412 *p1 = p2 - (p1 + 1);
1413 p1 = p2;
1414
1415 if (!*p2)
1416 break;
1417
1418 *(p2++) = '\0';
1419 }
1420 return 0;
1421#else
1422 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1423 return ERR_ALERT | ERR_FATAL;
1424#endif
1425}
1426
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001427#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1428static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1429{
1430 free(*out_alpn_str);
1431 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1432}
1433#endif
1434
1435/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001436static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1437{
1438#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001439 int ret = parse_alpn(args[*cur_arg + 1],
1440 &newsrv->ssl_ctx.alpn_str,
1441 &newsrv->ssl_ctx.alpn_len, err);
1442 if (ret)
1443 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1444 return ret;
1445#else
1446 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1447 return ERR_ALERT | ERR_FATAL;
1448#endif
1449}
William Lallemanddad31052020-05-14 17:47:32 +02001450
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001451/* parse the "check-alpn" server keyword */
1452static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1453{
1454#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1455 int ret = parse_alpn(args[*cur_arg + 1],
1456 &newsrv->check.alpn_str,
1457 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001458 if (ret)
1459 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1460 return ret;
1461#else
1462 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1463 return ERR_ALERT | ERR_FATAL;
1464#endif
1465}
1466
1467/* parse the "ca-file" server keyword */
1468static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1469{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001470 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1471
William Lallemanddad31052020-05-14 17:47:32 +02001472 if (!*args[*cur_arg + 1]) {
1473 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1474 return ERR_ALERT | ERR_FATAL;
1475 }
1476
1477 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1478 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1479 else
1480 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1481
Amaury Denoyelle48255022021-05-19 09:46:59 +02001482 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001483 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1484 return ERR_ALERT | ERR_FATAL;
1485 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001486
William Lallemanddad31052020-05-14 17:47:32 +02001487 return 0;
1488}
1489
1490/* parse the "check-sni" server keyword */
1491static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1492{
1493 if (!*args[*cur_arg + 1]) {
1494 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1495 return ERR_ALERT | ERR_FATAL;
1496 }
1497
1498 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1499 if (!newsrv->check.sni) {
1500 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1501 return ERR_ALERT | ERR_FATAL;
1502 }
1503 return 0;
1504
1505}
1506
William Dauchyfc52f522020-11-14 19:25:32 +01001507/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001508static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001509{
William Dauchyfc52f522020-11-14 19:25:32 +01001510 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1511 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001512#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001513 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001514 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001515 if (!s->ssl_ctx.ciphersuites)
1516 return 1;
1517 }
William Lallemanddad31052020-05-14 17:47:32 +02001518#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001519 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1520 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1521
1522 if (!s->ssl_ctx.methods.min)
1523 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001524
William Dauchyfc52f522020-11-14 19:25:32 +01001525 if (!s->ssl_ctx.methods.max)
1526 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001527
1528 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001529}
1530
1531/* parse the "check-ssl" server keyword */
1532static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1533{
1534 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001535 if (ssl_sock_init_srv(newsrv)) {
1536 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1537 return ERR_ALERT | ERR_FATAL;
1538 }
1539
William Lallemanddad31052020-05-14 17:47:32 +02001540 return 0;
1541}
1542
1543/* parse the "ciphers" server keyword */
1544static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1545{
1546 if (!*args[*cur_arg + 1]) {
1547 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1548 return ERR_ALERT | ERR_FATAL;
1549 }
1550
1551 free(newsrv->ssl_ctx.ciphers);
1552 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001553
1554 if (!newsrv->ssl_ctx.ciphers) {
1555 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1556 return ERR_ALERT | ERR_FATAL;
1557 }
1558
William Lallemanddad31052020-05-14 17:47:32 +02001559 return 0;
1560}
1561
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001562#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001563/* parse the "ciphersuites" server keyword */
1564static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1565{
1566 if (!*args[*cur_arg + 1]) {
1567 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1568 return ERR_ALERT | ERR_FATAL;
1569 }
1570
1571 free(newsrv->ssl_ctx.ciphersuites);
1572 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001573
1574 if (!newsrv->ssl_ctx.ciphersuites) {
1575 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1576 return ERR_ALERT | ERR_FATAL;
1577 }
1578
William Lallemanddad31052020-05-14 17:47:32 +02001579 return 0;
1580}
1581#endif
1582
1583/* parse the "crl-file" server keyword */
1584static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1585{
1586#ifndef X509_V_FLAG_CRL_CHECK
1587 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1588 return ERR_ALERT | ERR_FATAL;
1589#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001590 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1591
William Lallemanddad31052020-05-14 17:47:32 +02001592 if (!*args[*cur_arg + 1]) {
1593 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1594 return ERR_ALERT | ERR_FATAL;
1595 }
1596
1597 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1598 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1599 else
1600 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1601
Amaury Denoyellefde82602021-06-14 10:10:32 +02001602 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001603 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1604 return ERR_ALERT | ERR_FATAL;
1605 }
1606 return 0;
1607#endif
1608}
1609
1610/* parse the "crt" server keyword */
1611static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1612{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001613
William Lallemanddad31052020-05-14 17:47:32 +02001614 if (!*args[*cur_arg + 1]) {
1615 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1616 return ERR_ALERT | ERR_FATAL;
1617 }
1618
1619 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001620 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001621 else
William Lallemand2c776f12021-12-28 18:47:17 +01001622 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001623
William Lallemand2c776f12021-12-28 18:47:17 +01001624 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001625}
1626
1627/* parse the "no-check-ssl" server keyword */
1628static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1629{
1630 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001631 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001632 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1633 return 0;
1634}
1635
1636/* parse the "no-send-proxy-v2-ssl" server keyword */
1637static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1638{
1639 newsrv->pp_opts &= ~SRV_PP_V2;
1640 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1641 return 0;
1642}
1643
1644/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1645static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1646{
1647 newsrv->pp_opts &= ~SRV_PP_V2;
1648 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1649 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1650 return 0;
1651}
1652
1653/* parse the "no-ssl" server keyword */
1654static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1655{
William Dauchyf6370442020-11-14 19:25:33 +01001656 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001657 if (newsrv->use_ssl == 1) {
1658 if (ssl_sock_init_srv(newsrv)) {
1659 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1660 return ERR_ALERT | ERR_FATAL;
1661 }
1662 }
William Dauchyf6370442020-11-14 19:25:33 +01001663 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001664 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001665 }
William Lallemanddad31052020-05-14 17:47:32 +02001666 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001667 return 0;
1668}
1669
1670/* parse the "allow-0rtt" server keyword */
1671static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1672{
1673 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1674 return 0;
1675}
1676
1677/* parse the "no-ssl-reuse" server keyword */
1678static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1679{
1680 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1681 return 0;
1682}
1683
1684/* parse the "no-tls-tickets" server keyword */
1685static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1686{
1687 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1688 return 0;
1689}
1690/* parse the "send-proxy-v2-ssl" server keyword */
1691static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1692{
1693 newsrv->pp_opts |= SRV_PP_V2;
1694 newsrv->pp_opts |= SRV_PP_V2_SSL;
1695 return 0;
1696}
1697
1698/* parse the "send-proxy-v2-ssl-cn" server keyword */
1699static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1700{
1701 newsrv->pp_opts |= SRV_PP_V2;
1702 newsrv->pp_opts |= SRV_PP_V2_SSL;
1703 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1704 return 0;
1705}
1706
1707/* parse the "sni" server keyword */
1708static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1709{
1710#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1711 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1712 return ERR_ALERT | ERR_FATAL;
1713#else
1714 char *arg;
1715
1716 arg = args[*cur_arg + 1];
1717 if (!*arg) {
1718 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1719 return ERR_ALERT | ERR_FATAL;
1720 }
1721
1722 free(newsrv->sni_expr);
1723 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001724 if (!newsrv->sni_expr) {
1725 memprintf(err, "out of memory");
1726 return ERR_ALERT | ERR_FATAL;
1727 }
William Lallemanddad31052020-05-14 17:47:32 +02001728
1729 return 0;
1730#endif
1731}
1732
1733/* parse the "ssl" server keyword */
1734static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1735{
1736 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001737 if (ssl_sock_init_srv(newsrv)) {
1738 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1739 return ERR_ALERT | ERR_FATAL;
1740 }
1741
William Lallemanddad31052020-05-14 17:47:32 +02001742 return 0;
1743}
1744
1745/* parse the "ssl-reuse" server keyword */
1746static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1747{
1748 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1749 return 0;
1750}
1751
1752/* parse the "tls-tickets" server keyword */
1753static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1754{
1755 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1756 return 0;
1757}
1758
1759/* parse the "verify" server keyword */
1760static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1761{
1762 if (!*args[*cur_arg + 1]) {
1763 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1764 return ERR_ALERT | ERR_FATAL;
1765 }
1766
1767 if (strcmp(args[*cur_arg + 1], "none") == 0)
1768 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1769 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1770 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1771 else {
1772 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1773 args[*cur_arg], args[*cur_arg + 1]);
1774 return ERR_ALERT | ERR_FATAL;
1775 }
1776
1777 return 0;
1778}
1779
1780/* parse the "verifyhost" server keyword */
1781static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1782{
1783 if (!*args[*cur_arg + 1]) {
1784 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1785 return ERR_ALERT | ERR_FATAL;
1786 }
1787
1788 free(newsrv->ssl_ctx.verify_host);
1789 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1790
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001791 if (!newsrv->ssl_ctx.verify_host) {
1792 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1793 return ERR_ALERT | ERR_FATAL;
1794 }
1795
William Lallemanddad31052020-05-14 17:47:32 +02001796 return 0;
1797}
1798
1799/* parse the "ssl-default-bind-options" keyword in global section */
1800static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001801 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001802 char **err) {
1803 int i = 1;
1804
1805 if (*(args[i]) == 0) {
1806 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1807 return -1;
1808 }
1809 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001810 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001811 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001812 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001813 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
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.listen_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.listen_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 "ssl-default-server-options" keyword in global section */
1832static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001833 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001834 char **err) {
1835 int i = 1;
1836
1837 if (*(args[i]) == 0) {
1838 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1839 return -1;
1840 }
1841 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001842 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001843 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001844 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001845 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1846 i++;
1847 else {
1848 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1849 return -1;
1850 }
1851 }
1852 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1853 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1854 return -1;
1855 }
1856 i++;
1857 }
1858 return 0;
1859}
1860
1861/* parse the "ca-base" / "crt-base" keywords in global section.
1862 * Returns <0 on alert, >0 on warning, 0 on success.
1863 */
1864static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001865 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001866 char **err)
1867{
1868 char **target;
1869
1870 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1871
1872 if (too_many_args(1, args, err, NULL))
1873 return -1;
1874
1875 if (*target) {
1876 memprintf(err, "'%s' already specified.", args[0]);
1877 return -1;
1878 }
1879
1880 if (*(args[1]) == 0) {
1881 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1882 return -1;
1883 }
1884 *target = strdup(args[1]);
1885 return 0;
1886}
1887
1888/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1889static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001890 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001891 char **err)
1892{
William Lallemand9a1d8392020-08-10 17:28:23 +02001893#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001894 global_ssl.skip_self_issued_ca = 1;
1895 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001896#else
1897 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1898 return -1;
1899#endif
William Lallemanddad31052020-05-14 17:47:32 +02001900}
1901
1902
1903
1904
1905
1906/* Note: must not be declared <const> as its list will be overwritten.
1907 * Please take care of keeping this list alphabetically sorted, doing so helps
1908 * all code contributors.
1909 * Optional keywords are also declared with a NULL ->parse() function so that
1910 * the config parser can report an appropriate error when a known keyword was
1911 * not enabled.
1912 */
1913
1914/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1915 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1916struct ssl_bind_kw ssl_bind_kws[] = {
1917 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1918 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1919 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1920 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1921 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001922#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001923 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1924#endif
1925 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1926 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1927 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1928 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1929 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1930 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1931 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1932 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
Remi Tricot-Le Breton03c5fff2022-12-20 11:11:10 +01001933 { "ocsp-update", ssl_bind_parse_ocsp_update, 1 }, /* ocsp update mode (on or off) */
William Lallemanddad31052020-05-14 17:47:32 +02001934 { NULL, NULL, 0 },
1935};
1936
1937/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1938
1939static struct bind_kw_list bind_kws = { "SSL", { }, {
1940 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1941 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1942 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1943 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1944 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1945 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1946 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1947 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001948#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001949 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1950#endif
1951 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1952 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1953 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1954 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1955 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1956 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1957 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1958 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1959 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1960 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1961 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1962 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1963 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1964 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1965 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1966 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1967 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1968 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1969 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1970 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1971 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1972 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1973 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1974 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1975 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1976 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1977 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1978 { NULL, NULL, 0 },
1979}};
1980
1981INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1982
1983/* Note: must not be declared <const> as its list will be overwritten.
1984 * Please take care of keeping this list alphabetically sorted, doing so helps
1985 * all code contributors.
1986 * Optional keywords are also declared with a NULL ->parse() function so that
1987 * the config parser can report an appropriate error when a known keyword was
1988 * not enabled.
1989 */
1990static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001991 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1992 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001993 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001994 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1995 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1996 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001997 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001998#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001999 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02002000#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02002001 { "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 +02002002 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002003 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
2004 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
2005 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
2006 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
2007 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01002008 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
2009 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
2010 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
2011 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002012 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
2013 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
2014 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
2015 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
2016 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
2017 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
2018 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
2019 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
2020 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
2021 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
2022 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02002023 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002024 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
2025 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01002026 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02002027 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
2028 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
2029 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02002030 { NULL, NULL, 0, 0 },
2031}};
2032
2033INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
2034
2035static struct cfg_kw_list cfg_kws = {ILH, {
2036 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
2037 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
2038 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
2039 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
2040 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
2041 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
2042#ifndef OPENSSL_NO_DH
2043 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
2044#endif
2045 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
William Lallemandd7bfbe22022-04-11 18:41:24 +02002046#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +02002047 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
2048#endif
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002049#ifdef HAVE_SSL_PROVIDERS
2050 { CFG_GLOBAL, "ssl-propquery", ssl_parse_global_ssl_propquery },
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +02002051 { CFG_GLOBAL, "ssl-provider", ssl_parse_global_ssl_provider },
Remi Tricot-Le Bretonccc03552022-05-17 15:18:37 +02002052 { CFG_GLOBAL, "ssl-provider-path", ssl_parse_global_ssl_provider_path },
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02002053#endif
William Lallemanddad31052020-05-14 17:47:32 +02002054 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
2055 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
2056#ifndef OPENSSL_NO_DH
2057 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
2058#endif
2059 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
2060 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
2061 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
Thomas Prückl10243932022-04-27 13:04:54 +02002062 { CFG_GLOBAL, "tune.ssl.hard-maxrecord", ssl_parse_global_int },
William Lallemanddad31052020-05-14 17:47:32 +02002063 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02002064 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
2065 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02002066 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02002067 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
2068 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05002069#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02002070 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
2071#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05002072#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02002073 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
2074 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
2075#endif
2076 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02002077 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02002078 { 0, NULL, NULL },
2079}};
2080
2081INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);