Blame SOURCES/0011-IPA-add-certmap-support.patch

bb7cd1
From d51754859a83e7fedf0cac90ad8bf5de09f35463 Mon Sep 17 00:00:00 2001
bb7cd1
From: Sumit Bose <sbose@redhat.com>
bb7cd1
Date: Mon, 6 Feb 2017 10:28:46 +0100
bb7cd1
Subject: [PATCH 11/15] IPA: add certmap support
bb7cd1
MIME-Version: 1.0
bb7cd1
Content-Type: text/plain; charset=UTF-8
bb7cd1
Content-Transfer-Encoding: 8bit
bb7cd1
bb7cd1
Read certificate mapping data from the IPA server and configure the
bb7cd1
certificate mapping library accordingly.
bb7cd1
bb7cd1
Related to https://pagure.io/SSSD/sssd/issue/3050
bb7cd1
bb7cd1
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
bb7cd1
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
bb7cd1
---
bb7cd1
 src/providers/ipa/ipa_config.h            |   2 +
bb7cd1
 src/providers/ipa/ipa_subdomains.c        | 354 ++++++++++++++++++++++++++++++
bb7cd1
 src/providers/ipa/ipa_subdomains_server.c |   4 +
bb7cd1
 src/providers/ldap/ldap_id.c              |   4 +-
bb7cd1
 src/providers/ldap/sdap.h                 |   4 +
bb7cd1
 5 files changed, 367 insertions(+), 1 deletion(-)
bb7cd1
bb7cd1
diff --git a/src/providers/ipa/ipa_config.h b/src/providers/ipa/ipa_config.h
bb7cd1
index 2f1e147d7edab0aca2a16269c6a73bc607b21bd5..60f2d5d7b71227a1d86889ceaf6f0f9ac868480d 100644
bb7cd1
--- a/src/providers/ipa/ipa_config.h
bb7cd1
+++ b/src/providers/ipa/ipa_config.h
bb7cd1
@@ -37,6 +37,8 @@
bb7cd1
 #define IPA_CONFIG_SEARCH_BASE_TEMPLATE "cn=etc,%s"
bb7cd1
 #define IPA_CONFIG_FILTER "(&(cn=ipaConfig)(objectClass=ipaGuiConfig))"
bb7cd1
 
