Blame SOURCES/0019-Ticket-49543-fix-certmap-dn-comparison.patch

583fac
From 66c96b915dd4a82ebd4228cba61d7c4bae96cbca Mon Sep 17 00:00:00 2001
583fac
From: Fraser Tweedale <ftweedal@redhat.com>
583fac
Date: Fri, 16 Mar 2018 15:16:56 +1000
583fac
Subject: [PATCH] Ticket 49543 - fix certmap dn comparison
583fac
583fac
Bug Description: Differences in DN string representations between
583fac
the value included in certmap.conf, and the stringified value of the
583fac
Issuer DN produced by NSS, as well as buggy DN normalisation code in
583fac
389 itself, cause 389 to wrongly reject the correct certmap
583fac
configuration to use.  Authentication fails.  This behaviour was
583fac
observed when there is an escaped comma in an attribute value.
583fac
583fac
Fix Description: Instead of comparing stringified DNs, parse the DN
583fac
represented in certmap.conf into an NSS CertNAME.  Use the NSS DN
583fac
comparison routine when comparing certificate Issuer DNs against the
583fac
certmap configurations.  Remove the buggy DN normalisation routine.
583fac
583fac
https://pagure.io/389-ds-base/issue/49543
583fac
583fac
Author: Fraser Tweedale <ftweedal@redhat.com>
583fac
583fac
Review by: ???
583fac
---
583fac
 include/ldaputil/certmap.h   |  20 +++--
583fac
 include/ldaputil/ldaputil.h  |   2 +-
583fac
 lib/ldaputil/cert.c          |  27 ++++--
583fac
 lib/ldaputil/certmap.c       | 162 ++++++-----------------------------
583fac
 lib/ldaputil/examples/init.c |   3 +-
583fac
 5 files changed, 62 insertions(+), 152 deletions(-)
583fac
583fac
diff --git a/include/ldaputil/certmap.h b/include/ldaputil/certmap.h
583fac
index fec2dd931..50fd4d158 100644
583fac
--- a/include/ldaputil/certmap.h
583fac
+++ b/include/ldaputil/certmap.h
583fac
@@ -16,6 +16,7 @@
583fac
 /* What was extcmap.h begins ... */
583fac
 
583fac
 #include <ldap.h>
583fac
+#include <nss3/cert.h>
583fac
 
583fac
 #ifndef NSAPI_PUBLIC
583fac
 #define NSAPI_PUBLIC
