Blame SOURCES/0059-IPA-lookup-AD-users-by-certificates-on-IPA-clients.patch

bb7cd1
From 537e057ef3bd140e418381f2ce74397ab8c34a73 Mon Sep 17 00:00:00 2001
bb7cd1
From: Sumit Bose <sbose@redhat.com>
bb7cd1
Date: Fri, 24 Mar 2017 15:40:41 +0100
bb7cd1
Subject: [PATCH 59/60] IPA: lookup AD users by certificates on IPA clients
bb7cd1
bb7cd1
Get a list of users mapped to a certificate back from the IPA server,
bb7cd1
look them up and store them together with the certificate used for the
bb7cd1
search as mapped attribute to the cache.
bb7cd1
bb7cd1
Related to https://pagure.io/SSSD/sssd/issue/3050
bb7cd1
bb7cd1
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
bb7cd1
---
bb7cd1
 src/providers/ipa/ipa_s2n_exop.c | 109 +++++++++++++++++++++++++++++++++++++--
bb7cd1
 1 file changed, 105 insertions(+), 4 deletions(-)
bb7cd1
bb7cd1
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
bb7cd1
index 05c32a24d61947e62884f460069083fb81f40fe0..8a3391b4093f1547d84fe44a0f24b1d063d1e28c 100644
bb7cd1
--- a/src/providers/ipa/ipa_s2n_exop.c
bb7cd1
+++ b/src/providers/ipa/ipa_s2n_exop.c
bb7cd1
@@ -52,7 +52,8 @@ enum response_types {
bb7cd1
     RESP_USER,
bb7cd1
     RESP_GROUP,
bb7cd1
     RESP_USER_GROUPLIST,
bb7cd1
-    RESP_GROUP_MEMBERS
bb7cd1
+    RESP_GROUP_MEMBERS,
bb7cd1
+    RESP_NAME_LIST
bb7cd1
 };
bb7cd1
 
bb7cd1
 /* ==Sid2Name Extended Operation============================================= */
