URL: https://github.com/SSSD/sssd/pull/209
Author: sumit-bose
 Title: #209: IPA: lookup AD users by certificates on IPA clients
Action: opened

PR body:
"""
Get a list of users mapped to a certificate back from the IPA server, look
them up and store them together with the certificate used for the search as
mapped attribute to the cache.

Related to https://pagure.io/SSSD/sssd/issue/3050

This is another puzzle piece of looking up users by certificate, this time for
AD users on IPA clients. If you think it should not run under #3050 anymore
please let me know, then I'll open a new ticket.

It turned out that although most of the code was already there to lookup AD
users with the whole certificate it so far never worked, see 3rd patch. Even if
this is fixed the fixed from a0b1bfa76073d3ce3208e67e6d72bb92088edac5 is needed
on the IPA server side as well to allow the processing on reasonable sized
certificates.

Since it never worked it took the opportunity to replace the single user lookup
with a lookup which returns a list of user to support mapping a certificate to
multiple users. To test this the IPA server side must use the patch from
https://github.com/freeipa/freeipa/pull/644 to get the user list reply.

To test it the InfoPipe or python listbycert request can be used.
"""

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/209/head:pr209
git checkout pr209
From fefa2f4115521d4beef92b3c4863640ddb748d58 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Wed, 22 Mar 2017 14:13:05 +0100
Subject: [PATCH 1/3] IPA: add mapped attributes to user from trusted domains

Allow the usage of the mapped attribute for the lookup of AD users on
IPA clients as already used for the normal LDAP lookup.

Related to https://pagure.io/SSSD/sssd/issue/3050
---
 src/providers/ipa/ipa_s2n_exop.c | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index c993122..05c32a2 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -761,6 +761,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
                                     struct resp_attrs *simple_attrs,
                                     const char *view_name,
                                     struct sysdb_attrs *override_attrs,
+                                    struct sysdb_attrs *mapped_attrs,
                                     bool update_initgr_timeout);
 
 static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
@@ -1009,6 +1010,7 @@ struct ipa_s2n_get_list_state {
     struct resp_attrs *attrs;
     struct sss_domain_info *obj_domain;
     struct sysdb_attrs *override_attrs;
+    struct sysdb_attrs *mapped_attrs;
 };
 
 static errno_t ipa_s2n_get_list_step(struct tevent_req *req);
@@ -1025,7 +1027,8 @@ static struct tevent_req *ipa_s2n_get_list_send(TALLOC_CTX *mem_ctx,
                                                 int entry_type,
                                                 enum request_types request_type,
                                                 enum req_input_type list_type,
-                                                char **list)
+                                                char **list,
+                                                struct sysdb_attrs *mapped_attrs)
 {
     int ret;
     struct ipa_s2n_get_list_state *state;
@@ -1057,6 +1060,7 @@ static struct tevent_req *ipa_s2n_get_list_send(TALLOC_CTX *mem_ctx,
     state->request_type = request_type;
     state->attrs = NULL;
     state->override_attrs = NULL;
+    state->mapped_attrs = mapped_attrs;
 
     ret = ipa_s2n_get_list_step(req);
     if (ret != EOK) {
@@ -1288,7 +1292,8 @@ static errno_t ipa_s2n_get_list_save_step(struct tevent_req *req)
 
     ret = ipa_s2n_save_objects(state->dom, &state->req_input, state->attrs,
                                NULL, state->ipa_ctx->view_name,
-                               state->override_attrs, false);
+                               state->override_attrs, state->mapped_attrs,
+                               false);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
         return ret;
@@ -1704,7 +1709,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
                                                  BE_REQ_GROUP,
                                                  REQ_FULL_WITH_MEMBERS,
                                                  REQ_INP_NAME,
-                                                 missing_list);
+                                                 missing_list, NULL);
                 if (subreq == NULL) {
                     DEBUG(SSSDBG_OP_FAILURE,
                           "ipa_s2n_get_list_send failed.\n");
@@ -1732,7 +1737,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
                                                  BE_REQ_USER,
                                                  REQ_FULL_WITH_MEMBERS,
                                                  REQ_INP_NAME,
-                                                 missing_list);
+                                                 missing_list, NULL);
                 if (subreq == NULL) {
                     DEBUG(SSSDBG_OP_FAILURE,
                           "ipa_s2n_get_list_send failed.\n");
@@ -1810,7 +1815,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
 
     if (ret == ENOENT || is_default_view(state->ipa_ctx->view_name)) {
         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
-                                   state->simple_attrs, NULL, NULL, true);
+                                   state->simple_attrs, NULL, NULL, NULL, true);
         if (ret != EOK) {
             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
             goto done;
@@ -1978,6 +1983,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
                                     struct resp_attrs *simple_attrs,
                                     const char *view_name,
                                     struct sysdb_attrs *override_attrs,
+                                    struct sysdb_attrs *mapped_attrs,
                                     bool update_initgr_timeout)
 {
     int ret;
@@ -2305,6 +2311,15 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
                 goto done;
             }
 