583fac
@@ -156,7 +157,7 @@ typedef int (*CertVerifyFn_t)(void *cert, LDAP *ld, void *certmap_info, LDAPMess
583fac
  *  otherwise return LDAPU_CERT_MAP_INITFN_FAILED.  The server startup will be
583fac
  *  aborted if the return value is not LDAPU_SUCCESS.
583fac
  */
583fac
-typedef int (*CertMapInitFn_t)(void *certmap_info, const char *issuerName, const char *issuerDN, const char *libname);
583fac
+typedef int (*CertMapInitFn_t)(void *certmap_info, const char *issuerName, const CERTName *issuerDN, const char *libname);
583fac
 
583fac
 /*
583fac
  * Refer to the description of the function ldapu_get_cert_ava_val
583fac
@@ -209,27 +210,30 @@ extern "C" {
583fac
 
583fac
 NSAPI_PUBLIC int ldapu_cert_to_ldap_entry(void *cert, LDAP *ld, const char *basedn, LDAPMessage **res);
583fac
 
583fac
-NSAPI_PUBLIC int ldapu_set_cert_mapfn(const char *issuerDN,
583fac
+NSAPI_PUBLIC int ldapu_set_cert_mapfn(const CERTName *issuerDN,
583fac
                                       CertMapFn_t mapfn);
583fac
 
583fac
 
583fac
-NSAPI_PUBLIC CertMapFn_t ldapu_get_cert_mapfn(const char *issuerDN);
583fac
+NSAPI_PUBLIC CertMapFn_t ldapu_get_cert_mapfn(const CERTName *issuerDN);
583fac
 
583fac
-NSAPI_PUBLIC int ldapu_set_cert_searchfn(const char *issuerDN,
583fac
+NSAPI_PUBLIC int ldapu_set_cert_searchfn(const CERTName *issuerDN,
583fac
                                          CertSearchFn_t searchfn);
583fac
 
583fac
 
583fac
-NSAPI_PUBLIC CertSearchFn_t ldapu_get_cert_searchfn(const char *issuerDN);
583fac
+NSAPI_PUBLIC CertSearchFn_t ldapu_get_cert_searchfn(const CERTName *issuerDN);
583fac
 
583fac
-NSAPI_PUBLIC int ldapu_set_cert_verifyfn(const char *issuerDN,
583fac
+NSAPI_PUBLIC int ldapu_set_cert_verifyfn(const CERTName *issuerDN,
583fac
                                          CertVerifyFn_t verifyFn);
583fac
 
583fac
-NSAPI_PUBLIC CertVerifyFn_t ldapu_get_cert_verifyfn(const char *issuerDN);
583fac
+NSAPI_PUBLIC CertVerifyFn_t ldapu_get_cert_verifyfn(const CERTName *issuerDN);
583fac
 
583fac
 
583fac
 NSAPI_PUBLIC int ldapu_get_cert_subject_dn(void *cert, char **subjectDN);
583fac
 
583fac
 
583fac
+NSAPI_PUBLIC CERTName *ldapu_get_cert_issuer_dn_as_CERTName(CERTCertificate *cert);
583fac
+
583fac
+
583fac
 NSAPI_PUBLIC int ldapu_get_cert_issuer_dn(void *cert, char **issuerDN);
583fac
 
583fac
 
583fac
@@ -242,7 +246,7 @@ NSAPI_PUBLIC int ldapu_free_cert_ava_val(char **val);
583fac
 NSAPI_PUBLIC int ldapu_get_cert_der(void *cert, unsigned char **derCert, unsigned int *len);
583fac
 
583fac
 
583fac
-NSAPI_PUBLIC int ldapu_issuer_certinfo(const char *issuerDN,
583fac
+NSAPI_PUBLIC int ldapu_issuer_certinfo(const CERTName *issuerDN,
583fac
                                        void **certmap_info);
583fac
 
583fac
 
583fac
diff --git a/include/ldaputil/ldaputil.h b/include/ldaputil/ldaputil.h
583fac
index e0e028c5c..b172819b0 100644
583fac
--- a/include/ldaputil/ldaputil.h
583fac
+++ b/include/ldaputil/ldaputil.h
583fac
@@ -48,7 +48,7 @@ enum
583fac
 typedef struct
583fac
 {
583fac
     char *issuerName;            /* issuer (symbolic/short) name */
583fac
-    char *issuerDN;              /* cert issuer's DN */
583fac
+    CERTName *issuerDN;          /* cert issuer's DN */
583fac
     LDAPUPropValList_t *propval; /* pointer to the prop-val pairs list */
583fac
     CertMapFn_t mapfn;           /* cert to ldapdn & filter mapping func */
583fac
     CertVerifyFn_t verifyfn;     /* verify cert function */
583fac
diff --git a/lib/ldaputil/cert.c b/lib/ldaputil/cert.c
583fac
index 65a481541..73abba12a 100644
583fac
--- a/lib/ldaputil/cert.c
583fac
+++ b/lib/ldaputil/cert.c
583fac
@@ -54,15 +54,30 @@ ldapu_get_cert_subject_dn(void *cert_in, char **subjectDN)
583fac
     return *subjectDN ? LDAPU_SUCCESS : LDAPU_ERR_EXTRACT_SUBJECTDN_FAILED;
583fac
 }
583fac
 
