[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