+            if (mapped_attrs != NULL) {
+                ret = sysdb_set_user_attr(dom, name, mapped_attrs,
+                                          SYSDB_MOD_ADD);
+                if (ret != EOK) {
+                    DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_user_attr failed.\n");
+                    goto done;
+                }
+            }
+
             if (gid_override_attrs != NULL) {
                 ret = sysdb_set_user_attr(dom, name, gid_override_attrs,
                                           SYSDB_MOD_REP);
@@ -2487,7 +2502,7 @@ static void ipa_s2n_get_list_done(struct tevent_req  *subreq)
                                  &sid_str);
     if (ret == ENOENT) {
         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
-                                   state->simple_attrs, NULL, NULL, true);
+                                   state->simple_attrs, NULL, NULL, NULL, true);
         if (ret != EOK) {
             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
             goto fail;
@@ -2525,7 +2540,7 @@ static void ipa_s2n_get_list_done(struct tevent_req  *subreq)
         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
                                    state->simple_attrs,
                                    state->ipa_ctx->view_name,
-                                   state->override_attrs, true);
+                                   state->override_attrs, NULL, true);
         if (ret != EOK) {
             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
             tevent_req_error(req, ret);
@@ -2561,7 +2576,7 @@ static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq)
 
     ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
                                state->simple_attrs, state->ipa_ctx->view_name,
-                               override_attrs, true);
+                               override_attrs, NULL, true);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
         tevent_req_error(req, ret);
@@ -2662,7 +2677,7 @@ struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx,
                                dp_opt_get_int(ipa_ctx->sdap_id_ctx->opts->basic,
                                               SDAP_SEARCH_TIMEOUT),
                                BE_REQ_BY_SECID, REQ_FULL, REQ_INP_SECID,