583fac
+/*
583fac
+ * Return the Issuer DN as a CERTName.
583fac
+ * The CERTName is owned by the CERTCertificate.
583fac
+ */
583fac
+NSAPI_PUBLIC CERTName *
583fac
+ldapu_get_cert_issuer_dn_as_CERTName(CERTCertificate *cert_in)
583fac
+{
583fac
+    return &cert_in->issuer;
583fac
+}
583fac
+
583fac
+/*
583fac
+ * Return the Issuer DN as a string.
583fac
+ * The string should be freed by the caller.
583fac
+ */
583fac
 NSAPI_PUBLIC int
583fac
 ldapu_get_cert_issuer_dn(void *cert_in, char **issuerDN)
583fac
 {
583fac
-    CERTCertificate *cert = (CERTCertificate *)cert_in;
583fac
-    char *cert_issuer = CERT_NameToAscii(&cert->issuer);
583fac
-
583fac
-    *issuerDN = strdup(cert_issuer);
583fac
-    PR_Free(cert_issuer);
583fac
-
583fac
+    *issuerDN = NULL;
583fac
+    CERTName *dn = ldapu_get_cert_issuer_dn_as_CERTName((CERTCertificate *)cert_in);
583fac
+    if (dn != NULL) {
583fac
+        char *cert_issuer = CERT_NameToAscii(dn);
583fac
+        *issuerDN = strdup(cert_issuer);
583fac
+        PR_Free(cert_issuer);
583fac
+    }
583fac
     return *issuerDN ? LDAPU_SUCCESS : LDAPU_ERR_EXTRACT_ISSUERDN_FAILED;
583fac
 }
583fac
 
583fac
diff --git a/lib/ldaputil/certmap.c b/lib/ldaputil/certmap.c
583fac
index 78bb3635b..0db2de12b 100644
583fac
--- a/lib/ldaputil/certmap.c
583fac
+++ b/lib/ldaputil/certmap.c
583fac
@@ -52,7 +52,6 @@ static char this_dllname[256];
583fac
 static const char *LIB_DIRECTIVE = "certmap";
583fac
 static const int LIB_DIRECTIVE_LEN = 7; /* strlen("LIB_DIRECTIVE") */
583fac
 
583fac
-static char *ldapu_dn_normalize(char *dn);
583fac
 static void *ldapu_propval_free(void *propval_in, void *arg);
583fac
 
583fac
 typedef struct
