On 9/19/2011 3:28 PM, Kaspar Brand wrote:
> IMO, you can always drop the first element of the chain, since you only
> want to remember CA certs in pkp->ca_certs.
>
OK, cool - I was unsure if the chain would ALWAYS contain the cert in
cases of validation OK or error. I'll make this quick update.
>> + else {
>> + int n=X509_STORE_CTX_get_error(sctx);
>> + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
>> + "SSL proxy client cert chain verification
failed for %s: %s",
>> + cert_cn, X509_verify_cert_error_string(n));
>> + }
> Here, cert_cn holds the X509_NAME_oneline() string of the subject DN.
> Either the variable name is a misnomer or a typo (did you mean cert_dn
> instead of cert_cn?)
Yes, indeed. s/_cn/_dn/g
>
> I have just added ssl_log_xerror() and SSL_X509_NAME_to_string() in
> r1172797, can you adapt the code in ssl_callback_proxy_cert() to make
> use of these where applicable/possible? Hopefully this makes logging
> cert details in mod_ssl more straightforward.
>
> Kaspar
Sure - no problem. Have a look at the update below. If this jives, I'll
commit to trunk when I have a minute to do so.
Also - any opposition to including SSL_X509_NAME_to_string as part of
the backport proposal? I would like to keep the patches consistent. If
not, would you prefer me to roll it into the
SSLProxyMachineCertificateChainFile patch or propose it separately?
Update...
X509_STORE_load_locations(store, pkp->ca_cert_file, NULL);
for (n = 0; n < ncerts; n++) {
int i, res;
X509_INFO *inf = sk_X509_INFO_value(pkp->certs, n);
X509_NAME *name = X509_get_subject_name(inf->x509);
char *cert_dn = SSL_X509_NAME_to_string(ptemp, name, 0);
X509_STORE_CTX_init(sctx, store, inf->x509, NULL);
if (X509_verify_cert(sctx) != 1) {
int err = X509_STORE_CTX_get_error(sctx);
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
"SSL proxy client cert chain verification
failed for %s: %s",
cert_dn, X509_verify_cert_error_string(err));
}
chain = X509_STORE_CTX_get1_chain(sctx);
/* Removing the client cert if verification is OK
* could save a loop when choosing which cert to send
* when more than one is available */
/* XXX: This is not needed if we collapse the two
* checks in ssl_engine_kernel in the future */
X509_free(sk_X509_shift(chain));
ERR_clear_error();
i = sk_X509_num(chain);
pkp->ca_certs[n] = chain;
if (i <= 1) {
/* zero or only the client cert won't be very useful
* due to verification failure */
sk_X509_pop_free(chain, X509_free);
i = 0;
pkp->ca_certs[n] = NULL;
}
X509_STORE_CTX_cleanup(sctx);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"loaded %i intermediate CA%s for cert %i (%s)",
i, i == 1 ? "" : "s", n, cert_dn);
if (i > 0) {
int j;
for (j=0; j<i; j++) {
X509_NAME *ca_name =
X509_get_subject_name(sk_X509_value(chain, j));
char *ca_dn = SSL_X509_NAME_to_string(ptemp, ca_name, 0);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "%i: %s", j,
ca_dn);
}
}
}
X509_STORE_CTX_free(sctx);
--
Daniel Ruggeri