diff -ru httpd-2.2.14.orig/modules/ssl/mod_ssl.c httpd-2.2.14.new/modules/ssl/mod_ssl.c --- httpd-2.2.14.orig/modules/ssl/mod_ssl.c 2009-05-19 13:44:59.000000000 +0200 +++ httpd-2.2.14.new/modules/ssl/mod_ssl.c 2010-07-06 11:56:50.897588899 +0200 @@ -108,6 +108,9 @@ SSL_CMD_SRV(CertificateKeyFile, TAKE1, "SSL Server Private Key file " "(`/path/to/file' - PEM or DER encoded)") + SSL_CMD_SRV(DHParametersFile, TAKE1, + "SSL Server Diffie-Hellman parameters file " + "(`/path/to/file' - PEM or DER encoded)") SSL_CMD_SRV(CertificateChainFile, TAKE1, "SSL Server CA Certificate Chain file " "(`/path/to/file' - PEM encoded)") diff -ru httpd-2.2.14.orig/modules/ssl/ssl_engine_config.c httpd-2.2.14.new/modules/ssl/ssl_engine_config.c --- httpd-2.2.14.orig/modules/ssl/ssl_engine_config.c 2009-05-19 13:44:59.000000000 +0200 +++ httpd-2.2.14.new/modules/ssl/ssl_engine_config.c 2010-07-06 11:56:50.897588899 +0200 @@ -72,6 +72,7 @@ mc->tVHostKeys = apr_hash_make(pool); mc->tPrivateKey = apr_hash_make(pool); mc->tPublicCert = apr_hash_make(pool); + mc->tDHParams = apr_hash_make(pool); #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) mc->szCryptoDevice = NULL; #endif @@ -156,6 +157,9 @@ mctx->pks = apr_pcalloc(p, sizeof(*mctx->pks)); /* mctx->pks->... certs/keys are set during module init */ + + mctx->pks->dhparams_file = NULL; + mctx->pks->dhparams = NULL; } static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p) @@ -246,6 +250,7 @@ cfgMergeString(pks->ca_name_path); cfgMergeString(pks->ca_name_file); + cfgMergeString(pks->dhparams_file); } /* @@ -762,6 +767,22 @@ return NULL; } +const char *ssl_cmd_SSLDHParametersFile(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + const char *err; + + if ((err = ssl_cmd_check_file(cmd, &arg))) { + return err; + } + + sc->server->pks->dhparams_file = arg; + + return NULL; +} + const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *cmd, void *dcfg, const char *arg) diff -ru httpd-2.2.14.orig/modules/ssl/ssl_engine_init.c httpd-2.2.14.new/modules/ssl/ssl_engine_init.c --- httpd-2.2.14.orig/modules/ssl/ssl_engine_init.c 2009-08-16 17:53:12.000000000 +0200 +++ httpd-2.2.14.new/modules/ssl/ssl_engine_init.c 2010-07-06 11:56:50.897588899 +0200 @@ -723,6 +723,42 @@ } } +static int ssl_server_import_dhparams(server_rec *s, + modssl_ctx_t *mctx, + const char *id) +{ + SSLModConfigRec *mc = myModConfig(s); + ssl_asn1_t *asn1; + MODSSL_D2I_DHparams_CONST unsigned char *ptr; + DH *dhparams = NULL; + + if (!(asn1 = ssl_asn1_table_get(mc->tDHParams, id))) { + return FALSE; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "Configuring server Diffie-Hellman parameters"); + + ptr = asn1->cpData; + if (!(dhparams = d2i_DHparams(NULL, &ptr, asn1->nData))) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to import server Diffie-Hellman parameters"); + ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_die(); + } + + if (SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams) <= 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to configure server Diffie-Hellman parameters"); + ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_die(); + } + + mctx->pks->dhparams = dhparams; + + return TRUE; +} + static int ssl_server_import_cert(server_rec *s, modssl_ctx_t *mctx, const char *id, @@ -882,16 +918,18 @@ apr_pool_t *ptemp, modssl_ctx_t *mctx) { - const char *rsa_id, *dsa_id; + const char *rsa_id, *dsa_id, *dh_id; const char *vhost_id = mctx->sc->vhost_id; int i; int have_rsa, have_dsa; rsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_RSA); dsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_DSA); + dh_id = apr_pstrcat(ptemp, vhost_id, ":", "DH", NULL); have_rsa = ssl_server_import_cert(s, mctx, rsa_id, SSL_AIDX_RSA); have_dsa = ssl_server_import_cert(s, mctx, dsa_id, SSL_AIDX_DSA); + (void)ssl_server_import_dhparams(s, mctx, dh_id); if (!(have_rsa || have_dsa)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, @@ -1265,6 +1303,7 @@ MODSSL_CFG_ITEM_FREE(EVP_PKEY_free, mctx->pks->keys[i]); } + MODSSL_CFG_ITEM_FREE(DH_free, mctx->pks->dhparams); } apr_status_t ssl_init_ModuleKill(void *data) diff -ru httpd-2.2.14.orig/modules/ssl/ssl_engine_pphrase.c httpd-2.2.14.new/modules/ssl/ssl_engine_pphrase.c --- httpd-2.2.14.orig/modules/ssl/ssl_engine_pphrase.c 2009-09-16 22:06:05.000000000 +0200 +++ httpd-2.2.14.new/modules/ssl/ssl_engine_pphrase.c 2010-07-06 11:56:50.897588899 +0200 @@ -144,6 +144,7 @@ unsigned char *ucp; long int length; X509 *pX509Cert; + DH *pDHParams; BOOL bReadable; apr_array_header_t *aPassPhrase; int nPassPhrase; @@ -192,8 +193,10 @@ pServ->defn_name, pServ->defn_line_number); ssl_die(); } + algoCert = SSL_ALGO_UNKNOWN; algoKey = SSL_ALGO_UNKNOWN; + for (i = 0, j = 0; i < SSL_AIDX_MAX && sc->server->pks->cert_files[i] != NULL; i++) { apr_cpystrn(szPath, sc->server->pks->cert_files[i], sizeof(szPath)); @@ -517,6 +520,45 @@ */ EVP_PKEY_free(pPrivateKey); } + + /* + * Read in Diffie-Hellman parameters file if such a file is + * specified. + */ + if (sc->server->pks->dhparams_file) { + apr_cpystrn(szPath, sc->server->pks->dhparams_file, sizeof(szPath)); + if ((rv = exists_and_readable(szPath, p, NULL)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "Init: Can't open server Diffie-Hellman parameters file %s", + szPath); + ssl_die(); + } + if ((pDHParams = SSL_read_DHparams(szPath, NULL, NULL)) == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Init: Unable to read server Diffie-Hellman parameters from file %s", szPath); + ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_die(); + } + + /* + * Insert the DH params into global module configuration + * to let it survive the processing between the 1st Apache + * API init round (where we operate here) and the 2nd + * Apache init round (where it will be actually used to + * configure mod_ssl's per-server configuration + * structures). + */ + cp = asn1_table_vhost_key(mc, p, cpVHostID, "DH"); + length = i2d_DHparams(pDHParams, NULL); + ucp = ssl_asn1_table_set(mc->tDHParams, cp, length); + (void)i2d_DHparams(pDHParams, &ucp); /* 2nd arg increments */ + + /* + * Free the DH structure + */ + DH_free(pDHParams); + } + } /* diff -ru httpd-2.2.14.orig/modules/ssl/ssl_private.h httpd-2.2.14.new/modules/ssl/ssl_private.h --- httpd-2.2.14.orig/modules/ssl/ssl_private.h 2009-05-19 13:44:59.000000000 +0200 +++ httpd-2.2.14.new/modules/ssl/ssl_private.h 2010-07-06 11:56:50.897588899 +0200 @@ -378,6 +378,7 @@ void *pTmpKeys[SSL_TMP_KEY_MAX]; apr_hash_t *tPublicCert; apr_hash_t *tPrivateKey; + apr_hash_t *tDHParams; #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) const char *szCryptoDevice; #endif @@ -394,8 +395,10 @@ */ const char *cert_files[SSL_AIDX_MAX]; const char *key_files[SSL_AIDX_MAX]; + const char *dhparams_file; X509 *certs[SSL_AIDX_MAX]; EVP_PKEY *keys[SSL_AIDX_MAX]; + DH *dhparams; /** Certificates which specify the set of CA names which should be * sent in the CertificateRequest message: */ @@ -510,6 +513,7 @@ const char *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *); const char *ssl_cmd_SSLEngine(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLDHParametersFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *); diff -ru httpd-2.2.14.orig/modules/ssl/ssl_toolkit_compat.h httpd-2.2.14.new/modules/ssl/ssl_toolkit_compat.h --- httpd-2.2.14.orig/modules/ssl/ssl_toolkit_compat.h 2009-05-19 13:44:59.000000000 +0200 +++ httpd-2.2.14.new/modules/ssl/ssl_toolkit_compat.h 2010-07-06 11:56:50.897588899 +0200 @@ -100,9 +100,11 @@ #if (OPENSSL_VERSION_NUMBER >= 0x00908000) # define MODSSL_D2I_PrivateKey_CONST const # define MODSSL_D2I_X509_CONST const +# define MODSSL_D2I_DHparams_CONST const #else # define MODSSL_D2I_PrivateKey_CONST # define MODSSL_D2I_X509_CONST +# define MODSSL_D2I_DHparams_CONST #endif #if (OPENSSL_VERSION_NUMBER >= 0x00909000) @@ -117,8 +119,10 @@ #if (OPENSSL_VERSION_NUMBER < 0x00904000) #define modssl_PEM_read_bio_X509(b, x, cb, arg) PEM_read_bio_X509(b, x, cb) +#define modssl_PEM_read_bio_DHparams(b, x, cb, arg) PEM_read_bio_DHparams(b, x, cb) #else #define modssl_PEM_read_bio_X509(b, x, cb, arg) PEM_read_bio_X509(b, x, cb, arg) +#define modssl_PEM_read_bio_DHparams(b, x, cb, arg) PEM_read_bio_DHparams(b, x, cb, arg) #endif #define modssl_PEM_X509_INFO_read_bio PEM_X509_INFO_read_bio diff -ru httpd-2.2.14.orig/modules/ssl/ssl_util_ssl.c httpd-2.2.14.new/modules/ssl/ssl_util_ssl.c --- httpd-2.2.14.orig/modules/ssl/ssl_util_ssl.c 2009-08-06 09:28:47.000000000 +0200 +++ httpd-2.2.14.new/modules/ssl/ssl_util_ssl.c 2010-07-06 11:56:50.897588899 +0200 @@ -115,6 +115,47 @@ return rc; } +DH *SSL_read_DHparams(char* filename, DH **DHparams, modssl_read_bio_cb_fn *cb) +{ + DH *rc; + BIO *bioS; + BIO *bioF; + + /* 1. try PEM (= DER+Base64+headers) */ + if ((bioS=BIO_new_file(filename, "r")) == NULL) + return NULL; + rc = modssl_PEM_read_bio_DHparams (bioS, DHparams, cb, NULL); + BIO_free(bioS); + + if (rc == NULL) { + /* 2. try DER+Base64 */ + if ((bioS=BIO_new_file(filename, "r")) == NULL) + return NULL; + + if ((bioF = BIO_new(BIO_f_base64())) == NULL) { + BIO_free(bioS); + return NULL; + } + bioS = BIO_push(bioF, bioS); + rc = d2i_DHparams_bio(bioS, NULL); + BIO_free_all(bioS); + + if (rc == NULL) { + /* 3. try plain DER */ + if ((bioS=BIO_new_file(filename, "r")) == NULL) + return NULL; + rc = d2i_DHparams_bio(bioS, NULL); + BIO_free(bioS); + } + } + if (rc != NULL && DHparams != NULL) { + if (*DHparams != NULL) + DH_free(*DHparams); + *DHparams = rc; + } + return rc; +} + #if SSL_LIBRARY_VERSION <= 0x00904100 static EVP_PKEY *d2i_PrivateKey_bio(BIO *bio, EVP_PKEY **key) {