583fac
@@ -337,8 +336,13 @@ dbinfo_to_certinfo(DBConfDBInfo_t *db_info,
583fac
     certinfo->issuerName = db_info->dbname;
583fac
     db_info->dbname = 0;
583fac
 
583fac
-    certinfo->issuerDN = ldapu_dn_normalize(db_info->url);
583fac
-    db_info->url = 0;
583fac
+    /* Parse the Issuer DN. */
583fac
+    certinfo->issuerDN = CERT_AsciiToName(db_info->url);
583fac
+    if (NULL == certinfo->issuerDN                            /* invalid DN */
583fac
+            && ldapu_strcasecmp(db_info->url, "default") != 0 /* not "default" */) {
583fac
+        rv = LDAPU_ERR_MALFORMED_SUBJECT_DN;
583fac
+        goto error;
583fac
+    }
583fac
 
583fac
     /* hijack actual prop-vals from dbinfo -- to avoid strdup calls */
583fac
     if (db_info->firstprop) {
583fac
@@ -890,24 +894,26 @@ ldapu_cert_searchfn_default(void *cert, LDAP *ld, void *certmap_info_in, const c
583fac
 }
583fac
 
583fac
 NSAPI_PUBLIC int
583fac
-ldapu_issuer_certinfo(const char *issuerDN, void **certmap_info)
583fac
+ldapu_issuer_certinfo(const CERTName *issuerDN, void **certmap_info)
583fac
 {
583fac
     *certmap_info = 0;
583fac
 
583fac
-    if (!issuerDN || !*issuerDN || !ldapu_strcasecmp(issuerDN, "default")) {
583fac
-        *certmap_info = default_certmap_info;
583fac
-    } else if (certmap_listinfo) {
583fac
-        char *n_issuerDN = ldapu_dn_normalize(ldapu_strdup(issuerDN));
583fac
+    if (certmap_listinfo) {
583fac
         LDAPUListNode_t *cur = certmap_listinfo->head;
583fac
         while (cur) {
583fac
-            if (!ldapu_strcasecmp(n_issuerDN, ((LDAPUCertMapInfo_t *)cur->info)->issuerDN)) {
583fac
+            LDAPUCertMapInfo_t *info = (LDAPUCertMapInfo_t *)cur->info;
583fac
+
583fac
+            if (NULL == info->issuerDN) {
583fac
+                /* no DN to compare to (probably the default certmap info) */
583fac
+                continue;
583fac
+            }
583fac
+
583fac
+            if (CERT_CompareName(issuerDN, info->issuerDN) == SECEqual) {
583fac
                 *certmap_info = cur->info;
583fac
                 break;
583fac
             }
583fac
             cur = cur->next;
583fac
         }
583fac
-        if (n_issuerDN)
583fac
-            ldapu_free(n_issuerDN);
583fac
     }
583fac
     return *certmap_info ? LDAPU_SUCCESS : LDAPU_FAILED;
583fac
 }
583fac
@@ -1128,7 +1134,7 @@ ldapu_cert_mapfn_default(void *cert_in, LDAP *ld __attribute__((unused)), void *
583fac
 }
583fac
 
583fac
 NSAPI_PUBLIC int
583fac
-ldapu_set_cert_mapfn(const char *issuerDN,
583fac
+ldapu_set_cert_mapfn(const CERTName *issuerDN,
583fac
                      CertMapFn_t mapfn)
583fac
 {
583fac
     LDAPUCertMapInfo_t *certmap_info;
583fac
@@ -1161,7 +1167,7 @@ ldapu_get_cert_mapfn_sub(LDAPUCertMapInfo_t *certmap_info)
583fac
 }
583fac
 
583fac
 NSAPI_PUBLIC CertMapFn_t
583fac
-ldapu_get_cert_mapfn(const char *issuerDN)
583fac
+ldapu_get_cert_mapfn(const CERTName *issuerDN)
583fac
 {
583fac
     LDAPUCertMapInfo_t *certmap_info = 0;
583fac
 
583fac
@@ -1173,7 +1179,7 @@ ldapu_get_cert_mapfn(const char *issuerDN)
583fac
 }
583fac
 
583fac
 NSAPI_PUBLIC int
583fac
-ldapu_set_cert_searchfn(const char *issuerDN,
583fac
+ldapu_set_cert_searchfn(const CERTName *issuerDN,
583fac
                         CertSearchFn_t searchfn)
583fac
 {
583fac
     LDAPUCertMapInfo_t *certmap_info;
583fac
@@ -1206,7 +1212,7 @@ ldapu_get_cert_searchfn_sub(LDAPUCertMapInfo_t *certmap_info)
583fac
 }
583fac
 
583fac
 NSAPI_PUBLIC CertSearchFn_t
583fac
-ldapu_get_cert_searchfn(const char *issuerDN)
583fac
+ldapu_get_cert_searchfn(const CERTName *issuerDN)
583fac
 {
583fac
     LDAPUCertMapInfo_t *certmap_info = 0;
583fac
 
583fac
@@ -1218,7 +1224,7 @@ ldapu_get_cert_searchfn(const char *issuerDN)
583fac
 }
583fac
 
583fac
 NSAPI_PUBLIC int
583fac
-ldapu_set_cert_verifyfn(const char *issuerDN,
583fac
+ldapu_set_cert_verifyfn(const CERTName *issuerDN,
583fac
                         CertVerifyFn_t verifyfn)
583fac
 {
583fac
     LDAPUCertMapInfo_t *certmap_info;
583fac
@@ -1251,7 +1257,7 @@ ldapu_get_cert_verifyfn_sub(LDAPUCertMapInfo_t *certmap_info)
583fac
 }
583fac
 
583fac
 NSAPI_PUBLIC CertVerifyFn_t
583fac
-ldapu_get_cert_verifyfn(const char *issuerDN)
583fac
+ldapu_get_cert_verifyfn(const CERTName *issuerDN)
583fac
 {
583fac
     LDAPUCertMapInfo_t *certmap_info = 0;
583fac
 
583fac
@@ -1288,7 +1294,6 @@ static int ldapu_certinfo_copy (const LDAPUCertMapInfo_t *from,
583fac
 NSAPI_PUBLIC int
583fac
 ldapu_cert_to_ldap_entry(void *cert, LDAP *ld, const char *basedn, LDAPMessage **res)
583fac
 {
583fac
-    char *issuerDN = 0;
583fac
     char *ldapDN = 0;
583fac
     char *filter = 0;
583fac
     LDAPUCertMapInfo_t *certmap_info;
583fac
@@ -1308,14 +1313,14 @@ ldapu_cert_to_ldap_entry(void *cert, LDAP *ld, const char *basedn, LDAPMessage *
583fac
         certmap_attrs[3] = 0;
583fac
     }
583fac
 
583fac
-    rv = ldapu_get_cert_issuer_dn(cert, &issuerDN);
583fac
+    CERTName *issuerDN = ldapu_get_cert_issuer_dn_as_CERTName(cert);
583fac
+    /*        ^ don't need to free this; it will be freed with ^ the cert */
583fac
 
583fac
-    if (rv != LDAPU_SUCCESS)
583fac
+    if (NULL == issuerDN)
583fac
         return LDAPU_ERR_NO_ISSUERDN_IN_CERT;
583fac
 
583fac
     /* don't free the certmap_info -- its a pointer to an internal structure */
583fac
     rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);
583fac
-    free(issuerDN);
583fac
 
583fac
     if (!certmap_info)
583fac
         certmap_info = default_certmap_info;
583fac
@@ -1604,118 +1609,3 @@ ldapu_realloc(void *ptr, int size)
583fac
 {
583fac
     return realloc(ptr, size);
583fac
 }
583fac
-
583fac
-#define DNSEPARATOR(c) (c == ',' || c == ';')
583fac
-#define SEPARATOR(c) (c == ',' || c == ';' || c == '+')
583fac
-#define SPACE(c) (c == ' ' || c == '\n')
583fac
-#define NEEDSESCAPE(c) (c == '\\' || c == '"')
583fac
-#define B4TYPE 0
583fac
-#define INTYPE 1
583fac
-#define B4EQUAL 2
583fac
-#define B4VALUE 3
583fac
-#define INVALUE 4
583fac
-#define INQUOTEDVALUE 5
583fac
-#define B4SEPARATOR 6
583fac
-
583fac
-static char *
583fac
-ldapu_dn_normalize(char *dn)
583fac
-{
583fac
-    char *d, *s;
583fac
-    int state, gotesc;
583fac
-
583fac
-    gotesc = 0;
583fac
-    state = B4TYPE;
583fac
-    for (d = s = dn; *s; s++) {
583fac
-        switch (state) {
583fac
-        case B4TYPE:
583fac
-            if (!SPACE(*s)) {
583fac
-                state = INTYPE;
583fac
-                *d++ = *s;
583fac
-            }
583fac
-            break;
583fac
-        case INTYPE:
583fac
-            if (*s == '=') {
583fac
-                state = B4VALUE;
583fac
-                *d++ = *s;
583fac
-            } else if (SPACE(*s)) {
583fac
-                state = B4EQUAL;
583fac
-            } else {
583fac
-                *d++ = *s;
583fac
-            }
583fac
-            break;
583fac
-        case B4EQUAL:
583fac
-            if (*s == '=') {
583fac
-                state = B4VALUE;
583fac
-                *d++ = *s;
583fac
-            } else if (!SPACE(*s)) {
583fac
-                /* not a valid dn - but what can we do here? */
583fac
-                *d++ = *s;
583fac
-            }
583fac
-            break;
583fac
-        case B4VALUE:
583fac
-            if (*s == '"') {
583fac
-                state = INQUOTEDVALUE;
583fac
-                *d++ = *s;
583fac
-            } else if (!SPACE(*s)) {
583fac
-                state = INVALUE;
583fac
-                *d++ = *s;
583fac
-            }
583fac
-            break;
583fac
-        case INVALUE:
583fac
-            if (!gotesc && SEPARATOR(*s)) {
583fac
-                while (SPACE(*(d - 1)))
583fac
-                    d--;
583fac
-                state = B4TYPE;
583fac
-                if (*s == '+') {
583fac
-                    *d++ = *s;
583fac
-                } else {
583fac
-                    *d++ = ',';
583fac
-                }
583fac
-            } else if (gotesc && !NEEDSESCAPE(*s) &&
583fac
-                       !SEPARATOR(*s)) {
583fac
-                *--d = *s;
583fac
-                d++;
583fac
-            } else {
583fac
-                *d++ = *s;
583fac
-            }
583fac
-            break;
583fac
-        case INQUOTEDVALUE:
583fac
-            if (!gotesc && *s == '"') {
583fac
-                state = B4SEPARATOR;
583fac
-                *d++ = *s;
583fac
-            } else if (gotesc && !NEEDSESCAPE(*s)) {
583fac
-                *--d = *s;
583fac
-                d++;
583fac
-            } else {
583fac
-                *d++ = *s;
583fac
-            }
583fac
-            break;
583fac
-        case B4SEPARATOR:
583fac
-            if (SEPARATOR(*s)) {
583fac
-                state = B4TYPE;
583fac
-                if (*s == '+') {
583fac
-                    *d++ = *s;
583fac
-                } else {
583fac
-                    *d++ = ',';
583fac
-                }
583fac
-            }
583fac
-            break;
583fac
-        default:
583fac
-            break;
583fac
-        }
583fac
-        if (*s == '\\') {
583fac
-            gotesc = 1;
583fac
-        } else {
583fac
-            gotesc = 0;
583fac
-        }
583fac
-    }
583fac
-    *d = '\0';
583fac
-
583fac
-    /* Trim trailing spaces */
583fac
-    d--;
583fac
-    while (d >= dn && *d == ' ') {
583fac
-        *d-- = '\0';
583fac
-    }
583fac
-
583fac
-    return (dn);
583fac
-}
583fac
diff --git a/lib/ldaputil/examples/init.c b/lib/ldaputil/examples/init.c
583fac
index 74db9775c..fd1edc97e 100644
583fac
--- a/lib/ldaputil/examples/init.c
583fac
+++ b/lib/ldaputil/examples/init.c
583fac
@@ -15,12 +15,13 @@
583fac
 #include <stdio.h>
583fac
 #include <string.h>
583fac
 #include <ctype.h>
583fac
+#include <nss3/cert.h>
583fac
 #include "certmap.h" /* Public Certmap API */
583fac
 #include "plugin.h"  /* must define extern "C" functions */
583fac
 
583fac
 
583fac
 NSAPI_PUBLIC int
583fac
-plugin_init_fn(void *certmap_info, const char *issuerName, const char *issuerDN, const char *libname)
583fac
+plugin_init_fn(void *certmap_info, const char *issuerName, const CERTName *issuerDN, const char *libname)
583fac
 {
583fac
     static int initialized = 0;
583fac
     int rv;
583fac
-- 
583fac
2.17.2
583fac