[Pkg-fedora-ds-maintainers] [libapache2-mod-nss] 10/156: Add support for the SSL_CLIENT_CERT_CHAIN_ environment variable. SSL_CLIENT_I_DN_ was incorrectly parsing the client certificate subject instead of the issuer subject. Print out PEM files the same way as OpenSSL

Timo Aaltonen tjaalton-guest at moszumanska.debian.org
Wed Jul 2 13:55:22 UTC 2014


This is an automated email from the git hooks/post-receive script.

tjaalton-guest pushed a commit to branch master
in repository libapache2-mod-nss.

commit d4ead13624e36b4f622b3f4c5e540427976dac4f
Author: rcritten <>
Date:   Tue May 24 21:25:42 2005 +0000

    Add support for the SSL_CLIENT_CERT_CHAIN_ environment variable.
    SSL_CLIENT_I_DN_ was incorrectly parsing the client certificate subject
    instead of the issuer subject.
    Print out PEM files the same way as OpenSSL
---
 nss_engine_kernel.c | 25 +++++++++++++++++
 nss_engine_vars.c   | 78 ++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 90 insertions(+), 13 deletions(-)

diff --git a/nss_engine_kernel.c b/nss_engine_kernel.c
index 6e164a8..fb47eff 100644
--- a/nss_engine_kernel.c
+++ b/nss_engine_kernel.c
@@ -809,6 +809,8 @@ int ssl_hook_Fixup(request_rec *r)
     apr_table_t *env = r->subprocess_env;
     char *var, *val = "";
     int i;
+    CERTCertificate *cert;
+    CERTCertificateList *chain = NULL;
 
     /*
      * Check to see if SSL is on
@@ -863,6 +865,29 @@ int ssl_hook_Fixup(request_rec *r)
         /* Need to fetch the entire SSL cert chain and add it to the 
          * variable SSL_CLIENT_CERT_CHAIN_[0..n]
          */
+        cert = SSL_PeerCertificate(ssl);
+
+        if (cert)
+            chain = CERT_CertChainFromCert(cert, certUsageSSLClient, PR_TRUE);
+
+        if (cert && chain) {
+            int n;
+
+            n = chain->len;
+
+            CERT_DestroyCertificateList(chain);
+
+            for (i = 0; i < n; i++) {
+                var = apr_psprintf(r->pool, "SSL_CLIENT_CERT_CHAIN_%d", i);
+                val = ssl_var_lookup(r->pool, r->server, r->connection,
+                                     r, var);
+                if (val) {
+                    apr_table_setn(env, var, val);
+                }
+            }
+        }
+        if (cert)
+            CERT_DestroyCertificate(cert);
     }
 
     return DECLINED;
diff --git a/nss_engine_vars.c b/nss_engine_vars.c
index a38013e..8cb24ce 100644
--- a/nss_engine_vars.c
+++ b/nss_engine_vars.c
@@ -29,8 +29,9 @@
 static char *ssl_var_lookup_header(apr_pool_t *p, request_rec *r, const char *name);
 static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var);
 static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, CERTCertificate *xs, char *var, conn_rec *c);
-static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, CERTCertificate *cert, char *var);
+static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, CERTName *cert, char *var);
 static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, CERTCertificate *xs, int type);
+static char *ssl_var_lookup_ssl_cert_chain(apr_pool_t *p, CERTCertificate *cert,char *var);
 static char *ssl_var_lookup_ssl_cert_PEM(apr_pool_t *p, CERTCertificate *xs);
 static char *ssl_var_lookup_ssl_cert_verify(apr_pool_t *p, conn_rec *c);
 static char *ssl_var_lookup_ssl_cipher(apr_pool_t *p, conn_rec *c, char *var);
@@ -259,6 +260,13 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var)
     else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) {
         result = ssl_var_lookup_ssl_cipher(p, c, var+6);
     }
+    else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) {
+        xs = SSL_PeerCertificate(ssl);
+        if (xs != NULL) {
+            result = ssl_var_lookup_ssl_cert_chain(p, xs, var+18);
+            CERT_DestroyCertificate(xs);
+        }
+    }
     else if (ssl != NULL && strcEQ(var, "CLIENT_VERIFY")) {
         result = ssl_var_lookup_ssl_cert_verify(p, c);
     }
