Blame SOURCES/0096-sc-escape-special-chars.patch

71ae41
From 045a27604d0df6e6215776c4b3a27eac2906dc4e Mon Sep 17 00:00:00 2001
71ae41
From: Sumit Bose <sbose@redhat.com>
71ae41
Date: Tue, 27 Nov 2018 16:40:01 +0100
71ae41
Subject: [PATCH 1/2] certmap: add sss_certmap_display_cert_content()
71ae41
71ae41
To make debugging and writing certificate mapping and matching rules
71ae41
more easy a new function is added to libsss_certmap to display the
71ae41
certificate content as seen by libsss_certmap. Please note that the
71ae41
actual output might change in future.
71ae41
71ae41
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
71ae41
(cherry picked from commit 1c40208aa1e0f9a17cc4f336c99bcaa6977592d3)
71ae41
71ae41
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
71ae41
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
71ae41
---
71ae41
 Makefile.am                              |   2 +-
71ae41
 src/lib/certmap/sss_certmap.c            | 142 ++++++++++++++++++++++
71ae41
 src/lib/certmap/sss_certmap.exports      |   5 +
71ae41
 src/lib/certmap/sss_certmap.h            |  18 +++
71ae41
 src/lib/certmap/sss_certmap_int.h        |  31 ++++-
71ae41
 src/lib/certmap/sss_certmap_krb5_match.c | 145 +++++++++++------------
71ae41
 6 files changed, 261 insertions(+), 82 deletions(-)
71ae41
71ae41
diff --git a/Makefile.am b/Makefile.am
71ae41
index ac234ed..87eb571 100644
71ae41
--- a/Makefile.am
71ae41
+++ b/Makefile.am
71ae41
@@ -1862,7 +1862,7 @@ libsss_certmap_la_LIBADD = \
71ae41
     $(NULL)
71ae41
 libsss_certmap_la_LDFLAGS = \
71ae41
     -Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \
71ae41
-    -version-info 0:0:0
71ae41
+    -version-info 1:0:1
71ae41
 
71ae41
 if HAVE_NSS
71ae41
 libsss_certmap_la_SOURCES += \
71ae41
diff --git a/src/lib/certmap/sss_certmap.c b/src/lib/certmap/sss_certmap.c
71ae41
index f6f6f98..c60ac24 100644
71ae41
--- a/src/lib/certmap/sss_certmap.c
71ae41
+++ b/src/lib/certmap/sss_certmap.c
71ae41
@@ -914,3 +914,145 @@ void sss_certmap_free_filter_and_domains(char *filter, char **domains)
71ae41
     talloc_free(filter);
71ae41
     talloc_free(domains);
71ae41
 }