bb7cd1
+#define IPA_OC_CONFIG "ipaConfig"
bb7cd1
+
bb7cd1
 struct tevent_req * ipa_get_config_send(TALLOC_CTX *mem_ctx,
bb7cd1
                                         struct tevent_context *ev,
bb7cd1
                                         struct sdap_handle *sh,
bb7cd1
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
bb7cd1
index b2e96b204213a52014edcc6042ffa1ff8152b8bf..7537550606ef09c0b87a80932c75aa4f93c0efab 100644
bb7cd1
--- a/src/providers/ipa/ipa_subdomains.c
bb7cd1
+++ b/src/providers/ipa/ipa_subdomains.c
bb7cd1
@@ -56,6 +56,24 @@
bb7cd1
 
bb7cd1
 #define IPA_SUBDOMAIN_DISABLED_PERIOD 3600
bb7cd1
 
bb7cd1
+#define IPA_OC_CERTMAP_CONFIG_OBJECT "ipaCertMapConfigObject"
bb7cd1
+#define IPA_CERTMAP_PROMPT_USERNAME "ipaCertMapPromptUserName"
bb7cd1
+
bb7cd1
+#define IPA_OC_CERTMAP_RULE "ipaCertMapRule"
bb7cd1
+#define IPA_CERTMAP_MAPRULE "ipaCertMapMapRule"
bb7cd1
+#define IPA_CERTMAP_MATCHRULE "ipaCertMapMatchRule"
bb7cd1
+#define IPA_CERTMAP_PRIORITY "ipaCertMapPriority"
bb7cd1
+#define IPA_ENABLED_FLAG "ipaEnabledFlag"
bb7cd1
+#define IPA_TRUE_VALUE "TRUE"
bb7cd1
+#define IPA_ASSOCIATED_DOMAIN "associatedDomain"
bb7cd1
+
bb7cd1
+#define OBJECTCLASS "objectClass"
bb7cd1
+
bb7cd1
+#define CERTMAP_FILTER "(|(&("OBJECTCLASS"="IPA_OC_CERTMAP_RULE")" \
bb7cd1
+                              "("IPA_ENABLED_FLAG"="IPA_TRUE_VALUE"))" \
bb7cd1
+                          "("OBJECTCLASS"="IPA_OC_CERTMAP_CONFIG_OBJECT"))"
bb7cd1
+
bb7cd1
+
bb7cd1
 struct ipa_subdomains_ctx {
bb7cd1
     struct be_ctx *be_ctx;
bb7cd1
     struct ipa_id_ctx *ipa_id_ctx;
bb7cd1
@@ -286,6 +304,193 @@ done:
bb7cd1
     return ret;
bb7cd1
 }
bb7cd1
 
bb7cd1
+struct priv_sss_debug {
bb7cd1
+    int level;
bb7cd1
+};
bb7cd1
+
bb7cd1
+void ext_debug(void *private, const char *file, long line, const char *function,
bb7cd1
+               const char *format, ...)
bb7cd1
+{
bb7cd1
+    va_list ap;
bb7cd1
+    struct priv_sss_debug *data = private;
bb7cd1
+    int level = SSSDBG_OP_FAILURE;
bb7cd1
+
bb7cd1
+    if (data != NULL) {
bb7cd1
+        level = data->level;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    if (DEBUG_IS_SET(level)) {
bb7cd1
+        va_start(ap, format);
bb7cd1
+        sss_vdebug_fn(file, line, function, level, APPEND_LINE_FEED,
bb7cd1
+                      format, ap);
bb7cd1
+        va_end(ap);
bb7cd1
+    }
bb7cd1
+}
bb7cd1
+
bb7cd1
+static errno_t ipa_certmap_parse_results(TALLOC_CTX *mem_ctx,
bb7cd1
+                                         struct sss_domain_info *domain,
bb7cd1
+                                         struct sdap_options *sdap_opts,
bb7cd1
+                                         size_t count,
bb7cd1
+                                         struct sysdb_attrs **reply,
bb7cd1
+                                         struct certmap_info ***_certmap_list)
bb7cd1
+{
bb7cd1
+    struct certmap_info **certmap_list = NULL;
bb7cd1
+    struct certmap_info *m;
bb7cd1
+    const char *value;
bb7cd1
+    const char **values;
bb7cd1
+    size_t c;
bb7cd1
+    size_t lc = 0;
bb7cd1
+    int ret;
bb7cd1
+    struct sss_certmap_ctx *certmap_ctx = NULL;
bb7cd1
+    const char **ocs = NULL;
bb7cd1
+    bool user_name_hint = false;
bb7cd1
+
bb7cd1
+    certmap_list = talloc_zero_array(mem_ctx, struct certmap_info *, count + 1);
bb7cd1
+    if (certmap_list == NULL) {
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
bb7cd1
+        return ENOMEM;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    for (c = 0; c < count; c++) {
bb7cd1
+        ret = sysdb_attrs_get_string_array(reply[c], SYSDB_OBJECTCLASS, mem_ctx,
bb7cd1
+                                           &ocs;;
bb7cd1
+        if (ret != EOK) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+                  "Missing objectclasses for config objects.\n");
bb7cd1
+            ret = EINVAL;
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        if (string_in_list(IPA_OC_CERTMAP_CONFIG_OBJECT, discard_const(ocs),
bb7cd1
+                           false)) {
bb7cd1
+            ret = sysdb_attrs_get_bool(reply[c], IPA_CERTMAP_PROMPT_USERNAME,
bb7cd1
+                                       &user_name_hint);
bb7cd1
+            if (ret != EOK) {
bb7cd1
+                DEBUG(SSSDBG_CRIT_FAILURE,
bb7cd1
+                      "Failed to read user name hint option, skipping.\n");
bb7cd1
+            }
bb7cd1
+            continue;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        m = talloc_zero(certmap_list, struct certmap_info);
bb7cd1
+        if (m == NULL) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
bb7cd1
+            ret = ENOMEM;
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value);
bb7cd1
+        if (ret != EOK) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        m->name = talloc_strdup(m, value);
bb7cd1
+        if (m->name == NULL) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
bb7cd1
+            ret = ENOMEM;
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = sysdb_attrs_get_string(reply[c], IPA_CERTMAP_MATCHRULE, &value);
bb7cd1
+        if (ret == EOK) {
bb7cd1
+            m->match_rule = talloc_strdup(m, value);
bb7cd1
+            if (m->match_rule == NULL) {
bb7cd1
+                DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
bb7cd1
+                ret = ENOMEM;
bb7cd1
+                goto done;
bb7cd1
+            }
bb7cd1
+        } else if (ret != ENOENT) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = sysdb_attrs_get_string(reply[c], IPA_CERTMAP_MAPRULE, &value);
bb7cd1
+        if (ret == EOK) {
bb7cd1
+            m->map_rule = talloc_strdup(m, value);
bb7cd1
+            if (m->map_rule == NULL) {
bb7cd1
+                DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
bb7cd1
+                ret = ENOMEM;
bb7cd1
+                goto done;
bb7cd1
+            }
bb7cd1
+        } else if (ret != ENOENT) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = sysdb_attrs_get_string_array(reply[c], IPA_ASSOCIATED_DOMAIN, m,
bb7cd1
+                                           &values);
bb7cd1
+        if (ret == EOK) {
bb7cd1
+            m->domains = values;
bb7cd1
+        } else if (ret != ENOENT) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        ret = sysdb_attrs_get_uint32_t(reply[c], IPA_CERTMAP_PRIORITY,
bb7cd1
+                                       &m->priority);
bb7cd1
+        if (ret != EOK && ret != ENOENT) {
bb7cd1
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
bb7cd1
+            goto done;
bb7cd1
+        } else if (ret == ENOENT) {
bb7cd1
+            m->priority = SSS_CERTMAP_MIN_PRIO;
bb7cd1
+        }
bb7cd1
+
bb7cd1
+        certmap_list[lc++] = m;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    certmap_list[lc] = NULL;
bb7cd1
+
bb7cd1
+    ret = sss_certmap_init(mem_ctx, ext_debug, NULL, &certmap_ctx);
bb7cd1
+    if (ret != 0) {
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_init failed.\n");
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    for (c = 0; certmap_list[c] != NULL; c++) {
bb7cd1
+        DEBUG(SSSDBG_TRACE_ALL, "Trying to add rule [%s][%d][%s][%s].\n",
bb7cd1
+                                certmap_list[c]->name,
bb7cd1
+                                certmap_list[c]->priority,
bb7cd1
+                                certmap_list[c]->match_rule,
bb7cd1
+                                certmap_list[c]->map_rule);
bb7cd1
+
bb7cd1
+        ret = sss_certmap_add_rule(certmap_ctx, certmap_list[c]->priority,
bb7cd1
+                                   certmap_list[c]->match_rule,
bb7cd1
+                                   certmap_list[c]->map_rule,
bb7cd1
+                                   certmap_list[c]->domains);
bb7cd1
+        if (ret != 0) {
bb7cd1
+            DEBUG(SSSDBG_CRIT_FAILURE,
bb7cd1
+                  "sss_certmap_add_rule failed for rule [%s], skipping. "
bb7cd1
+                  "Please check for typos and if rule syntax is supported.\n",
bb7cd1
+                  certmap_list[c]->name);
bb7cd1
+            goto done;
bb7cd1
+        }
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = sysdb_update_certmap(domain->sysdb, certmap_list, user_name_hint);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_certmap failed");
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    sss_certmap_free_ctx(sdap_opts->certmap_ctx);
bb7cd1
+    sdap_opts->certmap_ctx = talloc_steal(sdap_opts, certmap_ctx);
bb7cd1
+
bb7cd1
+    if (_certmap_list != NULL) {
bb7cd1
+        *_certmap_list = certmap_list;
bb7cd1
+    }
bb7cd1
+    ret = EOK;
bb7cd1
+
bb7cd1
+done:
bb7cd1
+    talloc_free(ocs);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        sss_certmap_free_ctx(certmap_ctx);
bb7cd1
+        talloc_free(certmap_list);
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    return ret;
bb7cd1
+}
bb7cd1
+
bb7cd1
 static errno_t ipa_subdom_enumerates(struct sss_domain_info *parent,
bb7cd1
                                      struct sysdb_attrs *attrs,
bb7cd1
                                      bool *_enumerates)
bb7cd1
@@ -801,6 +1006,125 @@ static errno_t ipa_subdomains_ranges_recv(struct tevent_req *req)
bb7cd1
     return EOK;
bb7cd1
 }
bb7cd1
 
bb7cd1
+#define IPA_CERTMAP_SEARCH_BASE_TEMPLATE "cn=certmap,%s"
bb7cd1
+
bb7cd1
+struct ipa_subdomains_certmap_state {
bb7cd1
+    struct sss_domain_info *domain;
bb7cd1
+    struct sdap_options *sdap_opts;
bb7cd1
+};
bb7cd1
+
bb7cd1
+static void ipa_subdomains_certmap_done(struct tevent_req *subreq);
bb7cd1
+
bb7cd1
+static struct tevent_req *
bb7cd1
+ipa_subdomains_certmap_send(TALLOC_CTX *mem_ctx,
bb7cd1
+                           struct tevent_context *ev,
bb7cd1
+                           struct ipa_subdomains_ctx *sd_ctx,
bb7cd1
+                           struct sdap_handle *sh)
bb7cd1
+{
bb7cd1
+    struct ipa_subdomains_certmap_state *state;
bb7cd1
+    struct tevent_req *subreq;
bb7cd1
+    struct tevent_req *req;
bb7cd1
+    errno_t ret;
bb7cd1
+    char *ldap_basedn;
bb7cd1
+    char *search_base;
bb7cd1
+    const char *attrs[] = { OBJECTCLASS, IPA_CN,
bb7cd1
+                            IPA_CERTMAP_MAPRULE, IPA_CERTMAP_MATCHRULE,
bb7cd1
+                            IPA_CERTMAP_PRIORITY, IPA_ASSOCIATED_DOMAIN,
bb7cd1
+                            IPA_CERTMAP_PROMPT_USERNAME,
bb7cd1
+                            NULL };
bb7cd1
+
bb7cd1
+    req = tevent_req_create(mem_ctx, &state,
bb7cd1
+                            struct ipa_subdomains_certmap_state);
bb7cd1
+    if (req == NULL) {
bb7cd1
+        DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
bb7cd1
+        return NULL;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    state->domain = sd_ctx->be_ctx->domain;
bb7cd1
+    state->sdap_opts = sd_ctx->sdap_id_ctx->opts;
bb7cd1
+
bb7cd1
+    ret = domain_to_basedn(state, state->domain->name, &ldap_basedn);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n");
bb7cd1
+        goto immediately;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    search_base = talloc_asprintf(state, IPA_CERTMAP_SEARCH_BASE_TEMPLATE,
bb7cd1
+                                  ldap_basedn);
bb7cd1
+    if (search_base == NULL) {
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
bb7cd1
+        ret = ENOMEM;
bb7cd1
+        goto immediately;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    subreq = sdap_get_generic_send(state, ev, sd_ctx->sdap_id_ctx->opts, sh,
bb7cd1
+                                   search_base, LDAP_SCOPE_SUBTREE,
bb7cd1
+                                   CERTMAP_FILTER,
bb7cd1
+                                   attrs, NULL, 0, 0, false);
bb7cd1
+    if (subreq == NULL) {
bb7cd1
+        ret = ENOMEM;
bb7cd1
+        goto immediately;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    tevent_req_set_callback(subreq, ipa_subdomains_certmap_done, req);
bb7cd1
+
bb7cd1
+    return req;
bb7cd1
+
bb7cd1
+immediately:
bb7cd1
+    if (ret == EOK) {
bb7cd1
+        tevent_req_done(req);
bb7cd1
+    } else {
bb7cd1
+        tevent_req_error(req, ret);
bb7cd1
+    }
bb7cd1
+    tevent_req_post(req, ev);
bb7cd1
+
bb7cd1
+    return req;
bb7cd1
+}
bb7cd1
+
bb7cd1
+static void ipa_subdomains_certmap_done(struct tevent_req *subreq)
bb7cd1
+{
bb7cd1
+    struct ipa_subdomains_certmap_state *state;
bb7cd1
+    struct tevent_req *req;
bb7cd1
+    struct sysdb_attrs **reply;
bb7cd1
+    size_t reply_count;
bb7cd1
+    errno_t ret;
bb7cd1
+
bb7cd1
+    req = tevent_req_callback_data(subreq, struct tevent_req);
bb7cd1
+    state = tevent_req_data(req, struct ipa_subdomains_certmap_state);
bb7cd1
+
bb7cd1
+    ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
bb7cd1
+    talloc_zfree(subreq);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get data from LDAP [%d]: %s\n",
bb7cd1
+                      ret, sss_strerror(ret));
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    ret = ipa_certmap_parse_results(state, state->domain,
bb7cd1
+                                    state->sdap_opts,
bb7cd1
+                                    reply_count, reply, NULL);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to parse certmap results [%d]: %s\n",
bb7cd1
+              ret, sss_strerror(ret));
bb7cd1
+        goto done;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+done:
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        tevent_req_error(req, ret);
bb7cd1
+        return;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    tevent_req_done(req);
bb7cd1
+}
bb7cd1
+
bb7cd1
+static errno_t ipa_subdomains_certmap_recv(struct tevent_req *req)
bb7cd1
+{
bb7cd1
+    TEVENT_REQ_RETURN_ON_ERROR(req);
bb7cd1
+
bb7cd1
+    return EOK;
bb7cd1
+}
bb7cd1
+
bb7cd1
 struct ipa_subdomains_master_state {
bb7cd1
     struct sss_domain_info *domain;
bb7cd1
     struct ipa_options *ipa_options;
bb7cd1
@@ -1365,6 +1689,7 @@ struct ipa_subdomains_refresh_state {
bb7cd1
 static errno_t ipa_subdomains_refresh_retry(struct tevent_req *req);
bb7cd1
 static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq);
bb7cd1
 static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq);
bb7cd1
+static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq);
bb7cd1
 static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq);
bb7cd1
 static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq);
bb7cd1
 static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq);
bb7cd1
@@ -1487,6 +1812,35 @@ static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq)
bb7cd1
         return;
bb7cd1
     }