@@ -308,7 +316,7 @@ static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, CERTCertificate *xs, char *v
         resdup = FALSE;
     }
     else if (strlen(var) > 5 && strcEQn(var, "S_DN_", 5)) {
-        result = ssl_var_lookup_ssl_cert_dn(p, xs, var+5);
+        result = ssl_var_lookup_ssl_cert_dn(p, &xs->subject, var+5);
         resdup = FALSE;
     }
     else if (strcEQ(var, "I_DN")) {
@@ -318,7 +326,7 @@ static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, CERTCertificate *xs, char *v
         resdup = FALSE;
     }
     else if (strlen(var) > 5 && strcEQn(var, "I_DN_", 5)) {
-        result = ssl_var_lookup_ssl_cert_dn(p, xs, var+5);
+        result = ssl_var_lookup_ssl_cert_dn(p, &xs->issuer, var+5);
         resdup = FALSE;
     }
     else if (strcEQ(var, "A_SIG")) {
@@ -367,7 +375,7 @@ static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, CERTCertificate *xs, char *v
     return result;
 }
 
-static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, CERTCertificate *cert, char *var)
+static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, CERTName *cert, char *var)
 {
     char *result;
     char *rv;
@@ -376,23 +384,23 @@ static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, CERTCertificate *cert, ch
     rv = NULL;
 
     if (strcEQ(var, "C")) {
-        rv = CERT_GetCountryName(&cert->subject);
+        rv = CERT_GetCountryName(cert);
     } else if (strcEQ(var, "ST")) {
-        rv = CERT_GetStateName(&cert->subject);
+        rv = CERT_GetStateName(cert);
     } else if (strcEQ(var, "SP")) { // for compatibility
-        rv = CERT_GetStateName(&cert->subject);
+        rv = CERT_GetStateName(cert);
     } else if (strcEQ(var, "L")) {
-        rv = CERT_GetLocalityName(&cert->subject);
+        rv = CERT_GetLocalityName(cert);
     } else if (strcEQ(var, "O")) {
-        rv = CERT_GetOrgName(&cert->subject);
+        rv = CERT_GetOrgName(cert);
     } else if (strcEQ(var, "OU")) {
-        rv = CERT_GetOrgUnitName(&cert->subject);
+        rv = CERT_GetOrgUnitName(cert);
     } else if (strcEQ(var, "CN")) {
-        rv = CERT_GetCommonName(&cert->subject);
+        rv = CERT_GetCommonName(cert);
     } else if (strcEQ(var, "UID")) {
-        rv = CERT_GetCertUid(&cert->subject);
+        rv = CERT_GetCertUid(cert);
     } else if (strcEQ(var, "EMAIL")) {
-        rv = CERT_GetCertEmailAddress(&cert->subject);
+        rv = CERT_GetCertEmailAddress(cert);
     } else {
         rv = NULL; // catch any values we don't support
     }
@@ -428,16 +436,60 @@ static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, CERTCertificate *xs, i
     return result;
 }
 
+static char *ssl_var_lookup_ssl_cert_chain(apr_pool_t *p, CERTCertificate *cert, char *var)
+{
+    char *result;
+    CERTCertificateList *chain = NULL;
+    int n;
+
+    result = NULL;
+
+    chain = CERT_CertChainFromCert(cert, certUsageSSLClient, PR_TRUE);
+
+    if (!chain)
+        return NULL;
+
+    if (strspn(var, "0123456789") == strlen(var)) {
+        n = atoi(var);
+        if (n <= chain->len-1) {
+            CERTCertificate *c;
+            c = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &chain->certs[n]);
+            result = ssl_var_lookup_ssl_cert_PEM(p, c);
+            CERT_DestroyCertificate(c);
+        }
+    }
+
+    CERT_DestroyCertificateList(chain);
+
+    return result;
+}
+
 #define CERT_HEADER  "-----BEGIN CERTIFICATE-----\n"
 #define CERT_TRAILER "\n-----END CERTIFICATE-----\n"
 static char *ssl_var_lookup_ssl_cert_PEM(apr_pool_t *p, CERTCertificate *xs)
 {
     char * result = NULL;
     char * tmp = NULL;
+    int i, len;
+
+    /* should never happen but we'll crash if it does */
+    if (!xs)
+        return NULL;
 
     tmp = BTOA_DataToAscii(xs->derCert.data,
                            xs->derCert.len);
 
+    /* NSS uses \r\n as the line terminator. Remove \r so the output is
+     * similar to mod_ssl. */
+    i=0;
+    len = strlen(tmp);
+    while (tmp[i] != '\0') {
+        if (tmp[i] == '\r') {
+            memmove(&tmp[i], &tmp[i+1], 1+(len - i));
+        }
+        i++;
+    }
+
     /* Allocate the size of the cert + header + footer + 1 */
     result = apr_palloc(p, strlen(tmp) + 29 + 27 + 1);
     strcpy(result, CERT_HEADER);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-fedora-ds/libapache2-mod-nss.git



More information about the Pkg-fedora-ds-maintainers mailing list