71ae41
+
71ae41
+static const char *sss_eku_oid2name(const char *oid)
71ae41
+{
71ae41
+    size_t c;
71ae41
+
71ae41
+    for (c = 0; sss_ext_key_usage[c].name != NULL; c++) {
71ae41
+        if (strcmp(sss_ext_key_usage[c].oid, oid) == 0) {
71ae41
+            return sss_ext_key_usage[c].name;
71ae41
+        }
71ae41
+    }
71ae41
+
71ae41
+    return NULL;
71ae41
+}
71ae41
+
71ae41
+struct parsed_template san_parsed_template[] = {
71ae41
+    { NULL, NULL, NULL }, /* SAN_OTHER_NAME handled separately */
71ae41
+    { "subject_rfc822_name", NULL, NULL},
71ae41
+    { "subject_dns_name", NULL, NULL},
71ae41
+    { "subject_x400_address", NULL, NULL},
71ae41
+    { "subject_directory_name", NULL, NULL},
71ae41
+    { "subject_ediparty_name", NULL, NULL},
71ae41
+    { "subject_uri", NULL, NULL},
71ae41
+    { "subject_ip_address", NULL, NULL},
71ae41
+    { "subject_registered_id", NULL, NULL},
71ae41
+    { "subject_pkinit_principal", NULL, NULL},
71ae41
+    { "subject_nt_principal", NULL, NULL},
71ae41
+    { "subject_principal", NULL, NULL},
71ae41
+    { NULL, NULL, NULL }, /* SAN_STRING_OTHER_NAME handled separately */
71ae41
+    { NULL, NULL, NULL }  /* SAN_END */
71ae41
+};
71ae41
+
71ae41
+int sss_cert_dump_content(TALLOC_CTX *mem_ctx, struct sss_cert_content *c,
71ae41
+                          char **content_str)
71ae41
+{
71ae41
+    char *out = NULL;
71ae41
+    size_t o;
71ae41
+    struct san_list *s;
71ae41
+    struct sss_certmap_ctx *ctx = NULL;
71ae41
+    char *expanded = NULL;
71ae41
+    int ret;
71ae41
+    char *b64 = NULL;
71ae41
+    const char *eku_str = NULL;
71ae41
+
71ae41
+    ret = sss_certmap_init(mem_ctx, NULL, NULL, &ctx;;
71ae41
+    if (ret != EOK) {
71ae41
+        return ret;
71ae41
+    }
71ae41
+
71ae41
+    out = talloc_strdup(mem_ctx, "sss cert content (format might change):\n");
71ae41
+    if (out == NULL) return ENOMEM;
71ae41
+
71ae41
+    out = talloc_asprintf_append(out, "Issuer: %s\n", c->issuer_str != NULL
71ae41
+                                                         ? c->issuer_str
71ae41
+                                                         : "- not available -");
71ae41
+    if (out == NULL) return ENOMEM;
71ae41
+    out = talloc_asprintf_append(out, "Subject: %s\n", c->subject_str != NULL
71ae41
+                                                         ? c->subject_str
71ae41
+                                                         : "- not available -");
71ae41
+    if (out == NULL) return ENOMEM;
71ae41
+
71ae41
+    out = talloc_asprintf_append(out, "Key Usage: %u(0x%04x)", c->key_usage,
71ae41
+                                                               c->key_usage);
71ae41
+    if (out == NULL) return ENOMEM;
71ae41
+
71ae41
+    if (c->key_usage != 0) {
71ae41
+        out = talloc_asprintf_append(out, " (");
71ae41
+        if (out == NULL) return ENOMEM;
71ae41
+        for (o = 0; sss_key_usage[o].name != NULL; o++) {
71ae41
+            if ((c->key_usage & sss_key_usage[o].flag) != 0) {
71ae41
+                out = talloc_asprintf_append(out, "%s%s",
71ae41
+                                             o == 0 ? "" : ",",
71ae41
+                                             sss_key_usage[o].name);
71ae41
+                if (out == NULL) return ENOMEM;
71ae41
+            }
71ae41
+        }
71ae41
+        out = talloc_asprintf_append(out, ")");
71ae41
+        if (out == NULL) return ENOMEM;
71ae41
+    }
71ae41
+    out = talloc_asprintf_append(out, "\n");
71ae41
+    if (out == NULL) return ENOMEM;
71ae41
+
71ae41
+    for (o = 0; c->extended_key_usage_oids[o] != NULL; o++) {
71ae41
+        eku_str = sss_eku_oid2name(c->extended_key_usage_oids[o]);
71ae41
+        out = talloc_asprintf_append(out, "Extended Key Usage #%zu: %s%s%s%s\n",
71ae41
+                                          o, c->extended_key_usage_oids[o],
71ae41
+                                          eku_str == NULL ? "" : " (",
71ae41
+                                          eku_str == NULL ? "" : eku_str,
71ae41
+                                          eku_str == NULL ? "" : ")");
71ae41
+        if (out == NULL) return ENOMEM;
71ae41
+    }
71ae41
+
71ae41
+    DLIST_FOR_EACH(s, c->san_list) {
71ae41
+        out = talloc_asprintf_append(out, "SAN type: %s\n",
71ae41
+                                     s->san_opt < SAN_END
71ae41
+                                                ? sss_san_names[s->san_opt].name
71ae41
+                                                : "- unsupported -");
71ae41
+        if (out == NULL) return ENOMEM;
71ae41
+
71ae41
+        if (san_parsed_template[s->san_opt].name != NULL) {
71ae41
+            ret = expand_san(ctx, &san_parsed_template[s->san_opt], c->san_list,
71ae41
+                             &expanded);
71ae41
+            if (ret != EOK) {
71ae41
+                return ret;
71ae41
+            }
71ae41
+            out = talloc_asprintf_append(out, " %s=%s\n\n",
71ae41
+                                         san_parsed_template[s->san_opt].name,
71ae41
+                                         expanded);
71ae41
+            talloc_free(expanded);
71ae41
+            if (out == NULL) return ENOMEM;
71ae41
+        } else if (s->san_opt == SAN_STRING_OTHER_NAME) {
71ae41
+            b64 = sss_base64_encode(mem_ctx, s->bin_val, s->bin_val_len);
71ae41
+            out = talloc_asprintf_append(out, " %s=%s\n\n", s->other_name_oid,
71ae41
+                                              b64 != NULL ? b64
71ae41
+                                                          : "- cannot encode -");
71ae41
+            talloc_free(b64);
71ae41
+        }
71ae41
+    }
71ae41
+
71ae41
+    *content_str = out;
71ae41
+
71ae41
+    return EOK;
71ae41
+}
71ae41
+
71ae41
+int sss_certmap_display_cert_content(TALLOC_CTX *mem_cxt,
71ae41
+                                     const uint8_t *der_cert, size_t der_size,
71ae41
+                                     char **desc)
71ae41
+{
71ae41
+    int ret;
71ae41
+    struct sss_cert_content *content;
71ae41
+
71ae41
+    ret = sss_cert_get_content(mem_cxt, der_cert, der_size, &content);
71ae41
+    if (ret != EOK) {
71ae41
+        return ret;
71ae41
+    }
71ae41
+
71ae41
+    ret = sss_cert_dump_content(mem_cxt, content, desc);
71ae41
+    if (ret != EOK) {
71ae41
+        return ret;
71ae41
+    }
71ae41
+
71ae41
+    return 0;
71ae41
+}
71ae41
diff --git a/src/lib/certmap/sss_certmap.exports b/src/lib/certmap/sss_certmap.exports
71ae41
index 8b5d536..a9e48d6 100644
71ae41
--- a/src/lib/certmap/sss_certmap.exports
71ae41
+++ b/src/lib/certmap/sss_certmap.exports
71ae41
@@ -11,3 +11,8 @@ SSS_CERTMAP_0.0 {
71ae41
     local:
71ae41
         *;
71ae41
 };
71ae41
+
71ae41
+SSS_CERTMAP_0.1 {
71ae41
+    global:
71ae41
+        sss_certmap_display_cert_content;
71ae41
+} SSS_CERTMAP_0.0;
71ae41
diff --git a/src/lib/certmap/sss_certmap.h b/src/lib/certmap/sss_certmap.h
71ae41
index 646e0f3..7da2d1c 100644
71ae41
--- a/src/lib/certmap/sss_certmap.h
71ae41
+++ b/src/lib/certmap/sss_certmap.h
71ae41
@@ -146,6 +146,24 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
71ae41
  */
71ae41
 void sss_certmap_free_filter_and_domains(char *filter, char **domains);
71ae41
 
71ae41
+/**
71ae41
+ * @brief Get a string with the content of the certificate used by the library
71ae41
+ *
71ae41
+ * @param[in]  mem_ctx    Talloc memory context, may be NULL
71ae41
+ * @param[in]  der_cert   binary blog with the DER encoded certificate
71ae41
+ * @param[in]  der_size   size of the certificate blob
71ae41
+ * @param[out] desc       Multiline string showing the certificate content
71ae41
+ *                        which is used by libsss_certmap
71ae41
+ *
71ae41
+ * @return
71ae41
+ *  - 0:      success
71ae41
+ *  - EINVAL: certificate cannot be parsed
71ae41
+ *  - ENOMEM: memory allocation failure
71ae41
+ */
71ae41
+int sss_certmap_display_cert_content(TALLOC_CTX *mem_cxt,
71ae41
+                                     const uint8_t *der_cert, size_t der_size,
71ae41
+                                     char **desc);
71ae41
+
71ae41
 /**
71ae41
  * @}
71ae41
  */
71ae41
diff --git a/src/lib/certmap/sss_certmap_int.h b/src/lib/certmap/sss_certmap_int.h
71ae41
index 479cc16..b1155e2 100644
71ae41
--- a/src/lib/certmap/sss_certmap_int.h
71ae41
+++ b/src/lib/certmap/sss_certmap_int.h
71ae41
@@ -101,9 +101,9 @@ enum comp_type {
71ae41
 };
71ae41
 
71ae41
 struct parsed_template {
71ae41
-    char *name;
71ae41
-    char *attr_name;
71ae41
-    char *conversion;
71ae41
+    const char *name;
71ae41
+    const char *attr_name;
71ae41
+    const char *conversion;
71ae41
 };
71ae41
 
71ae41
 struct ldap_mapping_rule_comp {
71ae41
@@ -166,6 +166,28 @@ struct san_list {
71ae41
 #define SSS_KU_ENCIPHER_ONLY        0x0001
71ae41
 #define SSS_KU_DECIPHER_ONLY        0x8000
71ae41
 
71ae41
+struct sss_key_usage {
71ae41
+    const char *name;
71ae41
+    uint32_t flag;
71ae41
+};
71ae41
+
71ae41
+extern const struct sss_key_usage sss_key_usage[];
71ae41
+
71ae41
+struct sss_ext_key_usage {
71ae41
+    const char *name;
71ae41
+    const char *oid;
71ae41
+};
71ae41
+
71ae41
+extern const struct sss_ext_key_usage sss_ext_key_usage[];
71ae41
+
71ae41
+struct sss_san_name {
71ae41
+    const char *name;
71ae41
+    enum san_opt san_opt;
71ae41
+    bool is_string;
71ae41
+};
71ae41
+
71ae41
+extern const struct sss_san_name sss_san_names[];
71ae41
+
71ae41
 struct sss_cert_content {
71ae41
     char *issuer_str;
71ae41
     const char **issuer_rdn_list;
71ae41
@@ -183,6 +205,9 @@ int sss_cert_get_content(TALLOC_CTX *mem_ctx,
71ae41
                          const uint8_t *der_blob, size_t der_size,
71ae41
                          struct sss_cert_content **content);
71ae41
 
71ae41
+int sss_cert_dump_content(TALLOC_CTX *mem_ctx, struct sss_cert_content *c,
71ae41
+                          char **content_str);
71ae41
+
71ae41
 char *check_ad_attr_name(TALLOC_CTX *mem_ctx, const char *rdn);
71ae41
 
71ae41
 char *openssl_2_nss_attr_name(const char *attr);
71ae41
diff --git a/src/lib/certmap/sss_certmap_krb5_match.c b/src/lib/certmap/sss_certmap_krb5_match.c
71ae41
index 125e925..398d3d2 100644
71ae41
--- a/src/lib/certmap/sss_certmap_krb5_match.c
71ae41
+++ b/src/lib/certmap/sss_certmap_krb5_match.c
71ae41
@@ -29,6 +29,59 @@
71ae41
 #include "lib/certmap/sss_certmap.h"
71ae41
 #include "lib/certmap/sss_certmap_int.h"
71ae41
 
71ae41
+const struct sss_key_usage sss_key_usage[] = {
71ae41
+    {"digitalSignature" , SSS_KU_DIGITAL_SIGNATURE},
71ae41
+    {"nonRepudiation"   , SSS_KU_NON_REPUDIATION},
71ae41
+    {"keyEncipherment"  , SSS_KU_KEY_ENCIPHERMENT},
71ae41
+    {"dataEncipherment" , SSS_KU_DATA_ENCIPHERMENT},
71ae41
+    {"keyAgreement"     , SSS_KU_KEY_AGREEMENT},
71ae41
+    {"keyCertSign"      , SSS_KU_KEY_CERT_SIGN},
71ae41
+    {"cRLSign"          , SSS_KU_CRL_SIGN},
71ae41
+    {"encipherOnly"     , SSS_KU_ENCIPHER_ONLY},
71ae41
+    {"decipherOnly"     , SSS_KU_DECIPHER_ONLY},
71ae41
+    {NULL ,0}
71ae41
+};
71ae41
+
71ae41
+const struct sss_ext_key_usage sss_ext_key_usage[] = {
71ae41
+    /* RFC 3280 section 4.2.1.13 */
71ae41
+    {"serverAuth",      "1.3.6.1.5.5.7.3.1"},
71ae41
+    {"clientAuth",      "1.3.6.1.5.5.7.3.2"},
71ae41
+    {"codeSigning",     "1.3.6.1.5.5.7.3.3"},
71ae41
+    {"emailProtection", "1.3.6.1.5.5.7.3.4"},
71ae41
+    {"timeStamping",    "1.3.6.1.5.5.7.3.8"},
71ae41
+    {"OCSPSigning",     "1.3.6.1.5.5.7.3.9"},
71ae41
+
71ae41
+    /* RFC 4556 section 3.2.2 */
71ae41
+    {"KPClientAuth",    "1.3.6.1.5.2.3.4"},
71ae41
+    {"pkinit",          "1.3.6.1.5.2.3.4"},
71ae41
+
71ae41
+    /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography*/
71ae41
+    {"msScLogin",       "1.3.6.1.4.1.311.20.2.2"},
71ae41
+
71ae41
+    {NULL ,0}
71ae41
+};
71ae41
+
71ae41
+const struct sss_san_name sss_san_names[] = {
71ae41
+    /* https://www.ietf.org/rfc/rfc3280.txt section 4.2.1.7 */
71ae41
+    {"otherName", SAN_OTHER_NAME, false},
71ae41
+    {"rfc822Name", SAN_RFC822_NAME, true},
71ae41
+    {"dNSName", SAN_DNS_NAME, true},
71ae41
+    {"x400Address", SAN_X400_ADDRESS, false},
71ae41
+    {"directoryName", SAN_DIRECTORY_NAME, true},
71ae41
+    {"ediPartyName", SAN_EDIPART_NAME, false},
71ae41
+    {"uniformResourceIdentifier", SAN_URI, true},
71ae41
+    {"iPAddress", SAN_IP_ADDRESS, true},
71ae41
+    {"registeredID", SAN_REGISTERED_ID, true},
71ae41
+    /* https://www.ietf.org/rfc/rfc4556.txt section 3.2.2 */
71ae41
+    {"pkinitSAN", SAN_PKINIT, true},
71ae41
+    /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography */
71ae41
+    {"ntPrincipalName", SAN_NT, true},
71ae41
+    /* both previous principal types */
71ae41
+    {"Principal", SAN_PRINCIPAL, true},
71ae41
+    {"stringOtherName", SAN_STRING_OTHER_NAME, true},
71ae41
+    {NULL, SAN_END, false}
71ae41
+};
71ae41
+
71ae41
 static bool is_dotted_decimal(const char *s, size_t len)
71ae41
 {
71ae41
     size_t c = 0;
71ae41
@@ -145,28 +198,6 @@ static int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx,
71ae41
     size_t e = 0;
71ae41
     int eku_list_size;
71ae41
 
71ae41
-    struct ext_key_usage {
71ae41
-        const char *name;
71ae41
-        const char *oid;
71ae41
-    } ext_key_usage[] = {
71ae41
-        /* RFC 3280 section 4.2.1.13 */
71ae41
-        {"serverAuth",      "1.3.6.1.5.5.7.3.1"},
71ae41
-        {"clientAuth",      "1.3.6.1.5.5.7.3.2"},
71ae41
-        {"codeSigning",     "1.3.6.1.5.5.7.3.3"},
71ae41
-        {"emailProtection", "1.3.6.1.5.5.7.3.4"},
71ae41
-        {"timeStamping",    "1.3.6.1.5.5.7.3.8"},
71ae41
-        {"OCSPSigning",     "1.3.6.1.5.5.7.3.9"},
71ae41
-
71ae41
-        /* RFC 4556 section 3.2.2 */
71ae41
-        {"KPClientAuth",    "1.3.6.1.5.2.3.4"},
71ae41
-        {"pkinit",          "1.3.6.1.5.2.3.4"},
71ae41
-
71ae41
-        /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography*/
71ae41
-        {"msScLogin",       "1.3.6.1.4.1.311.20.2.2"},
71ae41
-
71ae41
-        {NULL ,0}
71ae41
-    };
71ae41
-
71ae41
     ret = get_comp_value(mem_ctx, ctx, cur, &comp);
71ae41
     if (ret != 0) {
71ae41
         CM_DEBUG(ctx, "Failed to parse regexp.");
71ae41
@@ -188,11 +219,11 @@ static int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx,
71ae41
     }
71ae41
 
71ae41
     for (c = 0; eku_list[c] != NULL; c++) {
71ae41
-        for (k = 0; ext_key_usage[k].name != NULL; k++) {
71ae41
-CM_DEBUG(ctx, "[%s][%s].", eku_list[c], ext_key_usage[k].name);
71ae41
-            if (strcasecmp(eku_list[c], ext_key_usage[k].name) == 0) {
71ae41
+        for (k = 0; sss_ext_key_usage[k].name != NULL; k++) {
71ae41
+CM_DEBUG(ctx, "[%s][%s].", eku_list[c], sss_ext_key_usage[k].name);
71ae41
+            if (strcasecmp(eku_list[c], sss_ext_key_usage[k].name) == 0) {
71ae41
                 comp->eku_oid_list[e] = talloc_strdup(comp->eku_oid_list,
71ae41
-                                                      ext_key_usage[k].oid);
71ae41
+                                                      sss_ext_key_usage[k].oid);
71ae41
                 if (comp->eku_oid_list[e] == NULL) {
71ae41
                     ret = ENOMEM;
71ae41
                     goto done;
71ae41
@@ -202,7 +233,7 @@ CM_DEBUG(ctx, "[%s][%s].", eku_list[c], ext_key_usage[k].name);
71ae41
             }
71ae41
         }
71ae41
 
71ae41
-        if (ext_key_usage[k].name == NULL) {
71ae41
+        if (sss_ext_key_usage[k].name == NULL) {
71ae41
             /* check for an dotted-decimal OID */
71ae41
             if (*(eku_list[c]) != '.') {
71ae41
                 o = eku_list[c];
71ae41
@@ -252,23 +283,6 @@ static int parse_krb5_get_ku_value(TALLOC_CTX *mem_ctx,
71ae41
     size_t c;
71ae41
     size_t k;
71ae41
 
71ae41
-    struct key_usage {
71ae41
-        const char *name;
71ae41
-        uint32_t flag;
71ae41
-    } key_usage[] = {
71ae41
-        {"digitalSignature" , SSS_KU_DIGITAL_SIGNATURE},
71ae41
-        {"nonRepudiation"   , SSS_KU_NON_REPUDIATION},
71ae41
-        {"keyEncipherment"  , SSS_KU_KEY_ENCIPHERMENT},
71ae41
-        {"dataEncipherment" , SSS_KU_DATA_ENCIPHERMENT},
71ae41
-        {"keyAgreement"     , SSS_KU_KEY_AGREEMENT},
71ae41
-        {"keyCertSign"      , SSS_KU_KEY_CERT_SIGN},
71ae41
-        {"cRLSign"          , SSS_KU_CRL_SIGN},
71ae41
-        {"encipherOnly"     , SSS_KU_ENCIPHER_ONLY},
71ae41
-        {"decipherOnly"     , SSS_KU_DECIPHER_ONLY},
71ae41
-        {NULL ,0}
71ae41
-    };
71ae41
-
71ae41
-
71ae41
     ret = get_comp_value(mem_ctx, ctx, cur, &comp);
71ae41
     if (ret != 0) {
71ae41
         CM_DEBUG(ctx, "Failed to get value.");
71ae41
@@ -283,14 +297,14 @@ static int parse_krb5_get_ku_value(TALLOC_CTX *mem_ctx,
71ae41
     }
71ae41
 
71ae41
     for (c = 0; ku_list[c] != NULL; c++) {
71ae41
-        for (k = 0; key_usage[k].name != NULL; k++) {
71ae41
-            if (strcasecmp(ku_list[c], key_usage[k].name) == 0) {
71ae41
-                comp->ku |= key_usage[k].flag;
71ae41
+        for (k = 0; sss_key_usage[k].name != NULL; k++) {
71ae41
+            if (strcasecmp(ku_list[c], sss_key_usage[k].name) == 0) {
71ae41
+                comp->ku |= sss_key_usage[k].flag;
71ae41
                 break;
71ae41
             }
71ae41
         }
71ae41
 
71ae41
-        if (key_usage[k].name == NULL) {
71ae41
+        if (sss_key_usage[k].name == NULL) {
71ae41
             /* FIXME: add check for numerical ku */
71ae41
             CM_DEBUG(ctx, "No matching key usage found.");
71ae41
             ret = EINVAL;
71ae41
@@ -342,31 +356,6 @@ done:
71ae41
     return ret;
71ae41
 }
71ae41
 
71ae41
-struct san_name {
71ae41
-    const char *name;
71ae41
-    enum san_opt san_opt;
71ae41
-    bool is_string;
71ae41
-} san_names[] = {
71ae41
-    /* https://www.ietf.org/rfc/rfc3280.txt section 4.2.1.7 */
71ae41
-    {"otherName", SAN_OTHER_NAME, false},
71ae41
-    {"rfc822Name", SAN_RFC822_NAME,true},
71ae41
-    {"dNSName", SAN_DNS_NAME, true},
71ae41
-    {"x400Address", SAN_X400_ADDRESS, false},
71ae41
-    {"directoryName", SAN_DIRECTORY_NAME, true},
71ae41
-    {"ediPartyName", SAN_EDIPART_NAME, false},
71ae41
-    {"uniformResourceIdentifier", SAN_URI, true},
71ae41
-    {"iPAddress", SAN_IP_ADDRESS, true},
71ae41
-    {"registeredID", SAN_REGISTERED_ID, true},
71ae41
-    /* https://www.ietf.org/rfc/rfc4556.txt section 3.2.2 */
71ae41
-    {"pkinitSAN", SAN_PKINIT, true},
71ae41
-    /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography */
71ae41
-    {"ntPrincipalName", SAN_NT, true},
71ae41
-    /* both previous principal types */
71ae41
-    {"Principal", SAN_PRINCIPAL, true},
71ae41
-    {"stringOtherName", SAN_STRING_OTHER_NAME, true},
71ae41
-    {NULL, SAN_END, false}
71ae41
-};
71ae41
-
71ae41
 static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
71ae41
                                      struct sss_certmap_ctx *ctx,
71ae41
                                      const char **cur,
71ae41
@@ -388,12 +377,12 @@ static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
71ae41
     if (len == 0) {
71ae41
         c= SAN_PRINCIPAL;
71ae41
     } else {
71ae41
-        for (c = 0; san_names[c].name != NULL; c++) {
71ae41
-            if (strncasecmp(*cur, san_names[c].name, len) == 0) {
71ae41
+        for (c = 0; sss_san_names[c].name != NULL; c++) {
71ae41
+            if (strncasecmp(*cur, sss_san_names[c].name, len) == 0) {
71ae41
                 break;
71ae41
             }
71ae41
         }
71ae41
-        if (san_names[c].name == NULL) {
71ae41
+        if (sss_san_names[c].name == NULL) {
71ae41
             if (is_dotted_decimal(*cur, len)) {
71ae41
                 c = SAN_STRING_OTHER_NAME;
71ae41
                 *str_other_name_oid = talloc_strndup(mem_ctx, *cur, len);
71ae41
@@ -408,7 +397,7 @@ static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
71ae41
         }
71ae41
     }
71ae41
 
71ae41
-    *option = san_names[c].san_opt;
71ae41
+    *option = sss_san_names[c].san_opt;
71ae41
     *cur = end + 1;
71ae41
 
71ae41
     return 0;
71ae41
@@ -432,7 +421,7 @@ static int parse_krb5_get_san_value(TALLOC_CTX *mem_ctx,
71ae41
         }
71ae41
     }
71ae41
 
71ae41
-    if (san_names[san_opt].is_string) {
71ae41
+    if (sss_san_names[san_opt].is_string) {
71ae41
         ret = parse_krb5_get_component_value(mem_ctx, ctx, cur, &comp);
71ae41
         if (ret != 0) {
71ae41
             goto done;
71ae41
-- 
71ae41
2.37.3
71ae41
71ae41
71ae41
From 136858b1a5f7ed011287293fdf35cc7142ee3cf1 Mon Sep 17 00:00:00 2001
71ae41
From: Sumit Bose <sbose@redhat.com>
71ae41
Date: Mon, 9 Dec 2019 11:31:14 +0100
71ae41
Subject: [PATCH 2/2] certmap: sanitize LDAP search filter
71ae41
71ae41
The sss_certmap_get_search_filter() will now sanitize the values read
71ae41
from the certificates before adding them to a search filter. To be able
71ae41
to get the plain values as well sss_certmap_expand_mapping_rule() is
71ae41
added.
71ae41
71ae41
Resolves:
71ae41
https://github.com/SSSD/sssd/issues/5135
71ae41
71ae41
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
71ae41
(cherry picked from commit a2b9a84460429181f2a4fa7e2bb5ab49fd561274)
71ae41
71ae41
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
71ae41
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
71ae41
---
71ae41
 Makefile.am                         |  2 +-
71ae41
 src/lib/certmap/sss_certmap.c       | 42 ++++++++++--
71ae41
 src/lib/certmap/sss_certmap.exports |  5 ++
71ae41
 src/lib/certmap/sss_certmap.h       | 35 ++++++++--
71ae41
 src/responder/pam/pamsrv_p11.c      |  5 +-
71ae41
 src/tests/cmocka/test_certmap.c     | 98 +++++++++++++++++++++++++++-
71ae41
 src/util/util.c                     | 95 ---------------------------
71ae41
 src/util/util_ext.c                 | 99 +++++++++++++++++++++++++++++
71ae41
 8 files changed, 272 insertions(+), 109 deletions(-)
71ae41
71ae41
diff --git a/Makefile.am b/Makefile.am
71ae41
index 87eb571..d1568fb 100644
71ae41
--- a/Makefile.am
71ae41
+++ b/Makefile.am
71ae41
@@ -1862,7 +1862,7 @@ libsss_certmap_la_LIBADD = \
71ae41
     $(NULL)
71ae41
 libsss_certmap_la_LDFLAGS = \
71ae41
     -Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \
71ae41
-    -version-info 1:0:1
71ae41
+    -version-info 2:0:2
71ae41
 
71ae41
 if HAVE_NSS
71ae41
 libsss_certmap_la_SOURCES += \
71ae41
diff --git a/src/lib/certmap/sss_certmap.c b/src/lib/certmap/sss_certmap.c
71ae41
index c60ac24..d7bc992 100644
71ae41
--- a/src/lib/certmap/sss_certmap.c
71ae41
+++ b/src/lib/certmap/sss_certmap.c
71ae41
@@ -441,10 +441,12 @@ static int expand_san(struct sss_certmap_ctx *ctx,
71ae41
 static int expand_template(struct sss_certmap_ctx *ctx,
71ae41
                            struct parsed_template *parsed_template,
71ae41
                            struct sss_cert_content *cert_content,
71ae41
+                           bool sanitize,
71ae41
                            char **expanded)
71ae41
 {
71ae41
     int ret;
71ae41
     char *exp = NULL;
71ae41
+    char *exp_sanitized = NULL;
71ae41
 
71ae41
     if (strcmp("issuer_dn", parsed_template->name) == 0) {
71ae41
         ret = rdn_list_2_dn_str(ctx, parsed_template->conversion,
71ae41
@@ -455,6 +457,8 @@ static int expand_template(struct sss_certmap_ctx *ctx,
71ae41
     } else if (strncmp("subject_", parsed_template->name, 8) == 0) {
71ae41
         ret = expand_san(ctx, parsed_template, cert_content->san_list, &exp);
71ae41
     } else if (strcmp("cert", parsed_template->name) == 0) {
71ae41
+        /* cert blob is already sanitized */
71ae41
+        sanitize = false;
71ae41
         ret = expand_cert(ctx, parsed_template, cert_content, &exp);
71ae41
     } else {
71ae41
         CM_DEBUG(ctx, "Unsupported template name.");
71ae41
@@ -471,6 +475,16 @@ static int expand_template(struct sss_certmap_ctx *ctx,
71ae41
         goto done;
71ae41
     }
71ae41
 
71ae41
+    if (sanitize) {
71ae41
+        ret = sss_filter_sanitize(ctx, exp, &exp_sanitized);
71ae41
+        if (ret != EOK) {
71ae41
+            CM_DEBUG(ctx, "Failed to sanitize expanded template.");
71ae41
+            goto done;
71ae41
+        }
71ae41
+        talloc_free(exp);
71ae41
+        exp = exp_sanitized;
71ae41
+    }
71ae41
+
71ae41
     ret = 0;
71ae41
 
71ae41
 done:
71ae41
@@ -485,7 +499,7 @@ done:
71ae41
 
71ae41
 static int get_filter(struct sss_certmap_ctx *ctx,
71ae41
                       struct ldap_mapping_rule *parsed_mapping_rule,
71ae41
-                      struct sss_cert_content *cert_content,
71ae41
+                      struct sss_cert_content *cert_content, bool sanitize,
71ae41
                       char **filter)
71ae41
 {
71ae41
     struct ldap_mapping_rule_comp *comp;
71ae41
@@ -503,7 +517,7 @@ static int get_filter(struct sss_certmap_ctx *ctx,
71ae41
             result = talloc_strdup_append(result, comp->val);
71ae41
         } else if (comp->type == comp_template) {
71ae41
             ret = expand_template(ctx, comp->parsed_template, cert_content,
71ae41
-                                  &expanded);
71ae41
+                                  sanitize, &expanded);
71ae41
             if (ret != 0) {
71ae41
                 CM_DEBUG(ctx, "Failed to expanded template.");
71ae41
                 goto done;
71ae41
@@ -791,8 +805,9 @@ done:
71ae41
     return ret;
71ae41
 }
71ae41
 
71ae41
-int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
71ae41
+static int expand_mapping_rule_ex(struct sss_certmap_ctx *ctx,
71ae41
                                   const uint8_t *der_cert, size_t der_size,
71ae41
+                                  bool sanitize,
71ae41
                                   char **_filter, char ***_domains)
71ae41
 {
71ae41
     int ret;
71ae41
@@ -819,7 +834,8 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
71ae41
             return EINVAL;
71ae41
         }
71ae41
 
71ae41
-        ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, &filter);
71ae41
+        ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, sanitize,
71ae41
+                         &filter);
71ae41
         goto done;
71ae41
     }
71ae41
 
71ae41
@@ -829,7 +845,7 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
71ae41
             if (ret == 0) {
71ae41
                 /* match */
71ae41
                 ret = get_filter(ctx, r->parsed_mapping_rule, cert_content,
71ae41
-                                 &filter);
71ae41
+                                 sanitize, &filter);
71ae41
                 if (ret != 0) {
71ae41
                     CM_DEBUG(ctx, "Failed to get filter");
71ae41
                     goto done;
71ae41
@@ -873,6 +889,22 @@ done:
71ae41
     return ret;
71ae41
 }
71ae41
 
71ae41
+int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
71ae41
+                                  const uint8_t *der_cert, size_t der_size,
71ae41
+                                  char **_filter, char ***_domains)
71ae41
+{
71ae41
+    return expand_mapping_rule_ex(ctx, der_cert, der_size, true,
71ae41
+                                  _filter, _domains);
71ae41
+}
71ae41
+
71ae41
+int sss_certmap_expand_mapping_rule(struct sss_certmap_ctx *ctx,
71ae41
+                                    const uint8_t *der_cert, size_t der_size,
71ae41
+                                    char **_expanded, char ***_domains)
71ae41
+{
71ae41
+    return expand_mapping_rule_ex(ctx, der_cert, der_size, false,
71ae41
+                                  _expanded, _domains);
71ae41
+}
71ae41
+
71ae41
 int sss_certmap_init(TALLOC_CTX *mem_ctx,
71ae41
                      sss_certmap_ext_debug *debug, void *debug_priv,
71ae41
                      struct sss_certmap_ctx **ctx)
71ae41
diff --git a/src/lib/certmap/sss_certmap.exports b/src/lib/certmap/sss_certmap.exports
71ae41
index a9e48d6..7d76677 100644
71ae41
--- a/src/lib/certmap/sss_certmap.exports
71ae41
+++ b/src/lib/certmap/sss_certmap.exports
71ae41
@@ -16,3 +16,8 @@ SSS_CERTMAP_0.1 {
71ae41
     global:
71ae41
         sss_certmap_display_cert_content;
71ae41
 } SSS_CERTMAP_0.0;
71ae41
+
71ae41
+SSS_CERTMAP_0.2 {
71ae41
+    global:
71ae41
+        sss_certmap_expand_mapping_rule;
71ae41
+} SSS_CERTMAP_0.1;
71ae41
diff --git a/src/lib/certmap/sss_certmap.h b/src/lib/certmap/sss_certmap.h
71ae41
index 7da2d1c..058d4f9 100644
71ae41
--- a/src/lib/certmap/sss_certmap.h
71ae41
+++ b/src/lib/certmap/sss_certmap.h
71ae41
@@ -103,7 +103,7 @@ int sss_certmap_add_rule(struct sss_certmap_ctx *ctx,
71ae41
  *
71ae41
  * @param[in] ctx      certmap context previously initialized with
71ae41
  *                     @ref sss_certmap_init
71ae41
- * @param[in] der_cert binary blog with the DER encoded certificate
71ae41
+ * @param[in] der_cert binary blob with the DER encoded certificate
71ae41
  * @param[in] der_size size of the certificate blob
71ae41
  *
71ae41
  * @return
71ae41
@@ -119,10 +119,11 @@ int sss_certmap_match_cert(struct sss_certmap_ctx *ctx,
71ae41
  *
71ae41
  * @param[in] ctx      certmap context previously initialized with
71ae41
  *                     @ref sss_certmap_init
71ae41
- * @param[in] der_cert binary blog with the DER encoded certificate
71ae41
+ * @param[in] der_cert binary blob with the DER encoded certificate
71ae41
  * @param[in] der_size size of the certificate blob
71ae41
- * @param[out] filter  LDAP filter string, caller should free the data by
71ae41
- *                     calling sss_certmap_free_filter_and_domains
71ae41
+ * @param[out] filter  LDAP filter string, expanded templates are sanitized,
71ae41
+ *                     caller should free the data by calling
71ae41
+ *                     sss_certmap_free_filter_and_domains
71ae41
  * @param[out] domains NULL-terminated array of strings with the domains the
71ae41
  *                     rule applies, caller should free the data by calling
71ae41
  *                     sss_certmap_free_filter_and_domains
71ae41
@@ -136,8 +137,32 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
71ae41
                                   const uint8_t *der_cert, size_t der_size,
71ae41
                                   char **filter, char ***domains);
71ae41
 
71ae41
+/**
71ae41
+ * @brief Expand the mapping rule by replacing the templates
71ae41
+ *
71ae41
+ * @param[in] ctx        certmap context previously initialized with
71ae41
+ *                       @ref sss_certmap_init
71ae41
+ * @param[in] der_cert   binary blob with the DER encoded certificate
71ae41
+ * @param[in] der_size   size of the certificate blob
71ae41
+ * @param[out] expanded  expanded mapping rule, templates are filled in
71ae41
+ *                       verbatim in contrast to sss_certmap_get_search_filter,
71ae41
+ *                       caller should free the data by
71ae41
+ *                       calling sss_certmap_free_filter_and_domains
71ae41
+ * @param[out] domains   NULL-terminated array of strings with the domains the
71ae41
+ *                       rule applies, caller should free the data by calling
71ae41
+ *                       sss_certmap_free_filter_and_domains
71ae41
+ *
71ae41
+ * @return
71ae41
+ *  - 0:      certificate matches a rule
71ae41
+ *  - ENOENT: certificate does not match
71ae41
+ *  - EINVAL: internal error
71ae41
+ */
71ae41
+int sss_certmap_expand_mapping_rule(struct sss_certmap_ctx *ctx,
71ae41
+                                    const uint8_t *der_cert, size_t der_size,
71ae41
+                                    char **_expanded, char ***_domains);
71ae41
 /**
71ae41
  * @brief Free data returned by @ref sss_certmap_get_search_filter
71ae41
+ *        and @ref sss_certmap_expand_mapping_rule
71ae41
  *
71ae41
  * @param[in] filter  LDAP filter strings returned by
71ae41
  *                    sss_certmap_get_search_filter
71ae41
@@ -150,7 +175,7 @@ void sss_certmap_free_filter_and_domains(char *filter, char **domains);
71ae41
  * @brief Get a string with the content of the certificate used by the library
71ae41
  *
71ae41
  * @param[in]  mem_ctx    Talloc memory context, may be NULL
71ae41
- * @param[in]  der_cert   binary blog with the DER encoded certificate
71ae41
+ * @param[in]  der_cert   binary blob with the DER encoded certificate
71ae41
  * @param[in]  der_size   size of the certificate blob
71ae41
  * @param[out] desc       Multiline string showing the certificate content
71ae41
  *                        which is used by libsss_certmap
71ae41
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
71ae41
index c58a8be..f01566e 100644
71ae41
--- a/src/responder/pam/pamsrv_p11.c
71ae41
+++ b/src/responder/pam/pamsrv_p11.c
71ae41
@@ -1044,9 +1044,10 @@ static char *get_cert_prompt(TALLOC_CTX *mem_ctx,
71ae41
         goto done;
71ae41
     }
71ae41
 
71ae41
-    ret = sss_certmap_get_search_filter(ctx, der, der_size, &filter, &domains);
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, der, der_size,
71ae41
+                                          &filter, &domains);
71ae41
     if (ret != 0) {
71ae41
-        DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_get_search_filter failed.\n");
71ae41
+        DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_expand_mapping_rule failed.\n");
71ae41
         goto done;
71ae41
     }
71ae41
 
71ae41
diff --git a/src/tests/cmocka/test_certmap.c b/src/tests/cmocka/test_certmap.c
71ae41
index c882202..232ff78 100644
71ae41
--- a/src/tests/cmocka/test_certmap.c
71ae41
+++ b/src/tests/cmocka/test_certmap.c
71ae41
@@ -1431,6 +1431,15 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
                                         &filter, &domains);
71ae41
     assert_int_equal(ret, 0);
71ae41
     assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "rule100=CN=Certificate\\20Authority,O=IPA.DEVEL"
71ae41
+                                "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
71ae41
+    assert_null(domains);
71ae41
+
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
71ae41
+                                          sizeof(test_cert_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
     assert_string_equal(filter, "rule100=CN=Certificate Authority,O=IPA.DEVEL"
71ae41
                                 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
71ae41
     assert_null(domains);
71ae41
@@ -1445,6 +1454,17 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
                                         &filter, &domains);
71ae41
     assert_int_equal(ret, 0);
71ae41
     assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "rule99=CN=Certificate\\20Authority,O=IPA.DEVEL"
71ae41
+                                "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
71ae41
+    assert_non_null(domains);
71ae41
+    assert_string_equal(domains[0], "test.dom");
71ae41
+    assert_null(domains[1]);
71ae41
+
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
71ae41
+                                          sizeof(test_cert_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
     assert_string_equal(filter, "rule99=CN=Certificate Authority,O=IPA.DEVEL"
71ae41
                                 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
71ae41
     assert_non_null(domains);
71ae41
@@ -1466,6 +1486,16 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
     assert_string_equal(domains[0], "test.dom");
71ae41
     assert_null(domains[1]);
71ae41
 
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
71ae41
+                                          sizeof(test_cert_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "rule98=userCertificate;binary=" TEST_CERT_BIN);
71ae41
+    assert_non_null(domains);
71ae41
+    assert_string_equal(domains[0], "test.dom");
71ae41
+    assert_null(domains[1]);
71ae41
+
71ae41
     ret = sss_certmap_add_rule(ctx, 97,
71ae41
                             "KRB5:<ISSUER>CN=Certificate Authority,O=IPA.DEVEL",
71ae41
                             "LDAP:rule97={issuer_dn!nss_x500}<S>{subject_dn}",
71ae41
@@ -1476,6 +1506,17 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
                                         &filter, &domains);
71ae41
     assert_int_equal(ret, 0);
71ae41
     assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "rule97=O=IPA.DEVEL,CN=Certificate\\20Authority"
71ae41
+                                "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
71ae41
+    assert_non_null(domains);
71ae41
+    assert_string_equal(domains[0], "test.dom");
71ae41
+    assert_null(domains[1]);
71ae41
+
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
71ae41
+                                          sizeof(test_cert_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
     assert_string_equal(filter, "rule97=O=IPA.DEVEL,CN=Certificate Authority"
71ae41
                                 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
71ae41
     assert_non_null(domains);
71ae41
@@ -1492,6 +1533,17 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
                                         &filter, &domains);
71ae41
     assert_int_equal(ret, 0);
71ae41
     assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "rule96=O=IPA.DEVEL,CN=Certificate\\20Authority"
71ae41
+                                "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
71ae41
+    assert_non_null(domains);
71ae41
+    assert_string_equal(domains[0], "test.dom");
71ae41
+    assert_null(domains[1]);
71ae41
+
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
71ae41
+                                          sizeof(test_cert_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
     assert_string_equal(filter, "rule96=O=IPA.DEVEL,CN=Certificate Authority"
71ae41
                                 "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
71ae41
     assert_non_null(domains);
71ae41
@@ -1510,6 +1562,14 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
     assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")");
71ae41
     assert_null(domains);
71ae41
 
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
71ae41
+                                          sizeof(test_cert_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")");
71ae41
+    assert_null(domains);
71ae41
+
71ae41
     ret = sss_certmap_add_rule(ctx, 94,
71ae41
                       "KRB5:<ISSUER>CN=Certificate Authority,O=IPA.DEVEL",
71ae41
                       "LDAP:rule94={issuer_dn!ad_x500}<S>{subject_dn!ad_x500}",
71ae41
@@ -1520,12 +1580,22 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
                                         &filter, &domains);
71ae41
     assert_int_equal(ret, 0);
71ae41
     assert_non_null(filter);
71ae41
-    assert_string_equal(filter, "rule94=O=IPA.DEVEL,CN=Certificate Authority"
71ae41
+    assert_string_equal(filter, "rule94=O=IPA.DEVEL,CN=Certificate\\20Authority"
71ae41
                                 "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
71ae41
     assert_non_null(domains);
71ae41
     assert_string_equal(domains[0], "test.dom");
71ae41
     assert_null(domains[1]);
71ae41
 
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
71ae41
+                                          sizeof(test_cert_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "rule94=O=IPA.DEVEL,CN=Certificate Authority"
71ae41
+                                "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
71ae41
+    assert_non_null(domains);
71ae41
+    assert_string_equal(domains[0], "test.dom");
71ae41
+    assert_null(domains[1]);
71ae41
 
71ae41
     ret = sss_certmap_add_rule(ctx, 89, NULL,
71ae41
                             "(rule89={subject_nt_principal})",
71ae41
@@ -1539,6 +1609,14 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
     assert_string_equal(filter, "(rule89=tu1@ad.devel)");
71ae41
     assert_null(domains);
71ae41
 
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
71ae41
+                                          sizeof(test_cert2_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "(rule89=tu1@ad.devel)");
71ae41
+    assert_null(domains);
71ae41
+
71ae41
     ret = sss_certmap_add_rule(ctx, 88, NULL,
71ae41
                             "(rule88={subject_nt_principal.short_name})",
71ae41
                             NULL);
71ae41
@@ -1560,6 +1638,15 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
                                         &filter, &domains);
71ae41
     assert_int_equal(ret, 0);
71ae41
     assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "rule87=DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
71ae41
+                  "<S>DC=devel,DC=ad,CN=Users,CN=t\\20u,E=test.user@email.domain");
71ae41
+    assert_null(domains);
71ae41
+
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
71ae41
+                                          sizeof(test_cert2_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
     assert_string_equal(filter, "rule87=DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
71ae41
                   "<S>DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain");
71ae41
     assert_null(domains);
71ae41
@@ -1573,6 +1660,15 @@ static void test_sss_certmap_get_search_filter(void **state)
71ae41
                                         &filter, &domains);
71ae41
     assert_int_equal(ret, 0);
71ae41
     assert_non_null(filter);
71ae41
+    assert_string_equal(filter, "rule86=DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
71ae41
+                  "<S>DC=devel,DC=ad,CN=Users,CN=t\\20u,E=test.user@email.domain");
71ae41
+    assert_null(domains);
71ae41
+
71ae41
+    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
71ae41
+                                          sizeof(test_cert2_der),
71ae41
+                                          &filter, &domains);
71ae41
+    assert_int_equal(ret, 0);
71ae41
+    assert_non_null(filter);
71ae41
     assert_string_equal(filter, "rule86=DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
71ae41
                   "<S>DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain");
71ae41
     assert_null(domains);
71ae41
diff --git a/src/util/util.c b/src/util/util.c
71ae41
index 4051c1f..9327f97 100644
71ae41
--- a/src/util/util.c
71ae41
+++ b/src/util/util.c
71ae41
@@ -436,101 +436,6 @@ errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count,
71ae41
     return sss_hash_create_ex(mem_ctx, count, tbl, 0, 0, 0, 0, NULL, NULL);
71ae41
 }
71ae41
 
71ae41
-errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
71ae41
-                               const char *input,
71ae41
-                               char **sanitized,
71ae41
-                               const char *ignore)
71ae41
-{
71ae41
-    char *output;
71ae41
-    size_t i = 0;
71ae41
-    size_t j = 0;
71ae41
-    char *allowed;
71ae41
-
71ae41
-    /* Assume the worst-case. We'll resize it later, once */
71ae41
-    output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1);
71ae41
-    if (!output) {
71ae41
-        return ENOMEM;
71ae41
-    }
71ae41
-
71ae41
-    while (input[i]) {
71ae41
-        /* Even though this character might have a special meaning, if it's
71ae41
-         * expliticly allowed, just copy it and move on
71ae41
-         */
71ae41
-        if (ignore == NULL) {
71ae41
-            allowed = NULL;
71ae41
-        } else {
71ae41
-            allowed = strchr(ignore, input[i]);
71ae41
-        }
71ae41
-        if (allowed) {
71ae41
-            output[j++] = input[i++];
71ae41
-            continue;
71ae41
-        }
71ae41
-
71ae41
-        switch(input[i]) {
71ae41
-        case '\t':
71ae41
-            output[j++] = '\\';
71ae41
-            output[j++] = '0';
71ae41
-            output[j++] = '9';
71ae41
-            break;
71ae41
-        case ' ':
71ae41
-            output[j++] = '\\';
71ae41
-            output[j++] = '2';
71ae41
-            output[j++] = '0';
71ae41
-            break;
71ae41
-        case '*':
71ae41
-            output[j++] = '\\';
71ae41
-            output[j++] = '2';
71ae41
-            output[j++] = 'a';
71ae41
-            break;
71ae41
-        case '(':
71ae41
-            output[j++] = '\\';
71ae41
-            output[j++] = '2';
71ae41
-            output[j++] = '8';
71ae41
-            break;
71ae41
-        case ')':
71ae41
-            output[j++] = '\\';
71ae41
-            output[j++] = '2';
71ae41
-            output[j++] = '9';
71ae41
-            break;
71ae41
-        case '\\':
71ae41
-            output[j++] = '\\';
71ae41
-            output[j++] = '5';
71ae41
-            output[j++] = 'c';
71ae41
-            break;
71ae41
-        case '\r':
71ae41
-            output[j++] = '\\';
71ae41
-            output[j++] = '0';
71ae41
-            output[j++] = 'd';
71ae41
-            break;
71ae41
-        case '\n':
71ae41
-            output[j++] = '\\';
71ae41
-            output[j++] = '0';
71ae41
-            output[j++] = 'a';
71ae41
-            break;
71ae41
-        default:
71ae41
-            output[j++] = input[i];
71ae41
-        }
71ae41
-
71ae41
-        i++;
71ae41
-    }
71ae41
-    output[j] = '\0';
71ae41
-    *sanitized = talloc_realloc(mem_ctx, output, char, j+1);
71ae41
-    if (!*sanitized) {
71ae41
-        talloc_free(output);
71ae41
-        return ENOMEM;
71ae41
-    }
71ae41
-
71ae41
-    return EOK;
71ae41
-}
71ae41
-
71ae41
-errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
71ae41
-                            const char *input,
71ae41
-                            char **sanitized)
71ae41
-{
71ae41
-    return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL);
71ae41
-}
71ae41
-
71ae41
-
71ae41
 /* There is similar function ldap_dn_normalize in openldap.
71ae41
  * To avoid dependecies across project we have this own func.
71ae41
  * Also ldb can do this but doesn't handle all the cases
71ae41
diff --git a/src/util/util_ext.c b/src/util/util_ext.c
71ae41
index 04dc02a..a89b60f 100644
71ae41
--- a/src/util/util_ext.c
71ae41
+++ b/src/util/util_ext.c
71ae41
@@ -29,6 +29,11 @@
71ae41
 
71ae41
 #define EOK 0
71ae41
 
71ae41
+#ifndef HAVE_ERRNO_T
71ae41
+#define HAVE_ERRNO_T
71ae41
+typedef int errno_t;
71ae41
+#endif
71ae41
+
71ae41
 int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
71ae41
                        const char sep, bool trim, bool skip_empty,
71ae41
                        char ***_list, int *size)
71ae41
@@ -141,3 +146,97 @@ bool string_in_list(const char *string, char **list, bool case_sensitive)
71ae41
 
71ae41
     return false;
71ae41
 }
71ae41
+
71ae41
+errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
71ae41
+                               const char *input,
71ae41
+                               char **sanitized,
71ae41
+                               const char *ignore)
71ae41
+{
71ae41
+    char *output;
71ae41
+    size_t i = 0;
71ae41
+    size_t j = 0;
71ae41
+    char *allowed;
71ae41
+
71ae41
+    /* Assume the worst-case. We'll resize it later, once */
71ae41
+    output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1);
71ae41
+    if (!output) {
71ae41
+        return ENOMEM;
71ae41
+    }
71ae41
+
71ae41
+    while (input[i]) {
71ae41
+        /* Even though this character might have a special meaning, if it's
71ae41
+         * explicitly allowed, just copy it and move on
71ae41
+         */
71ae41
+        if (ignore == NULL) {
71ae41
+            allowed = NULL;
71ae41
+        } else {
71ae41
+            allowed = strchr(ignore, input[i]);
71ae41
+        }
71ae41
+        if (allowed) {
71ae41
+            output[j++] = input[i++];
71ae41
+            continue;
71ae41
+        }
71ae41
+
71ae41
+        switch(input[i]) {
71ae41
+        case '\t':
71ae41
+            output[j++] = '\\';
71ae41
+            output[j++] = '0';
71ae41
+            output[j++] = '9';
71ae41
+            break;
71ae41
+        case ' ':
71ae41
+            output[j++] = '\\';
71ae41
+            output[j++] = '2';
71ae41
+            output[j++] = '0';
71ae41
+            break;
71ae41
+        case '*':
71ae41
+            output[j++] = '\\';
71ae41
+            output[j++] = '2';
71ae41
+            output[j++] = 'a';
71ae41
+            break;
71ae41
+        case '(':
71ae41
+            output[j++] = '\\';
71ae41
+            output[j++] = '2';
71ae41
+            output[j++] = '8';
71ae41
+            break;
71ae41
+        case ')':
71ae41
+            output[j++] = '\\';
71ae41
+            output[j++] = '2';
71ae41
+            output[j++] = '9';
71ae41
+            break;
71ae41
+        case '\\':
71ae41
+            output[j++] = '\\';
71ae41
+            output[j++] = '5';
71ae41
+            output[j++] = 'c';
71ae41
+            break;
71ae41
+        case '\r':
71ae41
+            output[j++] = '\\';
71ae41
+            output[j++] = '0';
71ae41
+            output[j++] = 'd';
71ae41
+            break;
71ae41
+        case '\n':
71ae41
+            output[j++] = '\\';
71ae41
+            output[j++] = '0';
71ae41
+            output[j++] = 'a';
71ae41
+            break;
71ae41
+        default:
71ae41
+            output[j++] = input[i];
71ae41
+        }
71ae41
+
71ae41
+        i++;
71ae41
+    }
71ae41
+    output[j] = '\0';
71ae41
+    *sanitized = talloc_realloc(mem_ctx, output, char, j+1);
71ae41
+    if (!*sanitized) {
71ae41
+        talloc_free(output);
71ae41
+        return ENOMEM;
71ae41
+    }
71ae41
+
71ae41
+    return EOK;
71ae41
+}
71ae41
+
71ae41
+errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
71ae41
+                            const char *input,
71ae41
+                            char **sanitized)
71ae41
+{
71ae41
+    return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL);
71ae41
+}
71ae41
-- 
71ae41
2.37.3
71ae41