bb7cd1
 
bb7cd1
+    subreq = ipa_subdomains_certmap_send(state, state->ev, state->sd_ctx,
bb7cd1
+                                         sdap_id_op_handle(state->sdap_op));
bb7cd1
+    if (subreq == NULL) {
bb7cd1
+        tevent_req_error(req, ENOMEM);
bb7cd1
+        return;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    tevent_req_set_callback(subreq, ipa_subdomains_refresh_certmap_done, req);
bb7cd1
+    return;
bb7cd1
+}
bb7cd1
+
bb7cd1
+static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq)
bb7cd1
+{
bb7cd1
+    struct ipa_subdomains_refresh_state *state;
bb7cd1
+    struct tevent_req *req;
bb7cd1
+    errno_t ret;
bb7cd1
+
bb7cd1
+    req = tevent_req_callback_data(subreq, struct tevent_req);
bb7cd1
+    state = tevent_req_data(req, struct ipa_subdomains_refresh_state);
bb7cd1
+
bb7cd1
+    ret = ipa_subdomains_certmap_recv(subreq);
bb7cd1
+    talloc_zfree(subreq);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to read certificate mapping rules "
bb7cd1
+              "[%d]: %s\n", ret, sss_strerror(ret));
bb7cd1
+        tevent_req_error(req, ret);
bb7cd1
+        return;
bb7cd1
+    }
bb7cd1
+
bb7cd1
     subreq = ipa_subdomains_master_send(state, state->ev, state->sd_ctx,
bb7cd1
                                         sdap_id_op_handle(state->sdap_op));
