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

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