diff --git a/SOURCES/0038-sssctl-sssctl-config-check-alternative-snippet-dir.patch b/SOURCES/0038-sssctl-sssctl-config-check-alternative-snippet-dir.patch
new file mode 100644
index 0000000..c4aa6ad
--- /dev/null
+++ b/SOURCES/0038-sssctl-sssctl-config-check-alternative-snippet-dir.patch
@@ -0,0 +1,63 @@
+From 72b8e02c77f0b0b7e36663fa3bd3fd6987ea1b80 Mon Sep 17 00:00:00 2001
+From: Tomas Halman <thalman@redhat.com>
+Date: Mon, 13 Jul 2020 18:11:40 +0200
+Subject: [PATCH] sssctl: sssctl config-check alternative snippet dir
+
+The sssctl config-check now allows to specify not only alternative
+config file but also snippet dir.
+
+    sssctl config-check -c ./sssd.conf -s /etc/sssd/conf.d
+
+Configuration snippets are still looked up in the same place under
+conf.d directory by default. It would be in ./conf.d/ for the example
+above.
+
+Resolves:
+https://github.com/SSSD/sssd/issues/5142
+
+Reviewed-by: Pawel Polawski <ppolawsk@redhat.com>
+---
+ src/tools/sssctl/sssctl_config.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/src/tools/sssctl/sssctl_config.c b/src/tools/sssctl/sssctl_config.c
+index de9f3de6e..db4aeeae4 100644
+--- a/src/tools/sssctl/sssctl_config.c
++++ b/src/tools/sssctl/sssctl_config.c
+@@ -75,6 +75,11 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline,
+     struct poptOption long_options[] = {
+         {"config", 'c', POPT_ARG_STRING, &config_path,
+             0, _("Specify a non-default config file"), NULL},
++        {"snippet", 's', POPT_ARG_STRING, &config_snippet_path,
++            0, _("Specify a non-default snippet dir (The default is to look in "
++                 "the same place where the main config file is located. For "
++                 "example if the config is set to \"/my/path/sssd.conf\", "
++                 "the snippet dir \"/my/path/conf.d\" is used)"), NULL},
+         POPT_TABLEEND
+     };
+ 
+@@ -92,16 +97,17 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline,
+         goto done;
+     }
+ 
+-    if (config_path != NULL) {
++    if (config_path == NULL) {
++        config_path = SSSD_CONFIG_FILE;
++    }
++
++    if (config_snippet_path == NULL) {
+         config_snippet_path = sssctl_config_snippet_path(tmp_ctx, config_path);
+         if (config_snippet_path == NULL) {
+             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create snippet path\n");
+             ret = ENOMEM;
+             goto done;
+         }
+-    } else {
+-        config_path = SSSD_CONFIG_FILE;
+-        config_snippet_path = CONFDB_DEFAULT_CONFIG_DIR;
+     }
+ 
+     ret = sss_ini_read_sssd_conf(init_data,
+-- 
+2.21.3
+
diff --git a/SOURCES/0039-certmap-sanitize-LDAP-search-filter.patch b/SOURCES/0039-certmap-sanitize-LDAP-search-filter.patch
new file mode 100644
index 0000000..909222b
--- /dev/null
+++ b/SOURCES/0039-certmap-sanitize-LDAP-search-filter.patch
@@ -0,0 +1,651 @@
+From a2b9a84460429181f2a4fa7e2bb5ab49fd561274 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Mon, 9 Dec 2019 11:31:14 +0100
+Subject: [PATCH] certmap: sanitize LDAP search filter
+
+The sss_certmap_get_search_filter() will now sanitize the values read
+from the certificates before adding them to a search filter. To be able
+to get the plain values as well sss_certmap_expand_mapping_rule() is
+added.
+
+Resolves:
+https://github.com/SSSD/sssd/issues/5135
+
+Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
+---
+ Makefile.am                         |  2 +-
+ src/lib/certmap/sss_certmap.c       | 42 ++++++++++--
+ src/lib/certmap/sss_certmap.exports |  5 ++
+ src/lib/certmap/sss_certmap.h       | 35 ++++++++--
+ src/responder/pam/pamsrv_p11.c      |  5 +-
+ src/tests/cmocka/test_certmap.c     | 98 +++++++++++++++++++++++++++-
+ src/util/util.c                     | 94 ---------------------------
+ src/util/util_ext.c                 | 99 +++++++++++++++++++++++++++++
+ 8 files changed, 272 insertions(+), 108 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 059e1eaf6..4bacabdda 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -2163,7 +2163,7 @@ libsss_certmap_la_LIBADD = \
+     $(NULL)
+ libsss_certmap_la_LDFLAGS = \
+     -Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \
+-    -version-info 1:0:1
++    -version-info 2:0:2
+ 
+ if HAVE_NSS
+ libsss_certmap_la_SOURCES += \
+diff --git a/src/lib/certmap/sss_certmap.c b/src/lib/certmap/sss_certmap.c
+index 703782b53..f19e57732 100644
+--- a/src/lib/certmap/sss_certmap.c
++++ b/src/lib/certmap/sss_certmap.c
+@@ -441,10 +441,12 @@ static int expand_san(struct sss_certmap_ctx *ctx,
+ static int expand_template(struct sss_certmap_ctx *ctx,
+                            struct parsed_template *parsed_template,
+                            struct sss_cert_content *cert_content,
++                           bool sanitize,
+                            char **expanded)
+ {
+     int ret;
+     char *exp = NULL;
++    char *exp_sanitized = NULL;
+ 
+     if (strcmp("issuer_dn", parsed_template->name) == 0) {
+         ret = rdn_list_2_dn_str(ctx, parsed_template->conversion,
+@@ -455,6 +457,8 @@ static int expand_template(struct sss_certmap_ctx *ctx,
+     } else if (strncmp("subject_", parsed_template->name, 8) == 0) {
+         ret = expand_san(ctx, parsed_template, cert_content->san_list, &exp);
+     } else if (strcmp("cert", parsed_template->name) == 0) {
++        /* cert blob is already sanitized */
++        sanitize = false;
+         ret = expand_cert(ctx, parsed_template, cert_content, &exp);
+     } else {
+         CM_DEBUG(ctx, "Unsupported template name.");
+@@ -471,6 +475,16 @@ static int expand_template(struct sss_certmap_ctx *ctx,
+         goto done;
+     }
+ 
++    if (sanitize) {
++        ret = sss_filter_sanitize(ctx, exp, &exp_sanitized);
++        if (ret != EOK) {
++            CM_DEBUG(ctx, "Failed to sanitize expanded template.");
++            goto done;
++        }
++        talloc_free(exp);
++        exp = exp_sanitized;
++    }
++
+     ret = 0;
+ 
+ done:
+@@ -485,7 +499,7 @@ done:
+ 
+ static int get_filter(struct sss_certmap_ctx *ctx,
+                       struct ldap_mapping_rule *parsed_mapping_rule,
+-                      struct sss_cert_content *cert_content,
++                      struct sss_cert_content *cert_content, bool sanitize,
+                       char **filter)
+ {
+     struct ldap_mapping_rule_comp *comp;
+@@ -503,7 +517,7 @@ static int get_filter(struct sss_certmap_ctx *ctx,
+             result = talloc_strdup_append(result, comp->val);
+         } else if (comp->type == comp_template) {
+             ret = expand_template(ctx, comp->parsed_template, cert_content,
+-                                  &expanded);
++                                  sanitize, &expanded);
+             if (ret != 0) {
+                 CM_DEBUG(ctx, "Failed to expanded template.");
+                 goto done;
+@@ -791,8 +805,9 @@ done:
+     return ret;
+ }
+ 
+-int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
++static int expand_mapping_rule_ex(struct sss_certmap_ctx *ctx,
+                                   const uint8_t *der_cert, size_t der_size,
++                                  bool sanitize,
+                                   char **_filter, char ***_domains)
+ {
+     int ret;
+@@ -819,7 +834,8 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
+             return EINVAL;
+         }
+ 
+-        ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, &filter);
++        ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, sanitize,
++                         &filter);
+         goto done;
+     }
+ 
+@@ -829,7 +845,7 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
+             if (ret == 0) {
+                 /* match */
+                 ret = get_filter(ctx, r->parsed_mapping_rule, cert_content,
+-                                 &filter);
++                                 sanitize, &filter);
+                 if (ret != 0) {
+                     CM_DEBUG(ctx, "Failed to get filter");
+                     goto done;
+@@ -873,6 +889,22 @@ done:
+     return ret;
+ }
+ 
++int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
++                                  const uint8_t *der_cert, size_t der_size,
++                                  char **_filter, char ***_domains)
++{
++    return expand_mapping_rule_ex(ctx, der_cert, der_size, true,
++                                  _filter, _domains);
++}
++
++int sss_certmap_expand_mapping_rule(struct sss_certmap_ctx *ctx,
++                                    const uint8_t *der_cert, size_t der_size,
++                                    char **_expanded, char ***_domains)
++{
++    return expand_mapping_rule_ex(ctx, der_cert, der_size, false,
++                                  _expanded, _domains);
++}
++
+ int sss_certmap_init(TALLOC_CTX *mem_ctx,
+                      sss_certmap_ext_debug *debug, void *debug_priv,
+                      struct sss_certmap_ctx **ctx)
+diff --git a/src/lib/certmap/sss_certmap.exports b/src/lib/certmap/sss_certmap.exports
+index a9e48d6d0..7d7667738 100644
+--- a/src/lib/certmap/sss_certmap.exports
++++ b/src/lib/certmap/sss_certmap.exports
+@@ -16,3 +16,8 @@ SSS_CERTMAP_0.1 {
+     global:
+         sss_certmap_display_cert_content;
+ } SSS_CERTMAP_0.0;
++
++SSS_CERTMAP_0.2 {
++    global:
++        sss_certmap_expand_mapping_rule;
++} SSS_CERTMAP_0.1;
+diff --git a/src/lib/certmap/sss_certmap.h b/src/lib/certmap/sss_certmap.h
+index 7da2d1c58..058d4f9e4 100644
+--- a/src/lib/certmap/sss_certmap.h
++++ b/src/lib/certmap/sss_certmap.h
+@@ -103,7 +103,7 @@ int sss_certmap_add_rule(struct sss_certmap_ctx *ctx,
+  *
+  * @param[in] ctx      certmap context previously initialized with
+  *                     @ref sss_certmap_init
+- * @param[in] der_cert binary blog with the DER encoded certificate
++ * @param[in] der_cert binary blob with the DER encoded certificate
+  * @param[in] der_size size of the certificate blob
+  *
+  * @return
+@@ -119,10 +119,11 @@ int sss_certmap_match_cert(struct sss_certmap_ctx *ctx,
+  *
+  * @param[in] ctx      certmap context previously initialized with
+  *                     @ref sss_certmap_init
+- * @param[in] der_cert binary blog with the DER encoded certificate
++ * @param[in] der_cert binary blob with the DER encoded certificate
+  * @param[in] der_size size of the certificate blob
+- * @param[out] filter  LDAP filter string, caller should free the data by
+- *                     calling sss_certmap_free_filter_and_domains
++ * @param[out] filter  LDAP filter string, expanded templates are sanitized,
++ *                     caller should free the data by calling
++ *                     sss_certmap_free_filter_and_domains
+  * @param[out] domains NULL-terminated array of strings with the domains the
+  *                     rule applies, caller should free the data by calling
+  *                     sss_certmap_free_filter_and_domains
+@@ -136,8 +137,32 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
+                                   const uint8_t *der_cert, size_t der_size,
+                                   char **filter, char ***domains);
+ 
++/**
++ * @brief Expand the mapping rule by replacing the templates
++ *
++ * @param[in] ctx        certmap context previously initialized with
++ *                       @ref sss_certmap_init
++ * @param[in] der_cert   binary blob with the DER encoded certificate
++ * @param[in] der_size   size of the certificate blob
++ * @param[out] expanded  expanded mapping rule, templates are filled in
++ *                       verbatim in contrast to sss_certmap_get_search_filter,
++ *                       caller should free the data by
++ *                       calling sss_certmap_free_filter_and_domains
++ * @param[out] domains   NULL-terminated array of strings with the domains the
++ *                       rule applies, caller should free the data by calling
++ *                       sss_certmap_free_filter_and_domains
++ *
++ * @return
++ *  - 0:      certificate matches a rule
++ *  - ENOENT: certificate does not match
++ *  - EINVAL: internal error
++ */
++int sss_certmap_expand_mapping_rule(struct sss_certmap_ctx *ctx,
++                                    const uint8_t *der_cert, size_t der_size,
++                                    char **_expanded, char ***_domains);
+ /**
+  * @brief Free data returned by @ref sss_certmap_get_search_filter
++ *        and @ref sss_certmap_expand_mapping_rule
+  *
+  * @param[in] filter  LDAP filter strings returned by
+  *                    sss_certmap_get_search_filter
+@@ -150,7 +175,7 @@ void sss_certmap_free_filter_and_domains(char *filter, char **domains);
+  * @brief Get a string with the content of the certificate used by the library
+  *
+  * @param[in]  mem_ctx    Talloc memory context, may be NULL
+- * @param[in]  der_cert   binary blog with the DER encoded certificate
++ * @param[in]  der_cert   binary blob with the DER encoded certificate
+  * @param[in]  der_size   size of the certificate blob
+  * @param[out] desc       Multiline string showing the certificate content
+  *                        which is used by libsss_certmap
+diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
+index 3f0afaeff..cdf239e07 100644
+--- a/src/responder/pam/pamsrv_p11.c
++++ b/src/responder/pam/pamsrv_p11.c
+@@ -1049,9 +1049,10 @@ static char *get_cert_prompt(TALLOC_CTX *mem_ctx,
+         goto done;
+     }
+ 
+-    ret = sss_certmap_get_search_filter(ctx, der, der_size, &filter, &domains);
++    ret = sss_certmap_expand_mapping_rule(ctx, der, der_size,
++                                          &filter, &domains);
+     if (ret != 0) {
+-        DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_get_search_filter failed.\n");
++        DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_expand_mapping_rule failed.\n");
+         goto done;
+     }
+ 
+diff --git a/src/tests/cmocka/test_certmap.c b/src/tests/cmocka/test_certmap.c
+index c882202a0..232ff7878 100644
+--- a/src/tests/cmocka/test_certmap.c
++++ b/src/tests/cmocka/test_certmap.c
+@@ -1431,6 +1431,15 @@ static void test_sss_certmap_get_search_filter(void **state)
+                                         &filter, &domains);
+     assert_int_equal(ret, 0);
+     assert_non_null(filter);
++    assert_string_equal(filter, "rule100=<I>CN=Certificate\\20Authority,O=IPA.DEVEL"
++                                "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
++    assert_null(domains);
++
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
++                                          sizeof(test_cert_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
+     assert_string_equal(filter, "rule100=<I>CN=Certificate Authority,O=IPA.DEVEL"
+                                 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
+     assert_null(domains);
+@@ -1445,6 +1454,17 @@ static void test_sss_certmap_get_search_filter(void **state)
+                                         &filter, &domains);
+     assert_int_equal(ret, 0);
+     assert_non_null(filter);
++    assert_string_equal(filter, "rule99=<I>CN=Certificate\\20Authority,O=IPA.DEVEL"
++                                "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
++    assert_non_null(domains);
++    assert_string_equal(domains[0], "test.dom");
++    assert_null(domains[1]);
++
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
++                                          sizeof(test_cert_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
+     assert_string_equal(filter, "rule99=<I>CN=Certificate Authority,O=IPA.DEVEL"
+                                 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
+     assert_non_null(domains);
+@@ -1466,6 +1486,16 @@ static void test_sss_certmap_get_search_filter(void **state)
+     assert_string_equal(domains[0], "test.dom");
+     assert_null(domains[1]);
+ 
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
++                                          sizeof(test_cert_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
++    assert_string_equal(filter, "rule98=userCertificate;binary=" TEST_CERT_BIN);
++    assert_non_null(domains);
++    assert_string_equal(domains[0], "test.dom");
++    assert_null(domains[1]);
++
+     ret = sss_certmap_add_rule(ctx, 97,
+                             "KRB5:<ISSUER>CN=Certificate Authority,O=IPA.DEVEL",
+                             "LDAP:rule97=<I>{issuer_dn!nss_x500}<S>{subject_dn}",
+@@ -1476,6 +1506,17 @@ static void test_sss_certmap_get_search_filter(void **state)
+                                         &filter, &domains);
+     assert_int_equal(ret, 0);
+     assert_non_null(filter);
++    assert_string_equal(filter, "rule97=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
++                                "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
++    assert_non_null(domains);
++    assert_string_equal(domains[0], "test.dom");
++    assert_null(domains[1]);
++
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
++                                          sizeof(test_cert_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
+     assert_string_equal(filter, "rule97=<I>O=IPA.DEVEL,CN=Certificate Authority"
+                                 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
+     assert_non_null(domains);
+@@ -1492,6 +1533,17 @@ static void test_sss_certmap_get_search_filter(void **state)
+                                         &filter, &domains);
+     assert_int_equal(ret, 0);
+     assert_non_null(filter);
++    assert_string_equal(filter, "rule96=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
++                                "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
++    assert_non_null(domains);
++    assert_string_equal(domains[0], "test.dom");
++    assert_null(domains[1]);
++
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
++                                          sizeof(test_cert_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
+     assert_string_equal(filter, "rule96=<I>O=IPA.DEVEL,CN=Certificate Authority"
+                                 "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
+     assert_non_null(domains);
+@@ -1510,6 +1562,14 @@ static void test_sss_certmap_get_search_filter(void **state)
+     assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")");
+     assert_null(domains);
+ 
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
++                                          sizeof(test_cert_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
++    assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")");
++    assert_null(domains);
++
+     ret = sss_certmap_add_rule(ctx, 94,
+                       "KRB5:<ISSUER>CN=Certificate Authority,O=IPA.DEVEL",
+                       "LDAP:rule94=<I>{issuer_dn!ad_x500}<S>{subject_dn!ad_x500}",
+@@ -1520,12 +1580,22 @@ static void test_sss_certmap_get_search_filter(void **state)
+                                         &filter, &domains);
+     assert_int_equal(ret, 0);
+     assert_non_null(filter);
+-    assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate Authority"
++    assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
+                                 "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
+     assert_non_null(domains);
+     assert_string_equal(domains[0], "test.dom");
+     assert_null(domains[1]);
+ 
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
++                                          sizeof(test_cert_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
++    assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate Authority"
++                                "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
++    assert_non_null(domains);
++    assert_string_equal(domains[0], "test.dom");
++    assert_null(domains[1]);
+ 
+     ret = sss_certmap_add_rule(ctx, 89, NULL,
+                             "(rule89={subject_nt_principal})",
+@@ -1539,6 +1609,14 @@ static void test_sss_certmap_get_search_filter(void **state)
+     assert_string_equal(filter, "(rule89=tu1@ad.devel)");
+     assert_null(domains);
+ 
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
++                                          sizeof(test_cert2_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
++    assert_string_equal(filter, "(rule89=tu1@ad.devel)");
++    assert_null(domains);
++
+     ret = sss_certmap_add_rule(ctx, 88, NULL,
+                             "(rule88={subject_nt_principal.short_name})",
+                             NULL);
+@@ -1560,6 +1638,15 @@ static void test_sss_certmap_get_search_filter(void **state)
+                                         &filter, &domains);
+     assert_int_equal(ret, 0);
+     assert_non_null(filter);
++    assert_string_equal(filter, "rule87=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
++                  "<S>DC=devel,DC=ad,CN=Users,CN=t\\20u,E=test.user@email.domain");
++    assert_null(domains);
++
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
++                                          sizeof(test_cert2_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
+     assert_string_equal(filter, "rule87=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
+                   "<S>DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain");
+     assert_null(domains);
+@@ -1573,6 +1660,15 @@ static void test_sss_certmap_get_search_filter(void **state)
+                                         &filter, &domains);
+     assert_int_equal(ret, 0);
+     assert_non_null(filter);
++    assert_string_equal(filter, "rule86=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
++                  "<S>DC=devel,DC=ad,CN=Users,CN=t\\20u,E=test.user@email.domain");
++    assert_null(domains);
++
++    ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
++                                          sizeof(test_cert2_der),
++                                          &filter, &domains);
++    assert_int_equal(ret, 0);
++    assert_non_null(filter);
+     assert_string_equal(filter, "rule86=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
+                   "<S>DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain");
+     assert_null(domains);
+diff --git a/src/util/util.c b/src/util/util.c
+index d9bd3cb59..19d447328 100644
+--- a/src/util/util.c
++++ b/src/util/util.c
+@@ -436,100 +436,6 @@ errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count,
+     return sss_hash_create_ex(mem_ctx, count, tbl, 0, 0, 0, 0, NULL, NULL);
+ }
+ 
+-errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
+-                               const char *input,
+-                               char **sanitized,
+-                               const char *ignore)
+-{
+-    char *output;
+-    size_t i = 0;
+-    size_t j = 0;
+-    char *allowed;
+-
+-    /* Assume the worst-case. We'll resize it later, once */
+-    output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1);
+-    if (!output) {
+-        return ENOMEM;
+-    }
+-
+-    while (input[i]) {
+-        /* Even though this character might have a special meaning, if it's
+-         * explicitly allowed, just copy it and move on
+-         */
+-        if (ignore == NULL) {
+-            allowed = NULL;
+-        } else {
+-            allowed = strchr(ignore, input[i]);
+-        }
+-        if (allowed) {
+-            output[j++] = input[i++];
+-            continue;
+-        }
+-
+-        switch(input[i]) {
+-        case '\t':
+-            output[j++] = '\\';
+-            output[j++] = '0';
+-            output[j++] = '9';
+-            break;
+-        case ' ':
+-            output[j++] = '\\';
+-            output[j++] = '2';
+-            output[j++] = '0';
+-            break;
+-        case '*':
+-            output[j++] = '\\';
+-            output[j++] = '2';
+-            output[j++] = 'a';
+-            break;
+-        case '(':
+-            output[j++] = '\\';
+-            output[j++] = '2';
+-            output[j++] = '8';
+-            break;
+-        case ')':
+-            output[j++] = '\\';
+-            output[j++] = '2';
+-            output[j++] = '9';
+-            break;
+-        case '\\':
+-            output[j++] = '\\';
+-            output[j++] = '5';
+-            output[j++] = 'c';
+-            break;
+-        case '\r':
+-            output[j++] = '\\';
+-            output[j++] = '0';
+-            output[j++] = 'd';
+-            break;
+-        case '\n':
+-            output[j++] = '\\';
+-            output[j++] = '0';
+-            output[j++] = 'a';
+-            break;
+-        default:
+-            output[j++] = input[i];
+-        }
+-
+-        i++;
+-    }
+-    output[j] = '\0';
+-    *sanitized = talloc_realloc(mem_ctx, output, char, j+1);
+-    if (!*sanitized) {
+-        talloc_free(output);
+-        return ENOMEM;
+-    }
+-
+-    return EOK;
+-}
+-
+-errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
+-                            const char *input,
+-                            char **sanitized)
+-{
+-    return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL);
+-}
+-
+ char *
+ sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr)
+ {
+diff --git a/src/util/util_ext.c b/src/util/util_ext.c
+index 04dc02a8a..a89b60f76 100644
+--- a/src/util/util_ext.c
++++ b/src/util/util_ext.c
+@@ -29,6 +29,11 @@
+ 
+ #define EOK 0
+ 
++#ifndef HAVE_ERRNO_T
++#define HAVE_ERRNO_T
++typedef int errno_t;
++#endif
++
+ int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
+                        const char sep, bool trim, bool skip_empty,
+                        char ***_list, int *size)
+@@ -141,3 +146,97 @@ bool string_in_list(const char *string, char **list, bool case_sensitive)
+ 
+     return false;
+ }
++
++errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
++                               const char *input,
++                               char **sanitized,
++                               const char *ignore)
++{
++    char *output;
++    size_t i = 0;
++    size_t j = 0;
++    char *allowed;
++
++    /* Assume the worst-case. We'll resize it later, once */
++    output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1);
++    if (!output) {
++        return ENOMEM;
++    }
++
++    while (input[i]) {
++        /* Even though this character might have a special meaning, if it's
++         * explicitly allowed, just copy it and move on
++         */
++        if (ignore == NULL) {
++            allowed = NULL;
++        } else {
++            allowed = strchr(ignore, input[i]);
++        }
++        if (allowed) {
++            output[j++] = input[i++];
++            continue;
++        }
++
++        switch(input[i]) {
++        case '\t':
++            output[j++] = '\\';
++            output[j++] = '0';
++            output[j++] = '9';
++            break;
++        case ' ':
++            output[j++] = '\\';
++            output[j++] = '2';
++            output[j++] = '0';
++            break;
++        case '*':
++            output[j++] = '\\';
++            output[j++] = '2';
++            output[j++] = 'a';
++            break;
++        case '(':
++            output[j++] = '\\';
++            output[j++] = '2';
++            output[j++] = '8';
++            break;
++        case ')':
++            output[j++] = '\\';
++            output[j++] = '2';
++            output[j++] = '9';
++            break;
++        case '\\':
++            output[j++] = '\\';
++            output[j++] = '5';
++            output[j++] = 'c';
++            break;
++        case '\r':
++            output[j++] = '\\';
++            output[j++] = '0';
++            output[j++] = 'd';
++            break;
++        case '\n':
++            output[j++] = '\\';
++            output[j++] = '0';
++            output[j++] = 'a';
++            break;
++        default:
++            output[j++] = input[i];
++        }
++
++        i++;
++    }
++    output[j] = '\0';
++    *sanitized = talloc_realloc(mem_ctx, output, char, j+1);
++    if (!*sanitized) {
++        talloc_free(output);
++        return ENOMEM;
++    }
++
++    return EOK;
++}
++
++errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
++                            const char *input,
++                            char **sanitized)
++{
++    return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL);
++}
+-- 
+2.21.3
+
diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec
index 1b30691..52cfcd4 100644
--- a/SPECS/sssd.spec
+++ b/SPECS/sssd.spec
@@ -26,7 +26,7 @@
 
 Name: sssd
 Version: 2.3.0
