diff --git a/config.h.in b/config.h.in index c22bdd7f5..e5c52f4ce 100644 --- a/config.h.in +++ b/config.h.in @@ -786,6 +786,9 @@ /* Define to 1 if you have the `SSL_CTX_get0_certificate' function. */ #undef HAVE_SSL_CTX_GET0_CERTIFICATE +/* Define to 1 if you have the `SSL_CTX_set0_tmp_dh_pkey' function. */ +#undef HAVE_SSL_CTX_SET0_TMP_DH_PKEY + /* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function or macro. */ #undef HAVE_SSL_CTX_SET_CIPHERSUITES diff --git a/configure b/configure index 37e07b8dc..9d8c44946 100755 --- a/configure +++ b/configure @@ -23787,6 +23787,12 @@ if test "x$ac_cv_func_SSL_CTX_get0_certificate" = xyes then : printf "%s\n" "#define HAVE_SSL_CTX_GET0_CERTIFICATE 1" >>confdefs.h +fi +ac_fn_c_check_func "$LINENO" "SSL_CTX_set0_tmp_dh_pkey" "ac_cv_func_SSL_CTX_set0_tmp_dh_pkey" +if test "x$ac_cv_func_SSL_CTX_set0_tmp_dh_pkey" = xyes +then : + printf "%s\n" "#define HAVE_SSL_CTX_SET0_TMP_DH_PKEY 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "TLS_method" "ac_cv_func_TLS_method" if test "x$ac_cv_func_TLS_method" = xyes diff --git a/configure.ac b/configure.ac index 8469acce9..4b661bb04 100644 --- a/configure.ac +++ b/configure.ac @@ -3037,7 +3037,7 @@ dnl if test "${enable_openssl-no}" != no; then OLIBS="$LIBS" LIBS="$LIBS $LIBTLS" - AC_CHECK_FUNCS([X509_STORE_CTX_get0_cert ASN1_STRING_get0_data SSL_CTX_get0_certificate TLS_method]) + AC_CHECK_FUNCS([X509_STORE_CTX_get0_cert ASN1_STRING_get0_data SSL_CTX_get0_certificate SSL_CTX_set0_tmp_dh_pkey TLS_method]) # SSL_CTX_set_min_proto_version may be a macro AC_CHECK_DECL([SSL_CTX_set_min_proto_version], [AC_DEFINE(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)], [], [ AC_INCLUDES_DEFAULT diff --git a/logsrvd/tls_init.c b/logsrvd/tls_init.c index 5b9e47702..a8dcabc3e 100644 --- a/logsrvd/tls_init.c +++ b/logsrvd/tls_init.c @@ -30,6 +30,8 @@ #endif #include #include +#include +#include #if defined(HAVE_OPENSSL) # include @@ -173,6 +175,85 @@ init_tls_ciphersuites(SSL_CTX *ctx, const char *ciphers_v12, debug_return_bool(true); } +/* + * Load diffie-hellman parameters from bio and store in ctx. + * Returns true on success, else false. + */ +#ifdef HAVE_SSL_CTX_SET0_TMP_DH_PKEY +static bool +set_dhparams_bio(SSL_CTX *ctx, BIO *bio) +{ + EVP_PKEY *dhparams; + bool ret = false; + debug_decl(set_dhparams_bio, SUDO_DEBUG_UTIL); + + dhparams = PEM_read_bio_Parameters(bio, NULL); + if (dhparams != NULL) { + /* dhparams is owned by ctx on success. */ + ret = SSL_CTX_set0_tmp_dh_pkey(ctx, dhparams); + if (!ret) { + const char *errstr = ERR_reason_error_string(ERR_get_error()); + sudo_warnx(U_("unable to set diffie-hellman parameters: %s"), + errstr); + EVP_PKEY_free(dhparams); + } + } + debug_return_bool(ret); +} +#else +static bool +set_dhparams_bio(SSL_CTX *ctx, BIO *bio) +{ + DH *dhparams; + bool ret = false; + debug_decl(set_dhparams_bio, SUDO_DEBUG_UTIL); + + dhparams = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + if (dhparams != NULL) { + /* LEAK: dhparams leaked on config reload */ + ret = SSL_CTX_set_tmp_dh(ctx, dhparams); + if (!ret) { + const char *errstr = ERR_reason_error_string(ERR_get_error()); + sudo_warnx(U_("unable to set diffie-hellman parameters: %s"), + errstr); + DH_free(dhparams); + } + } + debug_return_bool(ret); +} +#endif /* HAVE_SSL_CTX_SET0_TMP_DH_PKEY */ + +/* + * Load diffie-hellman parameters from the specified file and store in ctx. + * Returns true on success, else false. + */ +static bool +set_dhparams(SSL_CTX *ctx, const char *dhparam_file) +{ + BIO *bio = NULL; + bool ret = false; + int fd; + debug_decl(set_dhparams, SUDO_DEBUG_UTIL); + + fd = open(dhparam_file, O_RDONLY); + if (fd != -1) + bio = BIO_new_fd(fd, BIO_CLOSE); + if (bio != NULL) { + if (set_dhparams_bio(ctx, bio)) { + sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, + "loaded diffie-hellman parameters from %s", dhparam_file); + ret = true; + } + } else { + sudo_warn(U_("unable to open %s"), dhparam_file); + if (fd != -1) + close(fd); + } + BIO_free(bio); + + debug_return_bool(ret); +} + SSL_CTX * init_tls_context(const char *ca_bundle_file, const char *cert_file, const char *key_file, const char *dhparam_file, const char *ciphers_v12, @@ -270,27 +351,9 @@ init_tls_context(const char *ca_bundle_file, const char *cert_file, * Failure to open the file is not a fatal error. */ if (dhparam_file != NULL) { - FILE *fp = fopen(dhparam_file, "r"); - if (fp != NULL) { - DH *dhparams = PEM_read_DHparams(fp, NULL, NULL, NULL); - if (dhparams != NULL) { - if (!SSL_CTX_set_tmp_dh(ctx, dhparams)) { - errstr = ERR_reason_error_string(ERR_get_error()); - sudo_warnx(U_("unable to set diffie-hellman parameters: %s"), - errstr); - DH_free(dhparams); - } else { - sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, - "loaded diffie-hellman parameters from %s", dhparam_file); - } - } else { - errstr = ERR_reason_error_string(ERR_get_error()); - sudo_warnx(U_("unable to read diffie-hellman parameters: %s"), - errstr); - } - fclose(fp); - } else { - sudo_warn(U_("unable to open %s"), dhparam_file); + if (!set_dhparams(ctx, dhparam_file)) { + sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, + "unable to load dhparam file, using default parameters"); } } else { sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,