bb7cd1
     if (subreq == NULL) {
bb7cd1
diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
bb7cd1
index 1af8676c5a9c49121d0f0118a46796c6637f04f9..ae3baf036e4278fb67d86b42742fb7e80b46724e 100644
bb7cd1
--- a/src/providers/ipa/ipa_subdomains_server.c
bb7cd1
+++ b/src/providers/ipa/ipa_subdomains_server.c
bb7cd1
@@ -362,6 +362,10 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
bb7cd1
     ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
bb7cd1
         id_ctx->sdap_id_ctx->opts->idmap_ctx;
bb7cd1
 
bb7cd1
+    /* Set up the certificate mapping context */
bb7cd1
+    ad_id_ctx->sdap_id_ctx->opts->certmap_ctx =
bb7cd1
+        id_ctx->sdap_id_ctx->opts->certmap_ctx;
bb7cd1
+
bb7cd1
     *_ad_id_ctx = ad_id_ctx;
bb7cd1
     return EOK;
bb7cd1
 }
bb7cd1
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
bb7cd1
index 8e60769d09383ac8ebe33e5f64fd4fd9788e82cd..0bee0ca8d71abece6749fdb8393b9ceacb64417d 100644
bb7cd1
--- a/src/providers/ldap/ldap_id.c
bb7cd1
+++ b/src/providers/ldap/ldap_id.c
bb7cd1
@@ -247,7 +247,9 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
bb7cd1
         }
