blob: 026e16d888f593e339153e9db6c663793614077a [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>
25#include <fcntl.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
31#include <sys/stat.h>
32#include <sys/types.h>
33
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020034#include <haproxy/api.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020035#include <haproxy/base64.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020036#include <haproxy/cfgparse.h>
Willy Tarreau0d1dd0e2021-10-06 19:00:49 +020037#include <haproxy/errors.h>
Willy Tarreau213e9902020-06-04 14:58:24 +020038#include <haproxy/listener.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +020039#include <haproxy/openssl-compat.h>
Willy Tarreau209108d2020-06-04 20:30:20 +020040#include <haproxy/ssl_sock.h>
Willy Tarreaucc81eca2021-05-08 12:54:42 +020041#include <haproxy/tools.h>
Remi Tricot-Le Bretonaf8820a2021-04-13 10:10:37 +020042#include <haproxy/ssl_ckch.h>
William Lallemanddad31052020-05-14 17:47:32 +020043
44
45/****************** Global Section Parsing ********************************************/
46
47static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +010048 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +020049 char **err)
50{
51 char *path;
52 struct dirent **de_list;
53 int i, n;
54 struct stat buf;
55 char *end;
56 char fp[MAXPATHLEN+1];
57
58 if (too_many_args(1, args, err, NULL))
59 return -1;
60
61 path = args[1];
62 if (*path == 0 || stat(path, &buf)) {
63 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
64 err && *err ? *err : "", args[0]);
65 return -1;
66 }
67 if (S_ISDIR(buf.st_mode) == 0) {
68 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
69 err && *err ? *err : "", args[0], path);
70 return -1;
71 }
72
73 /* strip trailing slashes, including first one */
74 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
75 *end = 0;
76 /* path already parsed? */
77 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
78 return 0;
79 /* overwrite old issuers_chain_path */
80 free(global_ssl.issuers_chain_path);
81 global_ssl.issuers_chain_path = strdup(path);
82 ssl_free_global_issuers();
83
84 n = scandir(path, &de_list, 0, alphasort);
85 if (n < 0) {
86 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
87 err && *err ? *err : "", args[0], path, strerror(errno));
88 return -1;
89 }
90 for (i = 0; i < n; i++) {
91 struct dirent *de = de_list[i];
92 BIO *in = NULL;
93 char *warn = NULL;
94
95 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
96 free(de);
97 if (stat(fp, &buf) != 0) {
98 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
99 goto next;
100 }
101 if (!S_ISREG(buf.st_mode))
102 goto next;
103
104 in = BIO_new(BIO_s_file());
105 if (in == NULL)
106 goto next;
107 if (BIO_read_filename(in, fp) <= 0)
108 goto next;
109 ssl_load_global_issuer_from_BIO(in, fp, &warn);
110 if (warn) {
111 ha_warning("%s", warn);
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100112 ha_free(&warn);
William Lallemanddad31052020-05-14 17:47:32 +0200113 }
114 next:
115 if (in)
116 BIO_free(in);
117 }
118 free(de_list);
119
120 return 0;
121}
122
William Lallemanddad31052020-05-14 17:47:32 +0200123/* parse the "ssl-mode-async" keyword in global section.
124 * Returns <0 on alert, >0 on warning, 0 on success.
125 */
126static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100127 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200128 char **err)
129{
Ilya Shipitsinbdec3ba2020-11-14 01:56:34 +0500130#ifdef SSL_MODE_ASYNC
William Lallemanddad31052020-05-14 17:47:32 +0200131 global_ssl.async = 1;
132 global.ssl_used_async_engines = nb_engines;
133 return 0;
134#else
135 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
136 return -1;
137#endif
138}
139
William Lallemand5520d6f2020-05-18 13:42:49 +0200140#ifndef OPENSSL_NO_ENGINE
William Lallemanddad31052020-05-14 17:47:32 +0200141/* parse the "ssl-engine" keyword in global section.
142 * Returns <0 on alert, >0 on warning, 0 on success.
143 */
144static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100145 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200146 char **err)
147{
148 char *algo;
149 int ret = -1;
150
151 if (*(args[1]) == 0) {
152 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
153 return ret;
154 }
155
156 if (*(args[2]) == 0) {
157 /* if no list of algorithms is given, it defaults to ALL */
158 algo = strdup("ALL");
159 goto add_engine;
160 }
161
162 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
163 if (strcmp(args[2], "algo") != 0) {
164 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
165 return ret;
166 }
167
168 if (*(args[3]) == 0) {
169 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
170 return ret;
171 }
172 algo = strdup(args[3]);
173
174add_engine:
175 if (ssl_init_single_engine(args[1], algo)==0) {
176 openssl_engines_initialized++;
177 ret = 0;
178 }
179 free(algo);
180 return ret;
181}
182#endif
183
184/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
185 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
186 */
187static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100188 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200189 char **err)
190{
191 char **target;
192
193 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
194
195 if (too_many_args(1, args, err, NULL))
196 return -1;
197
198 if (*(args[1]) == 0) {
199 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
200 return -1;
201 }
202
203 free(*target);
204 *target = strdup(args[1]);
205 return 0;
206}
207
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500208#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200209/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
210 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
211 */
212static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100213 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200214 char **err)
215{
216 char **target;
217
218 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
219
220 if (too_many_args(1, args, err, NULL))
221 return -1;
222
223 if (*(args[1]) == 0) {
224 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
225 return -1;
226 }
227
228 free(*target);
229 *target = strdup(args[1]);
230 return 0;
231}
232#endif
233
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500234#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200235/*
236 * parse the "ssl-default-bind-curves" keyword in a global section.
237 * Returns <0 on alert, >0 on warning, 0 on success.
238 */
239static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100240 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200241 char **err)
242{
243 char **target;
244 target = &global_ssl.listen_default_curves;
245
246 if (too_many_args(1, args, err, NULL))
247 return -1;
248
249 if (*(args[1]) == 0) {
250 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
251 return -1;
252 }
253
254 free(*target);
255 *target = strdup(args[1]);
256 return 0;
257}
258#endif
259/* parse various global tune.ssl settings consisting in positive integers.
260 * Returns <0 on alert, >0 on warning, 0 on success.
261 */
262static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100263 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200264 char **err)
265{
266 int *target;
267
268 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
269 target = &global.tune.sslcachesize;
270 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
271 target = (int *)&global_ssl.max_record;
272 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
273 target = &global_ssl.ctx_cache;
274 else if (strcmp(args[0], "maxsslconn") == 0)
275 target = &global.maxsslconn;
Marcin Deranek310a2602021-07-13 19:04:24 +0200276 else if (strcmp(args[0], "tune.ssl.capture-buffer-size") == 0)
277 target = &global_ssl.capture_buffer_size;
278 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0) {
279 target = &global_ssl.capture_buffer_size;
280 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",
281 file, line, args[0]);
282 }
William Lallemanddad31052020-05-14 17:47:32 +0200283 else {
284 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
285 return -1;
286 }
287
288 if (too_many_args(1, args, err, NULL))
289 return -1;
290
291 if (*(args[1]) == 0) {
292 memprintf(err, "'%s' expects an integer argument.", args[0]);
293 return -1;
294 }
295
296 *target = atoi(args[1]);
297 if (*target < 0) {
298 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
299 return -1;
300 }
301 return 0;
302}
303
Marcin Deranek310a2602021-07-13 19:04:24 +0200304static int ssl_parse_global_capture_buffer(char **args, int section_type, struct proxy *curpx,
305 const struct proxy *defpx, const char *file, int line,
306 char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200307{
308 int ret;
309
310 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
311 if (ret != 0)
312 return ret;
313
314 if (pool_head_ssl_capture) {
315 memprintf(err, "'%s' is already configured.", args[0]);
316 return -1;
317 }
318
Marcin Deranek310a2602021-07-13 19:04:24 +0200319 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 +0200320 if (!pool_head_ssl_capture) {
321 memprintf(err, "Out of memory error.");
322 return -1;
323 }
324 return 0;
325}
326
William Lallemand7d42ef52020-07-06 11:41:30 +0200327/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200328#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200329static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100330 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200331 char **err)
332{
333
334 if (too_many_args(1, args, err, NULL))
335 return -1;
336
337 if (strcmp(args[1], "on") == 0)
338 global_ssl.keylog = 1;
339 else if (strcmp(args[1], "off") == 0)
340 global_ssl.keylog = 0;
341 else {
342 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
343 return -1;
344 }
345
346 if (pool_head_ssl_keylog) /* already configured */
347 return 0;
348
349 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
350 if (!pool_head_ssl_keylog) {
351 memprintf(err, "Out of memory error.");
352 return -1;
353 }
354
355 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
356 if (!pool_head_ssl_keylog_str) {
357 memprintf(err, "Out of memory error.");
358 return -1;
359 }
360
361 return 0;
362}
William Lallemand722180a2021-06-09 16:46:12 +0200363#else
364static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
365 const struct proxy *defpx, const char *file, int line,
366 char **err)
367{
368 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
369 return -1;
370}
William Lallemand7d42ef52020-07-06 11:41:30 +0200371#endif
372
William Lallemanddad31052020-05-14 17:47:32 +0200373/* parse "ssl.force-private-cache".
374 * Returns <0 on alert, >0 on warning, 0 on success.
375 */
376static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100377 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200378 char **err)
379{
380 if (too_many_args(0, args, err, NULL))
381 return -1;
382
383 global_ssl.private_cache = 1;
384 return 0;
385}
386
387/* parse "ssl.lifetime".
388 * Returns <0 on alert, >0 on warning, 0 on success.
389 */
390static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100391 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200392 char **err)
393{
394 const char *res;
395
396 if (too_many_args(1, args, err, NULL))
397 return -1;
398
399 if (*(args[1]) == 0) {
400 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
401 return -1;
402 }
403
404 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
405 if (res == PARSE_TIME_OVER) {
406 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
407 args[1], args[0]);
408 return -1;
409 }
410 else if (res == PARSE_TIME_UNDER) {
411 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
412 args[1], args[0]);
413 return -1;
414 }
415 else if (res) {
416 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
417 return -1;
418 }
419 return 0;
420}
421
422#ifndef OPENSSL_NO_DH
423/* parse "ssl-dh-param-file".
424 * Returns <0 on alert, >0 on warning, 0 on success.
425 */
426static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100427 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200428 char **err)
429{
430 if (too_many_args(1, args, err, NULL))
431 return -1;
432
433 if (*(args[1]) == 0) {
434 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
435 return -1;
436 }
437
438 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
439 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
440 return -1;
441 }
442 return 0;
443}
444
445/* parse "ssl.default-dh-param".
446 * Returns <0 on alert, >0 on warning, 0 on success.
447 */
448static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100449 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200450 char **err)
451{
452 if (too_many_args(1, args, err, NULL))
453 return -1;
454
455 if (*(args[1]) == 0) {
456 memprintf(err, "'%s' expects an integer argument.", args[0]);
457 return -1;
458 }
459
460 global_ssl.default_dh_param = atoi(args[1]);
461 if (global_ssl.default_dh_param < 1024) {
462 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
463 return -1;
464 }
465 return 0;
466}
467#endif
468
469
470/*
471 * parse "ssl-load-extra-files".
472 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
473 */
474static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100475 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200476 char **err)
477{
478 int i;
479 int gf = SSL_GF_NONE;
480
481 if (*(args[1]) == 0)
482 goto err_arg;
483
484 for (i = 1; *args[i]; i++) {
485
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100486 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200487 gf |= SSL_GF_BUNDLE;
488
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100489 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200490 gf |= SSL_GF_SCTL;
491
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100492 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200493 gf |= SSL_GF_OCSP;
494
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100495 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200496 gf |= SSL_GF_OCSP_ISSUER;
497
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100498 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200499 gf |= SSL_GF_KEY;
500
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100501 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200502 if (gf != SSL_GF_NONE)
503 goto err_alone;
504 gf = SSL_GF_NONE;
505 i++;
506 break;
507
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100508 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200509 if (gf != SSL_GF_NONE)
510 goto err_alone;
511 gf = SSL_GF_ALL;
512 i++;
513 break;
514 } else {
515 goto err_arg;
516 }
517 }
518 /* break from loop but there are still arguments */
519 if (*args[i])
520 goto err_alone;
521
522 global_ssl.extra_files = gf;
523
524 return 0;
525
526err_alone:
527 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
528 return -1;
529
530err_arg:
531 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
532 return -1;
533}
534
535
William Lallemand8e8581e2020-10-20 17:36:46 +0200536/* parse 'ssl-load-extra-del-ext */
537static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100538 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200539 char **err)
540{
541 global_ssl.extra_files_noext = 1;
542 return 0;
543}
544
William Lallemanddad31052020-05-14 17:47:32 +0200545/***************************** Bind keyword Parsing ********************************************/
546
547/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100548static 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 +0200549{
550 if (!*args[cur_arg + 1]) {
551 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
552 return ERR_ALERT | ERR_FATAL;
553 }
554
555 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
556 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
557 else
558 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
559
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200560 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200561 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
562 return ERR_ALERT | ERR_FATAL;
563 }
564 return 0;
565}
566
567/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100568static 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 +0200569{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100570 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200571}
572static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
573{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100574 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200575}
576
577/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100578static 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 +0200579{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100580 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200581}
582static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
583{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100584 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200585}
586
587/* parse the "ca-sign-file" bind keyword */
588static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
589{
590 if (!*args[cur_arg + 1]) {
591 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
592 return ERR_ALERT | ERR_FATAL;
593 }
594
595 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
596 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
597 else
598 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
599
600 return 0;
601}
602
603/* parse the "ca-sign-pass" bind keyword */
604static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
605{
606 if (!*args[cur_arg + 1]) {
607 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
608 return ERR_ALERT | ERR_FATAL;
609 }
610 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
611 return 0;
612}
613
614/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100615static 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 +0200616{
617 if (!*args[cur_arg + 1]) {
618 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
619 return ERR_ALERT | ERR_FATAL;
620 }
621
622 free(conf->ciphers);
623 conf->ciphers = strdup(args[cur_arg + 1]);
624 return 0;
625}
626static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
627{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100628 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200629}
630
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500631#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200632/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100633static 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 +0200634{
635 if (!*args[cur_arg + 1]) {
636 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
637 return ERR_ALERT | ERR_FATAL;
638 }
639
640 free(conf->ciphersuites);
641 conf->ciphersuites = strdup(args[cur_arg + 1]);
642 return 0;
643}
644static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
645{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100646 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200647}
648#endif
649
650/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
651static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
652{
653 char path[MAXPATHLEN];
654
655 if (!*args[cur_arg + 1]) {
656 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
657 return ERR_ALERT | ERR_FATAL;
658 }
659
660 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
661 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
662 memprintf(err, "'%s' : path too long", args[cur_arg]);
663 return ERR_ALERT | ERR_FATAL;
664 }
665 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
666 return ssl_sock_load_cert(path, conf, err);
667 }
668
669 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
670}
671
672/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
673static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
674{
675 int err_code;
676
677 if (!*args[cur_arg + 1]) {
678 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
679 return ERR_ALERT | ERR_FATAL;
680 }
681
682 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
683 if (err_code)
684 memprintf(err, "'%s' : %s", args[cur_arg], *err);
685
686 return err_code;
687}
688
689/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100690static 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 +0200691{
692#ifndef X509_V_FLAG_CRL_CHECK
693 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
694 return ERR_ALERT | ERR_FATAL;
695#else
696 if (!*args[cur_arg + 1]) {
697 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
698 return ERR_ALERT | ERR_FATAL;
699 }
700
701 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
702 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
703 else
704 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
705
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200706 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200707 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
708 return ERR_ALERT | ERR_FATAL;
709 }
710 return 0;
711#endif
712}
713static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
714{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100715 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200716}
717
718/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100719static 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 +0200720{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500721#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200722 if (!*args[cur_arg + 1]) {
723 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
724 return ERR_ALERT | ERR_FATAL;
725 }
726 conf->curves = strdup(args[cur_arg + 1]);
727 return 0;
728#else
729 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
730 return ERR_ALERT | ERR_FATAL;
731#endif
732}
733static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
734{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100735 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200736}
737
738/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100739static 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 +0200740{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500741#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200742 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
743 return ERR_ALERT | ERR_FATAL;
744#elif defined(OPENSSL_NO_ECDH)
745 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
746 return ERR_ALERT | ERR_FATAL;
747#else
748 if (!*args[cur_arg + 1]) {
749 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
750 return ERR_ALERT | ERR_FATAL;
751 }
752
753 conf->ecdhe = strdup(args[cur_arg + 1]);
754
755 return 0;
756#endif
757}
758static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
759{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100760 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200761}
762
763/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
764static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
765{
766 int code;
767 char *p = args[cur_arg + 1];
768 unsigned long long *ignerr = &conf->crt_ignerr;
769
770 if (!*p) {
771 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
772 return ERR_ALERT | ERR_FATAL;
773 }
774
775 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
776 ignerr = &conf->ca_ignerr;
777
778 if (strcmp(p, "all") == 0) {
779 *ignerr = ~0ULL;
780 return 0;
781 }
782
783 while (p) {
784 code = atoi(p);
785 if ((code <= 0) || (code > 63)) {
786 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
787 args[cur_arg], code, args[cur_arg + 1]);
788 return ERR_ALERT | ERR_FATAL;
789 }
790 *ignerr |= 1ULL << code;
791 p = strchr(p, ',');
792 if (p)
793 p++;
794 }
795
796 return 0;
797}
798
799/* parse tls_method_options "no-xxx" and "force-xxx" */
800static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
801{
802 uint16_t v;
803 char *p;
804 p = strchr(arg, '-');
805 if (!p)
806 goto fail;
807 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100808 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200809 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100810 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200811 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100812 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200813 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100814 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200815 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100816 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200817 v = CONF_TLSV13;
818 else
819 goto fail;
820 if (!strncmp(arg, "no-", 3))
821 methods->flags |= methodVersions[v].flag;
822 else if (!strncmp(arg, "force-", 6))
823 methods->min = methods->max = v;
824 else
825 goto fail;
826 return 0;
827 fail:
828 memprintf(err, "'%s' : option not implemented", arg);
829 return ERR_ALERT | ERR_FATAL;
830}
831
832static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
833{
834 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
835}
836
837static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
838{
839 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
840}
841
842/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
843static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
844{
845 uint16_t i, v = 0;
846 char *argv = args[cur_arg + 1];
847 if (!*argv) {
848 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
849 return ERR_ALERT | ERR_FATAL;
850 }
851 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100852 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200853 v = i;
854 if (!v) {
855 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
856 return ERR_ALERT | ERR_FATAL;
857 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100858 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200859 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100860 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200861 methods->max = v;
862 else {
863 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
864 return ERR_ALERT | ERR_FATAL;
865 }
866 return 0;
867}
868
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100869static 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 +0200870{
William Lallemand8177ad92020-05-20 16:49:02 +0200871 int ret;
872
William Lallemanddad31052020-05-14 17:47:32 +0200873#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
874 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
875#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200876 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
877 if (ret != ERR_NONE)
878 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200879
William Lallemand8177ad92020-05-20 16:49:02 +0200880 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
881 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
882
883 return ret;
884}
William Lallemanddad31052020-05-14 17:47:32 +0200885static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
886{
887 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
888}
889
890static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
891{
892 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
893}
894
895/* parse the "no-tls-tickets" bind keyword */
896static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
897{
898 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
899 return 0;
900}
901
902/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100903static 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 +0200904{
905 conf->early_data = 1;
906 return 0;
907}
908
909static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
910{
911 conf->ssl_conf.early_data = 1;
912 return 0;
913}
914
915/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100916static 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 +0200917{
918#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
919 char *p1, *p2;
920
921 if (!*args[cur_arg + 1]) {
922 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
923 return ERR_ALERT | ERR_FATAL;
924 }
925
926 free(conf->npn_str);
927
928 /* the NPN string is built as a suite of (<len> <name>)*,
929 * so we reuse each comma to store the next <len> and need
930 * one more for the end of the string.
931 */
932 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
933 conf->npn_str = calloc(1, conf->npn_len + 1);
934 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
935
936 /* replace commas with the name length */
937 p1 = conf->npn_str;
938 p2 = p1 + 1;
939 while (1) {
940 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
941 if (!p2)
942 p2 = p1 + 1 + strlen(p1 + 1);
943
944 if (p2 - (p1 + 1) > 255) {
945 *p2 = '\0';
946 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
947 return ERR_ALERT | ERR_FATAL;
948 }
949
950 *p1 = p2 - (p1 + 1);
951 p1 = p2;
952
953 if (!*p2)
954 break;
955
956 *(p2++) = '\0';
957 }
958 return 0;
959#else
960 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
961 return ERR_ALERT | ERR_FATAL;
962#endif
963}
964
965static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
966{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100967 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200968}
969
970
971/* Parses a alpn string and converts it to the right format for the SSL api */
972int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
973{
974 char *p1, *p2, *alpn = NULL;
975 int len, ret = 0;
976
977 *alpn_str = NULL;
978 *alpn_len = 0;
979
980 if (!*arg) {
981 memprintf(err, "missing the comma-delimited ALPN protocol suite");
982 goto error;
983 }
984
985 /* the ALPN string is built as a suite of (<len> <name>)*,
986 * so we reuse each comma to store the next <len> and need
987 * one more for the end of the string.
988 */
989 len = strlen(arg) + 1;
990 alpn = calloc(1, len+1);
991 if (!alpn) {
992 memprintf(err, "'%s' : out of memory", arg);
993 goto error;
994 }
995 memcpy(alpn+1, arg, len);
996
997 /* replace commas with the name length */
998 p1 = alpn;
999 p2 = p1 + 1;
1000 while (1) {
1001 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1002 if (!p2)
1003 p2 = p1 + 1 + strlen(p1 + 1);
1004
1005 if (p2 - (p1 + 1) > 255) {
1006 *p2 = '\0';
1007 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1008 goto error;
1009 }
1010
1011 *p1 = p2 - (p1 + 1);
1012 p1 = p2;
1013
1014 if (!*p2)
1015 break;
1016
1017 *(p2++) = '\0';
1018 }
1019
1020 *alpn_str = alpn;
1021 *alpn_len = len;
1022
1023 out:
1024 return ret;
1025
1026 error:
1027 free(alpn);
1028 ret = ERR_ALERT | ERR_FATAL;
1029 goto out;
1030}
1031
1032/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001033static 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 +02001034{
1035#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1036 int ret;
1037
1038 free(conf->alpn_str);
1039
1040 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1041 if (ret)
1042 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1043 return ret;
1044#else
1045 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1046 return ERR_ALERT | ERR_FATAL;
1047#endif
1048}
1049
1050static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1051{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001052 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001053}
1054
1055/* parse the "ssl" bind keyword */
1056static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1057{
Frédéric Lécaillee50afbd2020-11-23 11:33:12 +01001058 /* Do not change the xprt for QUIC. */
1059 if (conf->xprt != xprt_get(XPRT_QUIC))
1060 conf->xprt = &ssl_sock;
William Lallemanddad31052020-05-14 17:47:32 +02001061 conf->is_ssl = 1;
1062
1063 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1064 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001065#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001066 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1067 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1068#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001069#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001070 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1071 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1072#endif
1073 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1074 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1075 if (!conf->ssl_conf.ssl_methods.min)
1076 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1077 if (!conf->ssl_conf.ssl_methods.max)
1078 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1079
1080 return 0;
1081}
1082
1083/* parse the "prefer-client-ciphers" bind keyword */
1084static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1085{
1086 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1087 return 0;
1088}
1089
1090/* parse the "generate-certificates" bind keyword */
1091static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1092{
1093#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1094 conf->generate_certs = 1;
1095#else
1096 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1097 err && *err ? *err : "");
1098#endif
1099 return 0;
1100}
1101
1102/* parse the "strict-sni" bind keyword */
1103static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1104{
1105 conf->strict_sni = 1;
1106 return 0;
1107}
1108
1109/* parse the "tls-ticket-keys" bind keyword */
1110static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1111{
1112#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1113 FILE *f = NULL;
1114 int i = 0;
1115 char thisline[LINESIZE];
1116 struct tls_keys_ref *keys_ref = NULL;
1117
1118 if (!*args[cur_arg + 1]) {
1119 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1120 goto fail;
1121 }
1122
1123 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1124 if (keys_ref) {
1125 keys_ref->refcount++;
1126 conf->keys_ref = keys_ref;
1127 return 0;
1128 }
1129
1130 keys_ref = calloc(1, sizeof(*keys_ref));
1131 if (!keys_ref) {
1132 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1133 goto fail;
1134 }
1135
1136 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1137 if (!keys_ref->tlskeys) {
1138 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1139 goto fail;
1140 }
1141
1142 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1143 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1144 goto fail;
1145 }
1146
1147 keys_ref->filename = strdup(args[cur_arg + 1]);
1148 if (!keys_ref->filename) {
1149 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1150 goto fail;
1151 }
1152
1153 keys_ref->key_size_bits = 0;
1154 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1155 int len = strlen(thisline);
1156 int dec_size;
1157
1158 /* Strip newline characters from the end */
1159 if(thisline[len - 1] == '\n')
1160 thisline[--len] = 0;
1161
1162 if(thisline[len - 1] == '\r')
1163 thisline[--len] = 0;
1164
1165 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1166 if (dec_size < 0) {
1167 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1168 goto fail;
1169 }
1170 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1171 keys_ref->key_size_bits = 128;
1172 }
1173 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1174 keys_ref->key_size_bits = 256;
1175 }
1176 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1177 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1178 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1179 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1180 goto fail;
1181 }
1182 i++;
1183 }
1184
1185 if (i < TLS_TICKETS_NO) {
1186 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1187 goto fail;
1188 }
1189
1190 fclose(f);
1191
1192 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1193 i -= 2;
1194 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1195 keys_ref->unique_id = -1;
1196 keys_ref->refcount = 1;
1197 HA_RWLOCK_INIT(&keys_ref->lock);
1198 conf->keys_ref = keys_ref;
1199
Willy Tarreau2b718102021-04-21 07:32:39 +02001200 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001201
1202 return 0;
1203
1204 fail:
1205 if (f)
1206 fclose(f);
1207 if (keys_ref) {
1208 free(keys_ref->filename);
1209 free(keys_ref->tlskeys);
1210 free(keys_ref);
1211 }
1212 return ERR_ALERT | ERR_FATAL;
1213
1214#else
1215 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1216 return ERR_ALERT | ERR_FATAL;
1217#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1218}
1219
1220/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001221static 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 +02001222{
1223 if (!*args[cur_arg + 1]) {
1224 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1225 return ERR_ALERT | ERR_FATAL;
1226 }
1227
1228 if (strcmp(args[cur_arg + 1], "none") == 0)
1229 conf->verify = SSL_SOCK_VERIFY_NONE;
1230 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1231 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1232 else if (strcmp(args[cur_arg + 1], "required") == 0)
1233 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1234 else {
1235 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1236 args[cur_arg], args[cur_arg + 1]);
1237 return ERR_ALERT | ERR_FATAL;
1238 }
1239
1240 return 0;
1241}
1242static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1243{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001244 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001245}
1246
1247/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001248static 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 +02001249{
1250 conf->no_ca_names = 1;
1251 return 0;
1252}
1253static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1254{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001255 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001256}
1257
1258/***************************** "server" keywords Parsing ********************************************/
1259
1260/* parse the "npn" bind keyword */
1261static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1262{
1263#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1264 char *p1, *p2;
1265
1266 if (!*args[*cur_arg + 1]) {
1267 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1268 return ERR_ALERT | ERR_FATAL;
1269 }
1270
1271 free(newsrv->ssl_ctx.npn_str);
1272
1273 /* the NPN string is built as a suite of (<len> <name>)*,
1274 * so we reuse each comma to store the next <len> and need
1275 * one more for the end of the string.
1276 */
1277 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1278 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001279 if (!newsrv->ssl_ctx.npn_str) {
1280 memprintf(err, "out of memory");
1281 return ERR_ALERT | ERR_FATAL;
1282 }
1283
William Lallemanddad31052020-05-14 17:47:32 +02001284 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1285 newsrv->ssl_ctx.npn_len);
1286
1287 /* replace commas with the name length */
1288 p1 = newsrv->ssl_ctx.npn_str;
1289 p2 = p1 + 1;
1290 while (1) {
1291 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1292 newsrv->ssl_ctx.npn_len - (p1 + 1));
1293 if (!p2)
1294 p2 = p1 + 1 + strlen(p1 + 1);
1295
1296 if (p2 - (p1 + 1) > 255) {
1297 *p2 = '\0';
1298 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1299 return ERR_ALERT | ERR_FATAL;
1300 }
1301
1302 *p1 = p2 - (p1 + 1);
1303 p1 = p2;
1304
1305 if (!*p2)
1306 break;
1307
1308 *(p2++) = '\0';
1309 }
1310 return 0;
1311#else
1312 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1313 return ERR_ALERT | ERR_FATAL;
1314#endif
1315}
1316
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001317#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1318static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1319{
1320 free(*out_alpn_str);
1321 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1322}
1323#endif
1324
1325/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001326static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1327{
1328#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001329 int ret = parse_alpn(args[*cur_arg + 1],
1330 &newsrv->ssl_ctx.alpn_str,
1331 &newsrv->ssl_ctx.alpn_len, err);
1332 if (ret)
1333 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1334 return ret;
1335#else
1336 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1337 return ERR_ALERT | ERR_FATAL;
1338#endif
1339}
William Lallemanddad31052020-05-14 17:47:32 +02001340
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001341/* parse the "check-alpn" server keyword */
1342static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1343{
1344#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1345 int ret = parse_alpn(args[*cur_arg + 1],
1346 &newsrv->check.alpn_str,
1347 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001348 if (ret)
1349 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1350 return ret;
1351#else
1352 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1353 return ERR_ALERT | ERR_FATAL;
1354#endif
1355}
1356
1357/* parse the "ca-file" server keyword */
1358static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1359{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001360 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1361
William Lallemanddad31052020-05-14 17:47:32 +02001362 if (!*args[*cur_arg + 1]) {
1363 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1364 return ERR_ALERT | ERR_FATAL;
1365 }
1366
1367 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1368 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1369 else
1370 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1371
Amaury Denoyelle48255022021-05-19 09:46:59 +02001372 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001373 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1374 return ERR_ALERT | ERR_FATAL;
1375 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001376
William Lallemanddad31052020-05-14 17:47:32 +02001377 return 0;
1378}
1379
1380/* parse the "check-sni" server keyword */
1381static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1382{
1383 if (!*args[*cur_arg + 1]) {
1384 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1385 return ERR_ALERT | ERR_FATAL;
1386 }
1387
1388 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1389 if (!newsrv->check.sni) {
1390 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1391 return ERR_ALERT | ERR_FATAL;
1392 }
1393 return 0;
1394
1395}
1396
William Dauchyfc52f522020-11-14 19:25:32 +01001397/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001398static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001399{
William Dauchyfc52f522020-11-14 19:25:32 +01001400 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1401 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001402#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001403 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001404 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001405 if (!s->ssl_ctx.ciphersuites)
1406 return 1;
1407 }
William Lallemanddad31052020-05-14 17:47:32 +02001408#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001409 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1410 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1411
1412 if (!s->ssl_ctx.methods.min)
1413 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001414
William Dauchyfc52f522020-11-14 19:25:32 +01001415 if (!s->ssl_ctx.methods.max)
1416 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001417
1418 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001419}
1420
1421/* parse the "check-ssl" server keyword */
1422static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1423{
1424 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001425 if (ssl_sock_init_srv(newsrv)) {
1426 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1427 return ERR_ALERT | ERR_FATAL;
1428 }
1429
William Lallemanddad31052020-05-14 17:47:32 +02001430 return 0;
1431}
1432
1433/* parse the "ciphers" server keyword */
1434static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1435{
1436 if (!*args[*cur_arg + 1]) {
1437 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1438 return ERR_ALERT | ERR_FATAL;
1439 }
1440
1441 free(newsrv->ssl_ctx.ciphers);
1442 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001443
1444 if (!newsrv->ssl_ctx.ciphers) {
1445 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1446 return ERR_ALERT | ERR_FATAL;
1447 }
1448
William Lallemanddad31052020-05-14 17:47:32 +02001449 return 0;
1450}
1451
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001452#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001453/* parse the "ciphersuites" server keyword */
1454static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1455{
1456 if (!*args[*cur_arg + 1]) {
1457 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1458 return ERR_ALERT | ERR_FATAL;
1459 }
1460
1461 free(newsrv->ssl_ctx.ciphersuites);
1462 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001463
1464 if (!newsrv->ssl_ctx.ciphersuites) {
1465 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1466 return ERR_ALERT | ERR_FATAL;
1467 }
1468
William Lallemanddad31052020-05-14 17:47:32 +02001469 return 0;
1470}
1471#endif
1472
1473/* parse the "crl-file" server keyword */
1474static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1475{
1476#ifndef X509_V_FLAG_CRL_CHECK
1477 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1478 return ERR_ALERT | ERR_FATAL;
1479#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001480 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1481
William Lallemanddad31052020-05-14 17:47:32 +02001482 if (!*args[*cur_arg + 1]) {
1483 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1484 return ERR_ALERT | ERR_FATAL;
1485 }
1486
1487 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1488 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1489 else
1490 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1491
Amaury Denoyellefde82602021-06-14 10:10:32 +02001492 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001493 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1494 return ERR_ALERT | ERR_FATAL;
1495 }
1496 return 0;
1497#endif
1498}
1499
1500/* parse the "crt" server keyword */
1501static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1502{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001503
William Lallemanddad31052020-05-14 17:47:32 +02001504 if (!*args[*cur_arg + 1]) {
1505 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1506 return ERR_ALERT | ERR_FATAL;
1507 }
1508
1509 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001510 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001511 else
William Lallemand2c776f12021-12-28 18:47:17 +01001512 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001513
William Lallemand2c776f12021-12-28 18:47:17 +01001514 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001515}
1516
1517/* parse the "no-check-ssl" server keyword */
1518static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1519{
1520 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001521 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001522 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1523 return 0;
1524}
1525
1526/* parse the "no-send-proxy-v2-ssl" server keyword */
1527static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1528{
1529 newsrv->pp_opts &= ~SRV_PP_V2;
1530 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1531 return 0;
1532}
1533
1534/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1535static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1536{
1537 newsrv->pp_opts &= ~SRV_PP_V2;
1538 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1539 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1540 return 0;
1541}
1542
1543/* parse the "no-ssl" server keyword */
1544static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1545{
William Dauchyf6370442020-11-14 19:25:33 +01001546 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001547 if (newsrv->use_ssl == 1) {
1548 if (ssl_sock_init_srv(newsrv)) {
1549 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1550 return ERR_ALERT | ERR_FATAL;
1551 }
1552 }
William Dauchyf6370442020-11-14 19:25:33 +01001553 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001554 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001555 }
William Lallemanddad31052020-05-14 17:47:32 +02001556 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001557 return 0;
1558}
1559
1560/* parse the "allow-0rtt" server keyword */
1561static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1562{
1563 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1564 return 0;
1565}
1566
1567/* parse the "no-ssl-reuse" server keyword */
1568static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1569{
1570 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1571 return 0;
1572}
1573
1574/* parse the "no-tls-tickets" server keyword */
1575static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1576{
1577 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1578 return 0;
1579}
1580/* parse the "send-proxy-v2-ssl" server keyword */
1581static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1582{
1583 newsrv->pp_opts |= SRV_PP_V2;
1584 newsrv->pp_opts |= SRV_PP_V2_SSL;
1585 return 0;
1586}
1587
1588/* parse the "send-proxy-v2-ssl-cn" server keyword */
1589static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1590{
1591 newsrv->pp_opts |= SRV_PP_V2;
1592 newsrv->pp_opts |= SRV_PP_V2_SSL;
1593 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1594 return 0;
1595}
1596
1597/* parse the "sni" server keyword */
1598static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1599{
1600#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1601 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1602 return ERR_ALERT | ERR_FATAL;
1603#else
1604 char *arg;
1605
1606 arg = args[*cur_arg + 1];
1607 if (!*arg) {
1608 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1609 return ERR_ALERT | ERR_FATAL;
1610 }
1611
1612 free(newsrv->sni_expr);
1613 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001614 if (!newsrv->sni_expr) {
1615 memprintf(err, "out of memory");
1616 return ERR_ALERT | ERR_FATAL;
1617 }
William Lallemanddad31052020-05-14 17:47:32 +02001618
1619 return 0;
1620#endif
1621}
1622
1623/* parse the "ssl" server keyword */
1624static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1625{
1626 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001627 if (ssl_sock_init_srv(newsrv)) {
1628 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1629 return ERR_ALERT | ERR_FATAL;
1630 }
1631
William Lallemanddad31052020-05-14 17:47:32 +02001632 return 0;
1633}
1634
1635/* parse the "ssl-reuse" server keyword */
1636static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1637{
1638 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1639 return 0;
1640}
1641
1642/* parse the "tls-tickets" server keyword */
1643static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1644{
1645 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1646 return 0;
1647}
1648
1649/* parse the "verify" server keyword */
1650static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1651{
1652 if (!*args[*cur_arg + 1]) {
1653 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1654 return ERR_ALERT | ERR_FATAL;
1655 }
1656
1657 if (strcmp(args[*cur_arg + 1], "none") == 0)
1658 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1659 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1660 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1661 else {
1662 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1663 args[*cur_arg], args[*cur_arg + 1]);
1664 return ERR_ALERT | ERR_FATAL;
1665 }
1666
1667 return 0;
1668}
1669
1670/* parse the "verifyhost" server keyword */
1671static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1672{
1673 if (!*args[*cur_arg + 1]) {
1674 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1675 return ERR_ALERT | ERR_FATAL;
1676 }
1677
1678 free(newsrv->ssl_ctx.verify_host);
1679 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1680
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001681 if (!newsrv->ssl_ctx.verify_host) {
1682 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1683 return ERR_ALERT | ERR_FATAL;
1684 }
1685
William Lallemanddad31052020-05-14 17:47:32 +02001686 return 0;
1687}
1688
1689/* parse the "ssl-default-bind-options" keyword in global section */
1690static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001691 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001692 char **err) {
1693 int i = 1;
1694
1695 if (*(args[i]) == 0) {
1696 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1697 return -1;
1698 }
1699 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001700 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001701 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001702 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001703 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001704 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001705 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1706 i++;
1707 else {
1708 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1709 return -1;
1710 }
1711 }
1712 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1713 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1714 return -1;
1715 }
1716 i++;
1717 }
1718 return 0;
1719}
1720
1721/* parse the "ssl-default-server-options" keyword in global section */
1722static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001723 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001724 char **err) {
1725 int i = 1;
1726
1727 if (*(args[i]) == 0) {
1728 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1729 return -1;
1730 }
1731 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001732 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001733 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001734 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001735 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1736 i++;
1737 else {
1738 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1739 return -1;
1740 }
1741 }
1742 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1743 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1744 return -1;
1745 }
1746 i++;
1747 }
1748 return 0;
1749}
1750
1751/* parse the "ca-base" / "crt-base" keywords in global section.
1752 * Returns <0 on alert, >0 on warning, 0 on success.
1753 */
1754static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001755 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001756 char **err)
1757{
1758 char **target;
1759
1760 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1761
1762 if (too_many_args(1, args, err, NULL))
1763 return -1;
1764
1765 if (*target) {
1766 memprintf(err, "'%s' already specified.", args[0]);
1767 return -1;
1768 }
1769
1770 if (*(args[1]) == 0) {
1771 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1772 return -1;
1773 }
1774 *target = strdup(args[1]);
1775 return 0;
1776}
1777
1778/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1779static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001780 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001781 char **err)
1782{
William Lallemand9a1d8392020-08-10 17:28:23 +02001783#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001784 global_ssl.skip_self_issued_ca = 1;
1785 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001786#else
1787 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1788 return -1;
1789#endif
William Lallemanddad31052020-05-14 17:47:32 +02001790}
1791
1792
1793
1794
1795
1796/* Note: must not be declared <const> as its list will be overwritten.
1797 * Please take care of keeping this list alphabetically sorted, doing so helps
1798 * all code contributors.
1799 * Optional keywords are also declared with a NULL ->parse() function so that
1800 * the config parser can report an appropriate error when a known keyword was
1801 * not enabled.
1802 */
1803
1804/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1805 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1806struct ssl_bind_kw ssl_bind_kws[] = {
1807 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1808 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1809 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1810 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1811 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001812#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001813 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1814#endif
1815 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1816 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1817 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1818 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1819 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1820 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1821 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1822 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1823 { NULL, NULL, 0 },
1824};
1825
1826/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1827
1828static struct bind_kw_list bind_kws = { "SSL", { }, {
1829 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1830 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1831 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1832 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1833 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1834 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1835 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1836 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001837#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001838 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1839#endif
1840 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1841 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1842 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1843 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1844 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1845 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1846 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1847 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1848 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1849 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1850 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1851 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1852 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1853 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1854 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1855 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1856 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1857 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1858 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1859 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1860 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1861 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1862 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1863 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1864 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1865 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1866 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1867 { NULL, NULL, 0 },
1868}};
1869
1870INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1871
1872/* Note: must not be declared <const> as its list will be overwritten.
1873 * Please take care of keeping this list alphabetically sorted, doing so helps
1874 * all code contributors.
1875 * Optional keywords are also declared with a NULL ->parse() function so that
1876 * the config parser can report an appropriate error when a known keyword was
1877 * not enabled.
1878 */
1879static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001880 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1881 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001882 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001883 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1884 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1885 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001886 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001887#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001888 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001889#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001890 { "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 +02001891 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001892 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1893 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1894 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1895 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1896 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001897 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1898 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1899 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1900 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001901 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1902 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1903 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1904 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1905 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1906 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1907 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1908 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1909 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1910 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1911 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001912 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001913 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1914 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001915 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001916 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1917 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
1918 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001919 { NULL, NULL, 0, 0 },
1920}};
1921
1922INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1923
1924static struct cfg_kw_list cfg_kws = {ILH, {
1925 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1926 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1927 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1928 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1929 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1930 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1931#ifndef OPENSSL_NO_DH
1932 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1933#endif
1934 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
1935#ifndef OPENSSL_NO_ENGINE
1936 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1937#endif
1938 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1939 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1940#ifndef OPENSSL_NO_DH
1941 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1942#endif
1943 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
1944 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1945 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
1946 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02001947 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
1948 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02001949 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02001950 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1951 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001952#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001953 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
1954#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001955#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001956 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
1957 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
1958#endif
1959 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02001960 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02001961 { 0, NULL, NULL },
1962}};
1963
1964INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);