MEDIUM: ssl: implements 'default-crt' keyword for bind Lines

The 'default-crt' bind keyword allows to specify multiples
default/fallback certificates, allowing one to have an RSA as well as an
ECDSA default.
This commit is contained in:
William Lallemand 2024-01-12 17:32:48 +01:00
parent 47bae78147
commit 97832ab823
4 changed files with 29 additions and 8 deletions

View File

@ -15474,11 +15474,12 @@ crt <cert>
This means that when loading certificates from a directory, it is highly This means that when loading certificates from a directory, it is highly
recommended to load the default one first as a file or to ensure that it will recommended to load the default one first as a file or to ensure that it will
always be the first one in the directory. In order to chose multiple default always be the first one in the directory. In order to chose multiple default
certificates (1 rsa and 1 ecdsa), there are 2 options: certificates (1 rsa and 1 ecdsa), there are 3 options:
- A multi-cert bundle can be configured as the first certificate - A multi-cert bundle can be configured as the first certificate
(`crt foobar.pem` in the configuration where the existing files (`crt foobar.pem` in the configuration where the existing files
are `foobar.pem.ecdsa` and `foobar.pem.rsa`. are `foobar.pem.ecdsa` and `foobar.pem.rsa`.
- Or a '*' filter for each certificate in a crt-list line. - Or a '*' filter for each certificate in a crt-list line.
- The 'default-crt' keyword can be used.
Note that the same cert may be loaded multiple times without side effects. Note that the same cert may be loaded multiple times without side effects.
@ -15585,6 +15586,23 @@ crt-list <file>
default.pem.rsa * default.pem.rsa *
default.pem.ecdsa * default.pem.ecdsa *
default-crt <cert>
This option does the same as the "crt" option, with the difference that this
certificate will be used as a default one. It is possible to add multiple
default certificates to have an ECDSA and an RSA one, having more is not
really useful.
A default certificate is used when no "strict-sni" option is used on the bind
line. A default certificate is provided when the servername extension was not
used by the client, or when the servername does not match any configured
certificate.
Example:
bind *:443 default-crt foobar.pem.rsa default-crt foobar.pem.ecdsa crt website.pem.rsa
See also the "crt" keyword.
defer-accept defer-accept
Is an optional keyword which is supported only on certain Linux kernels. It 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, states that a connection will only be accepted once some data arrive on it,

View File

@ -123,7 +123,7 @@ void ssl_async_fd_free(int fd);
#endif #endif
struct issuer_chain* ssl_get0_issuer_chain(X509 *cert); struct issuer_chain* ssl_get0_issuer_chain(X509 *cert);
int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err); int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err);
int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err); int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, int is_default, char **err);
int ssl_sock_load_srv_cert(char *path, struct server *server, int create_if_none, char **err); int ssl_sock_load_srv_cert(char *path, struct server *server, int create_if_none, char **err);
void ssl_free_global_issuers(void); void ssl_free_global_issuers(void);
int ssl_initialize_random(void); int ssl_initialize_random(void);

View File

@ -777,6 +777,7 @@ static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, s
static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{ {
char path[MAXPATHLEN]; char path[MAXPATHLEN];
int default_crt = *args[cur_arg] == 'd' ? 1 : 0;
if (!*args[cur_arg + 1]) { if (!*args[cur_arg + 1]) {
memprintf(err, "'%s' : missing certificate location", args[cur_arg]); memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
@ -789,10 +790,10 @@ static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bin
memprintf(err, "'%s' : path too long", args[cur_arg]); memprintf(err, "'%s' : path too long", args[cur_arg]);
return ERR_ALERT | ERR_FATAL; return ERR_ALERT | ERR_FATAL;
} }
return ssl_sock_load_cert(path, conf, err); return ssl_sock_load_cert(path, conf, default_crt, err);
} }
return ssl_sock_load_cert(args[cur_arg + 1], conf, err); return ssl_sock_load_cert(args[cur_arg + 1], conf, default_crt, err);
} }
/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */ /* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
@ -2240,6 +2241,7 @@ static struct bind_kw_list bind_kws = { "SSL", { }, {
{ "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */ { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
{ "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */ { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
{ "curves", bind_parse_curves, 1 }, /* set SSL curve suite */ { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
{ "default-crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
{ "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */ { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
{ "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */ { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
{ "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */ { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */

View File

@ -3760,19 +3760,20 @@ int ssl_sock_load_cert_list_file(char *file, int dir, struct bind_conf *bind_con
} }
/* Returns a set of ERR_* flags possibly with an error in <err>. */ /* Returns a set of ERR_* flags possibly with an error in <err>. */
int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err) int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, int is_default, char **err)
{ {
struct stat buf; struct stat buf;
int cfgerr = 0; int cfgerr = 0;
struct ckch_store *ckchs; struct ckch_store *ckchs;
struct ckch_inst *ckch_inst = NULL; struct ckch_inst *ckch_inst = NULL;
int found = 0; /* did we found a file to load ? */ int found = 0; /* did we found a file to load ? */
int is_default = 0;
/* if the SNI trees were empty the first "crt" become a default certificate, /* if the SNI trees were empty the first "crt" become a default certificate,
* it can be applied on multiple certificates if it's a bundle */ * it can be applied on multiple certificates if it's a bundle */
if (is_default == 0) {
if (eb_is_empty(&bind_conf->sni_ctx) && eb_is_empty(&bind_conf->sni_w_ctx)) if (eb_is_empty(&bind_conf->sni_ctx) && eb_is_empty(&bind_conf->sni_w_ctx))
is_default = 1; is_default = 1;
}
if ((ckchs = ckchs_lookup(path))) { if ((ckchs = ckchs_lookup(path))) {
/* we found the ckchs in the tree, we can use it directly */ /* we found the ckchs in the tree, we can use it directly */