blob: 6df5911ebd3591e4a0fac0907af614d3dfd16be1 [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;
275 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
276 target = &global_ssl.capture_cipherlist;
277 else {
278 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
279 return -1;
280 }
281
282 if (too_many_args(1, args, err, NULL))
283 return -1;
284
285 if (*(args[1]) == 0) {
286 memprintf(err, "'%s' expects an integer argument.", args[0]);
287 return -1;
288 }
289
290 *target = atoi(args[1]);
291 if (*target < 0) {
292 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
293 return -1;
294 }
295 return 0;
296}
297
298static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100299 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200300 char **err)
301{
302 int ret;
303
304 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
305 if (ret != 0)
306 return ret;
307
308 if (pool_head_ssl_capture) {
309 memprintf(err, "'%s' is already configured.", args[0]);
310 return -1;
311 }
312
313 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
314 if (!pool_head_ssl_capture) {
315 memprintf(err, "Out of memory error.");
316 return -1;
317 }
318 return 0;
319}
320
William Lallemand7d42ef52020-07-06 11:41:30 +0200321/* init the SSLKEYLOGFILE pool */
William Lallemand722180a2021-06-09 16:46:12 +0200322#ifdef HAVE_SSL_KEYLOG
William Lallemand7d42ef52020-07-06 11:41:30 +0200323static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100324 const struct proxy *defpx, const char *file, int line,
William Lallemand7d42ef52020-07-06 11:41:30 +0200325 char **err)
326{
327
328 if (too_many_args(1, args, err, NULL))
329 return -1;
330
331 if (strcmp(args[1], "on") == 0)
332 global_ssl.keylog = 1;
333 else if (strcmp(args[1], "off") == 0)
334 global_ssl.keylog = 0;
335 else {
336 memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
337 return -1;
338 }
339
340 if (pool_head_ssl_keylog) /* already configured */
341 return 0;
342
343 pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
344 if (!pool_head_ssl_keylog) {
345 memprintf(err, "Out of memory error.");
346 return -1;
347 }
348
349 pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
350 if (!pool_head_ssl_keylog_str) {
351 memprintf(err, "Out of memory error.");
352 return -1;
353 }
354
355 return 0;
356}
William Lallemand722180a2021-06-09 16:46:12 +0200357#else
358static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
359 const struct proxy *defpx, const char *file, int line,
360 char **err)
361{
362 memprintf(err, "'%s' requires at least OpenSSL 1.1.1.", args[0]);
363 return -1;
364}
William Lallemand7d42ef52020-07-06 11:41:30 +0200365#endif
366
William Lallemanddad31052020-05-14 17:47:32 +0200367/* parse "ssl.force-private-cache".
368 * Returns <0 on alert, >0 on warning, 0 on success.
369 */
370static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100371 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200372 char **err)
373{
374 if (too_many_args(0, args, err, NULL))
375 return -1;
376
377 global_ssl.private_cache = 1;
378 return 0;
379}
380
381/* parse "ssl.lifetime".
382 * Returns <0 on alert, >0 on warning, 0 on success.
383 */
384static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100385 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200386 char **err)
387{
388 const char *res;
389
390 if (too_many_args(1, args, err, NULL))
391 return -1;
392
393 if (*(args[1]) == 0) {
394 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
395 return -1;
396 }
397
398 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
399 if (res == PARSE_TIME_OVER) {
400 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
401 args[1], args[0]);
402 return -1;
403 }
404 else if (res == PARSE_TIME_UNDER) {
405 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
406 args[1], args[0]);
407 return -1;
408 }
409 else if (res) {
410 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
411 return -1;
412 }
413 return 0;
414}
415
416#ifndef OPENSSL_NO_DH
417/* parse "ssl-dh-param-file".
418 * Returns <0 on alert, >0 on warning, 0 on success.
419 */
420static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100421 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200422 char **err)
423{
424 if (too_many_args(1, args, err, NULL))
425 return -1;
426
427 if (*(args[1]) == 0) {
428 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
429 return -1;
430 }
431
432 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
433 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
434 return -1;
435 }
436 return 0;
437}
438
439/* parse "ssl.default-dh-param".
440 * Returns <0 on alert, >0 on warning, 0 on success.
441 */
442static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100443 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200444 char **err)
445{
446 if (too_many_args(1, args, err, NULL))
447 return -1;
448
449 if (*(args[1]) == 0) {
450 memprintf(err, "'%s' expects an integer argument.", args[0]);
451 return -1;
452 }
453
454 global_ssl.default_dh_param = atoi(args[1]);
455 if (global_ssl.default_dh_param < 1024) {
456 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
457 return -1;
458 }
459 return 0;
460}
461#endif
462
463
464/*
465 * parse "ssl-load-extra-files".
466 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
467 */
468static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100469 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +0200470 char **err)
471{
472 int i;
473 int gf = SSL_GF_NONE;
474
475 if (*(args[1]) == 0)
476 goto err_arg;
477
478 for (i = 1; *args[i]; i++) {
479
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100480 if (strcmp("bundle", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200481 gf |= SSL_GF_BUNDLE;
482
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100483 } else if (strcmp("sctl", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200484 gf |= SSL_GF_SCTL;
485
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100486 } else if (strcmp("ocsp", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200487 gf |= SSL_GF_OCSP;
488
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100489 } else if (strcmp("issuer", args[i]) == 0){
William Lallemanddad31052020-05-14 17:47:32 +0200490 gf |= SSL_GF_OCSP_ISSUER;
491
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100492 } else if (strcmp("key", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200493 gf |= SSL_GF_KEY;
494
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100495 } else if (strcmp("none", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200496 if (gf != SSL_GF_NONE)
497 goto err_alone;
498 gf = SSL_GF_NONE;
499 i++;
500 break;
501
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100502 } else if (strcmp("all", args[i]) == 0) {
William Lallemanddad31052020-05-14 17:47:32 +0200503 if (gf != SSL_GF_NONE)
504 goto err_alone;
505 gf = SSL_GF_ALL;
506 i++;
507 break;
508 } else {
509 goto err_arg;
510 }
511 }
512 /* break from loop but there are still arguments */
513 if (*args[i])
514 goto err_alone;
515
516 global_ssl.extra_files = gf;
517
518 return 0;
519
520err_alone:
521 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
522 return -1;
523
524err_arg:
525 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
526 return -1;
527}
528
529
William Lallemand8e8581e2020-10-20 17:36:46 +0200530/* parse 'ssl-load-extra-del-ext */
531static int ssl_parse_global_extra_noext(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +0100532 const struct proxy *defpx, const char *file, int line,
William Lallemand8e8581e2020-10-20 17:36:46 +0200533 char **err)
534{
535 global_ssl.extra_files_noext = 1;
536 return 0;
537}
538
William Lallemanddad31052020-05-14 17:47:32 +0200539/***************************** Bind keyword Parsing ********************************************/
540
541/* for ca-file and ca-verify-file */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100542static 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 +0200543{
544 if (!*args[cur_arg + 1]) {
545 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
546 return ERR_ALERT | ERR_FATAL;
547 }
548
549 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
550 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
551 else
552 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
553
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200554 if (!ssl_store_load_locations_file(*ca_file_p, !from_cli, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +0200555 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
556 return ERR_ALERT | ERR_FATAL;
557 }
558 return 0;
559}
560
561/* parse the "ca-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100562static 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 +0200563{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100564 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200565}
566static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
567{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100568 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200569}
570
571/* parse the "ca-verify-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100572static 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 +0200573{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100574 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, from_cli, err);
William Lallemanddad31052020-05-14 17:47:32 +0200575}
576static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
577{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100578 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200579}
580
581/* parse the "ca-sign-file" bind keyword */
582static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
583{
584 if (!*args[cur_arg + 1]) {
585 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
586 return ERR_ALERT | ERR_FATAL;
587 }
588
589 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
590 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
591 else
592 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
593
594 return 0;
595}
596
597/* parse the "ca-sign-pass" bind keyword */
598static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
599{
600 if (!*args[cur_arg + 1]) {
601 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
602 return ERR_ALERT | ERR_FATAL;
603 }
604 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
605 return 0;
606}
607
608/* parse the "ciphers" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100609static 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 +0200610{
611 if (!*args[cur_arg + 1]) {
612 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
613 return ERR_ALERT | ERR_FATAL;
614 }
615
616 free(conf->ciphers);
617 conf->ciphers = strdup(args[cur_arg + 1]);
618 return 0;
619}
620static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
621{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100622 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200623}
624
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +0500625#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +0200626/* parse the "ciphersuites" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100627static 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 +0200628{
629 if (!*args[cur_arg + 1]) {
630 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
631 return ERR_ALERT | ERR_FATAL;
632 }
633
634 free(conf->ciphersuites);
635 conf->ciphersuites = strdup(args[cur_arg + 1]);
636 return 0;
637}
638static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
639{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100640 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200641}
642#endif
643
644/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
645static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
646{
647 char path[MAXPATHLEN];
648
649 if (!*args[cur_arg + 1]) {
650 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
651 return ERR_ALERT | ERR_FATAL;
652 }
653
654 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
655 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
656 memprintf(err, "'%s' : path too long", args[cur_arg]);
657 return ERR_ALERT | ERR_FATAL;
658 }
659 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
660 return ssl_sock_load_cert(path, conf, err);
661 }
662
663 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
664}
665
666/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
667static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
668{
669 int err_code;
670
671 if (!*args[cur_arg + 1]) {
672 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
673 return ERR_ALERT | ERR_FATAL;
674 }
675
676 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
677 if (err_code)
678 memprintf(err, "'%s' : %s", args[cur_arg], *err);
679
680 return err_code;
681}
682
683/* parse the "crl-file" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100684static 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 +0200685{
686#ifndef X509_V_FLAG_CRL_CHECK
687 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
688 return ERR_ALERT | ERR_FATAL;
689#else
690 if (!*args[cur_arg + 1]) {
691 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
692 return ERR_ALERT | ERR_FATAL;
693 }
694
695 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
696 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
697 else
698 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
699
Remi Tricot-Le Breton0bb48242021-04-16 17:59:23 +0200700 if (!ssl_store_load_locations_file(conf->crl_file, !from_cli, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +0200701 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
702 return ERR_ALERT | ERR_FATAL;
703 }
704 return 0;
705#endif
706}
707static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
708{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100709 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200710}
711
712/* parse the "curves" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100713static 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 +0200714{
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +0500715#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +0200716 if (!*args[cur_arg + 1]) {
717 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
718 return ERR_ALERT | ERR_FATAL;
719 }
720 conf->curves = strdup(args[cur_arg + 1]);
721 return 0;
722#else
723 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
724 return ERR_ALERT | ERR_FATAL;
725#endif
726}
727static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
728{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100729 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200730}
731
732/* parse the "ecdhe" bind keyword keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100733static 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 +0200734{
Ilya Shipitsina0fd35b2021-03-21 12:50:47 +0500735#if !defined(SSL_CTX_set_tmp_ecdh)
William Lallemanddad31052020-05-14 17:47:32 +0200736 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
737 return ERR_ALERT | ERR_FATAL;
738#elif defined(OPENSSL_NO_ECDH)
739 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
740 return ERR_ALERT | ERR_FATAL;
741#else
742 if (!*args[cur_arg + 1]) {
743 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
744 return ERR_ALERT | ERR_FATAL;
745 }
746
747 conf->ecdhe = strdup(args[cur_arg + 1]);
748
749 return 0;
750#endif
751}
752static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
753{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100754 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200755}
756
757/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
758static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
759{
760 int code;
761 char *p = args[cur_arg + 1];
762 unsigned long long *ignerr = &conf->crt_ignerr;
763
764 if (!*p) {
765 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
766 return ERR_ALERT | ERR_FATAL;
767 }
768
769 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
770 ignerr = &conf->ca_ignerr;
771
772 if (strcmp(p, "all") == 0) {
773 *ignerr = ~0ULL;
774 return 0;
775 }
776
777 while (p) {
778 code = atoi(p);
779 if ((code <= 0) || (code > 63)) {
780 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
781 args[cur_arg], code, args[cur_arg + 1]);
782 return ERR_ALERT | ERR_FATAL;
783 }
784 *ignerr |= 1ULL << code;
785 p = strchr(p, ',');
786 if (p)
787 p++;
788 }
789
790 return 0;
791}
792
793/* parse tls_method_options "no-xxx" and "force-xxx" */
794static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
795{
796 uint16_t v;
797 char *p;
798 p = strchr(arg, '-');
799 if (!p)
800 goto fail;
801 p++;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100802 if (strcmp(p, "sslv3") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200803 v = CONF_SSLV3;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100804 else if (strcmp(p, "tlsv10") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200805 v = CONF_TLSV10;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100806 else if (strcmp(p, "tlsv11") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200807 v = CONF_TLSV11;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100808 else if (strcmp(p, "tlsv12") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200809 v = CONF_TLSV12;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100810 else if (strcmp(p, "tlsv13") == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200811 v = CONF_TLSV13;
812 else
813 goto fail;
814 if (!strncmp(arg, "no-", 3))
815 methods->flags |= methodVersions[v].flag;
816 else if (!strncmp(arg, "force-", 6))
817 methods->min = methods->max = v;
818 else
819 goto fail;
820 return 0;
821 fail:
822 memprintf(err, "'%s' : option not implemented", arg);
823 return ERR_ALERT | ERR_FATAL;
824}
825
826static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
827{
828 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
829}
830
831static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
832{
833 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
834}
835
836/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
837static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
838{
839 uint16_t i, v = 0;
840 char *argv = args[cur_arg + 1];
841 if (!*argv) {
842 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
843 return ERR_ALERT | ERR_FATAL;
844 }
845 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100846 if (strcmp(argv, methodVersions[i].name) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200847 v = i;
848 if (!v) {
849 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
850 return ERR_ALERT | ERR_FATAL;
851 }
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100852 if (strcmp("ssl-min-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200853 methods->min = v;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100854 else if (strcmp("ssl-max-ver", args[cur_arg]) == 0)
William Lallemanddad31052020-05-14 17:47:32 +0200855 methods->max = v;
856 else {
857 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
858 return ERR_ALERT | ERR_FATAL;
859 }
860 return 0;
861}
862
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100863static 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 +0200864{
William Lallemand8177ad92020-05-20 16:49:02 +0200865 int ret;
866
William Lallemanddad31052020-05-14 17:47:32 +0200867#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
868 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
869#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200870 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
871 if (ret != ERR_NONE)
872 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200873
William Lallemand8177ad92020-05-20 16:49:02 +0200874 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
875 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
876
877 return ret;
878}
William Lallemanddad31052020-05-14 17:47:32 +0200879static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
880{
881 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
882}
883
884static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
885{
886 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
887}
888
889/* parse the "no-tls-tickets" bind keyword */
890static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
891{
892 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
893 return 0;
894}
895
896/* parse the "allow-0rtt" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100897static 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 +0200898{
899 conf->early_data = 1;
900 return 0;
901}
902
903static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
904{
905 conf->ssl_conf.early_data = 1;
906 return 0;
907}
908
909/* parse the "npn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100910static 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 +0200911{
912#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
913 char *p1, *p2;
914
915 if (!*args[cur_arg + 1]) {
916 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
917 return ERR_ALERT | ERR_FATAL;
918 }
919
920 free(conf->npn_str);
921
922 /* the NPN string is built as a suite of (<len> <name>)*,
923 * so we reuse each comma to store the next <len> and need
924 * one more for the end of the string.
925 */
926 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
927 conf->npn_str = calloc(1, conf->npn_len + 1);
928 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
929
930 /* replace commas with the name length */
931 p1 = conf->npn_str;
932 p2 = p1 + 1;
933 while (1) {
934 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
935 if (!p2)
936 p2 = p1 + 1 + strlen(p1 + 1);
937
938 if (p2 - (p1 + 1) > 255) {
939 *p2 = '\0';
940 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
941 return ERR_ALERT | ERR_FATAL;
942 }
943
944 *p1 = p2 - (p1 + 1);
945 p1 = p2;
946
947 if (!*p2)
948 break;
949
950 *(p2++) = '\0';
951 }
952 return 0;
953#else
954 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
955 return ERR_ALERT | ERR_FATAL;
956#endif
957}
958
959static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
960{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +0100961 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +0200962}
963
964
965/* Parses a alpn string and converts it to the right format for the SSL api */
966int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
967{
968 char *p1, *p2, *alpn = NULL;
969 int len, ret = 0;
970
971 *alpn_str = NULL;
972 *alpn_len = 0;
973
974 if (!*arg) {
975 memprintf(err, "missing the comma-delimited ALPN protocol suite");
976 goto error;
977 }
978
979 /* the ALPN string is built as a suite of (<len> <name>)*,
980 * so we reuse each comma to store the next <len> and need
981 * one more for the end of the string.
982 */
983 len = strlen(arg) + 1;
984 alpn = calloc(1, len+1);
985 if (!alpn) {
986 memprintf(err, "'%s' : out of memory", arg);
987 goto error;
988 }
989 memcpy(alpn+1, arg, len);
990
991 /* replace commas with the name length */
992 p1 = alpn;
993 p2 = p1 + 1;
994 while (1) {
995 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
996 if (!p2)
997 p2 = p1 + 1 + strlen(p1 + 1);
998
999 if (p2 - (p1 + 1) > 255) {
1000 *p2 = '\0';
1001 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
1002 goto error;
1003 }
1004
1005 *p1 = p2 - (p1 + 1);
1006 p1 = p2;
1007
1008 if (!*p2)
1009 break;
1010
1011 *(p2++) = '\0';
1012 }
1013
1014 *alpn_str = alpn;
1015 *alpn_len = len;
1016
1017 out:
1018 return ret;
1019
1020 error:
1021 free(alpn);
1022 ret = ERR_ALERT | ERR_FATAL;
1023 goto out;
1024}
1025
1026/* parse the "alpn" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001027static 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 +02001028{
1029#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1030 int ret;
1031
1032 free(conf->alpn_str);
1033
1034 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
1035 if (ret)
1036 memprintf(err, "'%s' : %s", args[cur_arg], *err);
1037 return ret;
1038#else
1039 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
1040 return ERR_ALERT | ERR_FATAL;
1041#endif
1042}
1043
1044static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1045{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001046 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001047}
1048
1049/* parse the "ssl" bind keyword */
1050static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1051{
Frédéric Lécaillee50afbd2020-11-23 11:33:12 +01001052 /* Do not change the xprt for QUIC. */
1053 if (conf->xprt != xprt_get(XPRT_QUIC))
1054 conf->xprt = &ssl_sock;
William Lallemanddad31052020-05-14 17:47:32 +02001055 conf->is_ssl = 1;
1056
1057 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1058 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001059#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001060 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1061 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1062#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001063#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001064 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1065 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1066#endif
1067 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1068 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1069 if (!conf->ssl_conf.ssl_methods.min)
1070 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1071 if (!conf->ssl_conf.ssl_methods.max)
1072 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1073
1074 return 0;
1075}
1076
1077/* parse the "prefer-client-ciphers" bind keyword */
1078static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1079{
1080 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1081 return 0;
1082}
1083
1084/* parse the "generate-certificates" bind keyword */
1085static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1086{
1087#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1088 conf->generate_certs = 1;
1089#else
1090 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1091 err && *err ? *err : "");
1092#endif
1093 return 0;
1094}
1095
1096/* parse the "strict-sni" bind keyword */
1097static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1098{
1099 conf->strict_sni = 1;
1100 return 0;
1101}
1102
1103/* parse the "tls-ticket-keys" bind keyword */
1104static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1105{
1106#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1107 FILE *f = NULL;
1108 int i = 0;
1109 char thisline[LINESIZE];
1110 struct tls_keys_ref *keys_ref = NULL;
1111
1112 if (!*args[cur_arg + 1]) {
1113 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1114 goto fail;
1115 }
1116
1117 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1118 if (keys_ref) {
1119 keys_ref->refcount++;
1120 conf->keys_ref = keys_ref;
1121 return 0;
1122 }
1123
1124 keys_ref = calloc(1, sizeof(*keys_ref));
1125 if (!keys_ref) {
1126 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1127 goto fail;
1128 }
1129
1130 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1131 if (!keys_ref->tlskeys) {
1132 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1133 goto fail;
1134 }
1135
1136 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1137 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1138 goto fail;
1139 }
1140
1141 keys_ref->filename = strdup(args[cur_arg + 1]);
1142 if (!keys_ref->filename) {
1143 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1144 goto fail;
1145 }
1146
1147 keys_ref->key_size_bits = 0;
1148 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1149 int len = strlen(thisline);
1150 int dec_size;
1151
1152 /* Strip newline characters from the end */
1153 if(thisline[len - 1] == '\n')
1154 thisline[--len] = 0;
1155
1156 if(thisline[len - 1] == '\r')
1157 thisline[--len] = 0;
1158
1159 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1160 if (dec_size < 0) {
1161 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1162 goto fail;
1163 }
1164 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1165 keys_ref->key_size_bits = 128;
1166 }
1167 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1168 keys_ref->key_size_bits = 256;
1169 }
1170 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1171 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1172 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1173 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1174 goto fail;
1175 }
1176 i++;
1177 }
1178
1179 if (i < TLS_TICKETS_NO) {
1180 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1181 goto fail;
1182 }
1183
1184 fclose(f);
1185
1186 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1187 i -= 2;
1188 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1189 keys_ref->unique_id = -1;
1190 keys_ref->refcount = 1;
1191 HA_RWLOCK_INIT(&keys_ref->lock);
1192 conf->keys_ref = keys_ref;
1193
Willy Tarreau2b718102021-04-21 07:32:39 +02001194 LIST_INSERT(&tlskeys_reference, &keys_ref->list);
William Lallemanddad31052020-05-14 17:47:32 +02001195
1196 return 0;
1197
1198 fail:
1199 if (f)
1200 fclose(f);
1201 if (keys_ref) {
1202 free(keys_ref->filename);
1203 free(keys_ref->tlskeys);
1204 free(keys_ref);
1205 }
1206 return ERR_ALERT | ERR_FATAL;
1207
1208#else
1209 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1210 return ERR_ALERT | ERR_FATAL;
1211#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1212}
1213
1214/* parse the "verify" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001215static 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 +02001216{
1217 if (!*args[cur_arg + 1]) {
1218 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1219 return ERR_ALERT | ERR_FATAL;
1220 }
1221
1222 if (strcmp(args[cur_arg + 1], "none") == 0)
1223 conf->verify = SSL_SOCK_VERIFY_NONE;
1224 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1225 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1226 else if (strcmp(args[cur_arg + 1], "required") == 0)
1227 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1228 else {
1229 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1230 args[cur_arg], args[cur_arg + 1]);
1231 return ERR_ALERT | ERR_FATAL;
1232 }
1233
1234 return 0;
1235}
1236static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1237{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001238 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001239}
1240
1241/* parse the "no-ca-names" bind keyword */
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001242static 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 +02001243{
1244 conf->no_ca_names = 1;
1245 return 0;
1246}
1247static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1248{
Remi Tricot-Le Bretonfb00f312021-03-23 16:41:53 +01001249 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, 0, err);
William Lallemanddad31052020-05-14 17:47:32 +02001250}
1251
1252/***************************** "server" keywords Parsing ********************************************/
1253
1254/* parse the "npn" bind keyword */
1255static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1256{
1257#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1258 char *p1, *p2;
1259
1260 if (!*args[*cur_arg + 1]) {
1261 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1262 return ERR_ALERT | ERR_FATAL;
1263 }
1264
1265 free(newsrv->ssl_ctx.npn_str);
1266
1267 /* the NPN string is built as a suite of (<len> <name>)*,
1268 * so we reuse each comma to store the next <len> and need
1269 * one more for the end of the string.
1270 */
1271 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1272 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001273 if (!newsrv->ssl_ctx.npn_str) {
1274 memprintf(err, "out of memory");
1275 return ERR_ALERT | ERR_FATAL;
1276 }
1277
William Lallemanddad31052020-05-14 17:47:32 +02001278 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1279 newsrv->ssl_ctx.npn_len);
1280
1281 /* replace commas with the name length */
1282 p1 = newsrv->ssl_ctx.npn_str;
1283 p2 = p1 + 1;
1284 while (1) {
1285 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1286 newsrv->ssl_ctx.npn_len - (p1 + 1));
1287 if (!p2)
1288 p2 = p1 + 1 + strlen(p1 + 1);
1289
1290 if (p2 - (p1 + 1) > 255) {
1291 *p2 = '\0';
1292 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1293 return ERR_ALERT | ERR_FATAL;
1294 }
1295
1296 *p1 = p2 - (p1 + 1);
1297 p1 = p2;
1298
1299 if (!*p2)
1300 break;
1301
1302 *(p2++) = '\0';
1303 }
1304 return 0;
1305#else
1306 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1307 return ERR_ALERT | ERR_FATAL;
1308#endif
1309}
1310
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001311#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1312static int parse_alpn(char *alpn, char **out_alpn_str, int *out_alpn_len, char **err)
1313{
1314 free(*out_alpn_str);
1315 return ssl_sock_parse_alpn(alpn, out_alpn_str, out_alpn_len, err);
1316}
1317#endif
1318
1319/* parse the "alpn" server keyword */
William Lallemanddad31052020-05-14 17:47:32 +02001320static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1321{
1322#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001323 int ret = parse_alpn(args[*cur_arg + 1],
1324 &newsrv->ssl_ctx.alpn_str,
1325 &newsrv->ssl_ctx.alpn_len, err);
1326 if (ret)
1327 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1328 return ret;
1329#else
1330 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1331 return ERR_ALERT | ERR_FATAL;
1332#endif
1333}
William Lallemanddad31052020-05-14 17:47:32 +02001334
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001335/* parse the "check-alpn" server keyword */
1336static int srv_parse_check_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1337{
1338#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1339 int ret = parse_alpn(args[*cur_arg + 1],
1340 &newsrv->check.alpn_str,
1341 &newsrv->check.alpn_len, err);
William Lallemanddad31052020-05-14 17:47:32 +02001342 if (ret)
1343 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1344 return ret;
1345#else
1346 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1347 return ERR_ALERT | ERR_FATAL;
1348#endif
1349}
1350
1351/* parse the "ca-file" server keyword */
1352static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1353{
Amaury Denoyelle48255022021-05-19 09:46:59 +02001354 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1355
William Lallemanddad31052020-05-14 17:47:32 +02001356 if (!*args[*cur_arg + 1]) {
1357 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1358 return ERR_ALERT | ERR_FATAL;
1359 }
1360
1361 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1362 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1363 else
1364 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1365
Amaury Denoyelle48255022021-05-19 09:46:59 +02001366 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file, create_if_none, CAFILE_CERT)) {
William Lallemanddad31052020-05-14 17:47:32 +02001367 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1368 return ERR_ALERT | ERR_FATAL;
1369 }
Amaury Denoyelle48255022021-05-19 09:46:59 +02001370
William Lallemanddad31052020-05-14 17:47:32 +02001371 return 0;
1372}
1373
1374/* parse the "check-sni" server keyword */
1375static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1376{
1377 if (!*args[*cur_arg + 1]) {
1378 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1379 return ERR_ALERT | ERR_FATAL;
1380 }
1381
1382 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1383 if (!newsrv->check.sni) {
1384 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1385 return ERR_ALERT | ERR_FATAL;
1386 }
1387 return 0;
1388
1389}
1390
William Dauchyfc52f522020-11-14 19:25:32 +01001391/* common function to init ssl_ctx */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001392static int ssl_sock_init_srv(struct server *s)
William Lallemanddad31052020-05-14 17:47:32 +02001393{
William Dauchyfc52f522020-11-14 19:25:32 +01001394 if (global_ssl.connect_default_ciphers && !s->ssl_ctx.ciphers)
1395 s->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001396#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001397 if (global_ssl.connect_default_ciphersuites && !s->ssl_ctx.ciphersuites) {
William Dauchyfc52f522020-11-14 19:25:32 +01001398 s->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001399 if (!s->ssl_ctx.ciphersuites)
1400 return 1;
1401 }
William Lallemanddad31052020-05-14 17:47:32 +02001402#endif
William Dauchyfc52f522020-11-14 19:25:32 +01001403 s->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1404 s->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1405
1406 if (!s->ssl_ctx.methods.min)
1407 s->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
William Lallemanddad31052020-05-14 17:47:32 +02001408
William Dauchyfc52f522020-11-14 19:25:32 +01001409 if (!s->ssl_ctx.methods.max)
1410 s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001411
1412 return 0;
William Dauchyfc52f522020-11-14 19:25:32 +01001413}
1414
1415/* parse the "check-ssl" server keyword */
1416static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1417{
1418 newsrv->check.use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001419 if (ssl_sock_init_srv(newsrv)) {
1420 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1421 return ERR_ALERT | ERR_FATAL;
1422 }
1423
William Lallemanddad31052020-05-14 17:47:32 +02001424 return 0;
1425}
1426
1427/* parse the "ciphers" server keyword */
1428static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1429{
1430 if (!*args[*cur_arg + 1]) {
1431 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1432 return ERR_ALERT | ERR_FATAL;
1433 }
1434
1435 free(newsrv->ssl_ctx.ciphers);
1436 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001437
1438 if (!newsrv->ssl_ctx.ciphers) {
1439 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1440 return ERR_ALERT | ERR_FATAL;
1441 }
1442
William Lallemanddad31052020-05-14 17:47:32 +02001443 return 0;
1444}
1445
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001446#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001447/* parse the "ciphersuites" server keyword */
1448static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1449{
1450 if (!*args[*cur_arg + 1]) {
1451 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1452 return ERR_ALERT | ERR_FATAL;
1453 }
1454
1455 free(newsrv->ssl_ctx.ciphersuites);
1456 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001457
1458 if (!newsrv->ssl_ctx.ciphersuites) {
1459 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1460 return ERR_ALERT | ERR_FATAL;
1461 }
1462
William Lallemanddad31052020-05-14 17:47:32 +02001463 return 0;
1464}
1465#endif
1466
1467/* parse the "crl-file" server keyword */
1468static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1469{
1470#ifndef X509_V_FLAG_CRL_CHECK
1471 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1472 return ERR_ALERT | ERR_FATAL;
1473#else
Amaury Denoyellefde82602021-06-14 10:10:32 +02001474 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
1475
William Lallemanddad31052020-05-14 17:47:32 +02001476 if (!*args[*cur_arg + 1]) {
1477 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1478 return ERR_ALERT | ERR_FATAL;
1479 }
1480
1481 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1482 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1483 else
1484 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1485
Amaury Denoyellefde82602021-06-14 10:10:32 +02001486 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file, create_if_none, CAFILE_CRL)) {
William Lallemanddad31052020-05-14 17:47:32 +02001487 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1488 return ERR_ALERT | ERR_FATAL;
1489 }
1490 return 0;
1491#endif
1492}
1493
1494/* parse the "crt" server keyword */
1495static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1496{
Amaury Denoyelle93be21e2021-05-21 16:22:53 +02001497 const int create_if_none = newsrv->flags & SRV_F_DYNAMIC ? 0 : 1;
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001498 int retval = -1;
1499 char *path = NULL;
1500
William Lallemanddad31052020-05-14 17:47:32 +02001501 if (!*args[*cur_arg + 1]) {
1502 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1503 return ERR_ALERT | ERR_FATAL;
1504 }
1505
1506 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001507 memprintf(&path, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
William Lallemanddad31052020-05-14 17:47:32 +02001508 else
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001509 memprintf(&path, "%s", args[*cur_arg + 1]);
1510
1511 if (path) {
Amaury Denoyelle93be21e2021-05-21 16:22:53 +02001512 retval = ssl_sock_load_srv_cert(path, newsrv, create_if_none, err);
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001513 free(path);
1514 }
William Lallemanddad31052020-05-14 17:47:32 +02001515
Remi Tricot-Le Bretonbb470aa2021-01-25 17:19:45 +01001516 return retval;
William Lallemanddad31052020-05-14 17:47:32 +02001517}
1518
1519/* parse the "no-check-ssl" server keyword */
1520static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1521{
1522 newsrv->check.use_ssl = -1;
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001523 ha_free(&newsrv->ssl_ctx.ciphers);
William Lallemanddad31052020-05-14 17:47:32 +02001524 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1525 return 0;
1526}
1527
1528/* parse the "no-send-proxy-v2-ssl" server keyword */
1529static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1530{
1531 newsrv->pp_opts &= ~SRV_PP_V2;
1532 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1533 return 0;
1534}
1535
1536/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1537static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1538{
1539 newsrv->pp_opts &= ~SRV_PP_V2;
1540 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1541 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1542 return 0;
1543}
1544
1545/* parse the "no-ssl" server keyword */
1546static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1547{
William Dauchyf6370442020-11-14 19:25:33 +01001548 /* if default-server have use_ssl, prepare ssl settings */
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001549 if (newsrv->use_ssl == 1) {
1550 if (ssl_sock_init_srv(newsrv)) {
1551 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1552 return ERR_ALERT | ERR_FATAL;
1553 }
1554 }
William Dauchyf6370442020-11-14 19:25:33 +01001555 else {
Willy Tarreau61cfdf42021-02-20 10:46:51 +01001556 ha_free(&newsrv->ssl_ctx.ciphers);
William Dauchyf6370442020-11-14 19:25:33 +01001557 }
William Lallemanddad31052020-05-14 17:47:32 +02001558 newsrv->use_ssl = -1;
William Lallemanddad31052020-05-14 17:47:32 +02001559 return 0;
1560}
1561
1562/* parse the "allow-0rtt" server keyword */
1563static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1564{
1565 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1566 return 0;
1567}
1568
1569/* parse the "no-ssl-reuse" server keyword */
1570static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1571{
1572 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1573 return 0;
1574}
1575
1576/* parse the "no-tls-tickets" server keyword */
1577static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1578{
1579 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1580 return 0;
1581}
1582/* parse the "send-proxy-v2-ssl" server keyword */
1583static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1584{
1585 newsrv->pp_opts |= SRV_PP_V2;
1586 newsrv->pp_opts |= SRV_PP_V2_SSL;
1587 return 0;
1588}
1589
1590/* parse the "send-proxy-v2-ssl-cn" server keyword */
1591static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1592{
1593 newsrv->pp_opts |= SRV_PP_V2;
1594 newsrv->pp_opts |= SRV_PP_V2_SSL;
1595 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1596 return 0;
1597}
1598
1599/* parse the "sni" server keyword */
1600static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1601{
1602#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1603 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1604 return ERR_ALERT | ERR_FATAL;
1605#else
1606 char *arg;
1607
1608 arg = args[*cur_arg + 1];
1609 if (!*arg) {
1610 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1611 return ERR_ALERT | ERR_FATAL;
1612 }
1613
1614 free(newsrv->sni_expr);
1615 newsrv->sni_expr = strdup(arg);
Amaury Denoyelle1f9333b2021-06-01 11:54:23 +02001616 if (!newsrv->sni_expr) {
1617 memprintf(err, "out of memory");
1618 return ERR_ALERT | ERR_FATAL;
1619 }
William Lallemanddad31052020-05-14 17:47:32 +02001620
1621 return 0;
1622#endif
1623}
1624
1625/* parse the "ssl" server keyword */
1626static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1627{
1628 newsrv->use_ssl = 1;
Amaury Denoyelle949c94e2021-05-19 11:52:50 +02001629 if (ssl_sock_init_srv(newsrv)) {
1630 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1631 return ERR_ALERT | ERR_FATAL;
1632 }
1633
William Lallemanddad31052020-05-14 17:47:32 +02001634 return 0;
1635}
1636
1637/* parse the "ssl-reuse" server keyword */
1638static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1639{
1640 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1641 return 0;
1642}
1643
1644/* parse the "tls-tickets" server keyword */
1645static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1646{
1647 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1648 return 0;
1649}
1650
1651/* parse the "verify" server keyword */
1652static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1653{
1654 if (!*args[*cur_arg + 1]) {
1655 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1656 return ERR_ALERT | ERR_FATAL;
1657 }
1658
1659 if (strcmp(args[*cur_arg + 1], "none") == 0)
1660 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1661 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1662 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1663 else {
1664 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1665 args[*cur_arg], args[*cur_arg + 1]);
1666 return ERR_ALERT | ERR_FATAL;
1667 }
1668
1669 return 0;
1670}
1671
1672/* parse the "verifyhost" server keyword */
1673static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1674{
1675 if (!*args[*cur_arg + 1]) {
1676 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1677 return ERR_ALERT | ERR_FATAL;
1678 }
1679
1680 free(newsrv->ssl_ctx.verify_host);
1681 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1682
Amaury Denoyellecbbf87f2021-05-19 14:57:04 +02001683 if (!newsrv->ssl_ctx.verify_host) {
1684 memprintf(err, "'%s' : not enough memory", args[*cur_arg]);
1685 return ERR_ALERT | ERR_FATAL;
1686 }
1687
William Lallemanddad31052020-05-14 17:47:32 +02001688 return 0;
1689}
1690
1691/* parse the "ssl-default-bind-options" keyword in global section */
1692static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001693 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001694 char **err) {
1695 int i = 1;
1696
1697 if (*(args[i]) == 0) {
1698 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1699 return -1;
1700 }
1701 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001702 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001703 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001704 else if (strcmp(args[i], "prefer-client-ciphers") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001705 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001706 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001707 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1708 i++;
1709 else {
1710 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1711 return -1;
1712 }
1713 }
1714 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1715 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1716 return -1;
1717 }
1718 i++;
1719 }
1720 return 0;
1721}
1722
1723/* parse the "ssl-default-server-options" keyword in global section */
1724static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001725 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001726 char **err) {
1727 int i = 1;
1728
1729 if (*(args[i]) == 0) {
1730 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1731 return -1;
1732 }
1733 while (*(args[i])) {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001734 if (strcmp(args[i], "no-tls-tickets") == 0)
William Lallemanddad31052020-05-14 17:47:32 +02001735 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Tim Duesterhuse5ff1412021-01-02 22:31:53 +01001736 else if (strcmp(args[i], "ssl-min-ver") == 0 || strcmp(args[i], "ssl-max-ver") == 0) {
William Lallemanddad31052020-05-14 17:47:32 +02001737 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1738 i++;
1739 else {
1740 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1741 return -1;
1742 }
1743 }
1744 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1745 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1746 return -1;
1747 }
1748 i++;
1749 }
1750 return 0;
1751}
1752
1753/* parse the "ca-base" / "crt-base" keywords in global section.
1754 * Returns <0 on alert, >0 on warning, 0 on success.
1755 */
1756static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001757 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001758 char **err)
1759{
1760 char **target;
1761
1762 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1763
1764 if (too_many_args(1, args, err, NULL))
1765 return -1;
1766
1767 if (*target) {
1768 memprintf(err, "'%s' already specified.", args[0]);
1769 return -1;
1770 }
1771
1772 if (*(args[1]) == 0) {
1773 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1774 return -1;
1775 }
1776 *target = strdup(args[1]);
1777 return 0;
1778}
1779
1780/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1781static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
Willy Tarreau01825162021-03-09 09:53:46 +01001782 const struct proxy *defpx, const char *file, int line,
William Lallemanddad31052020-05-14 17:47:32 +02001783 char **err)
1784{
William Lallemand9a1d8392020-08-10 17:28:23 +02001785#ifdef SSL_CTX_build_cert_chain
William Lallemanddad31052020-05-14 17:47:32 +02001786 global_ssl.skip_self_issued_ca = 1;
1787 return 0;
William Lallemand9a1d8392020-08-10 17:28:23 +02001788#else
1789 memprintf(err, "global statement '%s' requires at least OpenSSL 1.0.2.", args[0]);
1790 return -1;
1791#endif
William Lallemanddad31052020-05-14 17:47:32 +02001792}
1793
1794
1795
1796
1797
1798/* Note: must not be declared <const> as its list will be overwritten.
1799 * Please take care of keeping this list alphabetically sorted, doing so helps
1800 * all code contributors.
1801 * Optional keywords are also declared with a NULL ->parse() function so that
1802 * the config parser can report an appropriate error when a known keyword was
1803 * not enabled.
1804 */
1805
1806/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1807 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1808struct ssl_bind_kw ssl_bind_kws[] = {
1809 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1810 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1811 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1812 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1813 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001814#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001815 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1816#endif
1817 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1818 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1819 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1820 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1821 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1822 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1823 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1824 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1825 { NULL, NULL, 0 },
1826};
1827
1828/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1829
1830static struct bind_kw_list bind_kws = { "SSL", { }, {
1831 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1832 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1833 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1834 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1835 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1836 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1837 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1838 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001839#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001840 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1841#endif
1842 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1843 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1844 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1845 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1846 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1847 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1848 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1849 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1850 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1851 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1852 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1853 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1854 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1855 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1856 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1857 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1858 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1859 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1860 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1861 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1862 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1863 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1864 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1865 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1866 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1867 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1868 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1869 { NULL, NULL, 0 },
1870}};
1871
1872INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1873
1874/* Note: must not be declared <const> as its list will be overwritten.
1875 * Please take care of keeping this list alphabetically sorted, doing so helps
1876 * all code contributors.
1877 * Optional keywords are also declared with a NULL ->parse() function so that
1878 * the config parser can report an appropriate error when a known keyword was
1879 * not enabled.
1880 */
1881static struct srv_kw_list srv_kws = { "SSL", { }, {
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001882 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 1 }, /* Allow using early data on this server */
1883 { "alpn", srv_parse_alpn, 1, 1, 1 }, /* Set ALPN supported protocols */
Amaury Denoyelle48255022021-05-19 09:46:59 +02001884 { "ca-file", srv_parse_ca_file, 1, 1, 1 }, /* set CAfile to process verify server cert */
Amaury Denoyelle7addf562021-05-21 16:45:10 +02001885 { "check-alpn", srv_parse_check_alpn, 1, 1, 0 }, /* Set ALPN used for checks */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001886 { "check-sni", srv_parse_check_sni, 1, 1, 0 }, /* set SNI */
1887 { "check-ssl", srv_parse_check_ssl, 0, 1, 0 }, /* enable SSL for health checks */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001888 { "ciphers", srv_parse_ciphers, 1, 1, 1 }, /* select the cipher suite */
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001889#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001890 { "ciphersuites", srv_parse_ciphersuites, 1, 1, 1 }, /* select the cipher suite */
William Lallemanddad31052020-05-14 17:47:32 +02001891#endif
Amaury Denoyellefde82602021-06-14 10:10:32 +02001892 { "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 +02001893 { "crt", srv_parse_crt, 1, 1, 1 }, /* set client certificate */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001894 { "force-sslv3", srv_parse_tls_method_options, 0, 1, 1 }, /* force SSLv3 */
1895 { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv10 */
1896 { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv11 */
1897 { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv12 */
1898 { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 1 }, /* force TLSv13 */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001899 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */
1900 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */
1901 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */
1902 { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001903 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 1 }, /* disable session reuse */
1904 { "no-sslv3", srv_parse_tls_method_options, 0, 0, 1 }, /* disable SSLv3 */
1905 { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv10 */
1906 { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv11 */
1907 { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv12 */
1908 { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 1 }, /* disable TLSv13 */
1909 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 1 }, /* disable session resumption tickets */
1910 { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
1911 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
1912 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
1913 { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
Amaury Denoyelle34897d22021-05-19 09:49:41 +02001914 { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001915 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
1916 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* maximum version */
Amaury Denoyelle76e10e72021-03-08 17:08:01 +01001917 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */
Amaury Denoyelle71f9a062021-05-20 15:10:55 +02001918 { "tls-tickets", srv_parse_tls_tickets, 0, 1, 1 }, /* enable session resumption tickets */
1919 { "verify", srv_parse_verify, 1, 1, 1 }, /* set SSL verify method */
1920 { "verifyhost", srv_parse_verifyhost, 1, 1, 1 }, /* require that SSL cert verifies for hostname */
William Lallemanddad31052020-05-14 17:47:32 +02001921 { NULL, NULL, 0, 0 },
1922}};
1923
1924INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1925
1926static struct cfg_kw_list cfg_kws = {ILH, {
1927 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1928 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1929 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1930 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1931 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1932 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1933#ifndef OPENSSL_NO_DH
1934 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1935#endif
1936 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
1937#ifndef OPENSSL_NO_ENGINE
1938 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1939#endif
1940 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1941 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1942#ifndef OPENSSL_NO_DH
1943 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1944#endif
1945 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
1946 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1947 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
1948 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
1949 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
William Lallemand7d42ef52020-07-06 11:41:30 +02001950 { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
William Lallemanddad31052020-05-14 17:47:32 +02001951 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1952 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Ilya Shipitsin0aa8c292020-11-04 00:39:07 +05001953#if defined(SSL_CTX_set1_curves_list)
William Lallemanddad31052020-05-14 17:47:32 +02001954 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
1955#endif
Ilya Shipitsinf34ed0b2020-11-21 14:37:34 +05001956#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
William Lallemanddad31052020-05-14 17:47:32 +02001957 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
1958 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
1959#endif
1960 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
William Lallemand8e8581e2020-10-20 17:36:46 +02001961 { CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
William Lallemanddad31052020-05-14 17:47:32 +02001962 { 0, NULL, NULL },
1963}};
1964
1965INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);