blob: 462743e45e7329ae67f8ae3c38dfefedb95b382f [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
183/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
184 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
185 */
186static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100187 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200188 char **err)
189{
190 char **target;
191
192 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
193
194 if (too_many_args(1, args, err, NULL))
195 return -1;
196
197 if (*(args[1]) == 0) {
198 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
199 return -1;
200 }
201
202 free(*target);
203 *target = strdup(args[1]);
204 return 0;
205}
206
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500207#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200208/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
209 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
210 */
211static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100212 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200213 char **err)
214{
215 char **target;
216
217 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
218
219 if (too_many_args(1, args, err, NULL))
220 return -1;
221
222 if (*(args[1]) == 0) {
223 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
224 return -1;
225 }
226
227 free(*target);
228 *target = strdup(args[1]);
229 return 0;
230}
231#endif
232
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500233#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200234/*
235 * parse the "ssl-default-bind-curves" keyword in a global section.
236 * Returns <0 on alert, >0 on warning, 0 on success.
237 */
238static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100239 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200240 char **err)
241{
242 char **target;
243 target = &global_ssl.listen_default_curves;
244
245 if (too_many_args(1, args, err, NULL))
246 return -1;
247
248 if (*(args[1]) == 0) {
249 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
250 return -1;
251 }
252
253 free(*target);
254 *target = strdup(args[1]);
255 return 0;
256}
257#endif
258/* parse various global tune.ssl settings consisting in positive integers.
259 * Returns <0 on alert, >0 on warning, 0 on success.
260 */
261static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100262 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200263 char **err)
264{
265 int *target;
266
267 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
268 target = &global.tune.sslcachesize;
269 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
270 target = (int *)&global_ssl.max_record;
Thomas Prückl10243932022-04-27 13:04:54 +0200271 else if (strcmp(args[0], "tune.ssl.hard-maxrecord") == 0)
272 target = (int *)&global_ssl.hard_max_record;
William Lallemanddad31052020-05-14 17:47:32 +0200273 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
274 target = &global_ssl.ctx_cache;
275 else if (strcmp(args[0], "maxsslconn") == 0)
276 target = &global.maxsslconn;
Marcin Deranek310a2602021-07-13 19:04:24 +0200277 else if (strcmp(args[0], "tune.ssl.capture-buffer-size") == 0)
278 target = &global_ssl.capture_buffer_size;
279 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0) {
280 target = &global_ssl.capture_buffer_size;
281 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",
282 file, line, args[0]);
283 }
William Lallemanddad31052020-05-14 17:47:32 +0200284 else {
285 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
286 return -1;
287 }
288
289 if (too_many_args(1, args, err, NULL))
290 return -1;
291
292 if (*(args[1]) == 0) {
293 memprintf(err, "'%s' expects an integer argument.", args[0]);
294 return -1;
295 }
296
297 *target = atoi(args[1]);
298 if (*target < 0) {
299 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
300 return -1;
301 }
302 return 0;
303}
304
Marcin Deranek310a2602021-07-13 19:04:24 +0200305static int ssl_parse_global_capture_buffer(char **args, int section_type, struct proxy *curpx,
306 const struct proxy *defpx, const char *file, int line,
307 char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200308{
309 int ret;
310
311 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
312 if (ret != 0)
313 return ret;
314
315 if (pool_head_ssl_capture) {
316 memprintf(err, "'%s' is already configured.", args[0]);
317 return -1;
318 }
319
Marcin Deranek310a2602021-07-13 19:04:24 +0200320 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 +0200321 if (!pool_head_ssl_capture) {
322 memprintf(err, "Out of memory error.");
323 return -1;
324 }
325 return 0;
326}
327
William Lallemand7d42ef52020-07-06 11:41:30 +0200328/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200329#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200330static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100331 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200332 char **err)
333{
334
335 if (too_many_args(1, args, err, NULL))
336 return -1;
337
338 if (strcmp(args[1], "on") == 0)
339 global_ssl.keylog = 1;
340 else if (strcmp(args[1], "off") == 0)
341 global_ssl.keylog = 0;
342 else {
343 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
344 return -1;
345 }
346
347 if (pool_head_ssl_keylog) /* already configured */
348 return 0;
349
350 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
351 if (!pool_head_ssl_keylog) {
352 memprintf(err, "Out of memory error.");
353 return -1;
354 }
355
356 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
357 if (!pool_head_ssl_keylog_str) {
358 memprintf(err, "Out of memory error.");
359 return -1;
360 }
361
362 return 0;
363}
William Lallemand722180a2021-06-09 16:46:12 +0200364#else
365static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
366 const struct proxy *defpx, const char *file, int line,
367 char **err)
368{
369 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
370 return -1;
371}
William Lallemand7d42ef52020-07-06 11:41:30 +0200372#endif
373
William Lallemanddad31052020-05-14 17:47:32 +0200374/* parse "ssl.force-private-cache".
375 * Returns <0 on alert, >0 on warning, 0 on success.
376 */
377static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100378 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200379 char **err)
380{
381 if (too_many_args(0, args, err, NULL))
382 return -1;
383
384 global_ssl.private_cache = 1;
385 return 0;
386}
387
388/* parse "ssl.lifetime".
389 * Returns <0 on alert, >0 on warning, 0 on success.
390 */
391static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100392 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200393 char **err)
394{
395 const char *res;
396
397 if (too_many_args(1, args, err, NULL))
398 return -1;
399
400 if (*(args[1]) == 0) {
401 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
402 return -1;
403 }
404
405 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
406 if (res == PARSE_TIME_OVER) {
407 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
408 args[1], args[0]);
409 return -1;
410 }
411 else if (res == PARSE_TIME_UNDER) {
412 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
413 args[1], args[0]);
414 return -1;
415 }
416 else if (res) {
417 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
418 return -1;
419 }
420 return 0;
421}
422
423#ifndef OPENSSL_NO_DH
424/* parse "ssl-dh-param-file".
425 * Returns <0 on alert, >0 on warning, 0 on success.
426 */
427static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100428 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200429 char **err)
430{
431 if (too_many_args(1, args, err, NULL))
432 return -1;
433
434 if (*(args[1]) == 0) {
435 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
436 return -1;
437 }
438
439 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
440 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
441 return -1;
442 }
443 return 0;
444}
445
446/* parse "ssl.default-dh-param".
447 * Returns <0 on alert, >0 on warning, 0 on success.
448 */
449static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100450 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200451 char **err)
452{
453 if (too_many_args(1, args, err, NULL))
454 return -1;
455
456 if (*(args[1]) == 0) {
457 memprintf(err, "'%s' expects an integer argument.", args[0]);
458 return -1;
459 }
460
461 global_ssl.default_dh_param = atoi(args[1]);
462 if (global_ssl.default_dh_param < 1024) {
463 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
464 return -1;
465 }
466 return 0;
467}
468#endif
469
470
471/*
472 * parse "ssl-load-extra-files".
473 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
474 */
475static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100476 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200477 char **err)
478{
479 int i;
480 int gf = SSL_GF_NONE;
481
482 if (*(args[1]) == 0)
483 goto err_arg;
484
485 for (i = 1; *args[i]; i++) {
486
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100487 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200488 gf |= SSL_GF_BUNDLE;
489
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100490 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200491 gf |= SSL_GF_SCTL;
492
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100493 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200494 gf |= SSL_GF_OCSP;
495
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100496 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200497 gf |= SSL_GF_OCSP_ISSUER;
498
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100499 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200500 gf |= SSL_GF_KEY;
501
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100502 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200503 if (gf != SSL_GF_NONE)
504 goto err_alone;
505 gf = SSL_GF_NONE;
506 i++;
507 break;
508
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100509 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200510 if (gf != SSL_GF_NONE)
511 goto err_alone;
512 gf = SSL_GF_ALL;
513 i++;
514 break;
515 } else {
516 goto err_arg;
517 }
518 }
519 /* break from loop but there are still arguments */
520 if (*args[i])
521 goto err_alone;
522
523 global_ssl.extra_files = gf;
524
525 return 0;
526
527err_alone:
528 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
529 return -1;
530
531err_arg:
532 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
533 return -1;
534}
535
536
William Lallemand8e8581e2020-10-20 17:36:46 +0200537/* parse 'ssl-load-extra-del-ext */
538static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100539 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200540 char **err)
541{
542 global_ssl.extra_files_noext = 1;
543 return 0;
544}
545
William Lallemanddad31052020-05-14 17:47:32 +0200546/***************************** Bind keyword Parsing ********************************************/
547
548/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100549static 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 +0200550{
551 if (!*args[cur_arg + 1]) {
552 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
553 return ERR_ALERT | ERR_FATAL;
554 }
555
556 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
557 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
558 else
559 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
560
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200561 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200562 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
563 return ERR_ALERT | ERR_FATAL;
564 }
565 return 0;
566}
567
568/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100569static 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 +0200570{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100571 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200572}
573static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
574{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100575 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200576}
577
578/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100579static 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 +0200580{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100581 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200582}
583static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
584{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100585 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200586}
587
588/* parse the "ca-sign-file" bind keyword */
589static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
590{
591 if (!*args[cur_arg + 1]) {
592 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
593 return ERR_ALERT | ERR_FATAL;
594 }
595
596 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
597 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
598 else
599 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
600
601 return 0;
602}
603
604/* parse the "ca-sign-pass" bind keyword */
605static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
606{
607 if (!*args[cur_arg + 1]) {
608 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
609 return ERR_ALERT | ERR_FATAL;
610 }
611 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
612 return 0;
613}
614
615/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100616static 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 +0200617{
618 if (!*args[cur_arg + 1]) {
619 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
620 return ERR_ALERT | ERR_FATAL;
621 }
622
623 free(conf->ciphers);
624 conf->ciphers = strdup(args[cur_arg + 1]);
625 return 0;
626}
627static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
628{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100629 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200630}
631
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500632#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200633/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100634static 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 +0200635{
636 if (!*args[cur_arg + 1]) {
637 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
638 return ERR_ALERT | ERR_FATAL;
639 }
640
641 free(conf->ciphersuites);
642 conf->ciphersuites = strdup(args[cur_arg + 1]);
643 return 0;
644}
645static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
646{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100647 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200648}
649#endif
650
651/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
652static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
653{
654 char path[MAXPATHLEN];
655
656 if (!*args[cur_arg + 1]) {
657 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
658 return ERR_ALERT | ERR_FATAL;
659 }
660
661 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
Willy Tarreau393e42a2022-05-09 10:31:28 +0200662 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
663 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
William Lallemanddad31052020-05-14 17:47:32 +0200664 memprintf(err, "'%s' : path too long", args[cur_arg]);
665 return ERR_ALERT | ERR_FATAL;
666 }
William Lallemanddad31052020-05-14 17:47:32 +0200667 return ssl_sock_load_cert(path, conf, err);
668 }
669
670 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
671}
672
673/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
674static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
675{
676 int err_code;
677
678 if (!*args[cur_arg + 1]) {
679 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
680 return ERR_ALERT | ERR_FATAL;
681 }
682
683 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
684 if (err_code)
685 memprintf(err, "'%s' : %s", args[cur_arg], *err);
686
687 return err_code;
688}
689
690/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100691static 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 +0200692{
693#ifndef X509_V_FLAG_CRL_CHECK
694 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
695 return ERR_ALERT | ERR_FATAL;
696#else
697 if (!*args[cur_arg + 1]) {
698 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
699 return ERR_ALERT | ERR_FATAL;
700 }
701
702 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
703 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
704 else
705 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
706
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200707 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200708 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
709 return ERR_ALERT | ERR_FATAL;
710 }
711 return 0;
712#endif
713}
714static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
715{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100716 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200717}
718
719/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100720static 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 +0200721{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500722#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200723 if (!*args[cur_arg + 1]) {
724 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
725 return ERR_ALERT | ERR_FATAL;
726 }
727 conf->curves = strdup(args[cur_arg + 1]);
728 return 0;
729#else
730 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
731 return ERR_ALERT | ERR_FATAL;
732#endif
733}
734static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
735{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100736 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200737}
738
739/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100740static 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 +0200741{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500742#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200743 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
744 return ERR_ALERT | ERR_FATAL;
745#elif defined(OPENSSL_NO_ECDH)
746 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
747 return ERR_ALERT | ERR_FATAL;
748#else
749 if (!*args[cur_arg + 1]) {
750 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
751 return ERR_ALERT | ERR_FATAL;
752 }
753
754 conf->ecdhe = strdup(args[cur_arg + 1]);
755
756 return 0;
757#endif
758}
759static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
760{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100761 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200762}
763
764/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
765static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
766{
767 int code;
768 char *p = args[cur_arg + 1];
769 unsigned long long *ignerr = &conf->crt_ignerr;
770
771 if (!*p) {
772 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
773 return ERR_ALERT | ERR_FATAL;
774 }
775
776 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
777 ignerr = &conf->ca_ignerr;
778
779 if (strcmp(p, "all") == 0) {
780 *ignerr = ~0ULL;
781 return 0;
782 }
783
784 while (p) {
785 code = atoi(p);
786 if ((code <= 0) || (code > 63)) {
787 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
788 args[cur_arg], code, args[cur_arg + 1]);
789 return ERR_ALERT | ERR_FATAL;
790 }
791 *ignerr |= 1ULL << code;
792 p = strchr(p, ',');
793 if (p)
794 p++;
795 }
796
797 return 0;
798}
799
800/* parse tls_method_options "no-xxx" and "force-xxx" */
801static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
802{
803 uint16_t v;
804 char *p;
805 p = strchr(arg, '-');
806 if (!p)
807 goto fail;
808 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100809 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200810 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100811 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200812 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100813 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200814 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100815 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200816 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100817 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200818 v = CONF_TLSV13;
819 else
820 goto fail;
821 if (!strncmp(arg, "no-", 3))
822 methods->flags |= methodVersions[v].flag;
823 else if (!strncmp(arg, "force-", 6))
824 methods->min = methods->max = v;
825 else
826 goto fail;
827 return 0;
828 fail:
829 memprintf(err, "'%s' : option not implemented", arg);
830 return ERR_ALERT | ERR_FATAL;
831}
832
833static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
834{
835 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
836}
837
838static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
839{
840 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
841}
842
843/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
844static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
845{
846 uint16_t i, v = 0;
847 char *argv = args[cur_arg + 1];
848 if (!*argv) {
849 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
850 return ERR_ALERT | ERR_FATAL;
851 }
852 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100853 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200854 v = i;
855 if (!v) {
856 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
857 return ERR_ALERT | ERR_FATAL;
858 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100859 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200860 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100861 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200862 methods->max = v;
863 else {
864 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
865 return ERR_ALERT | ERR_FATAL;
866 }
867 return 0;
868}
869
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100870static 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 +0200871{
William Lallemand8177ad92020-05-20 16:49:02 +0200872 int ret;
873
William Lallemanddad31052020-05-14 17:47:32 +0200874#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
875 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
876#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200877 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
878 if (ret != ERR_NONE)
879 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200880
William Lallemand8177ad92020-05-20 16:49:02 +0200881 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
882 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
883
884 return ret;
885}
William Lallemanddad31052020-05-14 17:47:32 +0200886static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
887{
888 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
889}
890
891static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
892{
893 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
894}
895
896/* parse the "no-tls-tickets" bind keyword */
897static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
898{
899 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
900 return 0;
901}
902
903/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100904static 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 +0200905{
906 conf->early_data = 1;
907 return 0;
908}
909
910static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
911{
912 conf->ssl_conf.early_data = 1;
913 return 0;
914}
915
916/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100917static 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 +0200918{
919#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
920 char *p1, *p2;
921
922 if (!*args[cur_arg + 1]) {
923 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
924 return ERR_ALERT | ERR_FATAL;
925 }
926
927 free(conf->npn_str);
928
929 /* the NPN string is built as a suite of (<len> <name>)*,
930 * so we reuse each comma to store the next <len> and need
931 * one more for the end of the string.
932 */
933 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
934 conf->npn_str = calloc(1, conf->npn_len + 1);
935 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
936
937 /* replace commas with the name length */
938 p1 = conf->npn_str;
939 p2 = p1 + 1;
940 while (1) {
941 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
942 if (!p2)
943 p2 = p1 + 1 + strlen(p1 + 1);
944
945 if (p2 - (p1 + 1) > 255) {
946 *p2 = '\0';
947 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
948 return ERR_ALERT | ERR_FATAL;
949 }
950
951 *p1 = p2 - (p1 + 1);
952 p1 = p2;
953
954 if (!*p2)
955 break;
956
957 *(p2++) = '\0';
958 }
959 return 0;
960#else
961 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
962 return ERR_ALERT | ERR_FATAL;
963#endif
964}
965
966static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
967{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100968 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200969}
970
971
972/* Parses a alpn string and converts it to the right format for the SSL api */
973int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
974{
975 char *p1, *p2, *alpn = NULL;
976 int len, ret = 0;
977
978 *alpn_str = NULL;
979 *alpn_len = 0;
980
981 if (!*arg) {
982 memprintf(err, "missing the comma-delimited ALPN protocol suite");
983 goto error;
984 }
985
986 /* the ALPN string is built as a suite of (<len> <name>)*,
987 * so we reuse each comma to store the next <len> and need
988 * one more for the end of the string.
989 */
990 len = strlen(arg) + 1;
991 alpn = calloc(1, len+1);
992 if (!alpn) {
993 memprintf(err, "'%s' : out of memory", arg);
994 goto error;
995 }
996 memcpy(alpn+1, arg, len);
997
998 /* replace commas with the name length */
999 p1 = alpn;
1000 p2 = p1 + 1;
1001 while (1) {
1002 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1003 if (!p2)
1004 p2 = p1 + 1 + strlen(p1 + 1);
1005
1006 if (p2 - (p1 + 1) > 255) {
1007 *p2 = '\0';
1008 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1009 goto error;
1010 }
1011
1012 *p1 = p2 - (p1 + 1);
1013 p1 = p2;
1014
1015 if (!*p2)
1016 break;
1017
1018 *(p2++) = '\0';
1019 }
1020
1021 *alpn_str = alpn;
1022 *alpn_len = len;
1023
1024 out:
1025 return ret;
1026
1027 error:
1028 free(alpn);
1029 ret = ERR_ALERT | ERR_FATAL;
1030 goto out;
1031}
1032
1033/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001034static 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 +02001035{
1036#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1037 int ret;
1038
1039 free(conf->alpn_str);
1040
1041 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1042 if (ret)
1043 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1044 return ret;
1045#else
1046 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1047 return ERR_ALERT | ERR_FATAL;
1048#endif
1049}
1050
1051static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1052{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001053 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001054}
1055
1056/* parse the "ssl" bind keyword */
1057static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1058{
Frédéric Lécaillee50afbd2020-11-23 11:33:12 +01001059 /* Do not change the xprt for QUIC. */
1060 if (conf->xprt != xprt_get(XPRT_QUIC))
1061 conf->xprt = &ssl_sock;
William Lallemanddad31052020-05-14 17:47:32 +02001062 conf->is_ssl = 1;
1063
1064 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1065 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001066#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001067 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1068 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1069#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001070#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001071 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1072 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1073#endif
1074 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1075 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1076 if (!conf->ssl_conf.ssl_methods.min)
1077 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1078 if (!conf->ssl_conf.ssl_methods.max)
1079 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1080
1081 return 0;
1082}
1083
1084/* parse the "prefer-client-ciphers" bind keyword */
1085static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1086{
1087 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1088 return 0;
1089}
1090
1091/* parse the "generate-certificates" bind keyword */
1092static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1093{
1094#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1095 conf->generate_certs = 1;
1096#else
1097 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1098 err && *err ? *err : "");
1099#endif
1100 return 0;
1101}
1102
1103/* parse the "strict-sni" bind keyword */
1104static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1105{
1106 conf->strict_sni = 1;
1107 return 0;
1108}
1109
1110/* parse the "tls-ticket-keys" bind keyword */
1111static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1112{
1113#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1114 FILE *f = NULL;
1115 int i = 0;
1116 char thisline[LINESIZE];
1117 struct tls_keys_ref *keys_ref = NULL;
1118
1119 if (!*args[cur_arg + 1]) {
1120 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1121 goto fail;
1122 }
1123
1124 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1125 if (keys_ref) {
1126 keys_ref->refcount++;
1127 conf->keys_ref = keys_ref;
1128 return 0;
1129 }
1130
1131 keys_ref = calloc(1, sizeof(*keys_ref));
1132 if (!keys_ref) {
1133 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1134 goto fail;
1135 }
1136
1137 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1138 if (!keys_ref->tlskeys) {
1139 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1140 goto fail;
1141 }
1142
1143 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1144 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1145 goto fail;
1146 }
1147
1148 keys_ref->filename = strdup(args[cur_arg + 1]);
1149 if (!keys_ref->filename) {
1150 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1151 goto fail;
1152 }
1153
1154 keys_ref->key_size_bits = 0;
1155 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1156 int len = strlen(thisline);
1157 int dec_size;
1158
1159 /* Strip newline characters from the end */
1160 if(thisline[len - 1] == '\n')
1161 thisline[--len] = 0;
1162
1163 if(thisline[len - 1] == '\r')
1164 thisline[--len] = 0;
1165
1166 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1167 if (dec_size < 0) {
1168 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1169 goto fail;
1170 }
1171 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1172 keys_ref->key_size_bits = 128;
1173 }
1174 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1175 keys_ref->key_size_bits = 256;
1176 }
1177 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1178 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1179 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1180 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1181 goto fail;
1182 }
1183 i++;
1184 }
1185
1186 if (i < TLS_TICKETS_NO) {
1187 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1188 goto fail;
1189 }
1190
1191 fclose(f);
1192
1193 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1194 i -= 2;
1195 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1196 keys_ref->unique_id = -1;
1197 keys_ref->refcount = 1;
1198 HA_RWLOCK_INIT(&keys_ref->lock);
1199 conf->keys_ref = keys_ref;
1200
Willy Tarreau2b718102021-04-21 07:32:39 +02001201 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001202
1203 return 0;
1204
1205 fail:
1206 if (f)
1207 fclose(f);
1208 if (keys_ref) {
1209 free(keys_ref->filename);
1210 free(keys_ref->tlskeys);
1211 free(keys_ref);
1212 }
1213 return ERR_ALERT | ERR_FATAL;
1214
1215#else
1216 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1217 return ERR_ALERT | ERR_FATAL;
1218#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1219}
1220
1221/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001222static 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 +02001223{
1224 if (!*args[cur_arg + 1]) {
1225 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1226 return ERR_ALERT | ERR_FATAL;
1227 }
1228
1229 if (strcmp(args[cur_arg + 1], "none") == 0)
1230 conf->verify = SSL_SOCK_VERIFY_NONE;
1231 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1232 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1233 else if (strcmp(args[cur_arg + 1], "required") == 0)
1234 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1235 else {
1236 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1237 args[cur_arg], args[cur_arg + 1]);
1238 return ERR_ALERT | ERR_FATAL;
1239 }
1240
1241 return 0;
1242}
1243static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1244{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001245 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001246}
1247
1248/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001249static 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 +02001250{
1251 conf->no_ca_names = 1;
1252 return 0;
1253}
1254static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1255{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001256 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001257}
1258
1259/***************************** "server" keywords Parsing ********************************************/
1260
1261/* parse the "npn" bind keyword */
1262static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1263{
1264#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1265 char *p1, *p2;
1266
1267 if (!*args[*cur_arg + 1]) {
1268 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1269 return ERR_ALERT | ERR_FATAL;
1270 }
1271
1272 free(newsrv->ssl_ctx.npn_str);
1273
1274 /* the NPN string is built as a suite of (<len> <name>)*,
1275 * so we reuse each comma to store the next <len> and need
1276 * one more for the end of the string.
1277 */
1278 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1279 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001280 if (!newsrv->ssl_ctx.npn_str) {
1281 memprintf(err, "out of memory");
1282 return ERR_ALERT | ERR_FATAL;
1283 }
1284
William Lallemanddad31052020-05-14 17:47:32 +02001285 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1286 newsrv->ssl_ctx.npn_len);
1287
1288 /* replace commas with the name length */
1289 p1 = newsrv->ssl_ctx.npn_str;
1290 p2 = p1 + 1;
1291 while (1) {
1292 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1293 newsrv->ssl_ctx.npn_len - (p1 + 1));
1294 if (!p2)
1295 p2 = p1 + 1 + strlen(p1 + 1);
1296
1297 if (p2 - (p1 + 1) > 255) {
1298 *p2 = '\0';
1299 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1300 return ERR_ALERT | ERR_FATAL;
1301 }
1302
1303 *p1 = p2 - (p1 + 1);
1304 p1 = p2;
1305
1306 if (!*p2)
1307 break;
1308
1309 *(p2++) = '\0';
1310 }
1311 return 0;
1312#else
1313 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1314 return ERR_ALERT | ERR_FATAL;
1315#endif
1316}
1317
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001318#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1319static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1320{
1321 free(*out_alpn_str);
1322 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1323}
1324#endif
1325
1326/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001327static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1328{
1329#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001330 int ret = parse_alpn(args[*cur_arg + 1],
1331 &newsrv->ssl_ctx.alpn_str,
1332 &newsrv->ssl_ctx.alpn_len, err);
1333 if (ret)
1334 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1335 return ret;
1336#else
1337 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1338 return ERR_ALERT | ERR_FATAL;
1339#endif
1340}
William Lallemanddad31052020-05-14 17:47:32 +02001341
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001342/* parse the "check-alpn" server keyword */
1343static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1344{
1345#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1346 int ret = parse_alpn(args[*cur_arg + 1],
1347 &newsrv->check.alpn_str,
1348 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001349 if (ret)
1350 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1351 return ret;
1352#else
1353 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1354 return ERR_ALERT | ERR_FATAL;
1355#endif
1356}
1357
1358/* parse the "ca-file" server keyword */
1359static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1360{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001361 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1362
William Lallemanddad31052020-05-14 17:47:32 +02001363 if (!*args[*cur_arg + 1]) {
1364 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1365 return ERR_ALERT | ERR_FATAL;
1366 }
1367
1368 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1369 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1370 else
1371 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1372
Amaury Denoyelle48255022021-05-19 09:46:59 +02001373 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001374 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1375 return ERR_ALERT | ERR_FATAL;
1376 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001377
William Lallemanddad31052020-05-14 17:47:32 +02001378 return 0;
1379}
1380
1381/* parse the "check-sni" server keyword */
1382static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1383{
1384 if (!*args[*cur_arg + 1]) {
1385 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1386 return ERR_ALERT | ERR_FATAL;
1387 }
1388
1389 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1390 if (!newsrv->check.sni) {
1391 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1392 return ERR_ALERT | ERR_FATAL;
1393 }
1394 return 0;
1395
1396}
1397
William Dauchyfc52f522020-11-14 19:25:32 +01001398/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001399static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001400{
William Dauchyfc52f522020-11-14 19:25:32 +01001401 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1402 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001403#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001404 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001405 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001406 if (!s->ssl_ctx.ciphersuites)
1407 return 1;
1408 }
William Lallemanddad31052020-05-14 17:47:32 +02001409#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001410 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1411 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1412
1413 if (!s->ssl_ctx.methods.min)
1414 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001415
William Dauchyfc52f522020-11-14 19:25:32 +01001416 if (!s->ssl_ctx.methods.max)
1417 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001418
1419 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001420}
1421
1422/* parse the "check-ssl" server keyword */
1423static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1424{
1425 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001426 if (ssl_sock_init_srv(newsrv)) {
1427 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1428 return ERR_ALERT | ERR_FATAL;
1429 }
1430
William Lallemanddad31052020-05-14 17:47:32 +02001431 return 0;
1432}
1433
1434/* parse the "ciphers" server keyword */
1435static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1436{
1437 if (!*args[*cur_arg + 1]) {
1438 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1439 return ERR_ALERT | ERR_FATAL;
1440 }
1441
1442 free(newsrv->ssl_ctx.ciphers);
1443 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001444
1445 if (!newsrv->ssl_ctx.ciphers) {
1446 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1447 return ERR_ALERT | ERR_FATAL;
1448 }
1449
William Lallemanddad31052020-05-14 17:47:32 +02001450 return 0;
1451}
1452
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001453#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001454/* parse the "ciphersuites" server keyword */
1455static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1456{
1457 if (!*args[*cur_arg + 1]) {
1458 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1459 return ERR_ALERT | ERR_FATAL;
1460 }
1461
1462 free(newsrv->ssl_ctx.ciphersuites);
1463 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001464
1465 if (!newsrv->ssl_ctx.ciphersuites) {
1466 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1467 return ERR_ALERT | ERR_FATAL;
1468 }
1469
William Lallemanddad31052020-05-14 17:47:32 +02001470 return 0;
1471}
1472#endif
1473
1474/* parse the "crl-file" server keyword */
1475static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1476{
1477#ifndef X509_V_FLAG_CRL_CHECK
1478 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1479 return ERR_ALERT | ERR_FATAL;
1480#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001481 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1482
William Lallemanddad31052020-05-14 17:47:32 +02001483 if (!*args[*cur_arg + 1]) {
1484 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1485 return ERR_ALERT | ERR_FATAL;
1486 }
1487
1488 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1489 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1490 else
1491 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1492
Amaury Denoyellefde82602021-06-14 10:10:32 +02001493 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001494 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1495 return ERR_ALERT | ERR_FATAL;
1496 }
1497 return 0;
1498#endif
1499}
1500
1501/* parse the "crt" server keyword */
1502static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1503{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001504
William Lallemanddad31052020-05-14 17:47:32 +02001505 if (!*args[*cur_arg + 1]) {
1506 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1507 return ERR_ALERT | ERR_FATAL;
1508 }
1509
1510 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001511 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001512 else
William Lallemand2c776f12021-12-28 18:47:17 +01001513 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001514
William Lallemand2c776f12021-12-28 18:47:17 +01001515 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001516}
1517
1518/* parse the "no-check-ssl" server keyword */
1519static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1520{
1521 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001522 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001523 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1524 return 0;
1525}
1526
1527/* parse the "no-send-proxy-v2-ssl" server keyword */
1528static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1529{
1530 newsrv->pp_opts &= ~SRV_PP_V2;
1531 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1532 return 0;
1533}
1534
1535/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1536static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1537{
1538 newsrv->pp_opts &= ~SRV_PP_V2;
1539 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1540 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1541 return 0;
1542}
1543
1544/* parse the "no-ssl" server keyword */
1545static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1546{
William Dauchyf6370442020-11-14 19:25:33 +01001547 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001548 if (newsrv->use_ssl == 1) {
1549 if (ssl_sock_init_srv(newsrv)) {
1550 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1551 return ERR_ALERT | ERR_FATAL;
1552 }
1553 }
William Dauchyf6370442020-11-14 19:25:33 +01001554 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001555 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001556 }
William Lallemanddad31052020-05-14 17:47:32 +02001557 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001558 return 0;
1559}
1560
1561/* parse the "allow-0rtt" server keyword */
1562static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1563{
1564 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1565 return 0;
1566}
1567
1568/* parse the "no-ssl-reuse" server keyword */
1569static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1570{
1571 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1572 return 0;
1573}
1574
1575/* parse the "no-tls-tickets" server keyword */
1576static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1577{
1578 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1579 return 0;
1580}
1581/* parse the "send-proxy-v2-ssl" server keyword */
1582static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1583{
1584 newsrv->pp_opts |= SRV_PP_V2;
1585 newsrv->pp_opts |= SRV_PP_V2_SSL;
1586 return 0;
1587}
1588
1589/* parse the "send-proxy-v2-ssl-cn" server keyword */
1590static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1591{
1592 newsrv->pp_opts |= SRV_PP_V2;
1593 newsrv->pp_opts |= SRV_PP_V2_SSL;
1594 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1595 return 0;
1596}
1597
1598/* parse the "sni" server keyword */
1599static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1600{
1601#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1602 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1603 return ERR_ALERT | ERR_FATAL;
1604#else
1605 char *arg;
1606
1607 arg = args[*cur_arg + 1];
1608 if (!*arg) {
1609 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1610 return ERR_ALERT | ERR_FATAL;
1611 }
1612
1613 free(newsrv->sni_expr);
1614 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001615 if (!newsrv->sni_expr) {
1616 memprintf(err, "out of memory");
1617 return ERR_ALERT | ERR_FATAL;
1618 }
William Lallemanddad31052020-05-14 17:47:32 +02001619
1620 return 0;
1621#endif
1622}
1623
1624/* parse the "ssl" server keyword */
1625static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1626{
1627 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001628 if (ssl_sock_init_srv(newsrv)) {
1629 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1630 return ERR_ALERT | ERR_FATAL;
1631 }
1632
William Lallemanddad31052020-05-14 17:47:32 +02001633 return 0;
1634}
1635
1636/* parse the "ssl-reuse" server keyword */
1637static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1638{
1639 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1640 return 0;
1641}
1642
1643/* parse the "tls-tickets" server keyword */
1644static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1645{
1646 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1647 return 0;
1648}
1649
1650/* parse the "verify" server keyword */
1651static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1652{
1653 if (!*args[*cur_arg + 1]) {
1654 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1655 return ERR_ALERT | ERR_FATAL;
1656 }
1657
1658 if (strcmp(args[*cur_arg + 1], "none") == 0)
1659 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1660 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1661 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1662 else {
1663 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1664 args[*cur_arg], args[*cur_arg + 1]);
1665 return ERR_ALERT | ERR_FATAL;
1666 }
1667
1668 return 0;
1669}
1670
1671/* parse the "verifyhost" server keyword */
1672static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1673{
1674 if (!*args[*cur_arg + 1]) {
1675 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1676 return ERR_ALERT | ERR_FATAL;
1677 }
1678
1679 free(newsrv->ssl_ctx.verify_host);
1680 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1681
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001682 if (!newsrv->ssl_ctx.verify_host) {
1683 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1684 return ERR_ALERT | ERR_FATAL;
1685 }
1686
William Lallemanddad31052020-05-14 17:47:32 +02001687 return 0;
1688}
1689
1690/* parse the "ssl-default-bind-options" keyword in global section */
1691static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001692 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001693 char **err) {
1694 int i = 1;
1695
1696 if (*(args[i]) == 0) {
1697 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1698 return -1;
1699 }
1700 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001701 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001702 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001703 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001704 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001705 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001706 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1707 i++;
1708 else {
1709 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1710 return -1;
1711 }
1712 }
1713 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1714 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1715 return -1;
1716 }
1717 i++;
1718 }
1719 return 0;
1720}
1721
1722/* parse the "ssl-default-server-options" keyword in global section */
1723static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001724 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001725 char **err) {
1726 int i = 1;
1727
1728 if (*(args[i]) == 0) {
1729 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1730 return -1;
1731 }
1732 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001733 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001734 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001735 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001736 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1737 i++;
1738 else {
1739 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1740 return -1;
1741 }
1742 }
1743 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1744 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1745 return -1;
1746 }
1747 i++;
1748 }
1749 return 0;
1750}
1751
1752/* parse the "ca-base" / "crt-base" keywords in global section.
1753 * Returns <0 on alert, >0 on warning, 0 on success.
1754 */
1755static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001756 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001757 char **err)
1758{
1759 char **target;
1760
1761 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1762
1763 if (too_many_args(1, args, err, NULL))
1764 return -1;
1765
1766 if (*target) {
1767 memprintf(err, "'%s' already specified.", args[0]);
1768 return -1;
1769 }
1770
1771 if (*(args[1]) == 0) {
1772 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1773 return -1;
1774 }
1775 *target = strdup(args[1]);
1776 return 0;
1777}
1778
1779/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1780static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001781 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001782 char **err)
1783{
William Lallemand9a1d8392020-08-10 17:28:23 +02001784#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001785 global_ssl.skip_self_issued_ca = 1;
1786 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001787#else
1788 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1789 return -1;
1790#endif
William Lallemanddad31052020-05-14 17:47:32 +02001791}
1792
1793
1794
1795
1796
1797/* Note: must not be declared <const> as its list will be overwritten.
1798 * Please take care of keeping this list alphabetically sorted, doing so helps
1799 * all code contributors.
1800 * Optional keywords are also declared with a NULL ->parse() function so that
1801 * the config parser can report an appropriate error when a known keyword was
1802 * not enabled.
1803 */
1804
1805/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1806 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1807struct ssl_bind_kw ssl_bind_kws[] = {
1808 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1809 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1810 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1811 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1812 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001813#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001814 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1815#endif
1816 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1817 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1818 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1819 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1820 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1821 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1822 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1823 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1824 { NULL, NULL, 0 },
1825};
1826
1827/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1828
1829static struct bind_kw_list bind_kws = { "SSL", { }, {
1830 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1831 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1832 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1833 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1834 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1835 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1836 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1837 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001838#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001839 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1840#endif
1841 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1842 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1843 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1844 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1845 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1846 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1847 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1848 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1849 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1850 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1851 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1852 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1853 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1854 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1855 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1856 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1857 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1858 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1859 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1860 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1861 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1862 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1863 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1864 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1865 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1866 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1867 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1868 { NULL, NULL, 0 },
1869}};
1870
1871INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1872
1873/* Note: must not be declared <const> as its list will be overwritten.
1874 * Please take care of keeping this list alphabetically sorted, doing so helps
1875 * all code contributors.
1876 * Optional keywords are also declared with a NULL ->parse() function so that
1877 * the config parser can report an appropriate error when a known keyword was
1878 * not enabled.
1879 */
1880static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001881 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1882 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001883 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001884 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1885 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1886 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001887 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001888#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001889 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001890#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001891 { "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 +02001892 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001893 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1894 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1895 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1896 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1897 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001898 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1899 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1900 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1901 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001902 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1903 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1904 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1905 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1906 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1907 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1908 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1909 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1910 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1911 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1912 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001913 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001914 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1915 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001916 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001917 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1918 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
1919 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001920 { NULL, NULL, 0, 0 },
1921}};
1922
1923INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1924
1925static struct cfg_kw_list cfg_kws = {ILH, {
1926 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1927 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1928 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1929 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1930 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1931 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1932#ifndef OPENSSL_NO_DH
1933 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1934#endif
1935 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
William Lallemandd7bfbe22022-04-11 18:41:24 +02001936#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +02001937 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1938#endif
1939 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1940 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1941#ifndef OPENSSL_NO_DH
1942 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1943#endif
1944 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
1945 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1946 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
Thomas Prückl10243932022-04-27 13:04:54 +02001947 { CFG_GLOBAL, "tune.ssl.hard-maxrecord", ssl_parse_global_int },
William Lallemanddad31052020-05-14 17:47:32 +02001948 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02001949 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
1950 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02001951 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02001952 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1953 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001954#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001955 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
1956#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001957#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001958 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
1959 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
1960#endif
1961 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02001962 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02001963 { 0, NULL, NULL },
1964}};
1965
1966INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);