bb7cd1
@@ -366,8 +367,8 @@ static errno_t s2n_encode_request(TALLOC_CTX *mem_ctx,
bb7cd1
             break;
bb7cd1
         case BE_REQ_BY_CERT:
bb7cd1
             if (req_input->type == REQ_INP_CERT) {
bb7cd1
-            ret = ber_printf(ber, "{ees}", INP_CERT, request_type,
bb7cd1
-                                           req_input->inp.cert);
bb7cd1
+                ret = ber_printf(ber, "{ees}", INP_CERT, request_type,
bb7cd1
+                                               req_input->inp.cert);
bb7cd1
             } else {
bb7cd1
                 DEBUG(SSSDBG_OP_FAILURE, "Unexpected input type [%d].\n",
bb7cd1
                                           req_input->type);
bb7cd1
@@ -463,6 +464,11 @@ done:
bb7cd1
  * GroupMemberList ::= SEQUENCE OF OCTET STRING
bb7cd1
  */
bb7cd1
 
bb7cd1
+struct name_list {
bb7cd1
+    char *domain_name;
bb7cd1
+    char *name;
bb7cd1
+};
bb7cd1
+
bb7cd1
 struct resp_attrs {
bb7cd1
     enum response_types response_type;
bb7cd1
     char *domain_name;
bb7cd1
@@ -475,6 +481,7 @@ struct resp_attrs {
bb7cd1
     size_t ngroups;
bb7cd1
     char **groups;
bb7cd1
     struct sysdb_attrs *sysdb_attrs;
bb7cd1
+    char **name_list;
bb7cd1
 };
bb7cd1
 
bb7cd1
 static errno_t get_extra_attrs(BerElement *ber, struct resp_attrs *resp_attrs)
bb7cd1
@@ -782,6 +789,9 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
bb7cd1
     struct resp_attrs *attrs = NULL;
bb7cd1
     char *sid_str;
bb7cd1
     bool is_v1 = false;
bb7cd1
+    char **name_list = NULL;
bb7cd1
+    ber_len_t ber_len;
bb7cd1
+    char *fq_name = NULL;
bb7cd1
 
bb7cd1
     if (retoid == NULL || retdata == NULL) {
bb7cd1
         DEBUG(SSSDBG_OP_FAILURE, "Missing OID or data.\n");
bb7cd1
@@ -947,6 +957,53 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
bb7cd1
                 goto done;
bb7cd1
             }
bb7cd1
             break;
bb7cd1
+        case RESP_NAME_LIST:
bb7cd1
+            tag = ber_scanf(ber, "{");
bb7cd1
+            if (tag == LBER_ERROR) {
bb7cd1
+                DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
bb7cd1
+                ret = EINVAL;
bb7cd1
+                goto done;
bb7cd1
+            }
bb7cd1
+
bb7cd1
+            while (ber_peek_tag(ber, &ber_len) ==  LBER_SEQUENCE) {
bb7cd1
+                tag = ber_scanf(ber, "{aa}", &domain_name, &name);
bb7cd1
+                if (tag == LBER_ERROR) {
bb7cd1
+                    DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
bb7cd1
+                    ret = EINVAL;
bb7cd1
+                    goto done;
bb7cd1
+                }
bb7cd1
+
bb7cd1
+                fq_name = sss_create_internal_fqname(attrs, name, domain_name);
bb7cd1
+                if (fq_name == NULL) {
bb7cd1
+                    DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+                          "sss_create_internal_fqname failed.\n");
bb7cd1
+                    ret = ENOMEM;
bb7cd1
+                    goto done;
bb7cd1
+                }
bb7cd1
+                DEBUG(SSSDBG_TRACE_ALL, "[%s][%s][%s].\n", domain_name, name,
bb7cd1
+                                                           fq_name);
bb7cd1
+
bb7cd1
+                ret = add_string_to_list(attrs, fq_name, &name_list);
bb7cd1
+                ber_memfree(domain_name);
bb7cd1
+                ber_memfree(name);
bb7cd1
+                talloc_free(fq_name);
bb7cd1
+                domain_name = NULL;
bb7cd1
+                name = NULL;
bb7cd1
+                fq_name = NULL;
bb7cd1
+                if (ret != EOK) {
bb7cd1
+                    DEBUG(SSSDBG_OP_FAILURE, "add_to_name_list failed.\n");
bb7cd1
+                    goto done;
bb7cd1
+                }
bb7cd1
+            }
bb7cd1
+
bb7cd1
+            tag = ber_scanf(ber, "}}");
bb7cd1
+            if (tag == LBER_ERROR) {
bb7cd1
+                DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
bb7cd1
+                ret = EINVAL;
bb7cd1
+                goto done;
bb7cd1
+            }
bb7cd1
+            attrs->name_list = name_list;
bb7cd1
+            break;
bb7cd1
         default:
bb7cd1
             DEBUG(SSSDBG_OP_FAILURE, "Unexpected response type [%d].\n",
bb7cd1
                                       type);
bb7cd1
@@ -955,7 +1012,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
bb7cd1
     }
bb7cd1
 
bb7cd1
     attrs->response_type = type;
bb7cd1
-    if (type != RESP_SID) {
bb7cd1
+    if (type != RESP_SID && type != RESP_NAME_LIST) {
bb7cd1
         attrs->domain_name = talloc_strdup(attrs, domain_name);
bb7cd1
         if (attrs->domain_name == NULL) {
bb7cd1
             DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
bb7cd1
@@ -969,6 +1026,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
bb7cd1
 done:
bb7cd1
     ber_memfree(domain_name);
bb7cd1
     ber_memfree(name);
bb7cd1
+    talloc_free(fq_name);
bb7cd1
     ber_free(ber, 1);
bb7cd1
 
bb7cd1
     if (ret == EOK) {
bb7cd1
@@ -1332,6 +1390,7 @@ struct ipa_s2n_get_user_state {
bb7cd1
     struct resp_attrs *attrs;
bb7cd1
     struct resp_attrs *simple_attrs;
bb7cd1
     struct sysdb_attrs *override_attrs;
bb7cd1
+    struct sysdb_attrs *mapped_attrs;
bb7cd1
     int exop_timeout;
bb7cd1
 };
bb7cd1
 
bb7cd1
@@ -1384,6 +1443,11 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx,
bb7cd1
         goto fail;
bb7cd1
     }
bb7cd1
 
bb7cd1
+    if (entry_type == BE_REQ_BY_CERT) {
bb7cd1
+        /* Only REQ_SIMPLE is supported for BE_REQ_BY_CERT */
bb7cd1
+        state->request_type = REQ_SIMPLE;
bb7cd1
+    }
bb7cd1
+
bb7cd1
     ret = s2n_encode_request(state, dom->name, entry_type, state->request_type,
bb7cd1
                              req_input, &bv_req);
bb7cd1
     if (ret != EOK) {
bb7cd1
@@ -1785,6 +1849,43 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
bb7cd1
             goto done;
bb7cd1
         }
bb7cd1
 
bb7cd1
+        if (state->simple_attrs->response_type == RESP_NAME_LIST
bb7cd1
+                && state->req_input->type == REQ_INP_CERT) {
bb7cd1
+            state->mapped_attrs = sysdb_new_attrs(state);
bb7cd1
+            if (state->mapped_attrs == NULL) {
bb7cd1
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
bb7cd1
+                ret = ENOMEM;
bb7cd1
+                goto done;
bb7cd1
+            }
bb7cd1
+
bb7cd1
+            ret = sysdb_attrs_add_base64_blob(state->mapped_attrs,
bb7cd1
+                                              SYSDB_USER_MAPPED_CERT,
bb7cd1
+                                              state->req_input->inp.cert);
bb7cd1
+            if (ret != EOK) {
bb7cd1
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_base64_blob failed.\n");
bb7cd1
+                goto done;
bb7cd1
+            }
bb7cd1
+
bb7cd1
+            subreq = ipa_s2n_get_list_send(state, state->ev,
bb7cd1
+                                           state->ipa_ctx, state->dom,
bb7cd1
+                                           state->sh, state->exop_timeout,
bb7cd1
+                                           BE_REQ_USER,
bb7cd1
+                                           REQ_FULL_WITH_MEMBERS,
bb7cd1
+                                           REQ_INP_NAME,
bb7cd1
+                                           state->simple_attrs->name_list,
bb7cd1
+                                           state->mapped_attrs);
bb7cd1
+            if (subreq == NULL) {
bb7cd1
+                DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+                      "ipa_s2n_get_list_send failed.\n");
bb7cd1
+                ret = ENOMEM;
bb7cd1
+                goto done;
bb7cd1
+            }
bb7cd1
+            tevent_req_set_callback(subreq, ipa_s2n_get_list_done,
bb7cd1
+                                    req);
bb7cd1
+
bb7cd1
+            return;
bb7cd1
+        }
bb7cd1
+
bb7cd1
         break;
bb7cd1
     default:
bb7cd1
         DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected request type.\n");
bb7cd1
-- 
bb7cd1
2.9.3
bb7cd1