From: Daniel Ruggeri Date: Wed, 14 Sep 2011 20:16:02 +0000 (+0000) Subject: Modify SSLProxyMachineCertificateChainFile to use X509 instead of X509_INFO and use... X-Git-Tag: 2.3.15~256 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47cf15b8520bd445ae6b2bf1a4a0dcdcf9a8d810;p=apache Modify SSLProxyMachineCertificateChainFile to use X509 instead of X509_INFO and use openssl to construct the chain git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1170833 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml index 37e766e083..933a12da74 100644 --- a/docs/manual/mod/mod_ssl.xml +++ b/docs/manual/mod/mod_ssl.xml @@ -1549,6 +1549,11 @@ This referenced file is simply the concatenation of the various PEM-encoded certificate files. Upon startup, each client certificate configured will be examined and a chain of trust will be constructed.

+Security warning +

If this directive is enabled, all of the certificates in the file will be +trusted as if they were also in +SSLProxyCACertificateFile.

+
Example SSLProxyMachineCertificateChainFile /usr/local/apache2/conf/ssl.crt/proxyCA.pem diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 48cb2b39f4..59fea93d01 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -1115,7 +1115,9 @@ static void ssl_init_proxy_certs(server_rec *s, int n, ncerts = 0; STACK_OF(X509_INFO) *sk; modssl_pk_proxy_t *pkp = mctx->pkp; - STACK_OF(X509_INFO) *chain; + STACK_OF(X509) *chain; + X509_STORE_CTX *sctx; + X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx); SSL_CTX_set_client_cert_cb(mctx->ssl_ctx, ssl_callback_proxy_cert); @@ -1161,29 +1163,42 @@ static void ssl_init_proxy_certs(server_rec *s, ncerts); pkp->certs = sk; - if (!pkp->ca_cert_file) { + + if (!pkp->ca_cert_file || !store) { return; } /* Load all of the CA certs and construct a chain */ - sk = sk_X509_INFO_new_null(); + pkp->ca_certs = (STACK_OF(X509) **) apr_pcalloc(p, ncerts * sizeof(sk)); + sctx = X509_STORE_CTX_new(); + + if (!sctx) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, + "SSL proxy client cert initialization failed"); + ssl_die(); + } - SSL_X509_INFO_load_file(ptemp, sk, pkp->ca_cert_file); - pkp->ca_certs = (STACK_OF(X509_INFO) **) apr_pcalloc(p, ncerts * sizeof(sk)); + X509_STORE_load_locations(store, pkp->ca_cert_file, NULL); for (n = 0; n < ncerts; n++) { - int len; + int i; X509_INFO *inf = sk_X509_INFO_value(pkp->certs, n); - chain = sk_X509_INFO_new_null(); - len = SSL_X509_INFO_create_chain(inf->x509, sk, chain); + X509_STORE_CTX_init(sctx, store, inf->x509, NULL); + X509_verify_cert(sctx); + ERR_clear_error(); + + chain = X509_STORE_CTX_get1_chain(sctx); + sk_X509_shift(chain); + i=sk_X509_num(chain); pkp->ca_certs[n] = chain; + X509_STORE_CTX_cleanup(sctx); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "client certificate %i has loaded %i " - "intermediary signers ", n, len); + "intermediate CA%s", n, i, i == 1 ? "" : "s"); } - sk_X509_INFO_free(sk); + X509_STORE_CTX_free(sctx); } static void ssl_init_proxy_ctx(server_rec *s, diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 3015130469..c88f6949cd 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -1588,11 +1588,12 @@ int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey) server_rec *s = mySrvFromConn(c); SSLSrvConfigRec *sc = mySrvConfig(s); X509_NAME *ca_name, *issuer, *ca_issuer; - X509_INFO *info, *ca_info; + X509_INFO *info; + X509 *ca_cert; STACK_OF(X509_NAME) *ca_list; STACK_OF(X509_INFO) *certs = sc->proxy->pkp->certs; - STACK_OF(X509_INFO) *ca_certs; - STACK_OF(X509_INFO) **ca_cert_chains; + STACK_OF(X509) *ca_certs; + STACK_OF(X509) **ca_cert_chains; int i, j, k; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, @@ -1640,21 +1641,21 @@ int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey) return TRUE; } - if (ca_cert_chains) { + if (ca_cert_chains) { /* - * Failed to find direct issuer - search intermediaries + * Failed to find direct issuer - search intermediates * (by issuer name), if provided. */ ca_certs = ca_cert_chains[j]; - for (k = 0; k < sk_X509_INFO_num(ca_certs); k++) { - ca_info = sk_X509_INFO_value(ca_certs, k); - ca_issuer = X509_get_issuer_name(ca_info->x509); + for (k = 0; k < sk_X509_num(ca_certs); k++) { + ca_cert = sk_X509_value(ca_certs, k); + ca_issuer = X509_get_issuer_name(ca_cert); if(X509_NAME_cmp(ca_issuer, ca_name) == 0 ) { - modssl_proxy_info_log(c, info, "found acceptable cert by intermediary"); + modssl_proxy_info_log(c, info, "found acceptable cert by intermediate CA"); modssl_set_cert_info(info, x509, pkey); - + return TRUE; } } /* end loop through chained certs */ diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index fd9ff2bd95..2a55f6795e 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -539,7 +539,7 @@ typedef struct { const char *cert_path; const char *ca_cert_file; STACK_OF(X509_INFO) *certs; - STACK_OF(X509_INFO) **ca_certs; /* ptr to array of ptrs */ + STACK_OF(X509) **ca_certs; /* ptr to array of ptrs */ } modssl_pk_proxy_t; /** stuff related to authentication that can also be per-dir */ diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c index f9ae5ee38a..dc59224734 100644 --- a/modules/ssl/ssl_util_ssl.c +++ b/modules/ssl/ssl_util_ssl.c @@ -385,46 +385,6 @@ BOOL SSL_X509_INFO_load_path(apr_pool_t *ptemp, return ok; } -/* - * Construct a stack of X509_INFO containing only certificates - * that have signed the provided certificate or are an intermediary - * signer of the certificate -*/ -int SSL_X509_INFO_create_chain(const X509 *x509, - STACK_OF(X509_INFO) *ca_certs, - STACK_OF(X509_INFO) *chain) -{ - int can_proceed = 1; - int len = 0; - int i; - X509 *certificate = (X509 *)x509; - X509_INFO *info; - X509_NAME *cert_issuer_name, *ca_name, *ca_issuer_name; - - while (can_proceed) { - can_proceed = 0; - cert_issuer_name = X509_get_issuer_name(certificate); - - for (i = 0; i < sk_X509_INFO_num(ca_certs); i++) { - info = sk_X509_INFO_value(ca_certs, i); - ca_name = X509_get_subject_name(info->x509); - ca_issuer_name = X509_get_issuer_name(info->x509); - - if (X509_NAME_cmp(cert_issuer_name, ca_name) == 0) { - /* Check for a self-signed cert (no issuer) */ - can_proceed = X509_NAME_cmp(ca_name, ca_issuer_name) == 0 - ? 0 : 1; - len++; - certificate = info->x509; - sk_X509_INFO_unshift(chain, info); - break; - } - } - } - - return len; -} - /* _________________________________________________________________ ** ** Extra Server Certificate Chain Support diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h index d2f995de2b..3da9c462f9 100644 --- a/modules/ssl/ssl_util_ssl.h +++ b/modules/ssl/ssl_util_ssl.h @@ -72,7 +72,6 @@ BOOL SSL_X509_INFO_load_file(apr_pool_t *, STACK_OF(X509_INFO) *, const c BOOL SSL_X509_INFO_load_path(apr_pool_t *, STACK_OF(X509_INFO) *, const char *); int SSL_CTX_use_certificate_chain(SSL_CTX *, char *, int, pem_password_cb *); char *SSL_SESSION_id2sz(unsigned char *, int, char *, int); -int SSL_X509_INFO_create_chain(const X509 *, STACK_OF(X509_INFO) *, STACK_OF(X509_INFO) *); #endif /* __SSL_UTIL_SSL_H__ */ /** @} */