-                               state->missing_sids);
+                               state->missing_sids, NULL);
     if (subreq == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_send failed.\n");
         ret = ENOMEM;

From a1e9faf6fad73f0accd02993d5ae44aea0e99a6f Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 24 Mar 2017 15:40:41 +0100
Subject: [PATCH 2/3] IPA: lookup AD users by certificates on IPA clients

Get a list of users mapped to a certificate back from the IPA server,
look them up and store them together with the certificate used for the
search as mapped attribute to the cache.

Related to https://pagure.io/SSSD/sssd/issue/3050
---
 src/providers/ipa/ipa_s2n_exop.c | 109 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 105 insertions(+), 4 deletions(-)

diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index 05c32a2..8a3391b 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -52,7 +52,8 @@ enum response_types {
     RESP_USER,
     RESP_GROUP,
     RESP_USER_GROUPLIST,
-    RESP_GROUP_MEMBERS
+    RESP_GROUP_MEMBERS,
+    RESP_NAME_LIST
 };
 
 /* ==Sid2Name Extended Operation============================================= */
@@ -366,8 +367,8 @@ static errno_t s2n_encode_request(TALLOC_CTX *mem_ctx,
             break;
         case BE_REQ_BY_CERT:
             if (req_input->type == REQ_INP_CERT) {
-            ret = ber_printf(ber, "{ees}", INP_CERT, request_type,
-                                           req_input->inp.cert);
+                ret = ber_printf(ber, "{ees}", INP_CERT, request_type,
+                                               req_input->inp.cert);
             } else {
                 DEBUG(SSSDBG_OP_FAILURE, "Unexpected input type [%d].\n",
                                           req_input->type);
@@ -463,6 +464,11 @@ static errno_t s2n_encode_request(TALLOC_CTX *mem_ctx,
  * GroupMemberList ::= SEQUENCE OF OCTET STRING
  */
 
+struct name_list {
+    char *domain_name;
+    char *name;
+};
+
 struct resp_attrs {
     enum response_types response_type;
     char *domain_name;
@@ -475,6 +481,7 @@ struct resp_attrs {
     size_t ngroups;
     char **groups;
     struct sysdb_attrs *sysdb_attrs;
+    char **name_list;
 };
 
 static errno_t get_extra_attrs(BerElement *ber, struct resp_attrs *resp_attrs)
@@ -782,6 +789,9 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
     struct resp_attrs *attrs = NULL;
     char *sid_str;
     bool is_v1 = false;
+    char **name_list = NULL;
+    ber_len_t ber_len;
+    char *fq_name = NULL;
 
     if (retoid == NULL || retdata == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "Missing OID or data.\n");
@@ -947,6 +957,53 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
                 goto done;
             }
             break;
+        case RESP_NAME_LIST:
+            tag = ber_scanf(ber, "{");
+            if (tag == LBER_ERROR) {
+                DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
+                ret = EINVAL;
+                goto done;
+            }
+
+            while (ber_peek_tag(ber, &ber_len) ==  LBER_SEQUENCE) {
+                tag = ber_scanf(ber, "{aa}", &domain_name, &name);
+                if (tag == LBER_ERROR) {
+                    DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
+                    ret = EINVAL;
+                    goto done;
+                }
+
+                fq_name = sss_create_internal_fqname(attrs, name, domain_name);
+                if (fq_name == NULL) {
+                    DEBUG(SSSDBG_OP_FAILURE,
+                          "sss_create_internal_fqname failed.\n");
+                    ret = ENOMEM;
+                    goto done;
+                }
+                DEBUG(SSSDBG_TRACE_ALL, "[%s][%s][%s].\n", domain_name, name,
+                                                           fq_name);
+
+                ret = add_string_to_list(attrs, fq_name, &name_list);
+                ber_memfree(domain_name);
+                ber_memfree(name);
+                talloc_free(fq_name);
+                domain_name = NULL;
+                name = NULL;
+                fq_name = NULL;
+                if (ret != EOK) {
+                    DEBUG(SSSDBG_OP_FAILURE, "add_to_name_list failed.\n");
+                    goto done;
+                }
+            }
+
+            tag = ber_scanf(ber, "}}");
+            if (tag == LBER_ERROR) {
+                DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
+                ret = EINVAL;
+                goto done;
+            }
+            attrs->name_list = name_list;
+            break;
         default:
             DEBUG(SSSDBG_OP_FAILURE, "Unexpected response type [%d].\n",
                                       type);
@@ -955,7 +1012,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
     }
 
     attrs->response_type = type;
-    if (type != RESP_SID) {
+    if (type != RESP_SID && type != RESP_NAME_LIST) {
         attrs->domain_name = talloc_strdup(attrs, domain_name);
         if (attrs->domain_name == NULL) {
             DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
@@ -969,6 +1026,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
 done:
     ber_memfree(domain_name);
     ber_memfree(name);
+    talloc_free(fq_name);
     ber_free(ber, 1);
 
     if (ret == EOK) {
@@ -1332,6 +1390,7 @@ struct ipa_s2n_get_user_state {
     struct resp_attrs *attrs;
     struct resp_attrs *simple_attrs;
     struct sysdb_attrs *override_attrs;
+    struct sysdb_attrs *mapped_attrs;
     int exop_timeout;
 };
 
@@ -1384,6 +1443,11 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx,
         goto fail;
     }
 
+    if (entry_type == BE_REQ_BY_CERT) {
+        /* Only REQ_SIMPLE is supported for BE_REQ_BY_CERT */
+        state->request_type = REQ_SIMPLE;
+    }
+
     ret = s2n_encode_request(state, dom->name, entry_type, state->request_type,
                              req_input, &bv_req);
     if (ret != EOK) {
@@ -1785,6 +1849,43 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
             goto done;
         }
 
+        if (state->simple_attrs->response_type == RESP_NAME_LIST
+                && state->req_input->type == REQ_INP_CERT) {
+            state->mapped_attrs = sysdb_new_attrs(state);
+            if (state->mapped_attrs == NULL) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
+                ret = ENOMEM;
+                goto done;
+            }
+
+            ret = sysdb_attrs_add_base64_blob(state->mapped_attrs,
+                                              SYSDB_USER_MAPPED_CERT,
+                                              state->req_input->inp.cert);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_base64_blob failed.\n");
+                goto done;
+            }
+
+            subreq = ipa_s2n_get_list_send(state, state->ev,
+                                           state->ipa_ctx, state->dom,
+                                           state->sh, state->exop_timeout,
+                                           BE_REQ_USER,
+                                           REQ_FULL_WITH_MEMBERS,
+                                           REQ_INP_NAME,
+                                           state->simple_attrs->name_list,
+                                           state->mapped_attrs);
+            if (subreq == NULL) {
+                DEBUG(SSSDBG_OP_FAILURE,
+                      "ipa_s2n_get_list_send failed.\n");
+                ret = ENOMEM;
+                goto done;
+            }
+            tevent_req_set_callback(subreq, ipa_s2n_get_list_done,
+                                    req);
+
+            return;
+        }
+
         break;
     default:
         DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected request type.\n");

From 5ae9d9337b50966074efeab784338b48331ef2e3 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 24 Mar 2017 15:41:37 +0100
Subject: [PATCH 3/3] IPA: enable AD user lookup by certificate

Without this the lookup by certificate for AD users on an IPA client
will just error out.

Related to https://pagure.io/SSSD/sssd/issue/3050
---
 src/providers/ipa/ipa_subdomains_id.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 4777d7c..3530af9 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -399,6 +399,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
         case BE_REQ_USER:
         case BE_REQ_GROUP:
         case BE_REQ_BY_SECID:
+        case BE_REQ_BY_CERT:
         case BE_REQ_USER_AND_GROUP:
             ret = EOK;
             break;
_______________________________________________
sssd-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to