On 18.11.2013 15:38, Dr Stephen Henson wrote:
> Erk typo.. I of course meant "...after you call SSL_CTX_use_certificate_file 
> or
> SSL_CTX_use_certificate_chain_file..."

Yeah this was obvious... makes me cringe as well but here we go:

  https://people.apache.org/~kbrand/mod_ssl_pkey_2013-11-18_wip.patch

(interdiff attached to this message)

For the SSL_CONF_cmd loop, I had to insert a call to
ssl_stapling_init_cert as well - currently I'm testing for the
"Certificate" parameter name being set, but if there's a better way to
figure out if we need to call ssl_stapling_init_cert, I'm all ears.

> Unfortunately due to a limitation in OpenSSL 1.0.1 and earlier you can only 
> have
> one chain for the SSL_CTX shared by all certificate types and all SSL 
> structures
> created from it.
> 
> That means if you have more than one certificate configured and they have
> different chains the second will replace the first in the SSL_CTX and it will
> end up sending the wrong chain in some cases.

Right, that's essentially what the last paragraph of the
SSLCertificateChainFile is stating
(http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcertificatechainfile),
so I wouldn't worry too much about the behavior with releases up to 1.0.1.

> For OpenSSL 1.0.2 this limitation is removed and you can have different chains
> for each certificate type (and for SSL structures too) and it just uses the
> right one. This uses the function SSL_CTX_add1_chain_cert which adds a
> certificate to the chain for the current certificate.
> 
> I *could* change SSL_CTX_use_certificate_chain_file to use
> SSL_CTX_add1_chain_cert instead of SSL_CTX_add_extra_chain_cert or perhaps 
> have
> a different function. I'm always cautious about changing the behaviour of
> existing functions though as the most innocent change will usually break
> *something*, though I can't see how it can in this case.

I would be in favor this change for 1.0.2 - to me that would be more
like a "fix" of SSL_CTX_use_certificate_chain_file than a change in
behavior, actually.

Kaspar
diff -u trunk/modules/ssl/ssl_engine_init.c trunk/modules/ssl/ssl_engine_init.c
--- trunk/modules/ssl/ssl_engine_init.c (working copy)
+++ trunk/modules/ssl/ssl_engine_init.c (working copy)
@@ -836,6 +836,8 @@
     DH *dhparams;
     ssl_asn1_t *asn1;
     EVP_PKEY *pkey;
+    SSL *ssl;
+    X509 *cert;
     SSLModConfigRec *mc = myModConfig(s);
 
     const char *certfile, *keyfile;
@@ -889,31 +891,39 @@
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO()
                          "Certificate and private key #%d for %s do not match",
                          i + 1, vhost_id);
-            /* 
-             * XXX we can't call ssl_check_public_cert() here, currently,
-             * as there's no way to get at the X509 * which was configured
-             * by SSL_CTX_use_certificate_[chain_]file... eventually, we
-             * would probably want to call:
-             * ssl_check_public_cert(s, ptemp, cert, i + 1);
-             */
             break;
         }
 
+        /* 
+         * workaround for those OpenSSL versions where SSL_CTX_get_certificate
+         * is not yet available: create an SSL * which we'll simply throw away
+         * a few lines further down
+         */
+        if (!(ssl = SSL_new(mctx->ssl_ctx)) ||
+            !(cert = SSL_get_certificate(ssl))) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO()
+                         "Unable to retrieve certificate #%d for %s",
+                         i + 1, vhost_id);
+            if (ssl)
+                SSL_free(ssl);
+            break;
+        }
+
+        /* warn about potential cert issues */
+        ssl_check_public_cert(s, ptemp, cert, i + 1);
+
 #ifdef HAVE_OCSP_STAPLING
         if ((mctx->pkp == FALSE) && (mctx->stapling_enabled == TRUE)) {
-            /* 
-             * XXX can't call ssl_stapling_init_cert currently, for the
-             * same reason as above with ssl_check_public_cert
-             * 
             if (!ssl_stapling_init_cert(s, mctx, cert)) {
                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02235)
                              "Unable to configure certificate #%d for %s "
                              "for stapling", i + 1, vhost_id);
             }
-             */
         }
 #endif
 
+        SSL_free(ssl);
+
         ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO()
                      "Certificate and key #%d for %s configured from %s and 
%s",
                      i + 1, vhost_id, certfile, keyfile);
@@ -1189,6 +1199,23 @@
             ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
             ssl_die(s);
         }
+#ifdef HAVE_OCSP_STAPLING
+        if (!strcasecmp(param->name, "Certificate") &&
+            sc->server->stapling_enabled == TRUE) {
+            SSL *ssl;
+            X509 *cert;
+            if (!(ssl = SSL_new(sc->server->ssl_ctx)) ||
+                !(cert = SSL_get_certificate(ssl)) ||
+                !ssl_stapling_init_cert(s, sc->server, cert)) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO()
+                             "Unable to configure certificate loaded "
+                             "from %s for %s for stapling",
+                             param->value, sc->vhost_id);
+            }
+            if (ssl)
+                SSL_free(ssl);
+        }
+#endif
     }
     if (SSL_CONF_CTX_finish(cctx) == 0) {
             ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO()

Reply via email to