MINOR: ssl: ssl-load-extra-files configure loading of files
This new setting in the global section alters the way HAProxy will look for unspecified files (.ocsp, .sctl, .issuer, bundles) during the loading of the SSL certificates. By default, HAProxy discovers automatically a lot of files not specified in the configuration, and you may want to disable this behavior if you want to optimize the startup time. This patch sets flags in global_ssl.extra_files and then check them before trying to load an extra file.
This commit is contained in:
parent
1c7c0d6b97
commit
3af48e706c
|
@ -1306,6 +1306,46 @@ ssl-dh-param-file <file>
|
|||
"openssl dhparam <size>", where size should be at least 2048, as 1024-bit DH
|
||||
parameters should not be considered secure anymore.
|
||||
|
||||
ssl-load-extra-files <none|all|bundle|sctl|ocsp|issuer>*
|
||||
This setting alters the way HAProxy will look for unspecified files during
|
||||
the loading of the SSL certificates.
|
||||
|
||||
By default, HAProxy discovers automatically a lot of files not specified in
|
||||
the configuration, and you may want to disable this behavior if you want to
|
||||
optimize the startup time.
|
||||
|
||||
"none": Only load the files specified in the configuration. Don't try to load
|
||||
a certificate bundle if the file does not exist. In the case of a directory,
|
||||
it won't try to bundle the certificates if they have the same basename.
|
||||
|
||||
"all": This is the default behavior, it will try to load everything,
|
||||
bundles, sctl, ocsp, issuer.
|
||||
|
||||
"bundle": When a file specified in the configuration does not exist, HAProxy
|
||||
will try to load a certificate bundle. This is done by looking for
|
||||
<basename>.rsa, .ecdsa and .dsa. In the case of directories, HAProxy will
|
||||
try to gather the files with the same basename in a multi-certificate bundle.
|
||||
The bundles were introduced with OpenSSL 1.0.2 and were the only way back
|
||||
then to load an ECDSA certificate and a RSA one, with the same SNI. Since
|
||||
OpenSSL 1.1.1 it is not recommended anymore, you can specifiy both the ECDSA
|
||||
and the RSA file on the bind line.
|
||||
|
||||
"sctl": Try to load "<basename>.sctl" for each crt keyword.
|
||||
|
||||
"ocsp": Try to load "<basename>.ocsp" for each crt keyword.
|
||||
|
||||
"issuer": Try to load "<basename>.issuer" if the issuer of the OCSP file is
|
||||
not provided in the PEM file.
|
||||
|
||||
The default behavior is "all".
|
||||
|
||||
Example:
|
||||
ssl-load-extra-files bundle sctl
|
||||
ssl-load-extra-files sctl ocsp issuer
|
||||
ssl-load-extra-files none
|
||||
|
||||
See also: "crt", section 5.1 about bind options.
|
||||
|
||||
ssl-server-verify [none|required]
|
||||
The default behavior for SSL verify on servers side. If specified to 'none',
|
||||
servers certificates are not verified. The default is 'required' except if
|
||||
|
|
104
src/ssl_sock.c
104
src/ssl_sock.c
|
@ -124,6 +124,15 @@
|
|||
#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
|
||||
#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
|
||||
|
||||
/* file to guess during file loading */
|
||||
#define SSL_GF_NONE 0x00000000 /* Don't guess any file, only open the files specified in the configuration files */
|
||||
#define SSL_GF_BUNDLE 0x00000001 /* try to open the bundles */
|
||||
#define SSL_GF_SCTL 0x00000002 /* try to open the .sctl file */
|
||||
#define SSL_GF_OCSP 0x00000004 /* try to open the .ocsp file */
|
||||
#define SSL_GF_OCSP_ISSUER 0x00000008 /* try to open the .issuer file if an OCSP file was loaded */
|
||||
|
||||
#define SSL_GF_ALL (SSL_GF_BUNDLE|SSL_GF_SCTL|SSL_GF_OCSP|SSL_GF_OCSP_ISSUER)
|
||||
|
||||
/* ssl_methods versions */
|
||||
enum {
|
||||
CONF_TLSV_NONE = 0,
|
||||
|
@ -172,6 +181,7 @@ static struct {
|
|||
unsigned int default_dh_param; /* SSL maximum DH parameter size */
|
||||
int ctx_cache; /* max number of entries in the ssl_ctx cache. */
|
||||
int capture_cipherlist; /* Size of the cipherlist buffer. */
|
||||
int extra_files; /* which files not defined in the configuration file are we looking for */
|
||||
} global_ssl = {
|
||||
#ifdef LISTEN_DEFAULT_CIPHERS
|
||||
.listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
|
||||
|
@ -203,6 +213,7 @@ static struct {
|
|||
.default_dh_param = SSL_DEFAULT_DH_PARAM,
|
||||
.ctx_cache = DEFAULT_SSL_CTX_CACHE,
|
||||
.capture_cipherlist = 0,
|
||||
.extra_files = SSL_GF_ALL,
|
||||
};
|
||||
|
||||
static BIO_METHOD *ha_meth;
|
||||
|
@ -3442,7 +3453,7 @@ static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_c
|
|||
|
||||
#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
|
||||
/* try to load the sctl file */
|
||||
{
|
||||
if (global_ssl.extra_files & SSL_GF_SCTL) {
|
||||
char fp[MAXPATHLEN+1];
|
||||
struct stat st;
|
||||
|
||||
|
@ -3459,7 +3470,7 @@ static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_c
|
|||
#endif
|
||||
|
||||
/* try to load an ocsp response file */
|
||||
{
|
||||
if (global_ssl.extra_files & SSL_GF_OCSP) {
|
||||
char fp[MAXPATHLEN+1];
|
||||
struct stat st;
|
||||
|
||||
|
@ -3473,7 +3484,7 @@ static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_c
|
|||
}
|
||||
|
||||
#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
|
||||
if (ckch->ocsp_response) {
|
||||
if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
|
||||
/* if no issuer was found, try to load an issuer from the .issuer */
|
||||
if (!ckch->ocsp_issuer) {
|
||||
struct stat st;
|
||||
|
@ -4320,7 +4331,7 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
|
|||
is_bundle = 0;
|
||||
/* Check if current entry in directory is part of a multi-cert bundle */
|
||||
|
||||
if (end) {
|
||||
if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
|
||||
for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
|
||||
if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
|
||||
is_bundle = 1;
|
||||
|
@ -4370,14 +4381,23 @@ int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
|
|||
free(de_list);
|
||||
}
|
||||
return cfgerr;
|
||||
|
||||
} else {
|
||||
/* stat failed */
|
||||
|
||||
if (global_ssl.extra_files & SSL_GF_BUNDLE) {
|
||||
/* try to load a bundle if it is permitted */
|
||||
ckchs = ckchs_load_cert_file(path, 1, err);
|
||||
if (!ckchs)
|
||||
return ERR_ALERT | ERR_FATAL;
|
||||
cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
|
||||
} else {
|
||||
memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
|
||||
err && *err ? *err : "", fp, strerror(errno));
|
||||
cfgerr |= ERR_ALERT | ERR_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
ckchs = ckchs_load_cert_file(path, 1, err);
|
||||
if (!ckchs)
|
||||
return ERR_ALERT | ERR_FATAL;
|
||||
|
||||
cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
|
||||
|
||||
return cfgerr;
|
||||
}
|
||||
|
||||
|
@ -9941,6 +9961,69 @@ static int ssl_parse_global_default_dh(char **args, int section_type, struct pro
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* parse "ssl-load-extra-files".
|
||||
* multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
|
||||
*/
|
||||
static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
|
||||
struct proxy *defpx, const char *file, int line,
|
||||
char **err)
|
||||
{
|
||||
int i;
|
||||
int gf = SSL_GF_NONE;
|
||||
|
||||
if (*(args[1]) == 0)
|
||||
goto err_arg;
|
||||
|
||||
for (i = 1; *args[i]; i++) {
|
||||
|
||||
if (!strcmp("bundle", args[i])) {
|
||||
gf |= SSL_GF_BUNDLE;
|
||||
|
||||
} else if (!strcmp("sctl", args[i])) {
|
||||
gf |= SSL_GF_SCTL;
|
||||
|
||||
} else if (!strcmp("ocsp", args[i])){
|
||||
gf |= SSL_GF_OCSP;
|
||||
|
||||
} else if (!strcmp("issuer", args[i])){
|
||||
gf |= SSL_GF_OCSP_ISSUER;
|
||||
|
||||
} else if (!strcmp("none", args[i])) {
|
||||
if (gf != SSL_GF_NONE)
|
||||
goto err_alone;
|
||||
gf = SSL_GF_NONE;
|
||||
i++;
|
||||
break;
|
||||
|
||||
} else if (!strcmp("all", args[i])) {
|
||||
if (gf != SSL_GF_NONE)
|
||||
goto err_alone;
|
||||
gf = SSL_GF_ALL;
|
||||
i++;
|
||||
break;
|
||||
} else {
|
||||
goto err_arg;
|
||||
}
|
||||
}
|
||||
/* break from loop but there are still arguments */
|
||||
if (*args[i])
|
||||
goto err_alone;
|
||||
|
||||
global_ssl.extra_files = gf;
|
||||
|
||||
return 0;
|
||||
|
||||
err_alone:
|
||||
memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
|
||||
return -1;
|
||||
|
||||
err_arg:
|
||||
memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* This function is used with TLS ticket keys management. It permits to browse
|
||||
* each reference. The variable <getnext> must contain the current node,
|
||||
* <end> point to the root node.
|
||||
|
@ -11407,6 +11490,7 @@ static struct cfg_kw_list cfg_kws = {ILH, {
|
|||
{ CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
|
||||
{ CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
|
||||
#endif
|
||||
{ CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
|
||||
{ 0, NULL, NULL },
|
||||
}};
|
||||
|
||||
|
|
Loading…
Reference in New Issue