-Release: 6%{?dist}
+Release: 7%{?dist}
 Group: Applications/System
 Summary: System Security Services Daemon
 License: GPLv3+
@@ -71,6 +71,8 @@ Patch0034: 0034-mem-cache-comment-added.patch
 Patch0035: 0035-mem-cache-always-cleanup-old-content.patch
 Patch0036: 0036-TRANSLATIONS-updated-translations-to-include-new-sou.patch
 Patch0037: 0037-Updated-translation-files-Japanese-Chinese-China-Fre.patch
+Patch0038: 0038-sssctl-sssctl-config-check-alternative-snippet-dir.patch
+Patch0039: 0039-certmap-sanitize-LDAP-search-filter.patch
 
 ### Downstream Patches ###
 
@@ -1243,6 +1245,10 @@ fi
                                 %{_libdir}/%{name}/modules/libwbclient.so
 
 %changelog
+* Fri Aug 07 2020 Alexey Tikhonov <atikhono@redhat.com> - 2.3.0-7
+- Resolves: rhbz#1723273 - RFE: Add option to specify alternate sssd config file location with "sssctl config-check" command.
+- Resolves: rhbz#1780404 - smartcards: special characters must be escaped when building search filter
+
 * Fri Jul 24 2020 Alexey Tikhonov <atikhono@redhat.com> - 2.3.0-6
 - Resolves: rhbz#1820574 - [sssd] RHEL 8.3 Tier 0 Localization