Current mod_ssl code tries to read embedded DH and ECC parameters only
from the first certificate file. Although this is documented
"DH and ECDH parameters, however, are only read from the first
SSLCertificateFile directive, as they are applied independently of the
authentication algorithm type."
I find it questionable. I would find it more natural to embed the params
in the cert files they apply to, so e.g. the DH params in the RSA cert
file and the EC params in the ECDH cert file and also to not require a
special order for the files which at the end we do not check. Since
missing the embedded params goes unnoticed (finding them is only a DEBUG
log line) it is not very user friendly.
Can't we simply try to read DH and ECC params from every certificate
file and stop in each of the two cases when we have found some? That
would tighten the user unfriendlyness to the case of having multiple
inconsistent parameters embedded in different cert files. And even that
could be checked and logged as a warning.
I would suggest to move the param extraction a little above in the
certificate loop and only try to extract and use the params if a
previous extraction for that type did not already succeed. See below for
a patch suggestion. It moved the read code into the cert loop, removes
the NULL check for certfile (it is done in the loop condition), adds a
boolean dhparams_found and ecparams_found to track whether we already
found some and adds warnings if we find them more than once or if found
ecparams are not valid. The final "auto" behavior setting stays after
the loop and is executed if ecparams is still NULL.
Related is handling of keys embedded in cert files. AFAIK we only try to
read the key from the certificate file instead of a configured key file,
if there is no key file for the same index configured. That means if you
start mixing embedded keys and separate key files, all certificates with
separate key files must come first, then the certificates with the
embedded keys (and the order must match).For this I don't have a better
solution than just documenting it.
Regards,
Rainer
Index: modules/ssl/ssl_engine_init.c
===================================================================
--- modules/ssl/ssl_engine_init.c (revision 1681275)
+++ modules/ssl/ssl_engine_init.c (working copy)
@@ -1039,8 +1039,10 @@
int i;
X509 *cert;
DH *dhparams;
+ int dhparams_found = 0;
#ifdef HAVE_ECC
EC_GROUP *ecparams;
+ int ecparams_found = 0;
int nid;
EC_KEY *eckey = NULL;
#endif
@@ -1174,40 +1176,67 @@
SSL_free(ssl);
#endif
+ /*
+ * Try to read DH parameters from the SSLCertificateFile
+ */
+ dhparams = ssl_dh_GetParamFromFile(certfile);
+ if (dhparams) {
+ if (dhparams_found) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
APLOGNO(02901)
+ "Custom DH parameters already loaded for %s,"
+ " ignored from %s",
+ vhost_id, certfile);
+ }
+ else {
+ SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams);
+ dhparams_found = 1;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02540)
+ "Custom DH parameters (%d bits) for %s
loaded from %s",
+ BN_num_bits(dhparams->p), vhost_id, certfile);
+ }
+ }
+
+#ifdef HAVE_ECC
+ /*
+ * Try to read the ECDH curve name from SSLCertificateFile
+ */
+ ecparams = ssl_ec_GetParamFromFile(certfile);
+ if (ecparams) {
+ if (ecparams_found) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
APLOGNO(02902)
+ "Custom ECDH parameters already loaded for
%s,"
+ " ignored from %s",
+ vhost_id, certfile);
+ }
+ else {
+ if ((nid = EC_GROUP_get_curve_name(ecparams)) &&
+ (eckey = EC_KEY_new_by_curve_name(nid))) {
+ SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
+ ecparams_found = 1;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
APLOGNO(02541)
+ "ECDH curve %s for %s specified in %s",
+ OBJ_nid2sn(nid), vhost_id, certfile);
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
APLOGNO(02903)
+ "Invalid ECDH parameters for %s
ignored from %s",
+ vhost_id, certfile);
+ }
+ }
+ }
+#endif
+
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02568)
"Certificate and private key %s configured from
%s and %s",
key_id, certfile, keyfile);
}
- /*
- * Try to read DH parameters from the (first) SSLCertificateFile
- */
- if ((certfile = APR_ARRAY_IDX(mctx->pks->cert_files, 0, const char
*)) &&
- (dhparams = ssl_dh_GetParamFromFile(certfile))) {
- SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams);
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02540)
- "Custom DH parameters (%d bits) for %s loaded from
%s",
- BN_num_bits(dhparams->p), vhost_id, certfile);
- }
-
#ifdef HAVE_ECC
/*
- * Similarly, try to read the ECDH curve name from
SSLCertificateFile...
- */
- if ((certfile != NULL) &&
- (ecparams = ssl_ec_GetParamFromFile(certfile)) &&
- (nid = EC_GROUP_get_curve_name(ecparams)) &&
- (eckey = EC_KEY_new_by_curve_name(nid))) {
- SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02541)
- "ECDH curve %s for %s specified in %s",
- OBJ_nid2sn(nid), vhost_id, certfile);
- }
- /*
- * ...otherwise, enable auto curve selection (OpenSSL 1.0.2 and later)
+ * If we didn't find any ECDH params, enable auto curve selection
(OpenSSL 1.0.2 and later)
* or configure NIST P-256 (required to enable ECDHE for earlier
versions)
*/
- else {
+ if (!ecparams_found) {
#if defined(SSL_CTX_set_ecdh_auto)
SSL_CTX_set_ecdh_auto(mctx->ssl_ctx, 1);
#else
Index: docs/log-message-tags/next-number
===================================================================
--- docs/log-message-tags/next-number (revision 1681275)
+++ docs/log-message-tags/next-number (working copy)
@@ -1 +1 @@
-2901
+2904