bb7cd1
 
bb7cd1
         ret = sss_cert_derb64_to_ldap_filter(state, filter_value, attr_name,
bb7cd1
-                                             NULL, NULL, &user_filter);
bb7cd1
+                                             ctx->opts->certmap_ctx,
bb7cd1
+                                             state->domain,
bb7cd1
+                                             &user_filter);
bb7cd1
         if (ret != EOK) {
bb7cd1
             DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
                   "sss_cert_derb64_to_ldap_filter failed.\n");
bb7cd1
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
bb7cd1
index 6079a8bf62d0bdf23c8d462dc0f19c705e391a6e..afdc01948eefe9dda943c8c7ad01a42dd76a1da8 100644
bb7cd1
--- a/src/providers/ldap/sdap.h
bb7cd1
+++ b/src/providers/ldap/sdap.h
bb7cd1
@@ -25,6 +25,7 @@
bb7cd1
 #include "providers/backend.h"
bb7cd1
 #include <ldap.h>
bb7cd1
 #include "util/sss_ldap.h"
bb7cd1
+#include "lib/certmap/sss_certmap.h"
bb7cd1
 
bb7cd1
 struct sdap_msg {
bb7cd1
     struct sdap_msg *next;
bb7cd1
@@ -478,6 +479,9 @@ struct sdap_options {
bb7cd1
 
bb7cd1
     bool support_matching_rule;
bb7cd1
     enum dc_functional_level dc_functional_level;
bb7cd1
+
bb7cd1
+    /* Certificate mapping support */
bb7cd1
+    struct sss_certmap_ctx *certmap_ctx;
bb7cd1
 };
bb7cd1
 
bb7cd1
 struct sdap_server_opts {
bb7cd1
-- 
bb7cd1
2.9.3
bb7cd1