"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
#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,
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,
.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;
#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;
#endif
/* try to load an ocsp response file */
- {
+ if (global_ssl.extra_files & SSL_GF_OCSP) {
char fp[MAXPATHLEN+1];
struct stat st;
}
#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;
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;
free(de_list);
}
return cfgerr;
- }
- ckchs = ckchs_load_cert_file(path, 1, err);
- if (!ckchs)
- return ERR_ALERT | ERR_FATAL;
+ } else {
+ /* stat failed */
- cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+ 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;
+ }
+ }
return cfgerr;
}
#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.
{ 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 },
}};