blob: 09bcc64f728d6f3b6b15773b64609cb95317d956 [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 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 Lallemand5520d6f2020-05-18 13:42:49 +0200139#ifndef OPENSSL_NO_ENGINE
William Lallemanddad31052020-05-14 17:47:32 +0200140/* parse the "ssl-engine" keyword in global section.
141 * Returns <0 on alert, >0 on warning, 0 on success.
142 */
143static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100144 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200145 char **err)
146{
147 char *algo;
148 int ret = -1;
149
150 if (*(args[1]) == 0) {
151 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
152 return ret;
153 }
154
155 if (*(args[2]) == 0) {
156 /* if no list of algorithms is given, it defaults to ALL */
157 algo = strdup("ALL");
158 goto add_engine;
159 }
160
161 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
162 if (strcmp(args[2], "algo") != 0) {
163 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
164 return ret;
165 }
166
167 if (*(args[3]) == 0) {
168 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
169 return ret;
170 }
171 algo = strdup(args[3]);
172
173add_engine:
174 if (ssl_init_single_engine(args[1], algo)==0) {
175 openssl_engines_initialized++;
176 ret = 0;
177 }
178 free(algo);
179 return ret;
180}
181#endif
182
183/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
184 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
185 */
186static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100187 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200188 char **err)
189{
190 char **target;
191
192 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
193
194 if (too_many_args(1, args, err, NULL))
195 return -1;
196
197 if (*(args[1]) == 0) {
198 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
199 return -1;
200 }
201
202 free(*target);
203 *target = strdup(args[1]);
204 return 0;
205}
206
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500207#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200208/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
209 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
210 */
211static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100212 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200213 char **err)
214{
215 char **target;
216
217 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
218
219 if (too_many_args(1, args, err, NULL))
220 return -1;
221
222 if (*(args[1]) == 0) {
223 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
224 return -1;
225 }
226
227 free(*target);
228 *target = strdup(args[1]);
229 return 0;
230}
231#endif
232
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500233#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200234/*
235 * parse the "ssl-default-bind-curves" keyword in a global section.
236 * Returns <0 on alert, >0 on warning, 0 on success.
237 */
238static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100239 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200240 char **err)
241{
242 char **target;
243 target = &global_ssl.listen_default_curves;
244
245 if (too_many_args(1, args, err, NULL))
246 return -1;
247
248 if (*(args[1]) == 0) {
249 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
250 return -1;
251 }
252
253 free(*target);
254 *target = strdup(args[1]);
255 return 0;
256}
257#endif
258/* parse various global tune.ssl settings consisting in positive integers.
259 * Returns <0 on alert, >0 on warning, 0 on success.
260 */
261static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100262 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200263 char **err)
264{
265 int *target;
266
267 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
268 target = &global.tune.sslcachesize;
269 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
270 target = (int *)&global_ssl.max_record;
271 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
272 target = &global_ssl.ctx_cache;
273 else if (strcmp(args[0], "maxsslconn") == 0)
274 target = &global.maxsslconn;
Marcin Deranek310a2602021-07-13 19:04:24 +0200275 else if (strcmp(args[0], "tune.ssl.capture-buffer-size") == 0)
276 target = &global_ssl.capture_buffer_size;
277 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0) {
278 target = &global_ssl.capture_buffer_size;
279 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",
280 file, line, args[0]);
281 }
William Lallemanddad31052020-05-14 17:47:32 +0200282 else {
283 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
284 return -1;
285 }
286
287 if (too_many_args(1, args, err, NULL))
288 return -1;
289
290 if (*(args[1]) == 0) {
291 memprintf(err, "'%s' expects an integer argument.", args[0]);
292 return -1;
293 }
294
295 *target = atoi(args[1]);
296 if (*target < 0) {
297 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
298 return -1;
299 }
300 return 0;
301}
302
Marcin Deranek310a2602021-07-13 19:04:24 +0200303static int ssl_parse_global_capture_buffer(char **args, int section_type, struct proxy *curpx,
304 const struct proxy *defpx, const char *file, int line,
305 char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200306{
307 int ret;
308
309 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
310 if (ret != 0)
311 return ret;
312
313 if (pool_head_ssl_capture) {
314 memprintf(err, "'%s' is already configured.", args[0]);
315 return -1;
316 }
317
Marcin Deranek310a2602021-07-13 19:04:24 +0200318 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 +0200319 if (!pool_head_ssl_capture) {
320 memprintf(err, "Out of memory error.");
321 return -1;
322 }
323 return 0;
324}
325
William Lallemand7d42ef52020-07-06 11:41:30 +0200326/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200327#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200328static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100329 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200330 char **err)
331{
332
333 if (too_many_args(1, args, err, NULL))
334 return -1;
335
336 if (strcmp(args[1], "on") == 0)
337 global_ssl.keylog = 1;
338 else if (strcmp(args[1], "off") == 0)
339 global_ssl.keylog = 0;
340 else {
341 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
342 return -1;
343 }
344
345 if (pool_head_ssl_keylog) /* already configured */
346 return 0;
347
348 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
349 if (!pool_head_ssl_keylog) {
350 memprintf(err, "Out of memory error.");
351 return -1;
352 }
353
354 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
355 if (!pool_head_ssl_keylog_str) {
356 memprintf(err, "Out of memory error.");
357 return -1;
358 }
359
360 return 0;
361}
William Lallemand722180a2021-06-09 16:46:12 +0200362#else
363static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
364 const struct proxy *defpx, const char *file, int line,
365 char **err)
366{
367 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
368 return -1;
369}
William Lallemand7d42ef52020-07-06 11:41:30 +0200370#endif
371
William Lallemanddad31052020-05-14 17:47:32 +0200372/* parse "ssl.force-private-cache".
373 * Returns <0 on alert, >0 on warning, 0 on success.
374 */
375static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100376 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200377 char **err)
378{
379 if (too_many_args(0, args, err, NULL))
380 return -1;
381
382 global_ssl.private_cache = 1;
383 return 0;
384}
385
386/* parse "ssl.lifetime".
387 * Returns <0 on alert, >0 on warning, 0 on success.
388 */
389static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100390 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200391 char **err)
392{
393 const char *res;
394
395 if (too_many_args(1, args, err, NULL))
396 return -1;
397
398 if (*(args[1]) == 0) {
399 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
400 return -1;
401 }
402
403 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
404 if (res == PARSE_TIME_OVER) {
405 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
406 args[1], args[0]);
407 return -1;
408 }
409 else if (res == PARSE_TIME_UNDER) {
410 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
411 args[1], args[0]);
412 return -1;
413 }
414 else if (res) {
415 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
416 return -1;
417 }
418 return 0;
419}
420
421#ifndef OPENSSL_NO_DH
422/* parse "ssl-dh-param-file".
423 * Returns <0 on alert, >0 on warning, 0 on success.
424 */
425static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100426 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200427 char **err)
428{
429 if (too_many_args(1, args, err, NULL))
430 return -1;
431
432 if (*(args[1]) == 0) {
433 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
434 return -1;
435 }
436
437 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
438 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
439 return -1;
440 }
441 return 0;
442}
443
444/* parse "ssl.default-dh-param".
445 * Returns <0 on alert, >0 on warning, 0 on success.
446 */
447static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100448 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200449 char **err)
450{
451 if (too_many_args(1, args, err, NULL))
452 return -1;
453
454 if (*(args[1]) == 0) {
455 memprintf(err, "'%s' expects an integer argument.", args[0]);
456 return -1;
457 }
458
459 global_ssl.default_dh_param = atoi(args[1]);
460 if (global_ssl.default_dh_param < 1024) {
461 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
462 return -1;
463 }
464 return 0;
465}
466#endif
467
468
469/*
470 * parse "ssl-load-extra-files".
471 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
472 */
473static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100474 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200475 char **err)
476{
477 int i;
478 int gf = SSL_GF_NONE;
479
480 if (*(args[1]) == 0)
481 goto err_arg;
482
483 for (i = 1; *args[i]; i++) {
484
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100485 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200486 gf |= SSL_GF_BUNDLE;
487
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100488 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200489 gf |= SSL_GF_SCTL;
490
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100491 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200492 gf |= SSL_GF_OCSP;
493
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100494 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200495 gf |= SSL_GF_OCSP_ISSUER;
496
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100497 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200498 gf |= SSL_GF_KEY;
499
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100500 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200501 if (gf != SSL_GF_NONE)
502 goto err_alone;
503 gf = SSL_GF_NONE;
504 i++;
505 break;
506
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100507 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200508 if (gf != SSL_GF_NONE)
509 goto err_alone;
510 gf = SSL_GF_ALL;
511 i++;
512 break;
513 } else {
514 goto err_arg;
515 }
516 }
517 /* break from loop but there are still arguments */
518 if (*args[i])
519 goto err_alone;
520
521 global_ssl.extra_files = gf;
522
523 return 0;
524
525err_alone:
526 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
527 return -1;
528
529err_arg:
530 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
531 return -1;
532}
533
534
William Lallemand8e8581e2020-10-20 17:36:46 +0200535/* parse 'ssl-load-extra-del-ext */
536static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100537 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200538 char **err)
539{
540 global_ssl.extra_files_noext = 1;
541 return 0;
542}
543
William Lallemanddad31052020-05-14 17:47:32 +0200544/***************************** Bind keyword Parsing ********************************************/
545
546/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100547static 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 +0200548{
549 if (!*args[cur_arg + 1]) {
550 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
551 return ERR_ALERT | ERR_FATAL;
552 }
553
554 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
555 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
556 else
557 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
558
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200559 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200560 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
561 return ERR_ALERT | ERR_FATAL;
562 }
563 return 0;
564}
565
566/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100567static 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 +0200568{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100569 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200570}
571static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
572{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100573 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200574}
575
576/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100577static 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 +0200578{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100579 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200580}
581static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
582{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100583 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200584}
585
586/* parse the "ca-sign-file" bind keyword */
587static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
588{
589 if (!*args[cur_arg + 1]) {
590 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
591 return ERR_ALERT | ERR_FATAL;
592 }
593
594 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
595 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
596 else
597 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
598
599 return 0;
600}
601
602/* parse the "ca-sign-pass" bind keyword */
603static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
604{
605 if (!*args[cur_arg + 1]) {
606 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
607 return ERR_ALERT | ERR_FATAL;
608 }
609 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
610 return 0;
611}
612
613/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100614static 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 +0200615{
616 if (!*args[cur_arg + 1]) {
617 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
618 return ERR_ALERT | ERR_FATAL;
619 }
620
621 free(conf->ciphers);
622 conf->ciphers = strdup(args[cur_arg + 1]);
623 return 0;
624}
625static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
626{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100627 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200628}
629
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500630#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200631/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100632static 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 +0200633{
634 if (!*args[cur_arg + 1]) {
635 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
636 return ERR_ALERT | ERR_FATAL;
637 }
638
639 free(conf->ciphersuites);
640 conf->ciphersuites = strdup(args[cur_arg + 1]);
641 return 0;
642}
643static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
644{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100645 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200646}
647#endif
648
649/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
650static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
651{
652 char path[MAXPATHLEN];
653
654 if (!*args[cur_arg + 1]) {
655 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
656 return ERR_ALERT | ERR_FATAL;
657 }
658
659 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
660 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
661 memprintf(err, "'%s' : path too long", args[cur_arg]);
662 return ERR_ALERT | ERR_FATAL;
663 }
664 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
665 return ssl_sock_load_cert(path, conf, err);
666 }
667
668 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
669}
670
671/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
672static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
673{
674 int err_code;
675
676 if (!*args[cur_arg + 1]) {
677 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
678 return ERR_ALERT | ERR_FATAL;
679 }
680
681 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
682 if (err_code)
683 memprintf(err, "'%s' : %s", args[cur_arg], *err);
684
685 return err_code;
686}
687
688/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100689static 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 +0200690{
691#ifndef X509_V_FLAG_CRL_CHECK
692 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
693 return ERR_ALERT | ERR_FATAL;
694#else
695 if (!*args[cur_arg + 1]) {
696 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
697 return ERR_ALERT | ERR_FATAL;
698 }
699
700 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
701 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
702 else
703 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
704
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200705 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200706 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
707 return ERR_ALERT | ERR_FATAL;
708 }
709 return 0;
710#endif
711}
712static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
713{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100714 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200715}
716
717/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100718static 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 +0200719{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500720#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200721 if (!*args[cur_arg + 1]) {
722 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
723 return ERR_ALERT | ERR_FATAL;
724 }
725 conf->curves = strdup(args[cur_arg + 1]);
726 return 0;
727#else
728 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
729 return ERR_ALERT | ERR_FATAL;
730#endif
731}
732static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
733{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100734 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200735}
736
737/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100738static 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 +0200739{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500740#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200741 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
742 return ERR_ALERT | ERR_FATAL;
743#elif defined(OPENSSL_NO_ECDH)
744 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
745 return ERR_ALERT | ERR_FATAL;
746#else
747 if (!*args[cur_arg + 1]) {
748 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
749 return ERR_ALERT | ERR_FATAL;
750 }
751
752 conf->ecdhe = strdup(args[cur_arg + 1]);
753
754 return 0;
755#endif
756}
757static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
758{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100759 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200760}
761
762/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
763static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
764{
765 int code;
766 char *p = args[cur_arg + 1];
767 unsigned long long *ignerr = &conf->crt_ignerr;
768
769 if (!*p) {
770 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
771 return ERR_ALERT | ERR_FATAL;
772 }
773
774 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
775 ignerr = &conf->ca_ignerr;
776
777 if (strcmp(p, "all") == 0) {
778 *ignerr = ~0ULL;
779 return 0;
780 }
781
782 while (p) {
783 code = atoi(p);
784 if ((code <= 0) || (code > 63)) {
785 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
786 args[cur_arg], code, args[cur_arg + 1]);
787 return ERR_ALERT | ERR_FATAL;
788 }
789 *ignerr |= 1ULL << code;
790 p = strchr(p, ',');
791 if (p)
792 p++;
793 }
794
795 return 0;
796}
797
798/* parse tls_method_options "no-xxx" and "force-xxx" */
799static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
800{
801 uint16_t v;
802 char *p;
803 p = strchr(arg, '-');
804 if (!p)
805 goto fail;
806 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100807 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200808 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100809 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200810 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100811 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200812 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100813 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200814 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100815 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200816 v = CONF_TLSV13;
817 else
818 goto fail;
819 if (!strncmp(arg, "no-", 3))
820 methods->flags |= methodVersions[v].flag;
821 else if (!strncmp(arg, "force-", 6))
822 methods->min = methods->max = v;
823 else
824 goto fail;
825 return 0;
826 fail:
827 memprintf(err, "'%s' : option not implemented", arg);
828 return ERR_ALERT | ERR_FATAL;
829}
830
831static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
832{
833 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
834}
835
836static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
837{
838 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
839}
840
841/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
842static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
843{
844 uint16_t i, v = 0;
845 char *argv = args[cur_arg + 1];
846 if (!*argv) {
847 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
848 return ERR_ALERT | ERR_FATAL;
849 }
850 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100851 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200852 v = i;
853 if (!v) {
854 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
855 return ERR_ALERT | ERR_FATAL;
856 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100857 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200858 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100859 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200860 methods->max = v;
861 else {
862 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
863 return ERR_ALERT | ERR_FATAL;
864 }
865 return 0;
866}
867
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100868static 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 +0200869{
William Lallemand8177ad92020-05-20 16:49:02 +0200870 int ret;
871
William Lallemanddad31052020-05-14 17:47:32 +0200872#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
873 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
874#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200875 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
876 if (ret != ERR_NONE)
877 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200878
William Lallemand8177ad92020-05-20 16:49:02 +0200879 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
880 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
881
882 return ret;
883}
William Lallemanddad31052020-05-14 17:47:32 +0200884static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
885{
886 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
887}
888
889static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
890{
891 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
892}
893
894/* parse the "no-tls-tickets" bind keyword */
895static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
896{
897 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
898 return 0;
899}
900
901/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100902static 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 +0200903{
904 conf->early_data = 1;
905 return 0;
906}
907
908static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
909{
910 conf->ssl_conf.early_data = 1;
911 return 0;
912}
913
914/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100915static 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 +0200916{
917#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
918 char *p1, *p2;
919
920 if (!*args[cur_arg + 1]) {
921 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
922 return ERR_ALERT | ERR_FATAL;
923 }
924
925 free(conf->npn_str);
926
927 /* the NPN string is built as a suite of (<len> <name>)*,
928 * so we reuse each comma to store the next <len> and need
929 * one more for the end of the string.
930 */
931 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
932 conf->npn_str = calloc(1, conf->npn_len + 1);
933 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
934
935 /* replace commas with the name length */
936 p1 = conf->npn_str;
937 p2 = p1 + 1;
938 while (1) {
939 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
940 if (!p2)
941 p2 = p1 + 1 + strlen(p1 + 1);
942
943 if (p2 - (p1 + 1) > 255) {
944 *p2 = '\0';
945 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
946 return ERR_ALERT | ERR_FATAL;
947 }
948
949 *p1 = p2 - (p1 + 1);
950 p1 = p2;
951
952 if (!*p2)
953 break;
954
955 *(p2++) = '\0';
956 }
957 return 0;
958#else
959 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
960 return ERR_ALERT | ERR_FATAL;
961#endif
962}
963
964static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
965{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100966 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200967}
968
969
970/* Parses a alpn string and converts it to the right format for the SSL api */
971int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
972{
973 char *p1, *p2, *alpn = NULL;
974 int len, ret = 0;
975
976 *alpn_str = NULL;
977 *alpn_len = 0;
978
979 if (!*arg) {
980 memprintf(err, "missing the comma-delimited ALPN protocol suite");
981 goto error;
982 }
983
984 /* the ALPN string is built as a suite of (<len> <name>)*,
985 * so we reuse each comma to store the next <len> and need
986 * one more for the end of the string.
987 */
988 len = strlen(arg) + 1;
989 alpn = calloc(1, len+1);
990 if (!alpn) {
991 memprintf(err, "'%s' : out of memory", arg);
992 goto error;
993 }
994 memcpy(alpn+1, arg, len);
995
996 /* replace commas with the name length */
997 p1 = alpn;
998 p2 = p1 + 1;
999 while (1) {
1000 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1001 if (!p2)
1002 p2 = p1 + 1 + strlen(p1 + 1);
1003
1004 if (p2 - (p1 + 1) > 255) {
1005 *p2 = '\0';
1006 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1007 goto error;
1008 }
1009
1010 *p1 = p2 - (p1 + 1);
1011 p1 = p2;
1012
1013 if (!*p2)
1014 break;
1015
1016 *(p2++) = '\0';
1017 }
1018
1019 *alpn_str = alpn;
1020 *alpn_len = len;
1021
1022 out:
1023 return ret;
1024
1025 error:
1026 free(alpn);
1027 ret = ERR_ALERT | ERR_FATAL;
1028 goto out;
1029}
1030
1031/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001032static 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 +02001033{
1034#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1035 int ret;
1036
1037 free(conf->alpn_str);
1038
1039 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1040 if (ret)
1041 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1042 return ret;
1043#else
1044 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1045 return ERR_ALERT | ERR_FATAL;
1046#endif
1047}
1048
1049static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1050{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001051 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001052}
1053
1054/* parse the "ssl" bind keyword */
1055static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1056{
Frédéric Lécaillee50afbd2020-11-23 11:33:12 +01001057 /* Do not change the xprt for QUIC. */
1058 if (conf->xprt != xprt_get(XPRT_QUIC))
1059 conf->xprt = &ssl_sock;
William Lallemanddad31052020-05-14 17:47:32 +02001060 conf->is_ssl = 1;
1061
1062 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1063 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001064#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001065 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1066 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1067#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001068#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001069 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1070 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1071#endif
1072 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1073 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1074 if (!conf->ssl_conf.ssl_methods.min)
1075 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1076 if (!conf->ssl_conf.ssl_methods.max)
1077 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1078
1079 return 0;
1080}
1081
1082/* parse the "prefer-client-ciphers" bind keyword */
1083static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1084{
1085 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1086 return 0;
1087}
1088
1089/* parse the "generate-certificates" bind keyword */
1090static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1091{
1092#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1093 conf->generate_certs = 1;
1094#else
1095 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1096 err && *err ? *err : "");
1097#endif
1098 return 0;
1099}
1100
1101/* parse the "strict-sni" bind keyword */
1102static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1103{
1104 conf->strict_sni = 1;
1105 return 0;
1106}
1107
1108/* parse the "tls-ticket-keys" bind keyword */
1109static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1110{
1111#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1112 FILE *f = NULL;
1113 int i = 0;
1114 char thisline[LINESIZE];
1115 struct tls_keys_ref *keys_ref = NULL;
1116
1117 if (!*args[cur_arg + 1]) {
1118 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1119 goto fail;
1120 }
1121
1122 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1123 if (keys_ref) {
1124 keys_ref->refcount++;
1125 conf->keys_ref = keys_ref;
1126 return 0;
1127 }
1128
1129 keys_ref = calloc(1, sizeof(*keys_ref));
1130 if (!keys_ref) {
1131 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1132 goto fail;
1133 }
1134
1135 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1136 if (!keys_ref->tlskeys) {
1137 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1138 goto fail;
1139 }
1140
1141 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1142 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1143 goto fail;
1144 }
1145
1146 keys_ref->filename = strdup(args[cur_arg + 1]);
1147 if (!keys_ref->filename) {
1148 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1149 goto fail;
1150 }
1151
1152 keys_ref->key_size_bits = 0;
1153 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1154 int len = strlen(thisline);
1155 int dec_size;
1156
1157 /* Strip newline characters from the end */
1158 if(thisline[len - 1] == '\n')
1159 thisline[--len] = 0;
1160
1161 if(thisline[len - 1] == '\r')
1162 thisline[--len] = 0;
1163
1164 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1165 if (dec_size < 0) {
1166 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1167 goto fail;
1168 }
1169 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1170 keys_ref->key_size_bits = 128;
1171 }
1172 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1173 keys_ref->key_size_bits = 256;
1174 }
1175 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1176 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1177 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1178 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1179 goto fail;
1180 }
1181 i++;
1182 }
1183
1184 if (i < TLS_TICKETS_NO) {
1185 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1186 goto fail;
1187 }
1188
1189 fclose(f);
1190
1191 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1192 i -= 2;
1193 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1194 keys_ref->unique_id = -1;
1195 keys_ref->refcount = 1;
1196 HA_RWLOCK_INIT(&keys_ref->lock);
1197 conf->keys_ref = keys_ref;
1198
Willy Tarreau2b718102021-04-21 07:32:39 +02001199 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001200
1201 return 0;
1202
1203 fail:
1204 if (f)
1205 fclose(f);
1206 if (keys_ref) {
1207 free(keys_ref->filename);
1208 free(keys_ref->tlskeys);
1209 free(keys_ref);
1210 }
1211 return ERR_ALERT | ERR_FATAL;
1212
1213#else
1214 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1215 return ERR_ALERT | ERR_FATAL;
1216#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1217}
1218
1219/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001220static 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 +02001221{
1222 if (!*args[cur_arg + 1]) {
1223 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1224 return ERR_ALERT | ERR_FATAL;
1225 }
1226
1227 if (strcmp(args[cur_arg + 1], "none") == 0)
1228 conf->verify = SSL_SOCK_VERIFY_NONE;
1229 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1230 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1231 else if (strcmp(args[cur_arg + 1], "required") == 0)
1232 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1233 else {
1234 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1235 args[cur_arg], args[cur_arg + 1]);
1236 return ERR_ALERT | ERR_FATAL;
1237 }
1238
1239 return 0;
1240}
1241static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1242{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001243 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001244}
1245
1246/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001247static 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 +02001248{
1249 conf->no_ca_names = 1;
1250 return 0;
1251}
1252static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1253{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001254 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001255}
1256
1257/***************************** "server" keywords Parsing ********************************************/
1258
1259/* parse the "npn" bind keyword */
1260static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1261{
1262#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1263 char *p1, *p2;
1264
1265 if (!*args[*cur_arg + 1]) {
1266 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1267 return ERR_ALERT | ERR_FATAL;
1268 }
1269
1270 free(newsrv->ssl_ctx.npn_str);
1271
1272 /* the NPN string is built as a suite of (<len> <name>)*,
1273 * so we reuse each comma to store the next <len> and need
1274 * one more for the end of the string.
1275 */
1276 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1277 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001278 if (!newsrv->ssl_ctx.npn_str) {
1279 memprintf(err, "out of memory");
1280 return ERR_ALERT | ERR_FATAL;
1281 }
1282
William Lallemanddad31052020-05-14 17:47:32 +02001283 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1284 newsrv->ssl_ctx.npn_len);
1285
1286 /* replace commas with the name length */
1287 p1 = newsrv->ssl_ctx.npn_str;
1288 p2 = p1 + 1;
1289 while (1) {
1290 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1291 newsrv->ssl_ctx.npn_len - (p1 + 1));
1292 if (!p2)
1293 p2 = p1 + 1 + strlen(p1 + 1);
1294
1295 if (p2 - (p1 + 1) > 255) {
1296 *p2 = '\0';
1297 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1298 return ERR_ALERT | ERR_FATAL;
1299 }
1300
1301 *p1 = p2 - (p1 + 1);
1302 p1 = p2;
1303
1304 if (!*p2)
1305 break;
1306
1307 *(p2++) = '\0';
1308 }
1309 return 0;
1310#else
1311 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1312 return ERR_ALERT | ERR_FATAL;
1313#endif
1314}
1315
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001316#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1317static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1318{
1319 free(*out_alpn_str);
1320 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1321}
1322#endif
1323
1324/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001325static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1326{
1327#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001328 int ret = parse_alpn(args[*cur_arg + 1],
1329 &newsrv->ssl_ctx.alpn_str,
1330 &newsrv->ssl_ctx.alpn_len, err);
1331 if (ret)
1332 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1333 return ret;
1334#else
1335 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1336 return ERR_ALERT | ERR_FATAL;
1337#endif
1338}
William Lallemanddad31052020-05-14 17:47:32 +02001339
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001340/* parse the "check-alpn" server keyword */
1341static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1342{
1343#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1344 int ret = parse_alpn(args[*cur_arg + 1],
1345 &newsrv->check.alpn_str,
1346 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001347 if (ret)
1348 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1349 return ret;
1350#else
1351 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1352 return ERR_ALERT | ERR_FATAL;
1353#endif
1354}
1355
1356/* parse the "ca-file" server keyword */
1357static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1358{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001359 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1360
William Lallemanddad31052020-05-14 17:47:32 +02001361 if (!*args[*cur_arg + 1]) {
1362 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1363 return ERR_ALERT | ERR_FATAL;
1364 }
1365
1366 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1367 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1368 else
1369 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1370
Amaury Denoyelle48255022021-05-19 09:46:59 +02001371 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001372 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1373 return ERR_ALERT | ERR_FATAL;
1374 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001375
William Lallemanddad31052020-05-14 17:47:32 +02001376 return 0;
1377}
1378
1379/* parse the "check-sni" server keyword */
1380static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1381{
1382 if (!*args[*cur_arg + 1]) {
1383 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1384 return ERR_ALERT | ERR_FATAL;
1385 }
1386
1387 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1388 if (!newsrv->check.sni) {
1389 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1390 return ERR_ALERT | ERR_FATAL;
1391 }
1392 return 0;
1393
1394}
1395
William Dauchyfc52f522020-11-14 19:25:32 +01001396/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001397static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001398{
William Dauchyfc52f522020-11-14 19:25:32 +01001399 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1400 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001401#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001402 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001403 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001404 if (!s->ssl_ctx.ciphersuites)
1405 return 1;
1406 }
William Lallemanddad31052020-05-14 17:47:32 +02001407#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001408 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1409 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1410
1411 if (!s->ssl_ctx.methods.min)
1412 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001413
William Dauchyfc52f522020-11-14 19:25:32 +01001414 if (!s->ssl_ctx.methods.max)
1415 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001416
1417 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001418}
1419
1420/* parse the "check-ssl" server keyword */
1421static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1422{
1423 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001424 if (ssl_sock_init_srv(newsrv)) {
1425 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1426 return ERR_ALERT | ERR_FATAL;
1427 }
1428
William Lallemanddad31052020-05-14 17:47:32 +02001429 return 0;
1430}
1431
1432/* parse the "ciphers" server keyword */
1433static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1434{
1435 if (!*args[*cur_arg + 1]) {
1436 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1437 return ERR_ALERT | ERR_FATAL;
1438 }
1439
1440 free(newsrv->ssl_ctx.ciphers);
1441 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001442
1443 if (!newsrv->ssl_ctx.ciphers) {
1444 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1445 return ERR_ALERT | ERR_FATAL;
1446 }
1447
William Lallemanddad31052020-05-14 17:47:32 +02001448 return 0;
1449}
1450
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001451#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001452/* parse the "ciphersuites" server keyword */
1453static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1454{
1455 if (!*args[*cur_arg + 1]) {
1456 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1457 return ERR_ALERT | ERR_FATAL;
1458 }
1459
1460 free(newsrv->ssl_ctx.ciphersuites);
1461 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001462
1463 if (!newsrv->ssl_ctx.ciphersuites) {
1464 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1465 return ERR_ALERT | ERR_FATAL;
1466 }
1467
William Lallemanddad31052020-05-14 17:47:32 +02001468 return 0;
1469}
1470#endif
1471
1472/* parse the "crl-file" server keyword */
1473static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1474{
1475#ifndef X509_V_FLAG_CRL_CHECK
1476 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1477 return ERR_ALERT | ERR_FATAL;
1478#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001479 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1480
William Lallemanddad31052020-05-14 17:47:32 +02001481 if (!*args[*cur_arg + 1]) {
1482 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1483 return ERR_ALERT | ERR_FATAL;
1484 }
1485
1486 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1487 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1488 else
1489 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1490
Amaury Denoyellefde82602021-06-14 10:10:32 +02001491 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001492 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1493 return ERR_ALERT | ERR_FATAL;
1494 }
1495 return 0;
1496#endif
1497}
1498
1499/* parse the "crt" server keyword */
1500static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1501{
Amaury Denoyelle93be21e2021-05-21 16:22:53 +02001502 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001503 int retval = -1;
1504 char *path = NULL;
1505
William Lallemanddad31052020-05-14 17:47:32 +02001506 if (!*args[*cur_arg + 1]) {
1507 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1508 return ERR_ALERT | ERR_FATAL;
1509 }
1510
1511 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001512 memprintf(&path, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001513 else
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001514 memprintf(&path, "%s", args[*cur_arg + 1]);
1515
1516 if (path) {
Amaury Denoyelle93be21e2021-05-21 16:22:53 +02001517 retval = ssl_sock_load_srv_cert(path, newsrv, create_if_none, err);
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001518 free(path);
1519 }
William Lallemanddad31052020-05-14 17:47:32 +02001520
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001521 return retval;
William Lallemanddad31052020-05-14 17:47:32 +02001522}
1523
1524/* parse the "no-check-ssl" server keyword */
1525static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1526{
1527 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001528 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001529 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1530 return 0;
1531}
1532
1533/* parse the "no-send-proxy-v2-ssl" server keyword */
1534static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1535{
1536 newsrv->pp_opts &= ~SRV_PP_V2;
1537 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1538 return 0;
1539}
1540
1541/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1542static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1543{
1544 newsrv->pp_opts &= ~SRV_PP_V2;
1545 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1546 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1547 return 0;
1548}
1549
1550/* parse the "no-ssl" server keyword */
1551static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1552{
William Dauchyf6370442020-11-14 19:25:33 +01001553 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001554 if (newsrv->use_ssl == 1) {
1555 if (ssl_sock_init_srv(newsrv)) {
1556 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1557 return ERR_ALERT | ERR_FATAL;
1558 }
1559 }
William Dauchyf6370442020-11-14 19:25:33 +01001560 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001561 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001562 }
William Lallemanddad31052020-05-14 17:47:32 +02001563 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001564 return 0;
1565}
1566
1567/* parse the "allow-0rtt" server keyword */
1568static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1569{
1570 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1571 return 0;
1572}
1573
1574/* parse the "no-ssl-reuse" server keyword */
1575static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1576{
1577 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1578 return 0;
1579}
1580
1581/* parse the "no-tls-tickets" server keyword */
1582static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1583{
1584 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1585 return 0;
1586}
1587/* parse the "send-proxy-v2-ssl" server keyword */
1588static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1589{
1590 newsrv->pp_opts |= SRV_PP_V2;
1591 newsrv->pp_opts |= SRV_PP_V2_SSL;
1592 return 0;
1593}
1594
1595/* parse the "send-proxy-v2-ssl-cn" server keyword */
1596static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1597{
1598 newsrv->pp_opts |= SRV_PP_V2;
1599 newsrv->pp_opts |= SRV_PP_V2_SSL;
1600 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1601 return 0;
1602}
1603
1604/* parse the "sni" server keyword */
1605static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1606{
1607#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1608 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1609 return ERR_ALERT | ERR_FATAL;
1610#else
1611 char *arg;
1612
1613 arg = args[*cur_arg + 1];
1614 if (!*arg) {
1615 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1616 return ERR_ALERT | ERR_FATAL;
1617 }
1618
1619 free(newsrv->sni_expr);
1620 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001621 if (!newsrv->sni_expr) {
1622 memprintf(err, "out of memory");
1623 return ERR_ALERT | ERR_FATAL;
1624 }
William Lallemanddad31052020-05-14 17:47:32 +02001625
1626 return 0;
1627#endif
1628}
1629
1630/* parse the "ssl" server keyword */
1631static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1632{
1633 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001634 if (ssl_sock_init_srv(newsrv)) {
1635 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1636 return ERR_ALERT | ERR_FATAL;
1637 }
1638
William Lallemanddad31052020-05-14 17:47:32 +02001639 return 0;
1640}
1641
1642/* parse the "ssl-reuse" server keyword */
1643static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1644{
1645 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1646 return 0;
1647}
1648
1649/* parse the "tls-tickets" server keyword */
1650static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1651{
1652 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1653 return 0;
1654}
1655
1656/* parse the "verify" server keyword */
1657static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1658{
1659 if (!*args[*cur_arg + 1]) {
1660 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1661 return ERR_ALERT | ERR_FATAL;
1662 }
1663
1664 if (strcmp(args[*cur_arg + 1], "none") == 0)
1665 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1666 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1667 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1668 else {
1669 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1670 args[*cur_arg], args[*cur_arg + 1]);
1671 return ERR_ALERT | ERR_FATAL;
1672 }
1673
1674 return 0;
1675}
1676
1677/* parse the "verifyhost" server keyword */
1678static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1679{
1680 if (!*args[*cur_arg + 1]) {
1681 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1682 return ERR_ALERT | ERR_FATAL;
1683 }
1684
1685 free(newsrv->ssl_ctx.verify_host);
1686 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1687
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001688 if (!newsrv->ssl_ctx.verify_host) {
1689 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1690 return ERR_ALERT | ERR_FATAL;
1691 }
1692
William Lallemanddad31052020-05-14 17:47:32 +02001693 return 0;
1694}
1695
1696/* parse the "ssl-default-bind-options" keyword in global section */
1697static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001698 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001699 char **err) {
1700 int i = 1;
1701
1702 if (*(args[i]) == 0) {
1703 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1704 return -1;
1705 }
1706 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001707 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001708 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001709 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001710 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001711 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001712 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1713 i++;
1714 else {
1715 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1716 return -1;
1717 }
1718 }
1719 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1720 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1721 return -1;
1722 }
1723 i++;
1724 }
1725 return 0;
1726}
1727
1728/* parse the "ssl-default-server-options" keyword in global section */
1729static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001730 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001731 char **err) {
1732 int i = 1;
1733
1734 if (*(args[i]) == 0) {
1735 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1736 return -1;
1737 }
1738 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001739 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001740 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001741 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001742 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1743 i++;
1744 else {
1745 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1746 return -1;
1747 }
1748 }
1749 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1750 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1751 return -1;
1752 }
1753 i++;
1754 }
1755 return 0;
1756}
1757
1758/* parse the "ca-base" / "crt-base" keywords in global section.
1759 * Returns <0 on alert, >0 on warning, 0 on success.
1760 */
1761static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001762 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001763 char **err)
1764{
1765 char **target;
1766
1767 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1768
1769 if (too_many_args(1, args, err, NULL))
1770 return -1;
1771
1772 if (*target) {
1773 memprintf(err, "'%s' already specified.", args[0]);
1774 return -1;
1775 }
1776
1777 if (*(args[1]) == 0) {
1778 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1779 return -1;
1780 }
1781 *target = strdup(args[1]);
1782 return 0;
1783}
1784
1785/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1786static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001787 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001788 char **err)
1789{
William Lallemand9a1d8392020-08-10 17:28:23 +02001790#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001791 global_ssl.skip_self_issued_ca = 1;
1792 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001793#else
1794 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1795 return -1;
1796#endif
William Lallemanddad31052020-05-14 17:47:32 +02001797}
1798
1799
1800
1801
1802
1803/* Note: must not be declared <const> as its list will be overwritten.
1804 * Please take care of keeping this list alphabetically sorted, doing so helps
1805 * all code contributors.
1806 * Optional keywords are also declared with a NULL ->parse() function so that
1807 * the config parser can report an appropriate error when a known keyword was
1808 * not enabled.
1809 */
1810
1811/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1812 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1813struct ssl_bind_kw ssl_bind_kws[] = {
1814 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1815 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1816 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1817 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1818 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001819#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001820 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1821#endif
1822 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1823 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1824 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1825 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1826 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1827 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1828 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1829 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1830 { NULL, NULL, 0 },
1831};
1832
1833/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1834
1835static struct bind_kw_list bind_kws = { "SSL", { }, {
1836 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1837 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1838 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1839 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1840 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1841 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1842 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1843 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001844#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001845 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1846#endif
1847 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1848 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1849 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1850 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1851 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1852 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1853 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1854 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1855 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1856 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1857 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1858 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1859 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1860 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1861 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1862 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1863 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1864 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1865 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1866 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1867 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1868 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1869 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1870 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1871 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1872 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1873 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1874 { NULL, NULL, 0 },
1875}};
1876
1877INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1878
1879/* Note: must not be declared <const> as its list will be overwritten.
1880 * Please take care of keeping this list alphabetically sorted, doing so helps
1881 * all code contributors.
1882 * Optional keywords are also declared with a NULL ->parse() function so that
1883 * the config parser can report an appropriate error when a known keyword was
1884 * not enabled.
1885 */
1886static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001887 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1888 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001889 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001890 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1891 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1892 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001893 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001894#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001895 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001896#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001897 { "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 +02001898 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001899 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1900 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1901 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1902 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1903 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001904 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1905 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1906 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1907 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001908 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1909 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1910 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1911 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1912 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1913 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1914 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1915 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1916 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1917 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1918 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001919 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001920 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1921 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001922 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001923 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1924 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
1925 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001926 { NULL, NULL, 0, 0 },
1927}};
1928
1929INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1930
1931static struct cfg_kw_list cfg_kws = {ILH, {
1932 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1933 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1934 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1935 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1936 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1937 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1938#ifndef OPENSSL_NO_DH
1939 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1940#endif
1941 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
1942#ifndef OPENSSL_NO_ENGINE
1943 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1944#endif
1945 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1946 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1947#ifndef OPENSSL_NO_DH
1948 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1949#endif
1950 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
1951 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1952 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
1953 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02001954 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
1955 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02001956 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02001957 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1958 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001959#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001960 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
1961#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001962#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001963 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
1964 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
1965#endif
1966 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02001967 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02001968 { 0, NULL, NULL },
1969}};
1970
1971INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);