From c282abb7ea366cc40885293fee4e693a3d676a5c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 27 Mar 2020 14:31:06 +0100
Subject: [PATCH 1/2] ipa: add missing new-line in debug message

---
 src/providers/ipa/ipa_subdomains.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 03127e0f4c..6d6b7b6359 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -450,7 +450,7 @@ static errno_t ipa_certmap_parse_results(TALLOC_CTX *mem_ctx,
 
     ret = sysdb_update_certmap(domain->sysdb, certmap_list, user_name_hint);
     if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_certmap failed");
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_certmap failed.\n");
         goto done;
     }
 

From 4b59b896dbde7ea42480a85b7fa081a18db6990e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 27 Mar 2020 17:05:14 +0100
Subject: [PATCH 2/2] sysdb: sanitize certmap rule name before using it in DN

The name of a certificate mapping and matching rule might contain
characters which are not allowed in RDNs an must be escaped before if
can be used in the DN of the cached certmap object.

Resolves: https://pagure.io/SSSD/sssd/issue/3721
---
 src/db/sysdb_certmap.c                | 29 ++++++++++++++++++++++++---
 src/tests/cmocka/test_sysdb_certmap.c | 25 +++++++++++++++++++++--
 2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/src/db/sysdb_certmap.c b/src/db/sysdb_certmap.c
index 0bcc54c4d1..4cc5b5b410 100644
--- a/src/db/sysdb_certmap.c
+++ b/src/db/sysdb_certmap.c
@@ -71,6 +71,30 @@ static errno_t sysdb_create_certmap_container(struct sysdb_ctx *sysdb,
     return ret;
 }
 
+static struct ldb_dn *sysdb_certmap_dn(TALLOC_CTX *mem_ctx,
+                                       struct sysdb_ctx *sysdb,
+                                       const char *name)
+{
+    int ret;
+    char *clean_name;
+    struct ldb_dn *dn = NULL;
+
+    ret = sysdb_dn_sanitize(mem_ctx, name, &clean_name);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_dn_sanitize failed.\n");
+        return NULL;
+    }
+
+    dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_CERTMAP, clean_name);
+    talloc_free(clean_name);
+    if (dn == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
+        return NULL;
+    }
+
+    return dn;
+}
+
 static errno_t sysdb_certmap_add(struct sysdb_ctx *sysdb,
                                  struct certmap_info *certmap)
 {
@@ -93,10 +117,9 @@ static errno_t sysdb_certmap_add(struct sysdb_ctx *sysdb,
         goto done;
     }
 
-    msg->dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
-                             SYSDB_TMPL_CERTMAP, certmap->name);
+    msg->dn = sysdb_certmap_dn(tmp_ctx, sysdb, certmap->name);
     if (msg->dn == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_certmap_dn failed.\n");
         ret = ENOMEM;
         goto done;
     }
diff --git a/src/tests/cmocka/test_sysdb_certmap.c b/src/tests/cmocka/test_sysdb_certmap.c
index 88c9737d8d..8e84d183cf 100644
--- a/src/tests/cmocka/test_sysdb_certmap.c
+++ b/src/tests/cmocka/test_sysdb_certmap.c
@@ -133,12 +133,20 @@ static void test_sysdb_update_certmap(void **state)
 {
     int ret;
     const char *domains[] = { "dom1.test", "dom2.test", "dom3.test", NULL };
-    struct certmap_info map_a = { discard_const("map_a"), 11, discard_const("abc"), discard_const("def"), NULL };
-    struct certmap_info map_b = { discard_const("map_b"), UINT_MAX, discard_const("abc"), NULL, domains };
+    struct certmap_info map_a = { discard_const("map_a"), 11,
+                                  discard_const("abc"), discard_const("def"),
+                                  NULL };
+    struct certmap_info map_b = { discard_const("map_b"), UINT_MAX,
+                                  discard_const("abc"), NULL, domains };
+    struct certmap_info map_c = { discard_const("cn=map_c,dc=sssd,dc=org"),
+                                  UINT_MAX, discard_const("abc"), NULL,
+                                  domains };
+
     struct certmap_info *certmap_empty[] = { NULL };
     struct certmap_info *certmap_a[] = { &map_a, NULL };
     struct certmap_info *certmap_b[] = { &map_b, NULL };
     struct certmap_info *certmap_ab[] = { &map_a, &map_b, NULL };
+    struct certmap_info *certmap_c[] = { &map_c, NULL };
     struct certmap_info **certmap;
     struct certmap_test_ctx *ctctx = talloc_get_type(*state,
                                                      struct certmap_test_ctx);
@@ -207,6 +215,19 @@ static void test_sysdb_update_certmap(void **state)
         check_certmap(certmap[1], &map_a, 0);
     }
     talloc_free(certmap);
+
+    ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_c, false);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap,
+                            &user_name_hint);
+    assert_int_equal(ret, EOK);
+    assert_false(user_name_hint);
+    assert_non_null(certmap);
+    assert_non_null(certmap[0]);
+    check_certmap(certmap[0], &map_c, 3);
+    assert_null(certmap[1]);
+    talloc_free(certmap);
 }
 
 int main(int argc, const char *argv[])
