blob: 513cfd6a7ed7bca2172792766466af346248120a [file] [log] [blame]
William Lallemanddad31052020-05-14 17:47:32 +02001/*
2 *
3 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
4 * Copyright (C) 2020 HAProxy Technologies, William Lallemand <wlallemand@haproxy.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 *
12 * Configuration parsing for SSL.
13 * This file is split in 3 parts:
14 * - global section parsing
15 * - bind keyword parsing
16 * - server keyword parsing
17 *
18 * Please insert the new keywords at the right place
19 */
20
21#define _GNU_SOURCE
22#include <ctype.h>
23#include <dirent.h>
24#include <errno.h>
William Lallemanddad31052020-05-14 17:47:32 +020025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include <sys/stat.h>
31#include <sys/types.h>
32
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020033#include <haproxy/api.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020034#include <haproxy/base64.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020035#include <haproxy/cfgparse.h>
Willy Tarreau0d1dd0e2021-10-06 19:00:49 +020036#include <haproxy/errors.h>
Willy Tarreau213e9902020-06-04 14:58:24 +020037#include <haproxy/listener.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +020038#include <haproxy/openssl-compat.h>
Willy Tarreau209108d2020-06-04 20:30:20 +020039#include <haproxy/ssl_sock.h>
Willy Tarreaucc81eca2021-05-08 12:54:42 +020040#include <haproxy/tools.h>
Remi Tricot-Le Bretonaf8820a2021-04-13 10:10:37 +020041#include <haproxy/ssl_ckch.h>
William Lallemanddad31052020-05-14 17:47:32 +020042
43
44/****************** Global Section Parsing ********************************************/
45
46static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +010047 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +020048 char **err)
49{
50 char *path;
51 struct dirent **de_list;
52 int i, n;
53 struct stat buf;
54 char *end;
55 char fp[MAXPATHLEN+1];
56
57 if (too_many_args(1, args, err, NULL))
58 return -1;
59
60 path = args[1];
61 if (*path == 0 || stat(path, &buf)) {
62 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
63 err && *err ? *err : "", args[0]);
64 return -1;
65 }
66 if (S_ISDIR(buf.st_mode) == 0) {
67 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
68 err && *err ? *err : "", args[0], path);
69 return -1;
70 }
71
72 /* strip trailing slashes, including first one */
73 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
74 *end = 0;
75 /* path already parsed? */
76 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
77 return 0;
78 /* overwrite old issuers_chain_path */
79 free(global_ssl.issuers_chain_path);
80 global_ssl.issuers_chain_path = strdup(path);
81 ssl_free_global_issuers();
82
83 n = scandir(path, &de_list, 0, alphasort);
84 if (n < 0) {
85 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
86 err && *err ? *err : "", args[0], path, strerror(errno));
87 return -1;
88 }
89 for (i = 0; i < n; i++) {
90 struct dirent *de = de_list[i];
91 BIO *in = NULL;
92 char *warn = NULL;
93
94 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
95 free(de);
96 if (stat(fp, &buf) != 0) {
97 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
98 goto next;
99 }
100 if (!S_ISREG(buf.st_mode))
101 goto next;
102
103 in = BIO_new(BIO_s_file());
104 if (in == NULL)
105 goto next;
106 if (BIO_read_filename(in, fp) <= 0)
107 goto next;
108 ssl_load_global_issuer_from_BIO(in, fp, &warn);
109 if (warn) {
110 ha_warning("%s", warn);
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100111 ha_free(&warn);
William Lallemanddad31052020-05-14 17:47:32 +0200112 }
113 next:
114 if (in)
115 BIO_free(in);
116 }
117 free(de_list);
118
119 return 0;
120}
121
William Lallemanddad31052020-05-14 17:47:32 +0200122/* parse the "ssl-mode-async" keyword in global section.
123 * Returns <0 on alert, >0 on warning, 0 on success.
124 */
125static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100126 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200127 char **err)
128{
Ilya Shipitsinbdec3ba2020-11-14 01:56:34 +0500129#ifdef SSL_MODE_ASYNC
William Lallemanddad31052020-05-14 17:47:32 +0200130 global_ssl.async = 1;
131 global.ssl_used_async_engines = nb_engines;
132 return 0;
133#else
134 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
135 return -1;
136#endif
137}
138
William Lallemandd7bfbe22022-04-11 18:41:24 +0200139#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +0200140/* parse the "ssl-engine" keyword in global section.
141 * Returns <0 on alert, >0 on warning, 0 on success.
142 */
143static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100144 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200145 char **err)
146{
147 char *algo;
148 int ret = -1;
149
150 if (*(args[1]) == 0) {
151 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
152 return ret;
153 }
154
155 if (*(args[2]) == 0) {
156 /* if no list of algorithms is given, it defaults to ALL */
157 algo = strdup("ALL");
158 goto add_engine;
159 }
160
161 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
162 if (strcmp(args[2], "algo") != 0) {
163 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
164 return ret;
165 }
166
167 if (*(args[3]) == 0) {
168 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
169 return ret;
170 }
171 algo = strdup(args[3]);
172
173add_engine:
174 if (ssl_init_single_engine(args[1], algo)==0) {
175 openssl_engines_initialized++;
176 ret = 0;
177 }
178 free(algo);
179 return ret;
180}
181#endif
182
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200183#ifdef HAVE_SSL_PROVIDERS
184/* parse the "ssl-propquery" keyword in global section.
185 * Returns <0 on alert, >0 on warning, 0 on success.
186 */
187static int ssl_parse_global_ssl_propquery(char **args, int section_type, struct proxy *curpx,
188 const struct proxy *defpx, const char *file, int line,
189 char **err)
190{
191 int ret = -1;
192
193 if (*(args[1]) == 0) {
194 memprintf(err, "global statement '%s' expects a property string as an argument.", args[0]);
195 return ret;
196 }
197
198 if (EVP_set_default_properties(NULL, args[1]))
199 ret = 0;
200
201 return ret;
202}
203#endif
204
William Lallemanddad31052020-05-14 17:47:32 +0200205/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
206 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
207 */
208static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100209 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200210 char **err)
211{
212 char **target;
213
214 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
215
216 if (too_many_args(1, args, err, NULL))
217 return -1;
218
219 if (*(args[1]) == 0) {
220 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
221 return -1;
222 }
223
224 free(*target);
225 *target = strdup(args[1]);
226 return 0;
227}
228
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500229#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200230/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
231 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
232 */
233static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100234 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200235 char **err)
236{
237 char **target;
238
239 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
240
241 if (too_many_args(1, args, err, NULL))
242 return -1;
243
244 if (*(args[1]) == 0) {
245 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
246 return -1;
247 }
248
249 free(*target);
250 *target = strdup(args[1]);
251 return 0;
252}
253#endif
254
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500255#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200256/*
257 * parse the "ssl-default-bind-curves" keyword in a global section.
258 * Returns <0 on alert, >0 on warning, 0 on success.
259 */
260static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100261 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200262 char **err)
263{
264 char **target;
265 target = &global_ssl.listen_default_curves;
266
267 if (too_many_args(1, args, err, NULL))
268 return -1;
269
270 if (*(args[1]) == 0) {
271 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
272 return -1;
273 }
274
275 free(*target);
276 *target = strdup(args[1]);
277 return 0;
278}
279#endif
280/* parse various global tune.ssl settings consisting in positive integers.
281 * Returns <0 on alert, >0 on warning, 0 on success.
282 */
283static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100284 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200285 char **err)
286{
287 int *target;
288
289 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
290 target = &global.tune.sslcachesize;
291 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
292 target = (int *)&global_ssl.max_record;
Thomas Prückl10243932022-04-27 13:04:54 +0200293 else if (strcmp(args[0], "tune.ssl.hard-maxrecord") == 0)
294 target = (int *)&global_ssl.hard_max_record;
William Lallemanddad31052020-05-14 17:47:32 +0200295 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
296 target = &global_ssl.ctx_cache;
297 else if (strcmp(args[0], "maxsslconn") == 0)
298 target = &global.maxsslconn;
Marcin Deranek310a2602021-07-13 19:04:24 +0200299 else if (strcmp(args[0], "tune.ssl.capture-buffer-size") == 0)
300 target = &global_ssl.capture_buffer_size;
301 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0) {
302 target = &global_ssl.capture_buffer_size;
303 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",
304 file, line, args[0]);
305 }
William Lallemanddad31052020-05-14 17:47:32 +0200306 else {
307 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
308 return -1;
309 }
310
311 if (too_many_args(1, args, err, NULL))
312 return -1;
313
314 if (*(args[1]) == 0) {
315 memprintf(err, "'%s' expects an integer argument.", args[0]);
316 return -1;
317 }
318
319 *target = atoi(args[1]);
320 if (*target < 0) {
321 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
322 return -1;
323 }
324 return 0;
325}
326
Marcin Deranek310a2602021-07-13 19:04:24 +0200327static int ssl_parse_global_capture_buffer(char **args, int section_type, struct proxy *curpx,
328 const struct proxy *defpx, const char *file, int line,
329 char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200330{
331 int ret;
332
333 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
334 if (ret != 0)
335 return ret;
336
337 if (pool_head_ssl_capture) {
338 memprintf(err, "'%s' is already configured.", args[0]);
339 return -1;
340 }
341
Marcin Deranek310a2602021-07-13 19:04:24 +0200342 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 +0200343 if (!pool_head_ssl_capture) {
344 memprintf(err, "Out of memory error.");
345 return -1;
346 }
347 return 0;
348}
349
William Lallemand7d42ef52020-07-06 11:41:30 +0200350/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200351#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200352static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100353 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200354 char **err)
355{
356
357 if (too_many_args(1, args, err, NULL))
358 return -1;
359
360 if (strcmp(args[1], "on") == 0)
361 global_ssl.keylog = 1;
362 else if (strcmp(args[1], "off") == 0)
363 global_ssl.keylog = 0;
364 else {
365 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
366 return -1;
367 }
368
369 if (pool_head_ssl_keylog) /* already configured */
370 return 0;
371
372 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
373 if (!pool_head_ssl_keylog) {
374 memprintf(err, "Out of memory error.");
375 return -1;
376 }
377
378 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
379 if (!pool_head_ssl_keylog_str) {
380 memprintf(err, "Out of memory error.");
381 return -1;
382 }
383
384 return 0;
385}
William Lallemand722180a2021-06-09 16:46:12 +0200386#else
387static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
388 const struct proxy *defpx, const char *file, int line,
389 char **err)
390{
391 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
392 return -1;
393}
William Lallemand7d42ef52020-07-06 11:41:30 +0200394#endif
395
William Lallemanddad31052020-05-14 17:47:32 +0200396/* parse "ssl.force-private-cache".
397 * Returns <0 on alert, >0 on warning, 0 on success.
398 */
399static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100400 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200401 char **err)
402{
403 if (too_many_args(0, args, err, NULL))
404 return -1;
405
406 global_ssl.private_cache = 1;
407 return 0;
408}
409
410/* parse "ssl.lifetime".
411 * Returns <0 on alert, >0 on warning, 0 on success.
412 */
413static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100414 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200415 char **err)
416{
417 const char *res;
418
419 if (too_many_args(1, args, err, NULL))
420 return -1;
421
422 if (*(args[1]) == 0) {
423 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
424 return -1;
425 }
426
427 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
428 if (res == PARSE_TIME_OVER) {
429 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
430 args[1], args[0]);
431 return -1;
432 }
433 else if (res == PARSE_TIME_UNDER) {
434 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
435 args[1], args[0]);
436 return -1;
437 }
438 else if (res) {
439 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
440 return -1;
441 }
442 return 0;
443}
444
445#ifndef OPENSSL_NO_DH
446/* parse "ssl-dh-param-file".
447 * Returns <0 on alert, >0 on warning, 0 on success.
448 */
449static int ssl_parse_global_dh_param_file(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 a file path as an argument.", args[0]);
458 return -1;
459 }
460
461 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
462 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
463 return -1;
464 }
465 return 0;
466}
467
468/* parse "ssl.default-dh-param".
469 * Returns <0 on alert, >0 on warning, 0 on success.
470 */
471static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100472 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200473 char **err)
474{
475 if (too_many_args(1, args, err, NULL))
476 return -1;
477
478 if (*(args[1]) == 0) {
479 memprintf(err, "'%s' expects an integer argument.", args[0]);
480 return -1;
481 }
482
483 global_ssl.default_dh_param = atoi(args[1]);
484 if (global_ssl.default_dh_param < 1024) {
485 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
486 return -1;
487 }
488 return 0;
489}
490#endif
491
492
493/*
494 * parse "ssl-load-extra-files".
495 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
496 */
497static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100498 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200499 char **err)
500{
501 int i;
502 int gf = SSL_GF_NONE;
503
504 if (*(args[1]) == 0)
505 goto err_arg;
506
507 for (i = 1; *args[i]; i++) {
508
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100509 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200510 gf |= SSL_GF_BUNDLE;
511
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100512 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200513 gf |= SSL_GF_SCTL;
514
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100515 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200516 gf |= SSL_GF_OCSP;
517
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100518 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200519 gf |= SSL_GF_OCSP_ISSUER;
520
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100521 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200522 gf |= SSL_GF_KEY;
523
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100524 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200525 if (gf != SSL_GF_NONE)
526 goto err_alone;
527 gf = SSL_GF_NONE;
528 i++;
529 break;
530
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100531 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200532 if (gf != SSL_GF_NONE)
533 goto err_alone;
534 gf = SSL_GF_ALL;
535 i++;
536 break;
537 } else {
538 goto err_arg;
539 }
540 }
541 /* break from loop but there are still arguments */
542 if (*args[i])
543 goto err_alone;
544
545 global_ssl.extra_files = gf;
546
547 return 0;
548
549err_alone:
550 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
551 return -1;
552
553err_arg:
554 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
555 return -1;
556}
557
558
William Lallemand8e8581e2020-10-20 17:36:46 +0200559/* parse 'ssl-load-extra-del-ext */
560static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100561 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200562 char **err)
563{
564 global_ssl.extra_files_noext = 1;
565 return 0;
566}
567
William Lallemanddad31052020-05-14 17:47:32 +0200568/***************************** Bind keyword Parsing ********************************************/
569
570/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100571static 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 +0200572{
573 if (!*args[cur_arg + 1]) {
574 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
575 return ERR_ALERT | ERR_FATAL;
576 }
577
578 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
579 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
580 else
581 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
582
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200583 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200584 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
585 return ERR_ALERT | ERR_FATAL;
586 }
587 return 0;
588}
589
590/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100591static 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 +0200592{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100593 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200594}
595static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
596{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100597 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200598}
599
600/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100601static 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 +0200602{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100603 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200604}
605static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
606{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100607 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200608}
609
610/* parse the "ca-sign-file" bind keyword */
611static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
612{
613 if (!*args[cur_arg + 1]) {
614 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
615 return ERR_ALERT | ERR_FATAL;
616 }
617
618 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
619 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
620 else
621 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
622
623 return 0;
624}
625
626/* parse the "ca-sign-pass" bind keyword */
627static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
628{
629 if (!*args[cur_arg + 1]) {
630 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
631 return ERR_ALERT | ERR_FATAL;
632 }
633 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
634 return 0;
635}
636
637/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100638static 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 +0200639{
640 if (!*args[cur_arg + 1]) {
641 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
642 return ERR_ALERT | ERR_FATAL;
643 }
644
645 free(conf->ciphers);
646 conf->ciphers = strdup(args[cur_arg + 1]);
647 return 0;
648}
649static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
650{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100651 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200652}
653
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500654#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200655/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100656static 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 +0200657{
658 if (!*args[cur_arg + 1]) {
659 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
660 return ERR_ALERT | ERR_FATAL;
661 }
662
663 free(conf->ciphersuites);
664 conf->ciphersuites = strdup(args[cur_arg + 1]);
665 return 0;
666}
667static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
668{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100669 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200670}
671#endif
672
673/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
674static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
675{
676 char path[MAXPATHLEN];
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 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
Willy Tarreau393e42a2022-05-09 10:31:28 +0200684 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
685 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
William Lallemanddad31052020-05-14 17:47:32 +0200686 memprintf(err, "'%s' : path too long", args[cur_arg]);
687 return ERR_ALERT | ERR_FATAL;
688 }
William Lallemanddad31052020-05-14 17:47:32 +0200689 return ssl_sock_load_cert(path, conf, err);
690 }
691
692 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
693}
694
695/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
696static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
697{
698 int err_code;
699
700 if (!*args[cur_arg + 1]) {
701 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
702 return ERR_ALERT | ERR_FATAL;
703 }
704
705 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
706 if (err_code)
707 memprintf(err, "'%s' : %s", args[cur_arg], *err);
708
709 return err_code;
710}
711
712/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100713static 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 +0200714{
715#ifndef X509_V_FLAG_CRL_CHECK
716 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
717 return ERR_ALERT | ERR_FATAL;
718#else
719 if (!*args[cur_arg + 1]) {
720 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
721 return ERR_ALERT | ERR_FATAL;
722 }
723
724 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
725 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
726 else
727 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
728
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200729 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200730 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
731 return ERR_ALERT | ERR_FATAL;
732 }
733 return 0;
734#endif
735}
736static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
737{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100738 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200739}
740
741/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100742static 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 +0200743{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500744#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200745 if (!*args[cur_arg + 1]) {
746 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
747 return ERR_ALERT | ERR_FATAL;
748 }
749 conf->curves = strdup(args[cur_arg + 1]);
750 return 0;
751#else
752 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
753 return ERR_ALERT | ERR_FATAL;
754#endif
755}
756static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
757{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100758 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200759}
760
761/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100762static 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 +0200763{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500764#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200765 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
766 return ERR_ALERT | ERR_FATAL;
767#elif defined(OPENSSL_NO_ECDH)
768 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
769 return ERR_ALERT | ERR_FATAL;
770#else
771 if (!*args[cur_arg + 1]) {
772 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
773 return ERR_ALERT | ERR_FATAL;
774 }
775
776 conf->ecdhe = strdup(args[cur_arg + 1]);
777
778 return 0;
779#endif
780}
781static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
782{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100783 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200784}
785
786/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
787static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
788{
789 int code;
790 char *p = args[cur_arg + 1];
791 unsigned long long *ignerr = &conf->crt_ignerr;
792
793 if (!*p) {
794 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
795 return ERR_ALERT | ERR_FATAL;
796 }
797
798 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
799 ignerr = &conf->ca_ignerr;
800
801 if (strcmp(p, "all") == 0) {
802 *ignerr = ~0ULL;
803 return 0;
804 }
805
806 while (p) {
807 code = atoi(p);
808 if ((code <= 0) || (code > 63)) {
809 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
810 args[cur_arg], code, args[cur_arg + 1]);
811 return ERR_ALERT | ERR_FATAL;
812 }
813 *ignerr |= 1ULL << code;
814 p = strchr(p, ',');
815 if (p)
816 p++;
817 }
818
819 return 0;
820}
821
822/* parse tls_method_options "no-xxx" and "force-xxx" */
823static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
824{
825 uint16_t v;
826 char *p;
827 p = strchr(arg, '-');
828 if (!p)
829 goto fail;
830 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100831 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200832 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100833 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200834 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100835 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200836 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100837 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200838 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100839 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200840 v = CONF_TLSV13;
841 else
842 goto fail;
843 if (!strncmp(arg, "no-", 3))
844 methods->flags |= methodVersions[v].flag;
845 else if (!strncmp(arg, "force-", 6))
846 methods->min = methods->max = v;
847 else
848 goto fail;
849 return 0;
850 fail:
851 memprintf(err, "'%s' : option not implemented", arg);
852 return ERR_ALERT | ERR_FATAL;
853}
854
855static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
856{
857 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
858}
859
860static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
861{
862 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
863}
864
865/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
866static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
867{
868 uint16_t i, v = 0;
869 char *argv = args[cur_arg + 1];
870 if (!*argv) {
871 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
872 return ERR_ALERT | ERR_FATAL;
873 }
874 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100875 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200876 v = i;
877 if (!v) {
878 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
879 return ERR_ALERT | ERR_FATAL;
880 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100881 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200882 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100883 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200884 methods->max = v;
885 else {
886 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
887 return ERR_ALERT | ERR_FATAL;
888 }
889 return 0;
890}
891
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100892static 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 +0200893{
William Lallemand8177ad92020-05-20 16:49:02 +0200894 int ret;
895
William Lallemanddad31052020-05-14 17:47:32 +0200896#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
897 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
898#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200899 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
900 if (ret != ERR_NONE)
901 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200902
William Lallemand8177ad92020-05-20 16:49:02 +0200903 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
904 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
905
906 return ret;
907}
William Lallemanddad31052020-05-14 17:47:32 +0200908static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
909{
910 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
911}
912
913static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
914{
915 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
916}
917
918/* parse the "no-tls-tickets" bind keyword */
919static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
920{
921 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
922 return 0;
923}
924
925/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100926static 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 +0200927{
928 conf->early_data = 1;
929 return 0;
930}
931
932static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
933{
934 conf->ssl_conf.early_data = 1;
935 return 0;
936}
937
938/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100939static 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 +0200940{
941#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
942 char *p1, *p2;
943
944 if (!*args[cur_arg + 1]) {
945 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
946 return ERR_ALERT | ERR_FATAL;
947 }
948
949 free(conf->npn_str);
950
951 /* the NPN string is built as a suite of (<len> <name>)*,
952 * so we reuse each comma to store the next <len> and need
953 * one more for the end of the string.
954 */
955 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
956 conf->npn_str = calloc(1, conf->npn_len + 1);
957 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
958
959 /* replace commas with the name length */
960 p1 = conf->npn_str;
961 p2 = p1 + 1;
962 while (1) {
963 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
964 if (!p2)
965 p2 = p1 + 1 + strlen(p1 + 1);
966
967 if (p2 - (p1 + 1) > 255) {
968 *p2 = '\0';
969 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
970 return ERR_ALERT | ERR_FATAL;
971 }
972
973 *p1 = p2 - (p1 + 1);
974 p1 = p2;
975
976 if (!*p2)
977 break;
978
979 *(p2++) = '\0';
980 }
981 return 0;
982#else
983 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
984 return ERR_ALERT | ERR_FATAL;
985#endif
986}
987
988static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
989{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100990 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200991}
992
993
994/* Parses a alpn string and converts it to the right format for the SSL api */
995int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
996{
997 char *p1, *p2, *alpn = NULL;
998 int len, ret = 0;
999
1000 *alpn_str = NULL;
1001 *alpn_len = 0;
1002
1003 if (!*arg) {
1004 memprintf(err, "missing the comma-delimited ALPN protocol suite");
1005 goto error;
1006 }
1007
1008 /* the ALPN string is built as a suite of (<len> <name>)*,
1009 * so we reuse each comma to store the next <len> and need
1010 * one more for the end of the string.
1011 */
1012 len = strlen(arg) + 1;
1013 alpn = calloc(1, len+1);
1014 if (!alpn) {
1015 memprintf(err, "'%s' : out of memory", arg);
1016 goto error;
1017 }
1018 memcpy(alpn+1, arg, len);
1019
1020 /* replace commas with the name length */
1021 p1 = alpn;
1022 p2 = p1 + 1;
1023 while (1) {
1024 p2 = memchr(p1 + 1, ',', alpn + 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, "ALPN protocol name too long : '%s'", p1 + 1);
1031 goto error;
1032 }
1033
1034 *p1 = p2 - (p1 + 1);
1035 p1 = p2;
1036
1037 if (!*p2)
1038 break;
1039
1040 *(p2++) = '\0';
1041 }
1042
1043 *alpn_str = alpn;
1044 *alpn_len = len;
1045
1046 out:
1047 return ret;
1048
1049 error:
1050 free(alpn);
1051 ret = ERR_ALERT | ERR_FATAL;
1052 goto out;
1053}
1054
1055/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001056static 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 +02001057{
1058#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1059 int ret;
1060
1061 free(conf->alpn_str);
1062
1063 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1064 if (ret)
1065 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1066 return ret;
1067#else
1068 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1069 return ERR_ALERT | ERR_FATAL;
1070#endif
1071}
1072
1073static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1074{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001075 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001076}
1077
1078/* parse the "ssl" bind keyword */
1079static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1080{
Frédéric Lécaillee50afbd2020-11-23 11:33:12 +01001081 /* Do not change the xprt for QUIC. */
1082 if (conf->xprt != xprt_get(XPRT_QUIC))
1083 conf->xprt = &ssl_sock;
William Lallemanddad31052020-05-14 17:47:32 +02001084 conf->is_ssl = 1;
1085
1086 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1087 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001088#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001089 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1090 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1091#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001092#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001093 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1094 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1095#endif
1096 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1097 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1098 if (!conf->ssl_conf.ssl_methods.min)
1099 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1100 if (!conf->ssl_conf.ssl_methods.max)
1101 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1102
1103 return 0;
1104}
1105
1106/* parse the "prefer-client-ciphers" bind keyword */
1107static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1108{
1109 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1110 return 0;
1111}
1112
1113/* parse the "generate-certificates" bind keyword */
1114static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1115{
1116#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1117 conf->generate_certs = 1;
1118#else
1119 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1120 err && *err ? *err : "");
1121#endif
1122 return 0;
1123}
1124
1125/* parse the "strict-sni" bind keyword */
1126static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1127{
1128 conf->strict_sni = 1;
1129 return 0;
1130}
1131
1132/* parse the "tls-ticket-keys" bind keyword */
1133static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1134{
1135#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1136 FILE *f = NULL;
1137 int i = 0;
1138 char thisline[LINESIZE];
1139 struct tls_keys_ref *keys_ref = NULL;
1140
1141 if (!*args[cur_arg + 1]) {
1142 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1143 goto fail;
1144 }
1145
1146 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1147 if (keys_ref) {
1148 keys_ref->refcount++;
1149 conf->keys_ref = keys_ref;
1150 return 0;
1151 }
1152
1153 keys_ref = calloc(1, sizeof(*keys_ref));
1154 if (!keys_ref) {
1155 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1156 goto fail;
1157 }
1158
1159 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1160 if (!keys_ref->tlskeys) {
1161 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1162 goto fail;
1163 }
1164
1165 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1166 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1167 goto fail;
1168 }
1169
1170 keys_ref->filename = strdup(args[cur_arg + 1]);
1171 if (!keys_ref->filename) {
1172 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1173 goto fail;
1174 }
1175
1176 keys_ref->key_size_bits = 0;
1177 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1178 int len = strlen(thisline);
1179 int dec_size;
1180
1181 /* Strip newline characters from the end */
1182 if(thisline[len - 1] == '\n')
1183 thisline[--len] = 0;
1184
1185 if(thisline[len - 1] == '\r')
1186 thisline[--len] = 0;
1187
1188 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1189 if (dec_size < 0) {
1190 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1191 goto fail;
1192 }
1193 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1194 keys_ref->key_size_bits = 128;
1195 }
1196 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1197 keys_ref->key_size_bits = 256;
1198 }
1199 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1200 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1201 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1202 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1203 goto fail;
1204 }
1205 i++;
1206 }
1207
1208 if (i < TLS_TICKETS_NO) {
1209 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1210 goto fail;
1211 }
1212
1213 fclose(f);
1214
1215 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1216 i -= 2;
1217 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1218 keys_ref->unique_id = -1;
1219 keys_ref->refcount = 1;
1220 HA_RWLOCK_INIT(&keys_ref->lock);
1221 conf->keys_ref = keys_ref;
1222
Willy Tarreau2b718102021-04-21 07:32:39 +02001223 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001224
1225 return 0;
1226
1227 fail:
1228 if (f)
1229 fclose(f);
1230 if (keys_ref) {
1231 free(keys_ref->filename);
1232 free(keys_ref->tlskeys);
1233 free(keys_ref);
1234 }
1235 return ERR_ALERT | ERR_FATAL;
1236
1237#else
1238 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1239 return ERR_ALERT | ERR_FATAL;
1240#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1241}
1242
1243/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001244static 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 +02001245{
1246 if (!*args[cur_arg + 1]) {
1247 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1248 return ERR_ALERT | ERR_FATAL;
1249 }
1250
1251 if (strcmp(args[cur_arg + 1], "none") == 0)
1252 conf->verify = SSL_SOCK_VERIFY_NONE;
1253 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1254 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1255 else if (strcmp(args[cur_arg + 1], "required") == 0)
1256 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1257 else {
1258 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1259 args[cur_arg], args[cur_arg + 1]);
1260 return ERR_ALERT | ERR_FATAL;
1261 }
1262
1263 return 0;
1264}
1265static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1266{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001267 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001268}
1269
1270/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001271static 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 +02001272{
1273 conf->no_ca_names = 1;
1274 return 0;
1275}
1276static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1277{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001278 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001279}
1280
1281/***************************** "server" keywords Parsing ********************************************/
1282
1283/* parse the "npn" bind keyword */
1284static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1285{
1286#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1287 char *p1, *p2;
1288
1289 if (!*args[*cur_arg + 1]) {
1290 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1291 return ERR_ALERT | ERR_FATAL;
1292 }
1293
1294 free(newsrv->ssl_ctx.npn_str);
1295
1296 /* the NPN string is built as a suite of (<len> <name>)*,
1297 * so we reuse each comma to store the next <len> and need
1298 * one more for the end of the string.
1299 */
1300 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1301 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001302 if (!newsrv->ssl_ctx.npn_str) {
1303 memprintf(err, "out of memory");
1304 return ERR_ALERT | ERR_FATAL;
1305 }
1306
William Lallemanddad31052020-05-14 17:47:32 +02001307 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1308 newsrv->ssl_ctx.npn_len);
1309
1310 /* replace commas with the name length */
1311 p1 = newsrv->ssl_ctx.npn_str;
1312 p2 = p1 + 1;
1313 while (1) {
1314 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1315 newsrv->ssl_ctx.npn_len - (p1 + 1));
1316 if (!p2)
1317 p2 = p1 + 1 + strlen(p1 + 1);
1318
1319 if (p2 - (p1 + 1) > 255) {
1320 *p2 = '\0';
1321 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1322 return ERR_ALERT | ERR_FATAL;
1323 }
1324
1325 *p1 = p2 - (p1 + 1);
1326 p1 = p2;
1327
1328 if (!*p2)
1329 break;
1330
1331 *(p2++) = '\0';
1332 }
1333 return 0;
1334#else
1335 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1336 return ERR_ALERT | ERR_FATAL;
1337#endif
1338}
1339
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001340#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1341static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1342{
1343 free(*out_alpn_str);
1344 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1345}
1346#endif
1347
1348/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001349static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1350{
1351#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001352 int ret = parse_alpn(args[*cur_arg + 1],
1353 &newsrv->ssl_ctx.alpn_str,
1354 &newsrv->ssl_ctx.alpn_len, err);
1355 if (ret)
1356 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1357 return ret;
1358#else
1359 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1360 return ERR_ALERT | ERR_FATAL;
1361#endif
1362}
William Lallemanddad31052020-05-14 17:47:32 +02001363
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001364/* parse the "check-alpn" server keyword */
1365static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1366{
1367#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1368 int ret = parse_alpn(args[*cur_arg + 1],
1369 &newsrv->check.alpn_str,
1370 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001371 if (ret)
1372 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1373 return ret;
1374#else
1375 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1376 return ERR_ALERT | ERR_FATAL;
1377#endif
1378}
1379
1380/* parse the "ca-file" server keyword */
1381static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1382{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001383 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1384
William Lallemanddad31052020-05-14 17:47:32 +02001385 if (!*args[*cur_arg + 1]) {
1386 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1387 return ERR_ALERT | ERR_FATAL;
1388 }
1389
1390 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1391 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1392 else
1393 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1394
Amaury Denoyelle48255022021-05-19 09:46:59 +02001395 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001396 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1397 return ERR_ALERT | ERR_FATAL;
1398 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001399
William Lallemanddad31052020-05-14 17:47:32 +02001400 return 0;
1401}
1402
1403/* parse the "check-sni" server keyword */
1404static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1405{
1406 if (!*args[*cur_arg + 1]) {
1407 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1408 return ERR_ALERT | ERR_FATAL;
1409 }
1410
1411 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1412 if (!newsrv->check.sni) {
1413 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1414 return ERR_ALERT | ERR_FATAL;
1415 }
1416 return 0;
1417
1418}
1419
William Dauchyfc52f522020-11-14 19:25:32 +01001420/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001421static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001422{
William Dauchyfc52f522020-11-14 19:25:32 +01001423 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1424 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001425#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001426 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001427 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001428 if (!s->ssl_ctx.ciphersuites)
1429 return 1;
1430 }
William Lallemanddad31052020-05-14 17:47:32 +02001431#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001432 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1433 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1434
1435 if (!s->ssl_ctx.methods.min)
1436 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001437
William Dauchyfc52f522020-11-14 19:25:32 +01001438 if (!s->ssl_ctx.methods.max)
1439 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001440
1441 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001442}
1443
1444/* parse the "check-ssl" server keyword */
1445static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1446{
1447 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001448 if (ssl_sock_init_srv(newsrv)) {
1449 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1450 return ERR_ALERT | ERR_FATAL;
1451 }
1452
William Lallemanddad31052020-05-14 17:47:32 +02001453 return 0;
1454}
1455
1456/* parse the "ciphers" server keyword */
1457static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1458{
1459 if (!*args[*cur_arg + 1]) {
1460 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1461 return ERR_ALERT | ERR_FATAL;
1462 }
1463
1464 free(newsrv->ssl_ctx.ciphers);
1465 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001466
1467 if (!newsrv->ssl_ctx.ciphers) {
1468 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1469 return ERR_ALERT | ERR_FATAL;
1470 }
1471
William Lallemanddad31052020-05-14 17:47:32 +02001472 return 0;
1473}
1474
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001475#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001476/* parse the "ciphersuites" server keyword */
1477static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1478{
1479 if (!*args[*cur_arg + 1]) {
1480 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1481 return ERR_ALERT | ERR_FATAL;
1482 }
1483
1484 free(newsrv->ssl_ctx.ciphersuites);
1485 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001486
1487 if (!newsrv->ssl_ctx.ciphersuites) {
1488 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1489 return ERR_ALERT | ERR_FATAL;
1490 }
1491
William Lallemanddad31052020-05-14 17:47:32 +02001492 return 0;
1493}
1494#endif
1495
1496/* parse the "crl-file" server keyword */
1497static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1498{
1499#ifndef X509_V_FLAG_CRL_CHECK
1500 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1501 return ERR_ALERT | ERR_FATAL;
1502#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001503 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1504
William Lallemanddad31052020-05-14 17:47:32 +02001505 if (!*args[*cur_arg + 1]) {
1506 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1507 return ERR_ALERT | ERR_FATAL;
1508 }
1509
1510 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1511 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1512 else
1513 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1514
Amaury Denoyellefde82602021-06-14 10:10:32 +02001515 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001516 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1517 return ERR_ALERT | ERR_FATAL;
1518 }
1519 return 0;
1520#endif
1521}
1522
1523/* parse the "crt" server keyword */
1524static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1525{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001526
William Lallemanddad31052020-05-14 17:47:32 +02001527 if (!*args[*cur_arg + 1]) {
1528 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1529 return ERR_ALERT | ERR_FATAL;
1530 }
1531
1532 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001533 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001534 else
William Lallemand2c776f12021-12-28 18:47:17 +01001535 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001536
William Lallemand2c776f12021-12-28 18:47:17 +01001537 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001538}
1539
1540/* parse the "no-check-ssl" server keyword */
1541static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1542{
1543 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001544 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001545 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1546 return 0;
1547}
1548
1549/* parse the "no-send-proxy-v2-ssl" server keyword */
1550static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1551{
1552 newsrv->pp_opts &= ~SRV_PP_V2;
1553 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1554 return 0;
1555}
1556
1557/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1558static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1559{
1560 newsrv->pp_opts &= ~SRV_PP_V2;
1561 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1562 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1563 return 0;
1564}
1565
1566/* parse the "no-ssl" server keyword */
1567static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1568{
William Dauchyf6370442020-11-14 19:25:33 +01001569 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001570 if (newsrv->use_ssl == 1) {
1571 if (ssl_sock_init_srv(newsrv)) {
1572 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1573 return ERR_ALERT | ERR_FATAL;
1574 }
1575 }
William Dauchyf6370442020-11-14 19:25:33 +01001576 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001577 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001578 }
William Lallemanddad31052020-05-14 17:47:32 +02001579 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001580 return 0;
1581}
1582
1583/* parse the "allow-0rtt" server keyword */
1584static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1585{
1586 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1587 return 0;
1588}
1589
1590/* parse the "no-ssl-reuse" server keyword */
1591static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1592{
1593 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1594 return 0;
1595}
1596
1597/* parse the "no-tls-tickets" server keyword */
1598static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1599{
1600 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1601 return 0;
1602}
1603/* parse the "send-proxy-v2-ssl" server keyword */
1604static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1605{
1606 newsrv->pp_opts |= SRV_PP_V2;
1607 newsrv->pp_opts |= SRV_PP_V2_SSL;
1608 return 0;
1609}
1610
1611/* parse the "send-proxy-v2-ssl-cn" server keyword */
1612static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1613{
1614 newsrv->pp_opts |= SRV_PP_V2;
1615 newsrv->pp_opts |= SRV_PP_V2_SSL;
1616 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1617 return 0;
1618}
1619
1620/* parse the "sni" server keyword */
1621static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1622{
1623#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1624 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1625 return ERR_ALERT | ERR_FATAL;
1626#else
1627 char *arg;
1628
1629 arg = args[*cur_arg + 1];
1630 if (!*arg) {
1631 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1632 return ERR_ALERT | ERR_FATAL;
1633 }
1634
1635 free(newsrv->sni_expr);
1636 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001637 if (!newsrv->sni_expr) {
1638 memprintf(err, "out of memory");
1639 return ERR_ALERT | ERR_FATAL;
1640 }
William Lallemanddad31052020-05-14 17:47:32 +02001641
1642 return 0;
1643#endif
1644}
1645
1646/* parse the "ssl" server keyword */
1647static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1648{
1649 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001650 if (ssl_sock_init_srv(newsrv)) {
1651 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1652 return ERR_ALERT | ERR_FATAL;
1653 }
1654
William Lallemanddad31052020-05-14 17:47:32 +02001655 return 0;
1656}
1657
1658/* parse the "ssl-reuse" server keyword */
1659static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1660{
1661 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1662 return 0;
1663}
1664
1665/* parse the "tls-tickets" server keyword */
1666static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1667{
1668 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1669 return 0;
1670}
1671
1672/* parse the "verify" server keyword */
1673static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1674{
1675 if (!*args[*cur_arg + 1]) {
1676 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1677 return ERR_ALERT | ERR_FATAL;
1678 }
1679
1680 if (strcmp(args[*cur_arg + 1], "none") == 0)
1681 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1682 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1683 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1684 else {
1685 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1686 args[*cur_arg], args[*cur_arg + 1]);
1687 return ERR_ALERT | ERR_FATAL;
1688 }
1689
1690 return 0;
1691}
1692
1693/* parse the "verifyhost" server keyword */
1694static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1695{
1696 if (!*args[*cur_arg + 1]) {
1697 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1698 return ERR_ALERT | ERR_FATAL;
1699 }
1700
1701 free(newsrv->ssl_ctx.verify_host);
1702 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1703
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001704 if (!newsrv->ssl_ctx.verify_host) {
1705 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1706 return ERR_ALERT | ERR_FATAL;
1707 }
1708
William Lallemanddad31052020-05-14 17:47:32 +02001709 return 0;
1710}
1711
1712/* parse the "ssl-default-bind-options" keyword in global section */
1713static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001714 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001715 char **err) {
1716 int i = 1;
1717
1718 if (*(args[i]) == 0) {
1719 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1720 return -1;
1721 }
1722 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001723 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001724 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001725 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001726 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001727 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001728 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1729 i++;
1730 else {
1731 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1732 return -1;
1733 }
1734 }
1735 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1736 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1737 return -1;
1738 }
1739 i++;
1740 }
1741 return 0;
1742}
1743
1744/* parse the "ssl-default-server-options" keyword in global section */
1745static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001746 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001747 char **err) {
1748 int i = 1;
1749
1750 if (*(args[i]) == 0) {
1751 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1752 return -1;
1753 }
1754 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001755 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001756 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001757 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001758 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1759 i++;
1760 else {
1761 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1762 return -1;
1763 }
1764 }
1765 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1766 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1767 return -1;
1768 }
1769 i++;
1770 }
1771 return 0;
1772}
1773
1774/* parse the "ca-base" / "crt-base" keywords in global section.
1775 * Returns <0 on alert, >0 on warning, 0 on success.
1776 */
1777static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001778 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001779 char **err)
1780{
1781 char **target;
1782
1783 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1784
1785 if (too_many_args(1, args, err, NULL))
1786 return -1;
1787
1788 if (*target) {
1789 memprintf(err, "'%s' already specified.", args[0]);
1790 return -1;
1791 }
1792
1793 if (*(args[1]) == 0) {
1794 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1795 return -1;
1796 }
1797 *target = strdup(args[1]);
1798 return 0;
1799}
1800
1801/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1802static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001803 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001804 char **err)
1805{
William Lallemand9a1d8392020-08-10 17:28:23 +02001806#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001807 global_ssl.skip_self_issued_ca = 1;
1808 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001809#else
1810 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1811 return -1;
1812#endif
William Lallemanddad31052020-05-14 17:47:32 +02001813}
1814
1815
1816
1817
1818
1819/* Note: must not be declared <const> as its list will be overwritten.
1820 * Please take care of keeping this list alphabetically sorted, doing so helps
1821 * all code contributors.
1822 * Optional keywords are also declared with a NULL ->parse() function so that
1823 * the config parser can report an appropriate error when a known keyword was
1824 * not enabled.
1825 */
1826
1827/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1828 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1829struct ssl_bind_kw ssl_bind_kws[] = {
1830 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1831 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1832 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1833 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1834 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001835#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001836 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1837#endif
1838 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1839 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1840 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1841 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1842 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1843 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1844 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1845 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1846 { NULL, NULL, 0 },
1847};
1848
1849/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1850
1851static struct bind_kw_list bind_kws = { "SSL", { }, {
1852 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1853 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1854 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1855 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1856 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1857 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1858 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1859 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001860#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001861 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1862#endif
1863 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1864 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1865 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1866 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1867 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1868 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1869 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1870 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1871 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1872 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1873 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1874 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1875 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1876 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1877 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1878 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1879 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1880 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1881 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1882 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1883 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1884 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1885 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1886 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1887 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1888 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1889 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1890 { NULL, NULL, 0 },
1891}};
1892
1893INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1894
1895/* Note: must not be declared <const> as its list will be overwritten.
1896 * Please take care of keeping this list alphabetically sorted, doing so helps
1897 * all code contributors.
1898 * Optional keywords are also declared with a NULL ->parse() function so that
1899 * the config parser can report an appropriate error when a known keyword was
1900 * not enabled.
1901 */
1902static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001903 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1904 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001905 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001906 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1907 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1908 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001909 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001910#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001911 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001912#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001913 { "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 +02001914 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001915 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1916 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1917 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1918 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1919 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001920 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1921 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1922 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1923 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001924 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1925 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1926 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1927 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1928 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1929 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1930 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1931 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1932 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1933 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1934 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001935 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001936 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1937 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001938 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001939 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1940 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
1941 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001942 { NULL, NULL, 0, 0 },
1943}};
1944
1945INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1946
1947static struct cfg_kw_list cfg_kws = {ILH, {
1948 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1949 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1950 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1951 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1952 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1953 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1954#ifndef OPENSSL_NO_DH
1955 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1956#endif
1957 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
William Lallemandd7bfbe22022-04-11 18:41:24 +02001958#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +02001959 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1960#endif
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02001961#ifdef HAVE_SSL_PROVIDERS
1962 { CFG_GLOBAL, "ssl-propquery", ssl_parse_global_ssl_propquery },
1963#endif
William Lallemanddad31052020-05-14 17:47:32 +02001964 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1965 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1966#ifndef OPENSSL_NO_DH
1967 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1968#endif
1969 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
1970 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1971 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
Thomas Prückl10243932022-04-27 13:04:54 +02001972 { CFG_GLOBAL, "tune.ssl.hard-maxrecord", ssl_parse_global_int },
William Lallemanddad31052020-05-14 17:47:32 +02001973 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02001974 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
1975 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02001976 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02001977 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1978 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001979#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001980 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
1981#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001982#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001983 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
1984 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
1985#endif
1986 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02001987 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02001988 { 0, NULL, NULL },
1989}};
1990
1991INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);