blob: 326cc210ccabddad6821096ec245eec53da49d65 [file] [log] [blame]
William Lallemanddad31052020-05-14 17:47:32 +02001/*
2 *
3 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
4 * Copyright (C) 2020 HAProxy Technologies, William Lallemand <wlallemand@haproxy.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 *
12 * Configuration parsing for SSL.
13 * This file is split in 3 parts:
14 * - global section parsing
15 * - bind keyword parsing
16 * - server keyword parsing
17 *
18 * Please insert the new keywords at the right place
19 */
20
21#define _GNU_SOURCE
22#include <ctype.h>
23#include <dirent.h>
24#include <errno.h>
William Lallemanddad31052020-05-14 17:47:32 +020025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include <sys/stat.h>
31#include <sys/types.h>
32
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020033#include <haproxy/api.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020034#include <haproxy/base64.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020035#include <haproxy/cfgparse.h>
Willy Tarreau0d1dd0e2021-10-06 19:00:49 +020036#include <haproxy/errors.h>
Willy Tarreau213e9902020-06-04 14:58:24 +020037#include <haproxy/listener.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +020038#include <haproxy/openssl-compat.h>
Willy Tarreau209108d2020-06-04 20:30:20 +020039#include <haproxy/ssl_sock.h>
Willy Tarreaucc81eca2021-05-08 12:54:42 +020040#include <haproxy/tools.h>
Remi Tricot-Le Bretonaf8820a2021-04-13 10:10:37 +020041#include <haproxy/ssl_ckch.h>
William Lallemanddad31052020-05-14 17:47:32 +020042
43
44/****************** Global Section Parsing ********************************************/
45
46static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +010047 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +020048 char **err)
49{
50 char *path;
51 struct dirent **de_list;
52 int i, n;
53 struct stat buf;
54 char *end;
55 char fp[MAXPATHLEN+1];
56
57 if (too_many_args(1, args, err, NULL))
58 return -1;
59
60 path = args[1];
61 if (*path == 0 || stat(path, &buf)) {
62 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
63 err && *err ? *err : "", args[0]);
64 return -1;
65 }
66 if (S_ISDIR(buf.st_mode) == 0) {
67 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
68 err && *err ? *err : "", args[0], path);
69 return -1;
70 }
71
72 /* strip trailing slashes, including first one */
73 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
74 *end = 0;
75 /* path already parsed? */
76 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
77 return 0;
78 /* overwrite old issuers_chain_path */
79 free(global_ssl.issuers_chain_path);
80 global_ssl.issuers_chain_path = strdup(path);
81 ssl_free_global_issuers();
82
83 n = scandir(path, &de_list, 0, alphasort);
84 if (n < 0) {
85 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
86 err && *err ? *err : "", args[0], path, strerror(errno));
87 return -1;
88 }
89 for (i = 0; i < n; i++) {
90 struct dirent *de = de_list[i];
91 BIO *in = NULL;
92 char *warn = NULL;
93
94 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
95 free(de);
96 if (stat(fp, &buf) != 0) {
97 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
98 goto next;
99 }
100 if (!S_ISREG(buf.st_mode))
101 goto next;
102
103 in = BIO_new(BIO_s_file());
104 if (in == NULL)
105 goto next;
106 if (BIO_read_filename(in, fp) <= 0)
107 goto next;
108 ssl_load_global_issuer_from_BIO(in, fp, &warn);
109 if (warn) {
110 ha_warning("%s", warn);
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100111 ha_free(&warn);
William Lallemanddad31052020-05-14 17:47:32 +0200112 }
113 next:
114 if (in)
115 BIO_free(in);
116 }
117 free(de_list);
118
119 return 0;
120}
121
William Lallemanddad31052020-05-14 17:47:32 +0200122/* parse the "ssl-mode-async" keyword in global section.
123 * Returns <0 on alert, >0 on warning, 0 on success.
124 */
125static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100126 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200127 char **err)
128{
Ilya Shipitsinbdec3ba2020-11-14 01:56:34 +0500129#ifdef SSL_MODE_ASYNC
William Lallemanddad31052020-05-14 17:47:32 +0200130 global_ssl.async = 1;
131 global.ssl_used_async_engines = nb_engines;
132 return 0;
133#else
134 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
135 return -1;
136#endif
137}
138
William Lallemandd7bfbe22022-04-11 18:41:24 +0200139#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +0200140/* parse the "ssl-engine" keyword in global section.
141 * Returns <0 on alert, >0 on warning, 0 on success.
142 */
143static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100144 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200145 char **err)
146{
147 char *algo;
148 int ret = -1;
149
150 if (*(args[1]) == 0) {
151 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
152 return ret;
153 }
154
155 if (*(args[2]) == 0) {
156 /* if no list of algorithms is given, it defaults to ALL */
157 algo = strdup("ALL");
158 goto add_engine;
159 }
160
161 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
162 if (strcmp(args[2], "algo") != 0) {
163 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
164 return ret;
165 }
166
167 if (*(args[3]) == 0) {
168 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
169 return ret;
170 }
171 algo = strdup(args[3]);
172
173add_engine:
174 if (ssl_init_single_engine(args[1], algo)==0) {
175 openssl_engines_initialized++;
176 ret = 0;
177 }
178 free(algo);
179 return ret;
180}
181#endif
182
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200183#ifdef HAVE_SSL_PROVIDERS
184/* parse the "ssl-propquery" keyword in global section.
185 * Returns <0 on alert, >0 on warning, 0 on success.
186 */
187static int ssl_parse_global_ssl_propquery(char **args, int section_type, struct proxy *curpx,
188 const struct proxy *defpx, const char *file, int line,
189 char **err)
190{
191 int ret = -1;
192
193 if (*(args[1]) == 0) {
194 memprintf(err, "global statement '%s' expects a property string as an argument.", args[0]);
195 return ret;
196 }
197
198 if (EVP_set_default_properties(NULL, args[1]))
199 ret = 0;
200
201 return ret;
202}
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +0200203
204/* parse the "ssl-provider" keyword in global section.
205 * Returns <0 on alert, >0 on warning, 0 on success.
206 */
207static int ssl_parse_global_ssl_provider(char **args, int section_type, struct proxy *curpx,
208 const struct proxy *defpx, const char *file, int line,
209 char **err)
210{
211 int ret = -1;
212
213 if (*(args[1]) == 0) {
214 memprintf(err, "global statement '%s' expects a valid engine provider name as an argument.", args[0]);
215 return ret;
216 }
217
218 if (ssl_init_provider(args[1]) == 0)
219 ret = 0;
220
221 return ret;
222}
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +0200223#endif
224
William Lallemanddad31052020-05-14 17:47:32 +0200225/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
226 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
227 */
228static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100229 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200230 char **err)
231{
232 char **target;
233
234 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
235
236 if (too_many_args(1, args, err, NULL))
237 return -1;
238
239 if (*(args[1]) == 0) {
240 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
241 return -1;
242 }
243
244 free(*target);
245 *target = strdup(args[1]);
246 return 0;
247}
248
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500249#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200250/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
251 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
252 */
253static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100254 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200255 char **err)
256{
257 char **target;
258
259 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
260
261 if (too_many_args(1, args, err, NULL))
262 return -1;
263
264 if (*(args[1]) == 0) {
265 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
266 return -1;
267 }
268
269 free(*target);
270 *target = strdup(args[1]);
271 return 0;
272}
273#endif
274
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500275#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200276/*
277 * parse the "ssl-default-bind-curves" keyword in a global section.
278 * Returns <0 on alert, >0 on warning, 0 on success.
279 */
280static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100281 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200282 char **err)
283{
284 char **target;
285 target = &global_ssl.listen_default_curves;
286
287 if (too_many_args(1, args, err, NULL))
288 return -1;
289
290 if (*(args[1]) == 0) {
291 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
292 return -1;
293 }
294
295 free(*target);
296 *target = strdup(args[1]);
297 return 0;
298}
299#endif
300/* parse various global tune.ssl settings consisting in positive integers.
301 * Returns <0 on alert, >0 on warning, 0 on success.
302 */
303static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100304 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200305 char **err)
306{
307 int *target;
308
309 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
310 target = &global.tune.sslcachesize;
311 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
312 target = (int *)&global_ssl.max_record;
Thomas Prückl10243932022-04-27 13:04:54 +0200313 else if (strcmp(args[0], "tune.ssl.hard-maxrecord") == 0)
314 target = (int *)&global_ssl.hard_max_record;
William Lallemanddad31052020-05-14 17:47:32 +0200315 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
316 target = &global_ssl.ctx_cache;
317 else if (strcmp(args[0], "maxsslconn") == 0)
318 target = &global.maxsslconn;
Marcin Deranek310a2602021-07-13 19:04:24 +0200319 else if (strcmp(args[0], "tune.ssl.capture-buffer-size") == 0)
320 target = &global_ssl.capture_buffer_size;
321 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0) {
322 target = &global_ssl.capture_buffer_size;
323 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",
324 file, line, args[0]);
325 }
William Lallemanddad31052020-05-14 17:47:32 +0200326 else {
327 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
328 return -1;
329 }
330
331 if (too_many_args(1, args, err, NULL))
332 return -1;
333
334 if (*(args[1]) == 0) {
335 memprintf(err, "'%s' expects an integer argument.", args[0]);
336 return -1;
337 }
338
339 *target = atoi(args[1]);
340 if (*target < 0) {
341 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
342 return -1;
343 }
344 return 0;
345}
346
Marcin Deranek310a2602021-07-13 19:04:24 +0200347static int ssl_parse_global_capture_buffer(char **args, int section_type, struct proxy *curpx,
348 const struct proxy *defpx, const char *file, int line,
349 char **err)
William Lallemanddad31052020-05-14 17:47:32 +0200350{
351 int ret;
352
353 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
354 if (ret != 0)
355 return ret;
356
357 if (pool_head_ssl_capture) {
358 memprintf(err, "'%s' is already configured.", args[0]);
359 return -1;
360 }
361
Marcin Deranek310a2602021-07-13 19:04:24 +0200362 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 +0200363 if (!pool_head_ssl_capture) {
364 memprintf(err, "Out of memory error.");
365 return -1;
366 }
367 return 0;
368}
369
William Lallemand7d42ef52020-07-06 11:41:30 +0200370/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200371#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200372static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100373 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200374 char **err)
375{
376
377 if (too_many_args(1, args, err, NULL))
378 return -1;
379
380 if (strcmp(args[1], "on") == 0)
381 global_ssl.keylog = 1;
382 else if (strcmp(args[1], "off") == 0)
383 global_ssl.keylog = 0;
384 else {
385 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
386 return -1;
387 }
388
389 if (pool_head_ssl_keylog) /* already configured */
390 return 0;
391
392 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
393 if (!pool_head_ssl_keylog) {
394 memprintf(err, "Out of memory error.");
395 return -1;
396 }
397
398 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
399 if (!pool_head_ssl_keylog_str) {
400 memprintf(err, "Out of memory error.");
401 return -1;
402 }
403
404 return 0;
405}
William Lallemand722180a2021-06-09 16:46:12 +0200406#else
407static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
408 const struct proxy *defpx, const char *file, int line,
409 char **err)
410{
411 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
412 return -1;
413}
William Lallemand7d42ef52020-07-06 11:41:30 +0200414#endif
415
William Lallemanddad31052020-05-14 17:47:32 +0200416/* parse "ssl.force-private-cache".
417 * Returns <0 on alert, >0 on warning, 0 on success.
418 */
419static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100420 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200421 char **err)
422{
423 if (too_many_args(0, args, err, NULL))
424 return -1;
425
426 global_ssl.private_cache = 1;
427 return 0;
428}
429
430/* parse "ssl.lifetime".
431 * Returns <0 on alert, >0 on warning, 0 on success.
432 */
433static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100434 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200435 char **err)
436{
437 const char *res;
438
439 if (too_many_args(1, args, err, NULL))
440 return -1;
441
442 if (*(args[1]) == 0) {
443 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
444 return -1;
445 }
446
447 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
448 if (res == PARSE_TIME_OVER) {
449 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
450 args[1], args[0]);
451 return -1;
452 }
453 else if (res == PARSE_TIME_UNDER) {
454 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
455 args[1], args[0]);
456 return -1;
457 }
458 else if (res) {
459 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
460 return -1;
461 }
462 return 0;
463}
464
465#ifndef OPENSSL_NO_DH
466/* parse "ssl-dh-param-file".
467 * Returns <0 on alert, >0 on warning, 0 on success.
468 */
469static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100470 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200471 char **err)
472{
473 if (too_many_args(1, args, err, NULL))
474 return -1;
475
476 if (*(args[1]) == 0) {
477 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
478 return -1;
479 }
480
481 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
482 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
483 return -1;
484 }
485 return 0;
486}
487
488/* parse "ssl.default-dh-param".
489 * Returns <0 on alert, >0 on warning, 0 on success.
490 */
491static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100492 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200493 char **err)
494{
495 if (too_many_args(1, args, err, NULL))
496 return -1;
497
498 if (*(args[1]) == 0) {
499 memprintf(err, "'%s' expects an integer argument.", args[0]);
500 return -1;
501 }
502
503 global_ssl.default_dh_param = atoi(args[1]);
504 if (global_ssl.default_dh_param < 1024) {
505 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
506 return -1;
507 }
508 return 0;
509}
510#endif
511
512
513/*
514 * parse "ssl-load-extra-files".
515 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
516 */
517static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100518 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200519 char **err)
520{
521 int i;
522 int gf = SSL_GF_NONE;
523
524 if (*(args[1]) == 0)
525 goto err_arg;
526
527 for (i = 1; *args[i]; i++) {
528
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100529 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200530 gf |= SSL_GF_BUNDLE;
531
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100532 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200533 gf |= SSL_GF_SCTL;
534
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100535 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200536 gf |= SSL_GF_OCSP;
537
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100538 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200539 gf |= SSL_GF_OCSP_ISSUER;
540
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100541 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200542 gf |= SSL_GF_KEY;
543
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100544 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200545 if (gf != SSL_GF_NONE)
546 goto err_alone;
547 gf = SSL_GF_NONE;
548 i++;
549 break;
550
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100551 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200552 if (gf != SSL_GF_NONE)
553 goto err_alone;
554 gf = SSL_GF_ALL;
555 i++;
556 break;
557 } else {
558 goto err_arg;
559 }
560 }
561 /* break from loop but there are still arguments */
562 if (*args[i])
563 goto err_alone;
564
565 global_ssl.extra_files = gf;
566
567 return 0;
568
569err_alone:
570 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
571 return -1;
572
573err_arg:
574 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
575 return -1;
576}
577
578
William Lallemand8e8581e2020-10-20 17:36:46 +0200579/* parse 'ssl-load-extra-del-ext */
580static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100581 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200582 char **err)
583{
584 global_ssl.extra_files_noext = 1;
585 return 0;
586}
587
William Lallemanddad31052020-05-14 17:47:32 +0200588/***************************** Bind keyword Parsing ********************************************/
589
590/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100591static 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 +0200592{
593 if (!*args[cur_arg + 1]) {
594 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
595 return ERR_ALERT | ERR_FATAL;
596 }
597
598 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
599 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
600 else
601 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
602
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200603 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200604 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
605 return ERR_ALERT | ERR_FATAL;
606 }
607 return 0;
608}
609
610/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100611static 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 +0200612{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100613 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200614}
615static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
616{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100617 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200618}
619
620/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100621static 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 +0200622{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100623 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200624}
625static int bind_parse_ca_verify_file(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_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200628}
629
630/* parse the "ca-sign-file" bind keyword */
631static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
632{
633 if (!*args[cur_arg + 1]) {
634 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
635 return ERR_ALERT | ERR_FATAL;
636 }
637
638 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
639 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
640 else
641 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
642
643 return 0;
644}
645
646/* parse the "ca-sign-pass" bind keyword */
647static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
648{
649 if (!*args[cur_arg + 1]) {
650 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
651 return ERR_ALERT | ERR_FATAL;
652 }
653 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
654 return 0;
655}
656
657/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100658static 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 +0200659{
660 if (!*args[cur_arg + 1]) {
661 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
662 return ERR_ALERT | ERR_FATAL;
663 }
664
665 free(conf->ciphers);
666 conf->ciphers = strdup(args[cur_arg + 1]);
667 return 0;
668}
669static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
670{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100671 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200672}
673
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500674#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200675/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100676static 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 +0200677{
678 if (!*args[cur_arg + 1]) {
679 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
680 return ERR_ALERT | ERR_FATAL;
681 }
682
683 free(conf->ciphersuites);
684 conf->ciphersuites = strdup(args[cur_arg + 1]);
685 return 0;
686}
687static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
688{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100689 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200690}
691#endif
692
693/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
694static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
695{
696 char path[MAXPATHLEN];
697
698 if (!*args[cur_arg + 1]) {
699 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
700 return ERR_ALERT | ERR_FATAL;
701 }
702
703 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
Willy Tarreau393e42a2022-05-09 10:31:28 +0200704 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > sizeof(path) ||
705 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]) > sizeof(path)) {
William Lallemanddad31052020-05-14 17:47:32 +0200706 memprintf(err, "'%s' : path too long", args[cur_arg]);
707 return ERR_ALERT | ERR_FATAL;
708 }
William Lallemanddad31052020-05-14 17:47:32 +0200709 return ssl_sock_load_cert(path, conf, err);
710 }
711
712 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
713}
714
715/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
716static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
717{
718 int err_code;
719
720 if (!*args[cur_arg + 1]) {
721 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
722 return ERR_ALERT | ERR_FATAL;
723 }
724
725 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
726 if (err_code)
727 memprintf(err, "'%s' : %s", args[cur_arg], *err);
728
729 return err_code;
730}
731
732/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100733static 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 +0200734{
735#ifndef X509_V_FLAG_CRL_CHECK
736 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
737 return ERR_ALERT | ERR_FATAL;
738#else
739 if (!*args[cur_arg + 1]) {
740 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
741 return ERR_ALERT | ERR_FATAL;
742 }
743
744 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
745 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
746 else
747 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
748
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200749 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200750 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
751 return ERR_ALERT | ERR_FATAL;
752 }
753 return 0;
754#endif
755}
756static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
757{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100758 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200759}
760
761/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100762static 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 +0200763{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500764#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200765 if (!*args[cur_arg + 1]) {
766 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
767 return ERR_ALERT | ERR_FATAL;
768 }
769 conf->curves = strdup(args[cur_arg + 1]);
770 return 0;
771#else
772 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
773 return ERR_ALERT | ERR_FATAL;
774#endif
775}
776static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
777{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100778 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200779}
780
781/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100782static 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 +0200783{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500784#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200785 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
786 return ERR_ALERT | ERR_FATAL;
787#elif defined(OPENSSL_NO_ECDH)
788 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
789 return ERR_ALERT | ERR_FATAL;
790#else
791 if (!*args[cur_arg + 1]) {
792 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
793 return ERR_ALERT | ERR_FATAL;
794 }
795
796 conf->ecdhe = strdup(args[cur_arg + 1]);
797
798 return 0;
799#endif
800}
801static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
802{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100803 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200804}
805
806/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
807static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
808{
809 int code;
810 char *p = args[cur_arg + 1];
811 unsigned long long *ignerr = &conf->crt_ignerr;
812
813 if (!*p) {
814 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
815 return ERR_ALERT | ERR_FATAL;
816 }
817
818 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
819 ignerr = &conf->ca_ignerr;
820
821 if (strcmp(p, "all") == 0) {
822 *ignerr = ~0ULL;
823 return 0;
824 }
825
826 while (p) {
827 code = atoi(p);
828 if ((code <= 0) || (code > 63)) {
829 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
830 args[cur_arg], code, args[cur_arg + 1]);
831 return ERR_ALERT | ERR_FATAL;
832 }
833 *ignerr |= 1ULL << code;
834 p = strchr(p, ',');
835 if (p)
836 p++;
837 }
838
839 return 0;
840}
841
842/* parse tls_method_options "no-xxx" and "force-xxx" */
843static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
844{
845 uint16_t v;
846 char *p;
847 p = strchr(arg, '-');
848 if (!p)
849 goto fail;
850 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100851 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200852 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100853 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200854 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100855 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200856 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100857 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200858 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100859 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200860 v = CONF_TLSV13;
861 else
862 goto fail;
863 if (!strncmp(arg, "no-", 3))
864 methods->flags |= methodVersions[v].flag;
865 else if (!strncmp(arg, "force-", 6))
866 methods->min = methods->max = v;
867 else
868 goto fail;
869 return 0;
870 fail:
871 memprintf(err, "'%s' : option not implemented", arg);
872 return ERR_ALERT | ERR_FATAL;
873}
874
875static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
876{
877 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
878}
879
880static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
881{
882 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
883}
884
885/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
886static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
887{
888 uint16_t i, v = 0;
889 char *argv = args[cur_arg + 1];
890 if (!*argv) {
891 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
892 return ERR_ALERT | ERR_FATAL;
893 }
894 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100895 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200896 v = i;
897 if (!v) {
898 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
899 return ERR_ALERT | ERR_FATAL;
900 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100901 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200902 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100903 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200904 methods->max = v;
905 else {
906 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
907 return ERR_ALERT | ERR_FATAL;
908 }
909 return 0;
910}
911
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100912static 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 +0200913{
William Lallemand8177ad92020-05-20 16:49:02 +0200914 int ret;
915
William Lallemanddad31052020-05-14 17:47:32 +0200916#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
917 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
918#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200919 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
920 if (ret != ERR_NONE)
921 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200922
William Lallemand8177ad92020-05-20 16:49:02 +0200923 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
924 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
925
926 return ret;
927}
William Lallemanddad31052020-05-14 17:47:32 +0200928static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
929{
930 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
931}
932
933static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
934{
935 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
936}
937
938/* parse the "no-tls-tickets" bind keyword */
939static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
940{
941 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
942 return 0;
943}
944
945/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100946static 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 +0200947{
948 conf->early_data = 1;
949 return 0;
950}
951
952static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
953{
954 conf->ssl_conf.early_data = 1;
955 return 0;
956}
957
958/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100959static 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 +0200960{
961#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
962 char *p1, *p2;
963
964 if (!*args[cur_arg + 1]) {
965 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
966 return ERR_ALERT | ERR_FATAL;
967 }
968
969 free(conf->npn_str);
970
971 /* the NPN string is built as a suite of (<len> <name>)*,
972 * so we reuse each comma to store the next <len> and need
973 * one more for the end of the string.
974 */
975 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
976 conf->npn_str = calloc(1, conf->npn_len + 1);
977 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
978
979 /* replace commas with the name length */
980 p1 = conf->npn_str;
981 p2 = p1 + 1;
982 while (1) {
983 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
984 if (!p2)
985 p2 = p1 + 1 + strlen(p1 + 1);
986
987 if (p2 - (p1 + 1) > 255) {
988 *p2 = '\0';
989 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
990 return ERR_ALERT | ERR_FATAL;
991 }
992
993 *p1 = p2 - (p1 + 1);
994 p1 = p2;
995
996 if (!*p2)
997 break;
998
999 *(p2++) = '\0';
1000 }
1001 return 0;
1002#else
1003 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
1004 return ERR_ALERT | ERR_FATAL;
1005#endif
1006}
1007
1008static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1009{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001010 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001011}
1012
1013
1014/* Parses a alpn string and converts it to the right format for the SSL api */
1015int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
1016{
1017 char *p1, *p2, *alpn = NULL;
1018 int len, ret = 0;
1019
1020 *alpn_str = NULL;
1021 *alpn_len = 0;
1022
1023 if (!*arg) {
1024 memprintf(err, "missing the comma-delimited ALPN protocol suite");
1025 goto error;
1026 }
1027
1028 /* the ALPN string is built as a suite of (<len> <name>)*,
1029 * so we reuse each comma to store the next <len> and need
1030 * one more for the end of the string.
1031 */
1032 len = strlen(arg) + 1;
1033 alpn = calloc(1, len+1);
1034 if (!alpn) {
1035 memprintf(err, "'%s' : out of memory", arg);
1036 goto error;
1037 }
1038 memcpy(alpn+1, arg, len);
1039
1040 /* replace commas with the name length */
1041 p1 = alpn;
1042 p2 = p1 + 1;
1043 while (1) {
1044 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
1045 if (!p2)
1046 p2 = p1 + 1 + strlen(p1 + 1);
1047
1048 if (p2 - (p1 + 1) > 255) {
1049 *p2 = '\0';
1050 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1051 goto error;
1052 }
1053
1054 *p1 = p2 - (p1 + 1);
1055 p1 = p2;
1056
1057 if (!*p2)
1058 break;
1059
1060 *(p2++) = '\0';
1061 }
1062
1063 *alpn_str = alpn;
1064 *alpn_len = len;
1065
1066 out:
1067 return ret;
1068
1069 error:
1070 free(alpn);
1071 ret = ERR_ALERT | ERR_FATAL;
1072 goto out;
1073}
1074
1075/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001076static 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 +02001077{
1078#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1079 int ret;
1080
1081 free(conf->alpn_str);
1082
1083 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1084 if (ret)
1085 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1086 return ret;
1087#else
1088 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1089 return ERR_ALERT | ERR_FATAL;
1090#endif
1091}
1092
1093static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1094{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001095 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001096}
1097
1098/* parse the "ssl" bind keyword */
1099static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1100{
Frédéric Lécaillee50afbd2020-11-23 11:33:12 +01001101 /* Do not change the xprt for QUIC. */
1102 if (conf->xprt != xprt_get(XPRT_QUIC))
1103 conf->xprt = &ssl_sock;
William Lallemanddad31052020-05-14 17:47:32 +02001104 conf->is_ssl = 1;
1105
1106 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1107 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001108#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001109 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1110 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1111#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001112#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001113 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1114 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1115#endif
1116 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1117 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1118 if (!conf->ssl_conf.ssl_methods.min)
1119 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1120 if (!conf->ssl_conf.ssl_methods.max)
1121 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1122
1123 return 0;
1124}
1125
1126/* parse the "prefer-client-ciphers" bind keyword */
1127static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1128{
1129 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1130 return 0;
1131}
1132
1133/* parse the "generate-certificates" bind keyword */
1134static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1135{
1136#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1137 conf->generate_certs = 1;
1138#else
1139 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1140 err && *err ? *err : "");
1141#endif
1142 return 0;
1143}
1144
1145/* parse the "strict-sni" bind keyword */
1146static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1147{
1148 conf->strict_sni = 1;
1149 return 0;
1150}
1151
1152/* parse the "tls-ticket-keys" bind keyword */
1153static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1154{
1155#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1156 FILE *f = NULL;
1157 int i = 0;
1158 char thisline[LINESIZE];
1159 struct tls_keys_ref *keys_ref = NULL;
1160
1161 if (!*args[cur_arg + 1]) {
1162 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1163 goto fail;
1164 }
1165
1166 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1167 if (keys_ref) {
1168 keys_ref->refcount++;
1169 conf->keys_ref = keys_ref;
1170 return 0;
1171 }
1172
1173 keys_ref = calloc(1, sizeof(*keys_ref));
1174 if (!keys_ref) {
1175 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1176 goto fail;
1177 }
1178
1179 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1180 if (!keys_ref->tlskeys) {
1181 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1182 goto fail;
1183 }
1184
1185 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1186 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1187 goto fail;
1188 }
1189
1190 keys_ref->filename = strdup(args[cur_arg + 1]);
1191 if (!keys_ref->filename) {
1192 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1193 goto fail;
1194 }
1195
1196 keys_ref->key_size_bits = 0;
1197 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1198 int len = strlen(thisline);
1199 int dec_size;
1200
1201 /* Strip newline characters from the end */
1202 if(thisline[len - 1] == '\n')
1203 thisline[--len] = 0;
1204
1205 if(thisline[len - 1] == '\r')
1206 thisline[--len] = 0;
1207
1208 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1209 if (dec_size < 0) {
1210 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1211 goto fail;
1212 }
1213 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1214 keys_ref->key_size_bits = 128;
1215 }
1216 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1217 keys_ref->key_size_bits = 256;
1218 }
1219 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1220 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1221 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1222 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1223 goto fail;
1224 }
1225 i++;
1226 }
1227
1228 if (i < TLS_TICKETS_NO) {
1229 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1230 goto fail;
1231 }
1232
1233 fclose(f);
1234
1235 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1236 i -= 2;
1237 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1238 keys_ref->unique_id = -1;
1239 keys_ref->refcount = 1;
1240 HA_RWLOCK_INIT(&keys_ref->lock);
1241 conf->keys_ref = keys_ref;
1242
Willy Tarreau2b718102021-04-21 07:32:39 +02001243 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001244
1245 return 0;
1246
1247 fail:
1248 if (f)
1249 fclose(f);
1250 if (keys_ref) {
1251 free(keys_ref->filename);
1252 free(keys_ref->tlskeys);
1253 free(keys_ref);
1254 }
1255 return ERR_ALERT | ERR_FATAL;
1256
1257#else
1258 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1259 return ERR_ALERT | ERR_FATAL;
1260#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1261}
1262
1263/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001264static 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 +02001265{
1266 if (!*args[cur_arg + 1]) {
1267 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1268 return ERR_ALERT | ERR_FATAL;
1269 }
1270
1271 if (strcmp(args[cur_arg + 1], "none") == 0)
1272 conf->verify = SSL_SOCK_VERIFY_NONE;
1273 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1274 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1275 else if (strcmp(args[cur_arg + 1], "required") == 0)
1276 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1277 else {
1278 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1279 args[cur_arg], args[cur_arg + 1]);
1280 return ERR_ALERT | ERR_FATAL;
1281 }
1282
1283 return 0;
1284}
1285static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1286{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001287 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001288}
1289
1290/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001291static 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 +02001292{
1293 conf->no_ca_names = 1;
1294 return 0;
1295}
1296static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1297{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001298 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001299}
1300
1301/***************************** "server" keywords Parsing ********************************************/
1302
1303/* parse the "npn" bind keyword */
1304static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1305{
1306#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1307 char *p1, *p2;
1308
1309 if (!*args[*cur_arg + 1]) {
1310 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1311 return ERR_ALERT | ERR_FATAL;
1312 }
1313
1314 free(newsrv->ssl_ctx.npn_str);
1315
1316 /* the NPN string is built as a suite of (<len> <name>)*,
1317 * so we reuse each comma to store the next <len> and need
1318 * one more for the end of the string.
1319 */
1320 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1321 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001322 if (!newsrv->ssl_ctx.npn_str) {
1323 memprintf(err, "out of memory");
1324 return ERR_ALERT | ERR_FATAL;
1325 }
1326
William Lallemanddad31052020-05-14 17:47:32 +02001327 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1328 newsrv->ssl_ctx.npn_len);
1329
1330 /* replace commas with the name length */
1331 p1 = newsrv->ssl_ctx.npn_str;
1332 p2 = p1 + 1;
1333 while (1) {
1334 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1335 newsrv->ssl_ctx.npn_len - (p1 + 1));
1336 if (!p2)
1337 p2 = p1 + 1 + strlen(p1 + 1);
1338
1339 if (p2 - (p1 + 1) > 255) {
1340 *p2 = '\0';
1341 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1342 return ERR_ALERT | ERR_FATAL;
1343 }
1344
1345 *p1 = p2 - (p1 + 1);
1346 p1 = p2;
1347
1348 if (!*p2)
1349 break;
1350
1351 *(p2++) = '\0';
1352 }
1353 return 0;
1354#else
1355 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1356 return ERR_ALERT | ERR_FATAL;
1357#endif
1358}
1359
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001360#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1361static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1362{
1363 free(*out_alpn_str);
1364 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1365}
1366#endif
1367
1368/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001369static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1370{
1371#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001372 int ret = parse_alpn(args[*cur_arg + 1],
1373 &newsrv->ssl_ctx.alpn_str,
1374 &newsrv->ssl_ctx.alpn_len, err);
1375 if (ret)
1376 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1377 return ret;
1378#else
1379 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1380 return ERR_ALERT | ERR_FATAL;
1381#endif
1382}
William Lallemanddad31052020-05-14 17:47:32 +02001383
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001384/* parse the "check-alpn" server keyword */
1385static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1386{
1387#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1388 int ret = parse_alpn(args[*cur_arg + 1],
1389 &newsrv->check.alpn_str,
1390 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001391 if (ret)
1392 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1393 return ret;
1394#else
1395 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1396 return ERR_ALERT | ERR_FATAL;
1397#endif
1398}
1399
1400/* parse the "ca-file" server keyword */
1401static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1402{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001403 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1404
William Lallemanddad31052020-05-14 17:47:32 +02001405 if (!*args[*cur_arg + 1]) {
1406 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1407 return ERR_ALERT | ERR_FATAL;
1408 }
1409
1410 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1411 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1412 else
1413 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1414
Amaury Denoyelle48255022021-05-19 09:46:59 +02001415 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001416 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1417 return ERR_ALERT | ERR_FATAL;
1418 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001419
William Lallemanddad31052020-05-14 17:47:32 +02001420 return 0;
1421}
1422
1423/* parse the "check-sni" server keyword */
1424static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1425{
1426 if (!*args[*cur_arg + 1]) {
1427 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1428 return ERR_ALERT | ERR_FATAL;
1429 }
1430
1431 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1432 if (!newsrv->check.sni) {
1433 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1434 return ERR_ALERT | ERR_FATAL;
1435 }
1436 return 0;
1437
1438}
1439
William Dauchyfc52f522020-11-14 19:25:32 +01001440/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001441static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001442{
William Dauchyfc52f522020-11-14 19:25:32 +01001443 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1444 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001445#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001446 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001447 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001448 if (!s->ssl_ctx.ciphersuites)
1449 return 1;
1450 }
William Lallemanddad31052020-05-14 17:47:32 +02001451#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001452 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1453 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1454
1455 if (!s->ssl_ctx.methods.min)
1456 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001457
William Dauchyfc52f522020-11-14 19:25:32 +01001458 if (!s->ssl_ctx.methods.max)
1459 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001460
1461 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001462}
1463
1464/* parse the "check-ssl" server keyword */
1465static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1466{
1467 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001468 if (ssl_sock_init_srv(newsrv)) {
1469 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1470 return ERR_ALERT | ERR_FATAL;
1471 }
1472
William Lallemanddad31052020-05-14 17:47:32 +02001473 return 0;
1474}
1475
1476/* parse the "ciphers" server keyword */
1477static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1478{
1479 if (!*args[*cur_arg + 1]) {
1480 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1481 return ERR_ALERT | ERR_FATAL;
1482 }
1483
1484 free(newsrv->ssl_ctx.ciphers);
1485 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001486
1487 if (!newsrv->ssl_ctx.ciphers) {
1488 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1489 return ERR_ALERT | ERR_FATAL;
1490 }
1491
William Lallemanddad31052020-05-14 17:47:32 +02001492 return 0;
1493}
1494
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001495#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001496/* parse the "ciphersuites" server keyword */
1497static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1498{
1499 if (!*args[*cur_arg + 1]) {
1500 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1501 return ERR_ALERT | ERR_FATAL;
1502 }
1503
1504 free(newsrv->ssl_ctx.ciphersuites);
1505 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001506
1507 if (!newsrv->ssl_ctx.ciphersuites) {
1508 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1509 return ERR_ALERT | ERR_FATAL;
1510 }
1511
William Lallemanddad31052020-05-14 17:47:32 +02001512 return 0;
1513}
1514#endif
1515
1516/* parse the "crl-file" server keyword */
1517static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1518{
1519#ifndef X509_V_FLAG_CRL_CHECK
1520 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1521 return ERR_ALERT | ERR_FATAL;
1522#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001523 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1524
William Lallemanddad31052020-05-14 17:47:32 +02001525 if (!*args[*cur_arg + 1]) {
1526 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1527 return ERR_ALERT | ERR_FATAL;
1528 }
1529
1530 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1531 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1532 else
1533 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1534
Amaury Denoyellefde82602021-06-14 10:10:32 +02001535 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001536 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1537 return ERR_ALERT | ERR_FATAL;
1538 }
1539 return 0;
1540#endif
1541}
1542
1543/* parse the "crt" server keyword */
1544static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1545{
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001546
William Lallemanddad31052020-05-14 17:47:32 +02001547 if (!*args[*cur_arg + 1]) {
1548 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1549 return ERR_ALERT | ERR_FATAL;
1550 }
1551
1552 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
William Lallemand2c776f12021-12-28 18:47:17 +01001553 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001554 else
William Lallemand2c776f12021-12-28 18:47:17 +01001555 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001556
William Lallemand2c776f12021-12-28 18:47:17 +01001557 return 0;
William Lallemanddad31052020-05-14 17:47:32 +02001558}
1559
1560/* parse the "no-check-ssl" server keyword */
1561static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1562{
1563 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001564 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001565 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1566 return 0;
1567}
1568
1569/* parse the "no-send-proxy-v2-ssl" server keyword */
1570static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1571{
1572 newsrv->pp_opts &= ~SRV_PP_V2;
1573 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1574 return 0;
1575}
1576
1577/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1578static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1579{
1580 newsrv->pp_opts &= ~SRV_PP_V2;
1581 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1582 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1583 return 0;
1584}
1585
1586/* parse the "no-ssl" server keyword */
1587static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1588{
William Dauchyf6370442020-11-14 19:25:33 +01001589 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001590 if (newsrv->use_ssl == 1) {
1591 if (ssl_sock_init_srv(newsrv)) {
1592 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1593 return ERR_ALERT | ERR_FATAL;
1594 }
1595 }
William Dauchyf6370442020-11-14 19:25:33 +01001596 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001597 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001598 }
William Lallemanddad31052020-05-14 17:47:32 +02001599 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001600 return 0;
1601}
1602
1603/* parse the "allow-0rtt" server keyword */
1604static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1605{
1606 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1607 return 0;
1608}
1609
1610/* parse the "no-ssl-reuse" server keyword */
1611static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1612{
1613 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1614 return 0;
1615}
1616
1617/* parse the "no-tls-tickets" server keyword */
1618static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1619{
1620 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1621 return 0;
1622}
1623/* parse the "send-proxy-v2-ssl" server keyword */
1624static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1625{
1626 newsrv->pp_opts |= SRV_PP_V2;
1627 newsrv->pp_opts |= SRV_PP_V2_SSL;
1628 return 0;
1629}
1630
1631/* parse the "send-proxy-v2-ssl-cn" server keyword */
1632static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1633{
1634 newsrv->pp_opts |= SRV_PP_V2;
1635 newsrv->pp_opts |= SRV_PP_V2_SSL;
1636 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1637 return 0;
1638}
1639
1640/* parse the "sni" server keyword */
1641static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1642{
1643#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1644 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1645 return ERR_ALERT | ERR_FATAL;
1646#else
1647 char *arg;
1648
1649 arg = args[*cur_arg + 1];
1650 if (!*arg) {
1651 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1652 return ERR_ALERT | ERR_FATAL;
1653 }
1654
1655 free(newsrv->sni_expr);
1656 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001657 if (!newsrv->sni_expr) {
1658 memprintf(err, "out of memory");
1659 return ERR_ALERT | ERR_FATAL;
1660 }
William Lallemanddad31052020-05-14 17:47:32 +02001661
1662 return 0;
1663#endif
1664}
1665
1666/* parse the "ssl" server keyword */
1667static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1668{
1669 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001670 if (ssl_sock_init_srv(newsrv)) {
1671 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1672 return ERR_ALERT | ERR_FATAL;
1673 }
1674
William Lallemanddad31052020-05-14 17:47:32 +02001675 return 0;
1676}
1677
1678/* parse the "ssl-reuse" server keyword */
1679static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1680{
1681 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1682 return 0;
1683}
1684
1685/* parse the "tls-tickets" server keyword */
1686static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1687{
1688 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1689 return 0;
1690}
1691
1692/* parse the "verify" server keyword */
1693static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1694{
1695 if (!*args[*cur_arg + 1]) {
1696 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1697 return ERR_ALERT | ERR_FATAL;
1698 }
1699
1700 if (strcmp(args[*cur_arg + 1], "none") == 0)
1701 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1702 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1703 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1704 else {
1705 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1706 args[*cur_arg], args[*cur_arg + 1]);
1707 return ERR_ALERT | ERR_FATAL;
1708 }
1709
1710 return 0;
1711}
1712
1713/* parse the "verifyhost" server keyword */
1714static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1715{
1716 if (!*args[*cur_arg + 1]) {
1717 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1718 return ERR_ALERT | ERR_FATAL;
1719 }
1720
1721 free(newsrv->ssl_ctx.verify_host);
1722 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1723
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001724 if (!newsrv->ssl_ctx.verify_host) {
1725 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1726 return ERR_ALERT | ERR_FATAL;
1727 }
1728
William Lallemanddad31052020-05-14 17:47:32 +02001729 return 0;
1730}
1731
1732/* parse the "ssl-default-bind-options" keyword in global section */
1733static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001734 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001735 char **err) {
1736 int i = 1;
1737
1738 if (*(args[i]) == 0) {
1739 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1740 return -1;
1741 }
1742 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001743 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001744 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001745 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001746 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001747 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001748 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1749 i++;
1750 else {
1751 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1752 return -1;
1753 }
1754 }
1755 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1756 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1757 return -1;
1758 }
1759 i++;
1760 }
1761 return 0;
1762}
1763
1764/* parse the "ssl-default-server-options" keyword in global section */
1765static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001766 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001767 char **err) {
1768 int i = 1;
1769
1770 if (*(args[i]) == 0) {
1771 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1772 return -1;
1773 }
1774 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001775 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001776 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001777 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001778 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1779 i++;
1780 else {
1781 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1782 return -1;
1783 }
1784 }
1785 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1786 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1787 return -1;
1788 }
1789 i++;
1790 }
1791 return 0;
1792}
1793
1794/* parse the "ca-base" / "crt-base" keywords in global section.
1795 * Returns <0 on alert, >0 on warning, 0 on success.
1796 */
1797static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001798 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001799 char **err)
1800{
1801 char **target;
1802
1803 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1804
1805 if (too_many_args(1, args, err, NULL))
1806 return -1;
1807
1808 if (*target) {
1809 memprintf(err, "'%s' already specified.", args[0]);
1810 return -1;
1811 }
1812
1813 if (*(args[1]) == 0) {
1814 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1815 return -1;
1816 }
1817 *target = strdup(args[1]);
1818 return 0;
1819}
1820
1821/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1822static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001823 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001824 char **err)
1825{
William Lallemand9a1d8392020-08-10 17:28:23 +02001826#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001827 global_ssl.skip_self_issued_ca = 1;
1828 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001829#else
1830 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1831 return -1;
1832#endif
William Lallemanddad31052020-05-14 17:47:32 +02001833}
1834
1835
1836
1837
1838
1839/* Note: must not be declared <const> as its list will be overwritten.
1840 * Please take care of keeping this list alphabetically sorted, doing so helps
1841 * all code contributors.
1842 * Optional keywords are also declared with a NULL ->parse() function so that
1843 * the config parser can report an appropriate error when a known keyword was
1844 * not enabled.
1845 */
1846
1847/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1848 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1849struct ssl_bind_kw ssl_bind_kws[] = {
1850 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1851 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1852 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1853 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1854 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001855#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001856 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1857#endif
1858 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1859 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1860 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1861 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1862 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1863 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1864 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1865 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1866 { NULL, NULL, 0 },
1867};
1868
1869/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1870
1871static struct bind_kw_list bind_kws = { "SSL", { }, {
1872 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1873 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1874 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1875 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1876 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1877 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1878 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1879 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001880#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001881 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1882#endif
1883 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1884 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1885 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1886 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1887 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1888 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1889 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1890 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1891 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1892 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1893 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1894 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1895 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1896 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1897 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1898 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1899 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1900 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1901 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1902 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1903 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1904 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1905 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1906 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1907 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1908 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1909 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1910 { NULL, NULL, 0 },
1911}};
1912
1913INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1914
1915/* Note: must not be declared <const> as its list will be overwritten.
1916 * Please take care of keeping this list alphabetically sorted, doing so helps
1917 * all code contributors.
1918 * Optional keywords are also declared with a NULL ->parse() function so that
1919 * the config parser can report an appropriate error when a known keyword was
1920 * not enabled.
1921 */
1922static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001923 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1924 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001925 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle79b90e82021-09-20 15:15:19 +02001926 { "check-alpn", srv_parse_check_alpn, 1, 1, 1 }, /* Set ALPN used for checks */
1927 { "check-sni", srv_parse_check_sni, 1, 1, 1 }, /* set SNI */
1928 { "check-ssl", srv_parse_check_ssl, 0, 1, 1 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001929 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001930#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001931 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001932#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001933 { "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 +02001934 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001935 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1936 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1937 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1938 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1939 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001940 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1941 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1942 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1943 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001944 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1945 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1946 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1947 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1948 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1949 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1950 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1951 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1952 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1953 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1954 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001955 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001956 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1957 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001958 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001959 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1960 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
1961 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001962 { NULL, NULL, 0, 0 },
1963}};
1964
1965INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1966
1967static struct cfg_kw_list cfg_kws = {ILH, {
1968 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1969 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1970 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1971 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1972 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1973 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1974#ifndef OPENSSL_NO_DH
1975 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1976#endif
1977 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
William Lallemandd7bfbe22022-04-11 18:41:24 +02001978#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE)
William Lallemanddad31052020-05-14 17:47:32 +02001979 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1980#endif
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02001981#ifdef HAVE_SSL_PROVIDERS
1982 { CFG_GLOBAL, "ssl-propquery", ssl_parse_global_ssl_propquery },
Remi Tricot-Le Breton1746a382022-05-16 16:24:33 +02001983 { CFG_GLOBAL, "ssl-provider", ssl_parse_global_ssl_provider },
Remi Tricot-Le Bretone8097652022-05-16 16:24:32 +02001984#endif
William Lallemanddad31052020-05-14 17:47:32 +02001985 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1986 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1987#ifndef OPENSSL_NO_DH
1988 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1989#endif
1990 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
1991 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1992 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
Thomas Prückl10243932022-04-27 13:04:54 +02001993 { CFG_GLOBAL, "tune.ssl.hard-maxrecord", ssl_parse_global_int },
William Lallemanddad31052020-05-14 17:47:32 +02001994 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Marcin Deranek310a2602021-07-13 19:04:24 +02001995 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_buffer },
1996 { CFG_GLOBAL, "tune.ssl.capture-buffer-size", ssl_parse_global_capture_buffer },
William Lallemand7d42ef52020-07-06 11:41:30 +02001997 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02001998 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1999 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05002000#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02002001 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
2002#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05002003#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02002004 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
2005 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
2006#endif
2007 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02002008 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02002009 { 0, NULL, NULL },
2010}};
2011
2012INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);