From 98263291cc3395a26a87408a900a93242f3f042d Mon Sep 17 00:00:00 2001 From: Emmanuel Hocdet Date: Thu, 29 Dec 2016 18:26:15 +0100 Subject: [PATCH] MAJOR: ssl: bind configuration per certificat crt-list is extend to support ssl configuration. You can now have such line in crt-list : mycert.pem [npn h2,http/1.1] Support include "npn", "alpn", "verify", "ca_file", "crl_file", "ecdhe", "ciphers" configuration and ssl options. "crt-base" is also supported to fetch certificates. --- doc/configuration.txt | 16 +- include/common/defaults.h | 7 +- include/proto/ssl_sock.h | 2 +- include/types/listener.h | 37 +++- include/types/ssl_sock.h | 2 + src/ssl_sock.c | 407 ++++++++++++++++++++++++++++---------- 6 files changed, 356 insertions(+), 115 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 739fad9d65..abb36df809 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -10248,10 +10248,14 @@ crt-ignore-err crt-list This setting is only available when support for OpenSSL was built in. It - designates a list of PEM file with an optional list of SNI filter per - certificate, with the following format for each line : + designates a list of PEM file with an optional ssl configuration and a SNI + filter per certificate, with the following format for each line : - [[!] ...] + [\[ ...\]] [[!] ...] + + sslbindconf support "npn", "alpn", "verify", "ca_file", "crl_file", "ecdhe", + "ciphers" configuration and ssl options (see "ssl-default-bind-options"). + It override the configuration set in bind line for the certificate. Wildcards are supported in the SNI filter. Negative filter are also supported, only useful in combination with a wildcard filter to exclude a particular SNI. @@ -10266,6 +10270,12 @@ crt-list the base name is given in the crt-list. SNI filter will do the same work on all bundled certificates. + crt-list file example: + cert1.pem + cert2.pem [npn h2,http/1.1] + certW.pem *.domain.tld !secure.domain.tld + certS.pem [ecdhe secp521r1 ciphers ECDHE-ECDSA-AES256-GCM-SHA384] secure.domain.tld + defer-accept Is an optional keyword which is supported only on certain Linux kernels. It states that a connection will only be accepted once some data arrive on it, diff --git a/include/common/defaults.h b/include/common/defaults.h index 3e04f022c8..1618ab40f7 100644 --- a/include/common/defaults.h +++ b/include/common/defaults.h @@ -74,8 +74,11 @@ // max # args on a configuration line #define MAX_LINE_ARGS 64 -// crt-list parsing factor for LINESIZE and MAX_LINE_ARGS -#define CRTLIST_FACTOR 32 +// maximum line size when parsing crt-bind-list config +#define CRT_LINESIZE 65536 + +// max # args on crt-bind-list configuration line +#define MAX_CRT_ARGS 2048 // max # args on a stats socket // This should cover at least 5 + twice the # of data_types diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h index 9f43adc3aa..6f779faaed 100644 --- a/include/proto/ssl_sock.h +++ b/include/proto/ssl_sock.h @@ -42,7 +42,7 @@ int ssl_sock_is_ssl(struct connection *conn) } int ssl_sock_handshake(struct connection *conn, unsigned int flag); -int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx); +int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *, SSL_CTX *ctx); int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf); int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf); int ssl_sock_prepare_srv_ctx(struct server *srv); diff --git a/include/types/listener.h b/include/types/listener.h index 03f4a72b5e..b534c477ce 100644 --- a/include/types/listener.h +++ b/include/types/listener.h @@ -115,22 +115,34 @@ enum li_state { #define BC_SSL_O_NO_TLS_TICKETS 0x0100 /* disable session resumption tickets */ #endif -/* "bind" line settings */ -struct bind_conf { +/* ssl "bind" settings */ +struct ssl_bind_conf { #ifdef USE_OPENSSL +#ifdef OPENSSL_NPN_NEGOTIATED + char *npn_str; /* NPN protocol string */ + int npn_len; /* NPN protocol string length */ +#endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + char *alpn_str; /* ALPN protocol string */ + int alpn_len; /* ALPN protocol string length */ +#endif + int verify; /* verify method (set of SSL_VERIFY_* flags) */ char *ca_file; /* CAfile to use on verify */ - unsigned long long ca_ignerr; /* ignored verify errors in handshake if depth > 0 */ - unsigned long long crt_ignerr; /* ignored verify errors in handshake if depth == 0 */ - char *ciphers; /* cipher suite to use if non-null */ char *crl_file; /* CRLfile to use on verify */ + char *ciphers; /* cipher suite to use if non-null */ char *ecdhe; /* named curve to use for ECDHE */ int ssl_options; /* ssl options */ - int verify; /* verify method (set of SSL_VERIFY_* flags) */ +#endif +}; + +/* "bind" line settings */ +struct bind_conf { +#ifdef USE_OPENSSL + struct ssl_bind_conf ssl_conf; /* ssl conf for ctx setting */ + unsigned long long ca_ignerr; /* ignored verify errors in handshake if depth > 0 */ + unsigned long long crt_ignerr; /* ignored verify errors in handshake if depth == 0 */ SSL_CTX *default_ctx; /* SSL context of first/default certificate */ - char *npn_str; /* NPN protocol string */ - int npn_len; /* NPN protocol string length */ - char *alpn_str; /* ALPN protocol string */ - int alpn_len; /* ALPN protocol string length */ + struct ssl_bind_conf *default_ssl_conf; /* custom SSL conf of default_ctx */ int strict_sni; /* refuse negotiation if sni doesn't match a certificate */ struct eb_root sni_ctx; /* sni_ctx tree of all known certs full-names sorted by name */ struct eb_root sni_w_ctx; /* sni_ctx tree of all known certs wildcards sorted by name */ @@ -213,6 +225,11 @@ struct bind_kw { int (*parse)(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err); int skip; /* nb of args to skip */ }; +struct ssl_bind_kw { + const char *kw; + int (*parse)(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err); + int skip; /* nb of args to skip */ +}; /* * A keyword list. It is a NULL-terminated array of keywords. It embeds a diff --git a/include/types/ssl_sock.h b/include/types/ssl_sock.h index e71ba793c4..a384f055d4 100644 --- a/include/types/ssl_sock.h +++ b/include/types/ssl_sock.h @@ -22,6 +22,7 @@ #ifndef _TYPES_SSL_SOCK_H #define _TYPES_SSL_SOCK_H +#include #include #include @@ -29,6 +30,7 @@ struct sni_ctx { SSL_CTX *ctx; /* context associated to the certificate */ int order; /* load order for the certificate */ int neg; /* reject if match */ + struct ssl_bind_conf *conf; /* ssl "bind" conf for the certificate */ struct ebmb_node name; /* node holding the servername value */ }; diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 3705917a8f..b94166cdce 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -194,6 +194,8 @@ static char *x509v3_ext_values[X509V3_EXT_SIZE] = { "nonRepudiation,digitalSignature,keyEncipherment" }; +static struct ssl_bind_kw ssl_bind_kws[]; + /* LRU cache to store generated certificate */ static struct lru64_head *ssl_ctx_lru_tree = NULL; static unsigned int ssl_ctx_lru_seed = 0; @@ -1182,7 +1184,7 @@ void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data, unsigned int *len, void *arg) { - struct bind_conf *conf = arg; + struct ssl_bind_conf *conf = arg; *data = (const unsigned char *)conf->npn_str; *len = conf->npn_len; @@ -1199,7 +1201,7 @@ static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out, const unsigned char *server, unsigned int server_len, void *arg) { - struct bind_conf *conf = arg; + struct ssl_bind_conf *conf = arg; if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str, conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) { @@ -1330,7 +1332,7 @@ ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh); #if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH) { - const char *ecdhe = (bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE); + const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE); EC_KEY *ecc; int nid; @@ -1776,7 +1778,8 @@ end: } #endif -static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order) +static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, + struct ssl_bind_conf *conf, char *name, int order) { struct sni_ctx *sc; int wild = 0, neg = 0; @@ -1809,7 +1812,7 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, node = ebst_lookup(&s->sni_ctx, trash.str); for (; node; node = ebmb_next_dup(node)) { sc = ebmb_entry(node, struct sni_ctx, name); - if (sc->ctx == ctx && sc->neg == neg) + if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg) return order; } @@ -1818,6 +1821,7 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, return order; memcpy(sc->name.key, trash.str, len + 1); sc->ctx = ctx; + sc->conf = conf; sc->order = order++; sc->neg = neg; if (wild) @@ -2072,7 +2076,8 @@ static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root * 0 on success * 1 on failure */ -static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, char **sni_filter, int fcount, char **err) +static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, + char **sni_filter, int fcount, char **err) { char fp[MAXPATHLEN+1] = {0}; int n = 0; @@ -2246,7 +2251,7 @@ static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_con } /* Update SNI Tree */ - key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, str, key_combos[i-1].order); + key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf, str, key_combos[i-1].order); node = ebmb_next(node); } @@ -2256,6 +2261,7 @@ static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_con for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) { if (key_combos[i].ctx) { bind_conf->default_ctx = key_combos[i].ctx; + bind_conf->default_ssl_conf = ssl_conf; break; } } @@ -2280,7 +2286,8 @@ end: } #else /* This is a dummy, that just logs an error and returns error */ -static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, char **sni_filter, int fcount, char **err) +static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, + char **sni_filter, int fcount, char **err) { memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n", err && *err ? *err : "", path, strerror(errno)); @@ -2292,7 +2299,8 @@ static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_con /* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if * an early error happens and the caller must call SSL_CTX_free() by itelf. */ -static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s, char **sni_filter, int fcount) +static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s, + struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount) { BIO *in; X509 *x = NULL, *ca; @@ -2325,7 +2333,7 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct if (fcount) { while (fcount--) - order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order); + order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, sni_filter[fcount], order); } else { #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME @@ -2335,7 +2343,7 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i); if (name->type == GEN_DNS) { if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) { - order = ssl_sock_add_cert_sni(ctx, s, str, order); + order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, str, order); OPENSSL_free(str); } } @@ -2351,7 +2359,7 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct value = X509_NAME_ENTRY_get_data(entry); if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) { - order = ssl_sock_add_cert_sni(ctx, s, str, order); + order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, str, order); OPENSSL_free(str); } } @@ -2394,7 +2402,8 @@ end: return ret; } -static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, char **sni_filter, int fcount, char **err) +static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, + char **sni_filter, int fcount, char **err) { int ret; SSL_CTX *ctx; @@ -2413,7 +2422,7 @@ static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf return 1; } - ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount); + ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount); if (ret <= 0) { memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n", err && *err ? *err : "", path); @@ -2476,8 +2485,10 @@ static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf return 1; } #endif - if (!bind_conf->default_ctx) + if (!bind_conf->default_ctx) { bind_conf->default_ctx = ctx; + bind_conf->default_ssl_conf = ssl_conf; + } return 0; } @@ -2499,7 +2510,7 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err) if (stat(path, &buf) == 0) { dir = opendir(path); if (!dir) - return ssl_sock_load_cert_file(path, bind_conf, NULL, 0, err); + return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err); /* strip trailing slashes, including first one */ for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--) @@ -2559,7 +2570,7 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err) } snprintf(fp, sizeof(fp), "%s/%s", path, dp); - ssl_sock_load_multi_cert(fp, bind_conf, NULL, 0, err); + ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err); /* Successfully processed the bundle */ goto ignore_entry; @@ -2567,7 +2578,7 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err) } #endif - cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, 0, err); + cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err); ignore_entry: free(de); } @@ -2577,7 +2588,7 @@ ignore_entry: return cfgerr; } - cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, 0, err); + cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err); return cfgerr; } @@ -2598,9 +2609,33 @@ static int ssl_initialize_random() return random_initialized; } -int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, char **err) +/* release ssl bind conf */ +void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf) { - char thisline[LINESIZE*CRTLIST_FACTOR]; + if (conf) { +#ifdef OPENSSL_NPN_NEGOTIATED + free(conf->npn_str); + conf->npn_str = NULL; +#endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + free(conf->alpn_str); + conf->alpn_str = NULL; +#endif + free(conf->ca_file); + conf->ca_file = NULL; + free(conf->crl_file); + conf->crl_file = NULL; + free(conf->ciphers); + conf->ciphers = NULL; + free(conf->ecdhe); + conf->ecdhe = NULL; + } +} + +int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err) +{ + char thisline[CRT_LINESIZE]; + char path[MAXPATHLEN+1]; FILE *f; struct stat buf; int linenum = 0; @@ -2612,11 +2647,12 @@ int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, char * } while (fgets(thisline, sizeof(thisline), f) != NULL) { - int arg; - int newarg; + int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0; char *end; - char *args[MAX_LINE_ARGS*CRTLIST_FACTOR + 1]; + char *args[MAX_CRT_ARGS + 1]; char *line = thisline; + char *crt_path; + struct ssl_bind_conf *ssl_conf = NULL; linenum++; end = line + strlen(line); @@ -2637,15 +2673,40 @@ int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, char * /* end of string, end of loop */ *line = 0; break; - } - else if (isspace(*line)) { + } else if (isspace(*line)) { newarg = 1; *line = 0; - } - else if (newarg) { - if (arg == MAX_LINE_ARGS*CRTLIST_FACTOR) { - memprintf(err, "too many args on line %d in file '%s'.", - linenum, file); + } else if (*line == '[') { + if (ssl_b) { + memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file); + cfgerr = 1; + break; + } + if (!arg) { + memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file); + cfgerr = 1; + break; + } + ssl_b = arg; + newarg = 1; + *line = 0; + } else if (*line == ']') { + if (ssl_e) { + memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file); + cfgerr = 1; + break; + } + if (!ssl_b) { + memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file); + cfgerr = 1; + break; + } + ssl_e = arg; + newarg = 1; + *line = 0; + } else if (newarg) { + if (arg == MAX_CRT_ARGS) { + memprintf(err, "too many args on line %d in file '%s'.", linenum, file); cfgerr = 1; break; } @@ -2656,15 +2717,61 @@ int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, char * } if (cfgerr) break; + args[arg++] = line; /* empty line */ - if (!arg) + if (!*args[0]) continue; - if (stat(args[0], &buf) == 0) { - cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, &args[1], arg-1, err); + crt_path = args[0]; + if (*crt_path != '/' && global_ssl.crt_base) { + if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) { + memprintf(err, "'%s' : path too long on line %d in file '%s'", + crt_path, linenum, file); + cfgerr = 1; + break; + } + snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path); + crt_path = path; + } + + ssl_conf = calloc(1, sizeof *ssl_conf); + cur_arg = ssl_b ? ssl_b : 1; + while (cur_arg < ssl_e) { + newarg = 0; + for (i = 0; ssl_bind_kws[i].kw != NULL; i++) { + if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) { + newarg = 1; + cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err); + if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) { + memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'", + args[cur_arg], linenum, file); + cfgerr = 1; + } + cur_arg += 1 + ssl_bind_kws[i].skip; + break; + } + } + if (!cfgerr && !newarg) { + memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.", + args[cur_arg], linenum, file); + cfgerr = 1; + break; + } + } + if (cfgerr) { + ssl_sock_free_ssl_conf(ssl_conf); + free(ssl_conf); + ssl_conf = NULL; + break; + } + + if (stat(crt_path, &buf) == 0) { + cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf, + &args[cur_arg], arg - cur_arg - 1, err); } else { - cfgerr = ssl_sock_load_multi_cert(args[0], bind_conf, &args[1], arg-1, err); + cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf, + &args[cur_arg], arg - cur_arg - 1, err); } if (cfgerr) { @@ -2712,7 +2819,7 @@ int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, char * #define SSL_MODE_SMALL_BUFFERS 0 #endif -int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) +int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx) { struct proxy *curproxy = bind_conf->frontend; int cfgerr = 0; @@ -2741,6 +2848,9 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) int idx = 0; int dhe_found = 0; SSL *ssl = NULL; + struct ssl_bind_conf *ssl_conf_cur; + int conf_ssl_options = bind_conf->ssl_conf.ssl_options | (ssl_conf ? ssl_conf->ssl_options : 0); + const char *conf_ciphers; /* Make sure openssl opens /dev/urandom before the chroot */ if (!ssl_initialize_random()) { @@ -2748,17 +2858,17 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) cfgerr++; } - if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3) + if (conf_ssl_options & BC_SSL_O_NO_SSLV3) ssloptions |= SSL_OP_NO_SSLv3; - if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10) + if (conf_ssl_options & BC_SSL_O_NO_TLSV10) ssloptions |= SSL_OP_NO_TLSv1; - if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11) + if (conf_ssl_options & BC_SSL_O_NO_TLSV11) ssloptions |= SSL_OP_NO_TLSv1_1; - if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12) + if (conf_ssl_options & BC_SSL_O_NO_TLSV12) ssloptions |= SSL_OP_NO_TLSv1_2; - if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS) + if (conf_ssl_options & BC_SSL_O_NO_TLS_TICKETS) ssloptions |= SSL_OP_NO_TICKET; - if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3) { + if (conf_ssl_options & BC_SSL_O_USE_SSLV3) { #ifndef OPENSSL_NO_SSL3 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method()); #else @@ -2766,20 +2876,20 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) cfgerr++; #endif } - if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10) + if (conf_ssl_options & BC_SSL_O_USE_TLSV10) SSL_CTX_set_ssl_version(ctx, TLSv1_server_method()); #if SSL_OP_NO_TLSv1_1 - if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11) + if (conf_ssl_options & BC_SSL_O_USE_TLSV11) SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method()); #endif #if SSL_OP_NO_TLSv1_2 - if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12) + if (conf_ssl_options & BC_SSL_O_USE_TLSV12) SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method()); #endif SSL_CTX_set_options(ctx, ssloptions); SSL_CTX_set_mode(ctx, sslmode); - switch (bind_conf->verify) { + switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) { case SSL_SOCK_VERIFY_NONE: verify = SSL_VERIFY_NONE; break; @@ -2792,15 +2902,17 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) } SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk); if (verify & SSL_VERIFY_PEER) { - if (bind_conf->ca_file) { + char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file; + char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file; + if (ca_file) { /* load CAfile to verify */ - if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) { + if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) { Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n", - curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line); + curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line); cfgerr++; } /* set CA names fo client cert request, function returns void */ - SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file)); + SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file)); } else { Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n", @@ -2808,12 +2920,12 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) cfgerr++; } #ifdef X509_V_FLAG_CRL_CHECK - if (bind_conf->crl_file) { + if (crl_file) { X509_STORE *store = SSL_CTX_get_cert_store(ctx); - if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) { + if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) { Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n", - curproxy->id, bind_conf->crl_file, bind_conf->arg, bind_conf->file, bind_conf->line); + curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line); cfgerr++; } else { @@ -2838,10 +2950,11 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) SSL_CTX_set_timeout(ctx, global_ssl.life_time); shared_context_set_cache(ctx); - if (bind_conf->ciphers && - !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) { + conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers; + if (conf_ciphers && + !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) { Alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n", - curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line); + curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line); cfgerr++; } @@ -2905,12 +3018,22 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) #endif #ifdef OPENSSL_NPN_NEGOTIATED - if (bind_conf->npn_str) - SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf); + ssl_conf_cur = NULL; + if (ssl_conf && ssl_conf->npn_str) + ssl_conf_cur = ssl_conf; + else if (bind_conf->ssl_conf.npn_str) + ssl_conf_cur = &bind_conf->ssl_conf; + if (ssl_conf_cur) + SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur); #endif #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation - if (bind_conf->alpn_str) - SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf); + ssl_conf_cur = NULL; + if (ssl_conf && ssl_conf->alpn_str) + ssl_conf_cur = ssl_conf; + else if (bind_conf->ssl_conf.alpn_str) + ssl_conf_cur = &bind_conf->ssl_conf; + if (ssl_conf_cur) + SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur); #endif #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME @@ -2921,12 +3044,13 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx) { int i; EC_KEY *ecdh; + const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe : + (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE); - i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE); + i = OBJ_sn2nid(ecdhe); if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) { Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n", - curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE, - bind_conf->arg, bind_conf->file, bind_conf->line); + curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line); cfgerr++; } else { @@ -3241,7 +3365,7 @@ int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf) global.ssl_used_frontend = 1; if (bind_conf->default_ctx) - err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ctx); + err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx); node = ebmb_first(&bind_conf->sni_ctx); while (node) { @@ -3249,7 +3373,7 @@ int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf) if (!sni->order && sni->ctx != bind_conf->default_ctx) /* only initialize the CTX on its first occurrence and if it is not the default_ctx */ - err += ssl_sock_prepare_ctx(bind_conf, sni->ctx); + err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx); node = ebmb_next(node); } @@ -3259,7 +3383,7 @@ int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf) if (!sni->order && sni->ctx != bind_conf->default_ctx) /* only initialize the CTX on its first occurrence and if it is not the default_ctx */ - err += ssl_sock_prepare_ctx(bind_conf, sni->ctx); + err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx); node = ebmb_next(node); } return err; @@ -3330,8 +3454,12 @@ void ssl_sock_free_all_ctx(struct bind_conf *bind_conf) sni = ebmb_entry(node, struct sni_ctx, name); back = ebmb_next(node); ebmb_delete(node); - if (!sni->order) /* only free the CTX on its first occurrence */ + if (!sni->order) { /* only free the CTX on its first occurrence */ SSL_CTX_free(sni->ctx); + ssl_sock_free_ssl_conf(sni->conf); + free(sni->conf); + sni->conf = NULL; + } free(sni); node = back; } @@ -3341,13 +3469,18 @@ void ssl_sock_free_all_ctx(struct bind_conf *bind_conf) sni = ebmb_entry(node, struct sni_ctx, name); back = ebmb_next(node); ebmb_delete(node); - if (!sni->order) /* only free the CTX on its first occurrence */ + if (!sni->order) { /* only free the CTX on its first occurrence */ SSL_CTX_free(sni->ctx); + ssl_sock_free_ssl_conf(sni->conf); + free(sni->conf); + sni->conf = NULL; + } free(sni); node = back; } bind_conf->default_ctx = NULL; + bind_conf->default_ssl_conf = NULL; } /* Destroys all the contexts for a bind_conf. This is used during deinit(). */ @@ -3355,12 +3488,9 @@ void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf) { ssl_sock_free_ca(bind_conf); ssl_sock_free_all_ctx(bind_conf); - free(bind_conf->ca_file); + ssl_sock_free_ssl_conf(&bind_conf->ssl_conf); free(bind_conf->ca_sign_file); free(bind_conf->ca_sign_pass); - free(bind_conf->ciphers); - free(bind_conf->ecdhe); - free(bind_conf->crl_file); if (bind_conf->keys_ref) { free(bind_conf->keys_ref->filename); free(bind_conf->keys_ref->tlskeys); @@ -3368,12 +3498,8 @@ void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf) free(bind_conf->keys_ref); } bind_conf->keys_ref = NULL; - bind_conf->crl_file = NULL; - bind_conf->ecdhe = NULL; - bind_conf->ciphers = NULL; bind_conf->ca_sign_pass = NULL; bind_conf->ca_sign_file = NULL; - bind_conf->ca_file = NULL; } /* Load CA cert file and private key used to generate certificates */ @@ -5249,7 +5375,7 @@ smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *k } /* parse the "ca-file" bind keyword */ -static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { if (!*args[cur_arg + 1]) { if (err) @@ -5264,6 +5390,10 @@ static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct return 0; } +static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "ca-sign-file" bind keyword */ static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) @@ -5295,7 +5425,7 @@ static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, s } /* parse the "ciphers" bind keyword */ -static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { if (!*args[cur_arg + 1]) { memprintf(err, "'%s' : missing cipher suite", args[cur_arg]); @@ -5306,7 +5436,10 @@ static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct conf->ciphers = strdup(args[cur_arg + 1]); return 0; } - +static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "crt" bind keyword */ static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) { @@ -5343,7 +5476,7 @@ static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struc return ERR_ALERT | ERR_FATAL; } - if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, err) > 0) { + if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) { memprintf(err, "'%s' : %s", args[cur_arg], *err); return ERR_ALERT | ERR_FATAL; } @@ -5352,7 +5485,7 @@ static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struc } /* parse the "crl-file" bind keyword */ -static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { #ifndef X509_V_FLAG_CRL_CHECK if (err) @@ -5373,9 +5506,13 @@ static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struc return 0; #endif } +static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "ecdhe" bind keyword keyword */ -static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { #if OPENSSL_VERSION_NUMBER < 0x0090800fL if (err) @@ -5397,6 +5534,10 @@ static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct b return 0; #endif } +static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */ static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) @@ -5437,21 +5578,29 @@ static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, str } /* parse the "force-sslv3" bind keyword */ -static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { conf->ssl_options |= BC_SSL_O_USE_SSLV3; return 0; } +static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_force_sslv3(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "force-tlsv10" bind keyword */ -static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { conf->ssl_options |= BC_SSL_O_USE_TLSV10; return 0; } +static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_force_tlsv10(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "force-tlsv11" bind keyword */ -static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { #if SSL_OP_NO_TLSv1_1 conf->ssl_options |= BC_SSL_O_USE_TLSV11; @@ -5462,9 +5611,13 @@ static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, s return ERR_ALERT | ERR_FATAL; #endif } +static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_force_tlsv11(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "force-tlsv12" bind keyword */ -static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { #if SSL_OP_NO_TLSv1_2 conf->ssl_options |= BC_SSL_O_USE_TLSV12; @@ -5475,46 +5628,68 @@ static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, s return ERR_ALERT | ERR_FATAL; #endif } - +static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_force_tlsv12(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "no-tls-tickets" bind keyword */ -static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS; return 0; } - +static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_no_tls_tickets(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "no-sslv3" bind keyword */ -static int bind_parse_no_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_no_sslv3(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { conf->ssl_options |= BC_SSL_O_NO_SSLV3; return 0; } +static int bind_parse_no_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_no_sslv3(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "no-tlsv10" bind keyword */ -static int bind_parse_no_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_no_tlsv10(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { conf->ssl_options |= BC_SSL_O_NO_TLSV10; return 0; } +static int bind_parse_no_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_no_tlsv10(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "no-tlsv11" bind keyword */ -static int bind_parse_no_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_no_tlsv11(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { conf->ssl_options |= BC_SSL_O_NO_TLSV11; return 0; } +static int bind_parse_no_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_no_tlsv11(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "no-tlsv12" bind keyword */ -static int bind_parse_no_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_no_tlsv12(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { conf->ssl_options |= BC_SSL_O_NO_TLSV12; return 0; } +static int bind_parse_no_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_no_tlsv12(args, cur_arg, px, &conf->ssl_conf, err); +} /* parse the "npn" bind keyword */ -static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { #ifdef OPENSSL_NPN_NEGOTIATED char *p1, *p2; @@ -5564,8 +5739,13 @@ static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bin #endif } +static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err); +} + /* parse the "alpn" bind keyword */ -static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation char *p1, *p2; @@ -5615,15 +5795,20 @@ static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bi #endif } +static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err); +} + /* parse the "ssl" bind keyword */ static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) { conf->xprt = &ssl_sock; conf->is_ssl = 1; - if (global_ssl.listen_default_ciphers && !conf->ciphers) - conf->ciphers = strdup(global_ssl.listen_default_ciphers); - conf->ssl_options |= global_ssl.listen_default_ssloptions; + if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers) + conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers); + conf->ssl_conf.ssl_options |= global_ssl.listen_default_ssloptions; return 0; } @@ -5723,7 +5908,7 @@ static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px } /* parse the "verify" bind keyword */ -static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +static int ssl_bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err) { if (!*args[cur_arg + 1]) { if (err) @@ -5746,6 +5931,10 @@ static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct return 0; } +static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err); +} /************** "server" keywords ****************/ @@ -6620,6 +6809,26 @@ static struct acl_kw_list acl_kws = {ILH, { * the config parser can report an appropriate error when a known keyword was * not enabled. */ +static struct ssl_bind_kw ssl_bind_kws[] = { + { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */ + { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */ + { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */ + { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */ + { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */ + { "force-sslv3", ssl_bind_parse_force_sslv3, 0 }, /* force SSLv3 */ + { "force-tlsv10", ssl_bind_parse_force_tlsv10, 0 }, /* force TLSv10 */ + { "force-tlsv11", ssl_bind_parse_force_tlsv11, 0 }, /* force TLSv11 */ + { "force-tlsv12", ssl_bind_parse_force_tlsv12, 0 }, /* force TLSv12 */ + { "no-sslv3", ssl_bind_parse_no_sslv3, 0 }, /* disable SSLv3 */ + { "no-tlsv10", ssl_bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */ + { "no-tlsv11", ssl_bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */ + { "no-tlsv12", ssl_bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */ + { "no-tls-tickets", ssl_bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */ + { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */ + { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */ + { NULL, NULL, 0 }, +}; + static struct bind_kw_list bind_kws = { "SSL", { }, { { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */ { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */ -- 2.39.5