MEDIUM: ssl: add the possibility to use a global DH parameters file

This patch adds the ssl-dh-param-file global setting. It sets the
default DH parameters that will be used during the SSL/TLS handshake when
ephemeral Diffie-Hellman (DHE) key exchange is used, for all "bind" lines
which do not explicitely define theirs.
This commit is contained in:
Remi Gacogne 2015-05-29 15:53:22 +02:00 committed by Willy Tarreau
parent 79318d79ba
commit 47783ef05b
4 changed files with 83 additions and 16 deletions

View File

@ -766,6 +766,20 @@ ssl-default-server-options [<option>]...
default ssl-options to force on all "server" lines. Please check the "server"
keyword to see available options.
ssl-dh-param-file <file>
This setting is only available when support for OpenSSL was built in. It sets
the default DH parameters that are used during the SSL/TLS handshake when
ephemeral Diffie-Hellman (DHE) key exchange is used, for all "bind" lines
which do not explicitely define theirs. It will be overridden by custom DH
parameters found in a bind certificate file if any. If custom DH parameters
are not specified either by using ssl-dh-param-file or by setting them directly
in the certificate file, pre-generated DH parameters of the size specified
by tune.ssl.default-dh-param will be used. Custom parameters are known to be
more secure and therefore their use is recommended.
Custom DH parameters may be generated by using the OpenSSL command
"openssl dhparam <size>", where size should be at least 2048, as 1024-bit DH
parameters should not be considered secure anymore.
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
@ -1224,7 +1238,8 @@ tune.ssl.default-dh-param <number>
this maximum value. Default value if 1024. Only 1024 or higher values are
allowed. Higher values will increase the CPU load, and values greater than
1024 bits are not supported by Java 7 and earlier clients. This value is not
used if static Diffie-Hellman parameters are supplied via the certificate file.
used if static Diffie-Hellman parameters are supplied either directly
in the certificate file or by using the ssl-dh-param-file parameter.
tune.zlib.memlevel <number>
Sets the memLevel parameter in zlib initialization for each session. It

View File

@ -64,6 +64,9 @@ struct tls_keys_ref *tlskeys_ref_lookup(const char *filename);
struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id);
void tlskeys_finalize_config(void);
#endif
#ifndef OPENSSL_NO_DH
int ssl_sock_load_global_dh_param_from_file(const char *filename);
#endif
#endif /* _PROTO_SSL_SOCK_H */

View File

@ -753,6 +753,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
}
global.tune.ssl_max_record = atol(args[1]);
}
#ifndef OPENSSL_NO_DH
else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
@ -768,6 +769,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
goto out;
}
}
#endif
#endif
else if (!strcmp(args[0], "tune.buffers.limit")) {
if (alertif_too_many_args(1, file, linenum, args, &err_code))
@ -1187,6 +1189,22 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
goto out;
#endif
}
#ifdef USE_OPENSSL
#ifndef OPENSSL_NO_DH
else if (!strcmp(args[0], "ssl-dh-param-file")) {
if (*(args[1]) == 0) {
Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (ssl_sock_load_global_dh_param_from_file(args[1])) {
Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
}
#endif
#endif
else if (!strcmp(args[0], "ssl-server-verify")) {
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;

View File

@ -124,6 +124,7 @@ struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
#ifndef OPENSSL_NO_DH
static int ssl_dh_ptr_index = -1;
static DH *global_dh = NULL;
static DH *local_dh_1024 = NULL;
static DH *local_dh_2048 = NULL;
static DH *local_dh_4096 = NULL;
@ -1332,22 +1333,44 @@ static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
return dh;
}
static DH * ssl_sock_get_dh_from_file(const char *filename)
{
DH *dh = NULL;
BIO *in = BIO_new(BIO_s_file());
if (in == NULL)
goto end;
if (BIO_read_filename(in, filename) <= 0)
goto end;
dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
end:
if (in)
BIO_free(in);
return dh;
}
int ssl_sock_load_global_dh_param_from_file(const char *filename)
{
global_dh = ssl_sock_get_dh_from_file(filename);
if (global_dh) {
return 0;
}
return -1;
}
/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
if an error occured, and 0 if parameter not found. */
int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
{
int ret = -1;
BIO *in;
DH *dh = NULL;
DH *dh = ssl_sock_get_dh_from_file(file);
in = BIO_new(BIO_s_file());
if (in == NULL)
goto end;
if (BIO_read_filename(in, file) <= 0)
goto end;
dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
if (dh) {
ret = 1;
SSL_CTX_set_tmp_dh(ctx, dh);
@ -1358,6 +1381,10 @@ int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
}
}
else if (global_dh) {
SSL_CTX_set_tmp_dh(ctx, global_dh);
ret = 0; /* DH params not found */
}
else {
/* Clear openssl global errors stack */
ERR_clear_error();
@ -1381,9 +1408,6 @@ end:
if (dh)
DH_free(dh);
if (in)
BIO_free(in);
return ret;
}
#endif
@ -1901,9 +1925,11 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy
cfgerr++;
}
/* If tune.ssl.default-dh-param has not been set and
no static DH params were in the certificate file. */
/* If tune.ssl.default-dh-param has not been set,
neither has ssl-default-dh-file and no static DH
params were in the certificate file. */
if (global.tune.ssl_default_dh_param == 0 &&
global_dh == NULL &&
(ssl_dh_ptr_index == -1 ||
SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
@ -5083,6 +5109,11 @@ static void __ssl_sock_deinit(void)
DH_free(local_dh_8192);
local_dh_8192 = NULL;
}
if (global_dh) {
DH_free(global_dh);
global_dh = NULL;
}
#endif
ERR_remove_state(0);