From 130ddf47f7c5e22e56534e8b0b0ef1e9f8d8e3c6 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Wed, 27 Feb 2019 22:26:40 +0000 Subject: [PATCH] Add `dhparamfile` option, to allow DH parameters to be loaded. This is for Ephemeral DH support on listeners. --- ChangeLog.txt | 2 ++ man/mosquitto.conf.5.xml | 12 ++++++++++++ mosquitto.conf | 12 ++++++++++++ src/conf.c | 10 ++++++++++ src/mosquitto_broker_internal.h | 1 + src/net.c | 17 ++++++++++++++++- 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index e0f5bc0a..c2322855 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -12,6 +12,8 @@ Broker features: specific network interface, in a similar fashion to the `bind_address` option. Linux only. - Add improved bridge restart interval based on Decorrelated Jitter. +- Add `dhparamfile` option, to allow DH parameters to be loaded for Ephemeral + DH support Client library features: - Add mosquitto_subscribe_multiple() for sending subscriptions to multiple diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml index edf1309f..a34feefb 100644 --- a/man/mosquitto.conf.5.xml +++ b/man/mosquitto.conf.5.xml @@ -1041,6 +1041,18 @@ encoded revocation file. + + file path + + To allow the use of ephemeral DH key exchange, + which provides forward security, the listener must + load DH parameters. This can be specified with the + dhparamfile option. The dhparamfile can be + generated with the command e.g. + +openssl dhparam -out dhparam.pem 2048 + + file path diff --git a/mosquitto.conf b/mosquitto.conf index 9bd0a708..2927a610 100644 --- a/mosquitto.conf +++ b/mosquitto.conf @@ -312,6 +312,12 @@ # If unset defaults to DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:@STRENGTH #ciphers DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:@STRENGTH +# To allow the use of ephemeral DH key exchange, which provides forward +# security, the listener must load DH parameters. This can be specified with +# the dhparamfile option. The dhparamfile can be generated with the command +# e.g. "openssl dhparam -out dhparam.pem 2048" +#dhparamfile + # ----------------------------------------------------------------- # Pre-shared-key based SSL/TLS support # ----------------------------------------------------------------- @@ -463,6 +469,12 @@ # that command. #ciphers +# To allow the use of ephemeral DH key exchange, which provides forward +# security, the listener must load DH parameters. This can be specified with +# the dhparamfile option. The dhparamfile can be generated with the command +# e.g. "openssl dhparam -out dhparam.pem 2048" +#dhparamfile + # ----------------------------------------------------------------- # Pre-shared-key based SSL/TLS support # ----------------------------------------------------------------- diff --git a/src/conf.c b/src/conf.c index 810f342b..941becb3 100644 --- a/src/conf.c +++ b/src/conf.c @@ -306,6 +306,7 @@ void config__cleanup(struct mosquitto__config *config) mosquitto__free(config->listeners[i].ciphers); mosquitto__free(config->listeners[i].psk_hint); mosquitto__free(config->listeners[i].crlfile); + mosquitto__free(config->listeners[i].dhparamfile); mosquitto__free(config->listeners[i].tls_version); mosquitto__free(config->listeners[i].tls_engine); mosquitto__free(config->listeners[i].tls_engine_kpass_sha1); @@ -448,6 +449,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config || config->default_listener.tls_keyform != mosq_k_pem || config->default_listener.tls_engine_kpass_sha1 || config->default_listener.ciphers + || config->default_listener.dhparamfile || config->default_listener.psk_hint || config->default_listener.require_certificate || config->default_listener.crlfile @@ -509,6 +511,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config config->listeners[config->listener_count-1].certfile = config->default_listener.certfile; config->listeners[config->listener_count-1].keyfile = config->default_listener.keyfile; config->listeners[config->listener_count-1].ciphers = config->default_listener.ciphers; + config->listeners[config->listener_count-1].dhparamfile = config->default_listener.dhparamfile; config->listeners[config->listener_count-1].psk_hint = config->default_listener.psk_hint; config->listeners[config->listener_count-1].require_certificate = config->default_listener.require_certificate; config->listeners[config->listener_count-1].ssl_ctx = NULL; @@ -1203,6 +1206,13 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct if(conf__parse_string(&token, "crlfile", &cur_listener->crlfile, saveptr)) return MOSQ_ERR_INVAL; #else log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available."); +#endif + }else if(!strcmp(token, "dhparamfile")){ +#ifdef WITH_TLS + if(reload) continue; // Listeners not valid for reloading. + if(conf__parse_string(&token, "dhparamfile", &cur_listener->dhparamfile, saveptr)) return MOSQ_ERR_INVAL; +#else + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available."); #endif }else if(!strcmp(token, "http_dir")){ #ifdef WITH_WEBSOCKETS diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h index 2677e1d0..dfbe0fa5 100644 --- a/src/mosquitto_broker_internal.h +++ b/src/mosquitto_broker_internal.h @@ -234,6 +234,7 @@ struct mosquitto__listener { SSL_CTX *ssl_ctx; char *crlfile; char *tls_version; + char *dhparamfile; bool use_identity_as_username; bool use_subject_as_username; bool require_certificate; diff --git a/src/net.c b/src/net.c index 63516ab7..d6220a0f 100644 --- a/src/net.c +++ b/src/net.c @@ -312,7 +312,8 @@ static int mosquitto__tls_server_ctx(struct mosquitto__listener *listener) { char buf[256]; int rc; - + FILE *dhparamfile; + DH *dhparam = NULL; #if OPENSSL_VERSION_NUMBER < 0x10100000L listener->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); @@ -371,6 +372,20 @@ static int mosquitto__tls_server_ctx(struct mosquitto__listener *listener) return 1; } } + if(listener->dhparamfile){ + dhparamfile = fopen(listener->dhparamfile, "r"); + if(!dhparamfile){ + log__printf(NULL, MOSQ_LOG_ERR, "Error loading dhparamfile \"%s\".", listener->dhparamfile); + return 1; + } + dhparam = PEM_read_DHparams(dhparamfile, NULL, NULL, NULL); + fclose(dhparamfile); + + if(dhparam == NULL || SSL_CTX_set_tmp_dh(listener->ssl_ctx, dhparam) != 1){ + log__printf(NULL, MOSQ_LOG_ERR, "Error loading dhparamfile \"%s\".", listener->dhparamfile); + return 1; + } + } return MOSQ_ERR_SUCCESS; } #endif