blob: 5c3688110f8dd5405de6bfbdf2a427f2f672a306 [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
34#include <common/base64.h>
35#include <common/cfgparse.h>
36#include <common/initcall.h>
37#include <common/openssl-compat.h>
38
39#include <types/ssl_sock.h>
40
41#include <proto/listener.h>
42#include <proto/ssl_sock.h>
43
44
45/****************** Global Section Parsing ********************************************/
46
47static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
48 struct proxy *defpx, const char *file, int line,
49 char **err)
50{
51 char *path;
52 struct dirent **de_list;
53 int i, n;
54 struct stat buf;
55 char *end;
56 char fp[MAXPATHLEN+1];
57
58 if (too_many_args(1, args, err, NULL))
59 return -1;
60
61 path = args[1];
62 if (*path == 0 || stat(path, &buf)) {
63 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
64 err && *err ? *err : "", args[0]);
65 return -1;
66 }
67 if (S_ISDIR(buf.st_mode) == 0) {
68 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
69 err && *err ? *err : "", args[0], path);
70 return -1;
71 }
72
73 /* strip trailing slashes, including first one */
74 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
75 *end = 0;
76 /* path already parsed? */
77 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
78 return 0;
79 /* overwrite old issuers_chain_path */
80 free(global_ssl.issuers_chain_path);
81 global_ssl.issuers_chain_path = strdup(path);
82 ssl_free_global_issuers();
83
84 n = scandir(path, &de_list, 0, alphasort);
85 if (n < 0) {
86 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
87 err && *err ? *err : "", args[0], path, strerror(errno));
88 return -1;
89 }
90 for (i = 0; i < n; i++) {
91 struct dirent *de = de_list[i];
92 BIO *in = NULL;
93 char *warn = NULL;
94
95 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
96 free(de);
97 if (stat(fp, &buf) != 0) {
98 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
99 goto next;
100 }
101 if (!S_ISREG(buf.st_mode))
102 goto next;
103
104 in = BIO_new(BIO_s_file());
105 if (in == NULL)
106 goto next;
107 if (BIO_read_filename(in, fp) <= 0)
108 goto next;
109 ssl_load_global_issuer_from_BIO(in, fp, &warn);
110 if (warn) {
111 ha_warning("%s", warn);
112 free(warn);
113 warn = NULL;
114 }
115 next:
116 if (in)
117 BIO_free(in);
118 }
119 free(de_list);
120
121 return 0;
122}
123
William Lallemanddad31052020-05-14 17:47:32 +0200124/* parse the "ssl-mode-async" keyword in global section.
125 * Returns <0 on alert, >0 on warning, 0 on success.
126 */
127static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
128 struct proxy *defpx, const char *file, int line,
129 char **err)
130{
131#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
132 global_ssl.async = 1;
133 global.ssl_used_async_engines = nb_engines;
134 return 0;
135#else
136 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
137 return -1;
138#endif
139}
140
William Lallemand5520d6f2020-05-18 13:42:49 +0200141#ifndef OPENSSL_NO_ENGINE
William Lallemanddad31052020-05-14 17:47:32 +0200142/* parse the "ssl-engine" keyword in global section.
143 * Returns <0 on alert, >0 on warning, 0 on success.
144 */
145static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
146 struct proxy *defpx, const char *file, int line,
147 char **err)
148{
149 char *algo;
150 int ret = -1;
151
152 if (*(args[1]) == 0) {
153 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
154 return ret;
155 }
156
157 if (*(args[2]) == 0) {
158 /* if no list of algorithms is given, it defaults to ALL */
159 algo = strdup("ALL");
160 goto add_engine;
161 }
162
163 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
164 if (strcmp(args[2], "algo") != 0) {
165 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
166 return ret;
167 }
168
169 if (*(args[3]) == 0) {
170 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
171 return ret;
172 }
173 algo = strdup(args[3]);
174
175add_engine:
176 if (ssl_init_single_engine(args[1], algo)==0) {
177 openssl_engines_initialized++;
178 ret = 0;
179 }
180 free(algo);
181 return ret;
182}
183#endif
184
185/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
186 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
187 */
188static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
189 struct proxy *defpx, const char *file, int line,
190 char **err)
191{
192 char **target;
193
194 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
195
196 if (too_many_args(1, args, err, NULL))
197 return -1;
198
199 if (*(args[1]) == 0) {
200 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
201 return -1;
202 }
203
204 free(*target);
205 *target = strdup(args[1]);
206 return 0;
207}
208
209#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
210/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
211 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
212 */
213static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
214 struct proxy *defpx, const char *file, int line,
215 char **err)
216{
217 char **target;
218
219 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
220
221 if (too_many_args(1, args, err, NULL))
222 return -1;
223
224 if (*(args[1]) == 0) {
225 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
226 return -1;
227 }
228
229 free(*target);
230 *target = strdup(args[1]);
231 return 0;
232}
233#endif
234
235#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
236/*
237 * parse the "ssl-default-bind-curves" keyword in a global section.
238 * Returns <0 on alert, >0 on warning, 0 on success.
239 */
240static int ssl_parse_global_curves(char **args, int section_type, struct proxy *curpx,
241 struct proxy *defpx, const char *file, int line,
242 char **err)
243{
244 char **target;
245 target = &global_ssl.listen_default_curves;
246
247 if (too_many_args(1, args, err, NULL))
248 return -1;
249
250 if (*(args[1]) == 0) {
251 memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
252 return -1;
253 }
254
255 free(*target);
256 *target = strdup(args[1]);
257 return 0;
258}
259#endif
260/* parse various global tune.ssl settings consisting in positive integers.
261 * Returns <0 on alert, >0 on warning, 0 on success.
262 */
263static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
264 struct proxy *defpx, const char *file, int line,
265 char **err)
266{
267 int *target;
268
269 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
270 target = &global.tune.sslcachesize;
271 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
272 target = (int *)&global_ssl.max_record;
273 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
274 target = &global_ssl.ctx_cache;
275 else if (strcmp(args[0], "maxsslconn") == 0)
276 target = &global.maxsslconn;
277 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
278 target = &global_ssl.capture_cipherlist;
279 else {
280 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
281 return -1;
282 }
283
284 if (too_many_args(1, args, err, NULL))
285 return -1;
286
287 if (*(args[1]) == 0) {
288 memprintf(err, "'%s' expects an integer argument.", args[0]);
289 return -1;
290 }
291
292 *target = atoi(args[1]);
293 if (*target < 0) {
294 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
295 return -1;
296 }
297 return 0;
298}
299
300static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
301 struct proxy *defpx, const char *file, int line,
302 char **err)
303{
304 int ret;
305
306 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
307 if (ret != 0)
308 return ret;
309
310 if (pool_head_ssl_capture) {
311 memprintf(err, "'%s' is already configured.", args[0]);
312 return -1;
313 }
314
315 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
316 if (!pool_head_ssl_capture) {
317 memprintf(err, "Out of memory error.");
318 return -1;
319 }
320 return 0;
321}
322
323/* parse "ssl.force-private-cache".
324 * Returns <0 on alert, >0 on warning, 0 on success.
325 */
326static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
327 struct proxy *defpx, const char *file, int line,
328 char **err)
329{
330 if (too_many_args(0, args, err, NULL))
331 return -1;
332
333 global_ssl.private_cache = 1;
334 return 0;
335}
336
337/* parse "ssl.lifetime".
338 * Returns <0 on alert, >0 on warning, 0 on success.
339 */
340static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
341 struct proxy *defpx, const char *file, int line,
342 char **err)
343{
344 const char *res;
345
346 if (too_many_args(1, args, err, NULL))
347 return -1;
348
349 if (*(args[1]) == 0) {
350 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
351 return -1;
352 }
353
354 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
355 if (res == PARSE_TIME_OVER) {
356 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
357 args[1], args[0]);
358 return -1;
359 }
360 else if (res == PARSE_TIME_UNDER) {
361 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
362 args[1], args[0]);
363 return -1;
364 }
365 else if (res) {
366 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
367 return -1;
368 }
369 return 0;
370}
371
372#ifndef OPENSSL_NO_DH
373/* parse "ssl-dh-param-file".
374 * Returns <0 on alert, >0 on warning, 0 on success.
375 */
376static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
377 struct proxy *defpx, const char *file, int line,
378 char **err)
379{
380 if (too_many_args(1, args, err, NULL))
381 return -1;
382
383 if (*(args[1]) == 0) {
384 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
385 return -1;
386 }
387
388 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
389 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
390 return -1;
391 }
392 return 0;
393}
394
395/* parse "ssl.default-dh-param".
396 * Returns <0 on alert, >0 on warning, 0 on success.
397 */
398static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
399 struct proxy *defpx, const char *file, int line,
400 char **err)
401{
402 if (too_many_args(1, args, err, NULL))
403 return -1;
404
405 if (*(args[1]) == 0) {
406 memprintf(err, "'%s' expects an integer argument.", args[0]);
407 return -1;
408 }
409
410 global_ssl.default_dh_param = atoi(args[1]);
411 if (global_ssl.default_dh_param < 1024) {
412 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
413 return -1;
414 }
415 return 0;
416}
417#endif
418
419
420/*
421 * parse "ssl-load-extra-files".
422 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
423 */
424static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
425 struct proxy *defpx, const char *file, int line,
426 char **err)
427{
428 int i;
429 int gf = SSL_GF_NONE;
430
431 if (*(args[1]) == 0)
432 goto err_arg;
433
434 for (i = 1; *args[i]; i++) {
435
436 if (!strcmp("bundle", args[i])) {
437 gf |= SSL_GF_BUNDLE;
438
439 } else if (!strcmp("sctl", args[i])) {
440 gf |= SSL_GF_SCTL;
441
442 } else if (!strcmp("ocsp", args[i])){
443 gf |= SSL_GF_OCSP;
444
445 } else if (!strcmp("issuer", args[i])){
446 gf |= SSL_GF_OCSP_ISSUER;
447
448 } else if (!strcmp("key", args[i])) {
449 gf |= SSL_GF_KEY;
450
451 } else if (!strcmp("none", args[i])) {
452 if (gf != SSL_GF_NONE)
453 goto err_alone;
454 gf = SSL_GF_NONE;
455 i++;
456 break;
457
458 } else if (!strcmp("all", args[i])) {
459 if (gf != SSL_GF_NONE)
460 goto err_alone;
461 gf = SSL_GF_ALL;
462 i++;
463 break;
464 } else {
465 goto err_arg;
466 }
467 }
468 /* break from loop but there are still arguments */
469 if (*args[i])
470 goto err_alone;
471
472 global_ssl.extra_files = gf;
473
474 return 0;
475
476err_alone:
477 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
478 return -1;
479
480err_arg:
481 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
482 return -1;
483}
484
485
486/***************************** Bind keyword Parsing ********************************************/
487
488/* for ca-file and ca-verify-file */
489static int ssl_bind_parse_ca_file_common(char **args, int cur_arg, char **ca_file_p, char **err)
490{
491 if (!*args[cur_arg + 1]) {
492 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
493 return ERR_ALERT | ERR_FATAL;
494 }
495
496 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
497 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
498 else
499 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
500
501 if (!ssl_store_load_locations_file(*ca_file_p)) {
502 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
503 return ERR_ALERT | ERR_FATAL;
504 }
505 return 0;
506}
507
508/* parse the "ca-file" bind keyword */
509static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
510{
511 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, err);
512}
513static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
514{
515 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
516}
517
518/* parse the "ca-verify-file" bind keyword */
519static int ssl_bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
520{
521 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, err);
522}
523static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
524{
525 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, err);
526}
527
528/* parse the "ca-sign-file" bind keyword */
529static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
530{
531 if (!*args[cur_arg + 1]) {
532 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
533 return ERR_ALERT | ERR_FATAL;
534 }
535
536 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
537 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
538 else
539 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
540
541 return 0;
542}
543
544/* parse the "ca-sign-pass" bind keyword */
545static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
546{
547 if (!*args[cur_arg + 1]) {
548 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
549 return ERR_ALERT | ERR_FATAL;
550 }
551 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
552 return 0;
553}
554
555/* parse the "ciphers" bind keyword */
556static int ssl_bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
557{
558 if (!*args[cur_arg + 1]) {
559 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
560 return ERR_ALERT | ERR_FATAL;
561 }
562
563 free(conf->ciphers);
564 conf->ciphers = strdup(args[cur_arg + 1]);
565 return 0;
566}
567static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
568{
569 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
570}
571
572#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
573/* parse the "ciphersuites" bind keyword */
574static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
575{
576 if (!*args[cur_arg + 1]) {
577 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
578 return ERR_ALERT | ERR_FATAL;
579 }
580
581 free(conf->ciphersuites);
582 conf->ciphersuites = strdup(args[cur_arg + 1]);
583 return 0;
584}
585static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
586{
587 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
588}
589#endif
590
591/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
592static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
593{
594 char path[MAXPATHLEN];
595
596 if (!*args[cur_arg + 1]) {
597 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
598 return ERR_ALERT | ERR_FATAL;
599 }
600
601 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
602 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
603 memprintf(err, "'%s' : path too long", args[cur_arg]);
604 return ERR_ALERT | ERR_FATAL;
605 }
606 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
607 return ssl_sock_load_cert(path, conf, err);
608 }
609
610 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
611}
612
613/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
614static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
615{
616 int err_code;
617
618 if (!*args[cur_arg + 1]) {
619 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
620 return ERR_ALERT | ERR_FATAL;
621 }
622
623 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], 0, conf, px, err);
624 if (err_code)
625 memprintf(err, "'%s' : %s", args[cur_arg], *err);
626
627 return err_code;
628}
629
630/* parse the "crl-file" bind keyword */
631static int ssl_bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
632{
633#ifndef X509_V_FLAG_CRL_CHECK
634 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
635 return ERR_ALERT | ERR_FATAL;
636#else
637 if (!*args[cur_arg + 1]) {
638 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
639 return ERR_ALERT | ERR_FATAL;
640 }
641
642 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
643 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
644 else
645 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
646
647 if (!ssl_store_load_locations_file(conf->crl_file)) {
648 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
649 return ERR_ALERT | ERR_FATAL;
650 }
651 return 0;
652#endif
653}
654static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
655{
656 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
657}
658
659/* parse the "curves" bind keyword keyword */
660static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
661{
662#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
663 if (!*args[cur_arg + 1]) {
664 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
665 return ERR_ALERT | ERR_FATAL;
666 }
667 conf->curves = strdup(args[cur_arg + 1]);
668 return 0;
669#else
670 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
671 return ERR_ALERT | ERR_FATAL;
672#endif
673}
674static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
675{
676 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
677}
678
679/* parse the "ecdhe" bind keyword keyword */
680static int ssl_bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
681{
682#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
683 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
684 return ERR_ALERT | ERR_FATAL;
685#elif defined(OPENSSL_NO_ECDH)
686 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
687 return ERR_ALERT | ERR_FATAL;
688#else
689 if (!*args[cur_arg + 1]) {
690 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
691 return ERR_ALERT | ERR_FATAL;
692 }
693
694 conf->ecdhe = strdup(args[cur_arg + 1]);
695
696 return 0;
697#endif
698}
699static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
700{
701 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
702}
703
704/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
705static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
706{
707 int code;
708 char *p = args[cur_arg + 1];
709 unsigned long long *ignerr = &conf->crt_ignerr;
710
711 if (!*p) {
712 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
713 return ERR_ALERT | ERR_FATAL;
714 }
715
716 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
717 ignerr = &conf->ca_ignerr;
718
719 if (strcmp(p, "all") == 0) {
720 *ignerr = ~0ULL;
721 return 0;
722 }
723
724 while (p) {
725 code = atoi(p);
726 if ((code <= 0) || (code > 63)) {
727 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
728 args[cur_arg], code, args[cur_arg + 1]);
729 return ERR_ALERT | ERR_FATAL;
730 }
731 *ignerr |= 1ULL << code;
732 p = strchr(p, ',');
733 if (p)
734 p++;
735 }
736
737 return 0;
738}
739
740/* parse tls_method_options "no-xxx" and "force-xxx" */
741static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
742{
743 uint16_t v;
744 char *p;
745 p = strchr(arg, '-');
746 if (!p)
747 goto fail;
748 p++;
749 if (!strcmp(p, "sslv3"))
750 v = CONF_SSLV3;
751 else if (!strcmp(p, "tlsv10"))
752 v = CONF_TLSV10;
753 else if (!strcmp(p, "tlsv11"))
754 v = CONF_TLSV11;
755 else if (!strcmp(p, "tlsv12"))
756 v = CONF_TLSV12;
757 else if (!strcmp(p, "tlsv13"))
758 v = CONF_TLSV13;
759 else
760 goto fail;
761 if (!strncmp(arg, "no-", 3))
762 methods->flags |= methodVersions[v].flag;
763 else if (!strncmp(arg, "force-", 6))
764 methods->min = methods->max = v;
765 else
766 goto fail;
767 return 0;
768 fail:
769 memprintf(err, "'%s' : option not implemented", arg);
770 return ERR_ALERT | ERR_FATAL;
771}
772
773static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
774{
775 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
776}
777
778static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
779{
780 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
781}
782
783/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
784static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
785{
786 uint16_t i, v = 0;
787 char *argv = args[cur_arg + 1];
788 if (!*argv) {
789 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
790 return ERR_ALERT | ERR_FATAL;
791 }
792 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
793 if (!strcmp(argv, methodVersions[i].name))
794 v = i;
795 if (!v) {
796 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
797 return ERR_ALERT | ERR_FATAL;
798 }
799 if (!strcmp("ssl-min-ver", args[cur_arg]))
800 methods->min = v;
801 else if (!strcmp("ssl-max-ver", args[cur_arg]))
802 methods->max = v;
803 else {
804 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
805 return ERR_ALERT | ERR_FATAL;
806 }
807 return 0;
808}
809
810static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
811{
William Lallemand8177ad92020-05-20 16:49:02 +0200812 int ret;
813
William Lallemanddad31052020-05-14 17:47:32 +0200814#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
815 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
816#endif
William Lallemand8177ad92020-05-20 16:49:02 +0200817 ret = parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods_cfg, err);
818 if (ret != ERR_NONE)
819 return ret;
William Lallemanddad31052020-05-14 17:47:32 +0200820
William Lallemand8177ad92020-05-20 16:49:02 +0200821 conf->ssl_methods.min = conf->ssl_methods_cfg.min;
822 conf->ssl_methods.max = conf->ssl_methods_cfg.max;
823
824 return ret;
825}
William Lallemanddad31052020-05-14 17:47:32 +0200826static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
827{
828 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
829}
830
831static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
832{
833 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
834}
835
836/* parse the "no-tls-tickets" bind keyword */
837static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
838{
839 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
840 return 0;
841}
842
843/* parse the "allow-0rtt" bind keyword */
844static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
845{
846 conf->early_data = 1;
847 return 0;
848}
849
850static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
851{
852 conf->ssl_conf.early_data = 1;
853 return 0;
854}
855
856/* parse the "npn" bind keyword */
857static int ssl_bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
858{
859#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
860 char *p1, *p2;
861
862 if (!*args[cur_arg + 1]) {
863 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
864 return ERR_ALERT | ERR_FATAL;
865 }
866
867 free(conf->npn_str);
868
869 /* the NPN string is built as a suite of (<len> <name>)*,
870 * so we reuse each comma to store the next <len> and need
871 * one more for the end of the string.
872 */
873 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
874 conf->npn_str = calloc(1, conf->npn_len + 1);
875 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
876
877 /* replace commas with the name length */
878 p1 = conf->npn_str;
879 p2 = p1 + 1;
880 while (1) {
881 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
882 if (!p2)
883 p2 = p1 + 1 + strlen(p1 + 1);
884
885 if (p2 - (p1 + 1) > 255) {
886 *p2 = '\0';
887 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
888 return ERR_ALERT | ERR_FATAL;
889 }
890
891 *p1 = p2 - (p1 + 1);
892 p1 = p2;
893
894 if (!*p2)
895 break;
896
897 *(p2++) = '\0';
898 }
899 return 0;
900#else
901 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
902 return ERR_ALERT | ERR_FATAL;
903#endif
904}
905
906static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
907{
908 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
909}
910
911
912/* Parses a alpn string and converts it to the right format for the SSL api */
913int ssl_sock_parse_alpn(char *arg, char **alpn_str, int *alpn_len, char **err)
914{
915 char *p1, *p2, *alpn = NULL;
916 int len, ret = 0;
917
918 *alpn_str = NULL;
919 *alpn_len = 0;
920
921 if (!*arg) {
922 memprintf(err, "missing the comma-delimited ALPN protocol suite");
923 goto error;
924 }
925
926 /* the ALPN string is built as a suite of (<len> <name>)*,
927 * so we reuse each comma to store the next <len> and need
928 * one more for the end of the string.
929 */
930 len = strlen(arg) + 1;
931 alpn = calloc(1, len+1);
932 if (!alpn) {
933 memprintf(err, "'%s' : out of memory", arg);
934 goto error;
935 }
936 memcpy(alpn+1, arg, len);
937
938 /* replace commas with the name length */
939 p1 = alpn;
940 p2 = p1 + 1;
941 while (1) {
942 p2 = memchr(p1 + 1, ',', alpn + len - (p1 + 1));
943 if (!p2)
944 p2 = p1 + 1 + strlen(p1 + 1);
945
946 if (p2 - (p1 + 1) > 255) {
947 *p2 = '\0';
948 memprintf(err, "ALPN protocol name too long : '%s'", p1 + 1);
949 goto error;
950 }
951
952 *p1 = p2 - (p1 + 1);
953 p1 = p2;
954
955 if (!*p2)
956 break;
957
958 *(p2++) = '\0';
959 }
960
961 *alpn_str = alpn;
962 *alpn_len = len;
963
964 out:
965 return ret;
966
967 error:
968 free(alpn);
969 ret = ERR_ALERT | ERR_FATAL;
970 goto out;
971}
972
973/* parse the "alpn" bind keyword */
974static int ssl_bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
975{
976#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
977 int ret;
978
979 free(conf->alpn_str);
980
981 ret = ssl_sock_parse_alpn(args[cur_arg + 1], &conf->alpn_str, &conf->alpn_len, err);
982 if (ret)
983 memprintf(err, "'%s' : %s", args[cur_arg], *err);
984 return ret;
985#else
986 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
987 return ERR_ALERT | ERR_FATAL;
988#endif
989}
990
991static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
992{
993 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
994}
995
996/* parse the "ssl" bind keyword */
997static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
998{
999 conf->xprt = &ssl_sock;
1000 conf->is_ssl = 1;
1001
1002 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
1003 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
1004#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
1005 if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
1006 conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
1007#endif
1008#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1009 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
1010 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
1011#endif
1012 conf->ssl_options |= global_ssl.listen_default_ssloptions;
1013 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
1014 if (!conf->ssl_conf.ssl_methods.min)
1015 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
1016 if (!conf->ssl_conf.ssl_methods.max)
1017 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
1018
1019 return 0;
1020}
1021
1022/* parse the "prefer-client-ciphers" bind keyword */
1023static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1024{
1025 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
1026 return 0;
1027}
1028
1029/* parse the "generate-certificates" bind keyword */
1030static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1031{
1032#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
1033 conf->generate_certs = 1;
1034#else
1035 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
1036 err && *err ? *err : "");
1037#endif
1038 return 0;
1039}
1040
1041/* parse the "strict-sni" bind keyword */
1042static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1043{
1044 conf->strict_sni = 1;
1045 return 0;
1046}
1047
1048/* parse the "tls-ticket-keys" bind keyword */
1049static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1050{
1051#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1052 FILE *f = NULL;
1053 int i = 0;
1054 char thisline[LINESIZE];
1055 struct tls_keys_ref *keys_ref = NULL;
1056
1057 if (!*args[cur_arg + 1]) {
1058 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
1059 goto fail;
1060 }
1061
1062 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
1063 if (keys_ref) {
1064 keys_ref->refcount++;
1065 conf->keys_ref = keys_ref;
1066 return 0;
1067 }
1068
1069 keys_ref = calloc(1, sizeof(*keys_ref));
1070 if (!keys_ref) {
1071 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1072 goto fail;
1073 }
1074
1075 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
1076 if (!keys_ref->tlskeys) {
1077 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1078 goto fail;
1079 }
1080
1081 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
1082 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
1083 goto fail;
1084 }
1085
1086 keys_ref->filename = strdup(args[cur_arg + 1]);
1087 if (!keys_ref->filename) {
1088 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
1089 goto fail;
1090 }
1091
1092 keys_ref->key_size_bits = 0;
1093 while (fgets(thisline, sizeof(thisline), f) != NULL) {
1094 int len = strlen(thisline);
1095 int dec_size;
1096
1097 /* Strip newline characters from the end */
1098 if(thisline[len - 1] == '\n')
1099 thisline[--len] = 0;
1100
1101 if(thisline[len - 1] == '\r')
1102 thisline[--len] = 0;
1103
1104 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
1105 if (dec_size < 0) {
1106 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
1107 goto fail;
1108 }
1109 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
1110 keys_ref->key_size_bits = 128;
1111 }
1112 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
1113 keys_ref->key_size_bits = 256;
1114 }
1115 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
1116 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
1117 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
1118 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
1119 goto fail;
1120 }
1121 i++;
1122 }
1123
1124 if (i < TLS_TICKETS_NO) {
1125 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
1126 goto fail;
1127 }
1128
1129 fclose(f);
1130
1131 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
1132 i -= 2;
1133 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
1134 keys_ref->unique_id = -1;
1135 keys_ref->refcount = 1;
1136 HA_RWLOCK_INIT(&keys_ref->lock);
1137 conf->keys_ref = keys_ref;
1138
1139 LIST_ADD(&tlskeys_reference, &keys_ref->list);
1140
1141 return 0;
1142
1143 fail:
1144 if (f)
1145 fclose(f);
1146 if (keys_ref) {
1147 free(keys_ref->filename);
1148 free(keys_ref->tlskeys);
1149 free(keys_ref);
1150 }
1151 return ERR_ALERT | ERR_FATAL;
1152
1153#else
1154 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
1155 return ERR_ALERT | ERR_FATAL;
1156#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1157}
1158
1159/* parse the "verify" bind keyword */
1160static int ssl_bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
1161{
1162 if (!*args[cur_arg + 1]) {
1163 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
1164 return ERR_ALERT | ERR_FATAL;
1165 }
1166
1167 if (strcmp(args[cur_arg + 1], "none") == 0)
1168 conf->verify = SSL_SOCK_VERIFY_NONE;
1169 else if (strcmp(args[cur_arg + 1], "optional") == 0)
1170 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
1171 else if (strcmp(args[cur_arg + 1], "required") == 0)
1172 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
1173 else {
1174 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
1175 args[cur_arg], args[cur_arg + 1]);
1176 return ERR_ALERT | ERR_FATAL;
1177 }
1178
1179 return 0;
1180}
1181static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1182{
1183 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
1184}
1185
1186/* parse the "no-ca-names" bind keyword */
1187static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
1188{
1189 conf->no_ca_names = 1;
1190 return 0;
1191}
1192static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1193{
1194 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
1195}
1196
1197/***************************** "server" keywords Parsing ********************************************/
1198
1199/* parse the "npn" bind keyword */
1200static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1201{
1202#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
1203 char *p1, *p2;
1204
1205 if (!*args[*cur_arg + 1]) {
1206 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
1207 return ERR_ALERT | ERR_FATAL;
1208 }
1209
1210 free(newsrv->ssl_ctx.npn_str);
1211
1212 /* the NPN string is built as a suite of (<len> <name>)*,
1213 * so we reuse each comma to store the next <len> and need
1214 * one more for the end of the string.
1215 */
1216 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
1217 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
1218 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
1219 newsrv->ssl_ctx.npn_len);
1220
1221 /* replace commas with the name length */
1222 p1 = newsrv->ssl_ctx.npn_str;
1223 p2 = p1 + 1;
1224 while (1) {
1225 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
1226 newsrv->ssl_ctx.npn_len - (p1 + 1));
1227 if (!p2)
1228 p2 = p1 + 1 + strlen(p1 + 1);
1229
1230 if (p2 - (p1 + 1) > 255) {
1231 *p2 = '\0';
1232 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
1233 return ERR_ALERT | ERR_FATAL;
1234 }
1235
1236 *p1 = p2 - (p1 + 1);
1237 p1 = p2;
1238
1239 if (!*p2)
1240 break;
1241
1242 *(p2++) = '\0';
1243 }
1244 return 0;
1245#else
1246 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
1247 return ERR_ALERT | ERR_FATAL;
1248#endif
1249}
1250
1251/* parse the "alpn" or the "check-alpn" server keyword */
1252static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1253{
1254#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
1255 char **alpn_str;
1256 int *alpn_len;
1257 int ret;
1258
1259 if (*args[*cur_arg] == 'c') {
1260 alpn_str = &newsrv->check.alpn_str;
1261 alpn_len = &newsrv->check.alpn_len;
1262 } else {
1263 alpn_str = &newsrv->ssl_ctx.alpn_str;
1264 alpn_len = &newsrv->ssl_ctx.alpn_len;
1265
1266 }
1267
1268 free(*alpn_str);
1269 ret = ssl_sock_parse_alpn(args[*cur_arg + 1], alpn_str, alpn_len, err);
1270 if (ret)
1271 memprintf(err, "'%s' : %s", args[*cur_arg], *err);
1272 return ret;
1273#else
1274 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
1275 return ERR_ALERT | ERR_FATAL;
1276#endif
1277}
1278
1279/* parse the "ca-file" server keyword */
1280static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1281{
1282 if (!*args[*cur_arg + 1]) {
1283 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
1284 return ERR_ALERT | ERR_FATAL;
1285 }
1286
1287 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1288 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1289 else
1290 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
1291
1292 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
1293 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
1294 return ERR_ALERT | ERR_FATAL;
1295 }
1296 return 0;
1297}
1298
1299/* parse the "check-sni" server keyword */
1300static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1301{
1302 if (!*args[*cur_arg + 1]) {
1303 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
1304 return ERR_ALERT | ERR_FATAL;
1305 }
1306
1307 newsrv->check.sni = strdup(args[*cur_arg + 1]);
1308 if (!newsrv->check.sni) {
1309 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
1310 return ERR_ALERT | ERR_FATAL;
1311 }
1312 return 0;
1313
1314}
1315
1316/* parse the "check-ssl" server keyword */
1317static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1318{
1319 newsrv->check.use_ssl = 1;
1320 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
1321 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
1322#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1323 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
1324 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
1325#endif
1326 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1327 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1328 if (!newsrv->ssl_ctx.methods.min)
1329 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
1330 if (!newsrv->ssl_ctx.methods.max)
1331 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
1332
1333 return 0;
1334}
1335
1336/* parse the "ciphers" server keyword */
1337static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1338{
1339 if (!*args[*cur_arg + 1]) {
1340 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1341 return ERR_ALERT | ERR_FATAL;
1342 }
1343
1344 free(newsrv->ssl_ctx.ciphers);
1345 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
1346 return 0;
1347}
1348
1349#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1350/* parse the "ciphersuites" server keyword */
1351static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1352{
1353 if (!*args[*cur_arg + 1]) {
1354 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
1355 return ERR_ALERT | ERR_FATAL;
1356 }
1357
1358 free(newsrv->ssl_ctx.ciphersuites);
1359 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
1360 return 0;
1361}
1362#endif
1363
1364/* parse the "crl-file" server keyword */
1365static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1366{
1367#ifndef X509_V_FLAG_CRL_CHECK
1368 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
1369 return ERR_ALERT | ERR_FATAL;
1370#else
1371 if (!*args[*cur_arg + 1]) {
1372 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
1373 return ERR_ALERT | ERR_FATAL;
1374 }
1375
1376 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
1377 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
1378 else
1379 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
1380
1381 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
1382 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
1383 return ERR_ALERT | ERR_FATAL;
1384 }
1385 return 0;
1386#endif
1387}
1388
1389/* parse the "crt" server keyword */
1390static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1391{
1392 if (!*args[*cur_arg + 1]) {
1393 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
1394 return ERR_ALERT | ERR_FATAL;
1395 }
1396
1397 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
1398 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
1399 else
1400 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
1401
1402 return 0;
1403}
1404
1405/* parse the "no-check-ssl" server keyword */
1406static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1407{
1408 newsrv->check.use_ssl = -1;
1409 free(newsrv->ssl_ctx.ciphers);
1410 newsrv->ssl_ctx.ciphers = NULL;
1411 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
1412 return 0;
1413}
1414
1415/* parse the "no-send-proxy-v2-ssl" server keyword */
1416static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1417{
1418 newsrv->pp_opts &= ~SRV_PP_V2;
1419 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1420 return 0;
1421}
1422
1423/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
1424static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1425{
1426 newsrv->pp_opts &= ~SRV_PP_V2;
1427 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
1428 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
1429 return 0;
1430}
1431
1432/* parse the "no-ssl" server keyword */
1433static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1434{
1435 newsrv->use_ssl = -1;
1436 free(newsrv->ssl_ctx.ciphers);
1437 newsrv->ssl_ctx.ciphers = NULL;
1438 return 0;
1439}
1440
1441/* parse the "allow-0rtt" server keyword */
1442static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1443{
1444 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
1445 return 0;
1446}
1447
1448/* parse the "no-ssl-reuse" server keyword */
1449static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1450{
1451 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
1452 return 0;
1453}
1454
1455/* parse the "no-tls-tickets" server keyword */
1456static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1457{
1458 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
1459 return 0;
1460}
1461/* parse the "send-proxy-v2-ssl" server keyword */
1462static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1463{
1464 newsrv->pp_opts |= SRV_PP_V2;
1465 newsrv->pp_opts |= SRV_PP_V2_SSL;
1466 return 0;
1467}
1468
1469/* parse the "send-proxy-v2-ssl-cn" server keyword */
1470static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1471{
1472 newsrv->pp_opts |= SRV_PP_V2;
1473 newsrv->pp_opts |= SRV_PP_V2_SSL;
1474 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
1475 return 0;
1476}
1477
1478/* parse the "sni" server keyword */
1479static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1480{
1481#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
1482 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
1483 return ERR_ALERT | ERR_FATAL;
1484#else
1485 char *arg;
1486
1487 arg = args[*cur_arg + 1];
1488 if (!*arg) {
1489 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
1490 return ERR_ALERT | ERR_FATAL;
1491 }
1492
1493 free(newsrv->sni_expr);
1494 newsrv->sni_expr = strdup(arg);
1495
1496 return 0;
1497#endif
1498}
1499
1500/* parse the "ssl" server keyword */
1501static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1502{
1503 newsrv->use_ssl = 1;
1504 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
1505 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
1506#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1507 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
1508 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
1509#endif
1510 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
1511 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
1512
1513 if (!newsrv->ssl_ctx.methods.min)
1514 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
1515
1516 if (!newsrv->ssl_ctx.methods.max)
1517 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
1518
1519
1520 return 0;
1521}
1522
1523/* parse the "ssl-reuse" server keyword */
1524static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1525{
1526 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
1527 return 0;
1528}
1529
1530/* parse the "tls-tickets" server keyword */
1531static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1532{
1533 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
1534 return 0;
1535}
1536
1537/* parse the "verify" server keyword */
1538static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1539{
1540 if (!*args[*cur_arg + 1]) {
1541 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
1542 return ERR_ALERT | ERR_FATAL;
1543 }
1544
1545 if (strcmp(args[*cur_arg + 1], "none") == 0)
1546 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
1547 else if (strcmp(args[*cur_arg + 1], "required") == 0)
1548 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
1549 else {
1550 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
1551 args[*cur_arg], args[*cur_arg + 1]);
1552 return ERR_ALERT | ERR_FATAL;
1553 }
1554
1555 return 0;
1556}
1557
1558/* parse the "verifyhost" server keyword */
1559static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
1560{
1561 if (!*args[*cur_arg + 1]) {
1562 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
1563 return ERR_ALERT | ERR_FATAL;
1564 }
1565
1566 free(newsrv->ssl_ctx.verify_host);
1567 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
1568
1569 return 0;
1570}
1571
1572/* parse the "ssl-default-bind-options" keyword in global section */
1573static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
1574 struct proxy *defpx, const char *file, int line,
1575 char **err) {
1576 int i = 1;
1577
1578 if (*(args[i]) == 0) {
1579 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1580 return -1;
1581 }
1582 while (*(args[i])) {
1583 if (!strcmp(args[i], "no-tls-tickets"))
1584 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
1585 else if (!strcmp(args[i], "prefer-client-ciphers"))
1586 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
1587 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
1588 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
1589 i++;
1590 else {
1591 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1592 return -1;
1593 }
1594 }
1595 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
1596 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1597 return -1;
1598 }
1599 i++;
1600 }
1601 return 0;
1602}
1603
1604/* parse the "ssl-default-server-options" keyword in global section */
1605static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
1606 struct proxy *defpx, const char *file, int line,
1607 char **err) {
1608 int i = 1;
1609
1610 if (*(args[i]) == 0) {
1611 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
1612 return -1;
1613 }
1614 while (*(args[i])) {
1615 if (!strcmp(args[i], "no-tls-tickets"))
1616 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
1617 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
1618 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
1619 i++;
1620 else {
1621 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
1622 return -1;
1623 }
1624 }
1625 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
1626 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
1627 return -1;
1628 }
1629 i++;
1630 }
1631 return 0;
1632}
1633
1634/* parse the "ca-base" / "crt-base" keywords in global section.
1635 * Returns <0 on alert, >0 on warning, 0 on success.
1636 */
1637static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
1638 struct proxy *defpx, const char *file, int line,
1639 char **err)
1640{
1641 char **target;
1642
1643 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
1644
1645 if (too_many_args(1, args, err, NULL))
1646 return -1;
1647
1648 if (*target) {
1649 memprintf(err, "'%s' already specified.", args[0]);
1650 return -1;
1651 }
1652
1653 if (*(args[1]) == 0) {
1654 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
1655 return -1;
1656 }
1657 *target = strdup(args[1]);
1658 return 0;
1659}
1660
1661/* parse the "ssl-skip-self-issued-ca" keyword in global section. */
1662static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct proxy *curpx,
1663 struct proxy *defpx, const char *file, int line,
1664 char **err)
1665{
1666 global_ssl.skip_self_issued_ca = 1;
1667 return 0;
1668}
1669
1670
1671
1672
1673
1674/* Note: must not be declared <const> as its list will be overwritten.
1675 * Please take care of keeping this list alphabetically sorted, doing so helps
1676 * all code contributors.
1677 * Optional keywords are also declared with a NULL ->parse() function so that
1678 * the config parser can report an appropriate error when a known keyword was
1679 * not enabled.
1680 */
1681
1682/* the <ssl_bind_kws> keywords are used for crt-list parsing, they *MUST* be safe
1683 * with their proxy argument NULL and must only fill the ssl_bind_conf */
1684struct ssl_bind_kw ssl_bind_kws[] = {
1685 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
1686 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1687 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1688 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1689 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
1690#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1691 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1692#endif
1693 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1694 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
1695 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1696 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1697 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
1698 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
1699 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
1700 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
1701 { NULL, NULL, 0 },
1702};
1703
1704/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
1705
1706static struct bind_kw_list bind_kws = { "SSL", { }, {
1707 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
1708 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
1709 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
1710 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
1711 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
1712 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
1713 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
1714 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
1715#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1716 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
1717#endif
1718 { "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
1719 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
1720 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
1721 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
1722 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
1723 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
1724 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
1725 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
1726 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
1727 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
1728 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
1729 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
1730 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
1731 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
1732 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
1733 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
1734 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
1735 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
1736 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
1737 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
1738 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
1739 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
1740 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
1741 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
1742 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
1743 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
1744 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
1745 { NULL, NULL, 0 },
1746}};
1747
1748INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
1749
1750/* Note: must not be declared <const> as its list will be overwritten.
1751 * Please take care of keeping this list alphabetically sorted, doing so helps
1752 * all code contributors.
1753 * Optional keywords are also declared with a NULL ->parse() function so that
1754 * the config parser can report an appropriate error when a known keyword was
1755 * not enabled.
1756 */
1757static struct srv_kw_list srv_kws = { "SSL", { }, {
1758 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
1759 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
1760 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
1761 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
1762 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
1763 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
1764 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
1765#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1766 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
1767#endif
1768 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
1769 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
1770 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
1771 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
1772 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
1773 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
1774 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
1775 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
1776 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
1777 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
1778 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
1779 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
1780 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
1781 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
1782 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
1783 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
1784 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
1785 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
1786 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
1787 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
1788 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
1789 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
1790 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
1791 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
1792 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
1793 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
1794 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
1795 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
1796 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
1797 { NULL, NULL, 0, 0 },
1798}};
1799
1800INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
1801
1802static struct cfg_kw_list cfg_kws = {ILH, {
1803 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
1804 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
1805 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
1806 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
1807 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
1808 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
1809#ifndef OPENSSL_NO_DH
1810 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
1811#endif
1812 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
1813#ifndef OPENSSL_NO_ENGINE
1814 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
1815#endif
1816 { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
1817 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
1818#ifndef OPENSSL_NO_DH
1819 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
1820#endif
1821 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
1822 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
1823 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
1824 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
1825 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
1826 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
1827 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
1828#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
1829 { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
1830#endif
1831#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
1832 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
1833 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
1834#endif
1835 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
1836 { 0, NULL, NULL },
1837}};
1838
1839INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);