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