Hi,

this patch-set should solve https://fedorahosted.org/sssd/ticket/2481
"ID Views implementation does not support IPA user&group overrides". It
depends on the already commit patches which bring back ldap_user_uuid
and ldap_group_uuid and "sysdb: add sysdb_search_object_by_uuid()" which
is still under review.

Most of the patches adds support for UUIDs here and there, The main part
of the work is done in the 0006 where the user and group lookup request
is extended in a similar way like for AD users where the overrides are
checked first, then the original object and eventually a final lookup in
the override tree. I will file a ticket to refactor the code so that code
paths for IPA and AD users are unified but for the time being I think
it is better to have them separate so that changes in one path do not
break the other path.

bye,
Sumit
From a2e39b9780727ea75f0a89c6f1cf6d54a3f2d87e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Thu, 6 Nov 2014 13:13:27 +0100
Subject: [PATCH 1/7] ipa: add split_ipa_anchor()

This call extracts the domain and the UUID part from an IPA override
anchor.

Related to https://fedorahosted.org/sssd/ticket/2481
---
 Makefile.am                         |  2 ++
 src/providers/ipa/ipa_id.h          |  2 ++
 src/providers/ipa/ipa_utils.c       | 63 +++++++++++++++++++++++++++++++++++++
 src/tests/cmocka/test_sysdb_views.c | 32 +++++++++++++++++++
 4 files changed, 99 insertions(+)
 create mode 100644 src/providers/ipa/ipa_utils.c

diff --git a/Makefile.am b/Makefile.am
index b85341f..c083a2e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2066,6 +2066,7 @@ endif # BUILD_IFP
 
 test_sysdb_views_SOURCES = \
     src/tests/cmocka/test_sysdb_views.c \
+    src/providers/ipa/ipa_utils.c \
     $(NULL)
 test_sysdb_views_CFLAGS = \
     $(AM_CFLAGS) \
@@ -2388,6 +2389,7 @@ libsss_ipa_la_SOURCES = \
     src/providers/ipa/ipa_subdomains_id.c \
     src/providers/ipa/ipa_subdomains_ext_groups.c \
     src/providers/ipa/ipa_views.c \
+    src/providers/ipa/ipa_utils.c \
     src/providers/ipa/ipa_s2n_exop.c \
     src/providers/ipa/ipa_hbac_hosts.c \
     src/providers/ipa/ipa_hbac_private.h \
diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
index e13aded..033ac40 100644
--- a/src/providers/ipa/ipa_id.h
+++ b/src/providers/ipa/ipa_id.h
@@ -103,4 +103,6 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX 
*memctx,
 
 errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out);
 
+errno_t split_ipa_anchor(TALLOC_CTX *mem_ctx, const char *anchor,
+                         char **_anchor_domain, char **_ipa_uuid);
 #endif
diff --git a/src/providers/ipa/ipa_utils.c b/src/providers/ipa/ipa_utils.c
new file mode 100644
index 0000000..86ba51c
--- /dev/null
+++ b/src/providers/ipa/ipa_utils.c
@@ -0,0 +1,63 @@
+/*
+    SSSD
+
+    IPA Module utility functions
+
+    Authors:
+        Sumit Bose <sb...@redhat.com>
+
+    Copyright (C) 2014 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+
+#define OVERRIDE_ANCHOR_IPA_PREFIX ":IPA:"
+#define OVERRIDE_ANCHOR_IPA_PREFIX_LEN (sizeof(OVERRIDE_ANCHOR_IPA_PREFIX) -1 )
+
+errno_t split_ipa_anchor(TALLOC_CTX *mem_ctx, const char *anchor,
+                         char **_anchor_domain, char **_ipa_uuid)
+{
+    const char *sep;
+
+    if (anchor == NULL) {
+        return EINVAL;
+    }
+    if (strncmp(OVERRIDE_ANCHOR_IPA_PREFIX, anchor,
+                OVERRIDE_ANCHOR_IPA_PREFIX_LEN) != 0) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "No IPA anchor [%s].\n", anchor);
+        return ENOMSG;
+    }
+
+    sep = strchr(anchor + OVERRIDE_ANCHOR_IPA_PREFIX_LEN, ':');
+    if (sep == NULL || sep[1] == '\0') {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Broken IPA anchor [%s].\n", anchor);
+        return EINVAL;
+    }
+
+    *_anchor_domain = talloc_strndup(mem_ctx,
+                                 anchor + OVERRIDE_ANCHOR_IPA_PREFIX_LEN,
+                                 sep - anchor - 
OVERRIDE_ANCHOR_IPA_PREFIX_LEN);
+    *_ipa_uuid = talloc_strdup(mem_ctx, sep + 1);
+
+    if (*_anchor_domain == NULL || *_ipa_uuid == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
+        talloc_free(*_anchor_domain);
+        talloc_free(*_ipa_uuid);
+        return ENOMEM;
+    }
+
+    return EOK;
+}
diff --git a/src/tests/cmocka/test_sysdb_views.c 
b/src/tests/cmocka/test_sysdb_views.c
index 56f2de1..4f2d37b 100644
--- a/src/tests/cmocka/test_sysdb_views.c
+++ b/src/tests/cmocka/test_sysdb_views.c
@@ -29,6 +29,7 @@
 #include <popt.h>
 
 #include "tests/cmocka/common_mock.h"
+#include "providers/ipa/ipa_id.h"
 
 #define TESTS_PATH "tests_sysdb_views"
 #define TEST_CONF_FILE "tests_conf.ldb"
@@ -265,6 +266,35 @@ void test_sysdb_add_overrides_to_object(void **state)
     assert_int_equal(ldb_val_string_cmp(&el->values[1], "OVERRIDEKEY2"), 0);
 }
 
+void test_split_ipa_anchor(void **state)
+{
+    int ret;
+    char *dom;
+    char *uuid;
+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                         struct 
sysdb_test_ctx);
+
+    ret = split_ipa_anchor(test_ctx, NULL, &dom, &uuid);
+    assert_int_equal(ret, EINVAL);
+
+    ret = split_ipa_anchor(test_ctx, "fwfkwjfkw", &dom, &uuid);
+    assert_int_equal(ret, ENOMSG);
+
+    ret = split_ipa_anchor(test_ctx, ":IPA:", &dom, &uuid);
+    assert_int_equal(ret, EINVAL);
+
+    ret = split_ipa_anchor(test_ctx, ":IPA:abc", &dom, &uuid);
+    assert_int_equal(ret, EINVAL);
+
+    ret = split_ipa_anchor(test_ctx, ":IPA:abc:", &dom, &uuid);
+    assert_int_equal(ret, EINVAL);
+
+    ret = split_ipa_anchor(test_ctx, ":IPA:abc:def", &dom, &uuid);
+    assert_int_equal(ret, EOK);
+    assert_string_equal(dom, "abc");
+    assert_string_equal(uuid, "def");
+}
+
 int main(int argc, const char *argv[])
 {
     int rv;
@@ -284,6 +314,8 @@ int main(int argc, const char *argv[])
                                  test_sysdb_setup, test_sysdb_teardown),
         unit_test_setup_teardown(test_sysdb_add_overrides_to_object,
                                  test_sysdb_setup, test_sysdb_teardown),
+        unit_test_setup_teardown(test_split_ipa_anchor,
+                                 test_sysdb_setup, test_sysdb_teardown),
     };
 
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-- 
1.8.3.1

From df4786e754fa7d2ee47c2c6740fc6bca2a94ae30 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 7 Nov 2014 13:55:01 +0100
Subject: [PATCH 2/7] LDAP: add support for lookups by UUID

Related to https://fedorahosted.org/sssd/ticket/2481
---
 src/providers/data_provider.h |  2 ++
 src/providers/ldap/ldap_id.c  | 58 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index e1cb4be..5df493e 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -127,6 +127,7 @@
 #define BE_FILTER_IDNUM 2
 #define BE_FILTER_ENUM 3
 #define BE_FILTER_SECID 4
+#define BE_FILTER_UUID 5
 
 #define BE_REQ_USER          0x0001
 #define BE_REQ_GROUP         0x0002
@@ -139,6 +140,7 @@
 #define BE_REQ_HOST          0x0010
 #define BE_REQ_BY_SECID      0x0011
 #define BE_REQ_USER_AND_GROUP 0x0012
+#define BE_REQ_BY_UUID      0x0013
 #define BE_REQ_TYPE_MASK     0x00FF
 #define BE_REQ_FAST          0x1000
 
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index e8b3a0e..2e58f4e 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -179,6 +179,20 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
             goto done;
         }
         break;
+    case BE_FILTER_UUID:
+        attr_name = ctx->opts->user_map[SDAP_AT_USER_UUID].name;
+        if (attr_name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "UUID search not configured for this backend.\n");
+            ret = EINVAL;
+            goto done;
+        }
+
+        ret = sss_filter_sanitize(state, name, &clean_name);
+        if (ret != EOK) {
+            goto done;
+        }
+        break;
     default:
         ret = EINVAL;
         goto done;
@@ -458,8 +472,9 @@ static void users_get_done(struct tevent_req *subreq)
             break;
 
         case BE_FILTER_SECID:
-            /* Since it is not clear if the SID belongs to a user or a group
-             * we have nothing to do here. */
+        case BE_FILTER_UUID:
+            /* Since it is not clear if the SID/UUID belongs to a user or a
+             * group we have nothing to do here. */
             break;
 
         default:
@@ -635,6 +650,20 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
             goto done;
         }
         break;
+    case BE_FILTER_UUID:
+        attr_name = ctx->opts->group_map[SDAP_AT_GROUP_UUID].name;
+        if (attr_name == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "UUID search not configured for this backend.\n");
+            ret = EINVAL;
+            goto done;
+        }
+
+        ret = sss_filter_sanitize(state, name, &clean_name);
+        if (ret != EOK) {
+            goto done;
+        }
+        break;
     default:
         ret = EINVAL;
         goto done;
@@ -884,8 +913,9 @@ static void groups_get_done(struct tevent_req *subreq)
             break;
 
         case BE_FILTER_SECID:
-            /* Since it is not clear if the SID belongs to a user or a group
-             * we have nothing to do here. */
+        case BE_FILTER_UUID:
+            /* Since it is not clear if the SID/UUID belongs to a user or a
+             * group we have nothing to do here. */
             break;
 
         default:
@@ -1401,7 +1431,8 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
             goto done;
         }
 
-        if (ar->filter_type == BE_FILTER_SECID) {
+        if (ar->filter_type == BE_FILTER_SECID
+                || ar->filter_type == BE_FILTER_UUID) {
             ret = EINVAL;
             state->err = "Invalid filter type";
             goto done;
@@ -1430,6 +1461,21 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
                                          noexist_delete);
         break;
 
+    case BE_REQ_BY_UUID:
+        if (ar->filter_type != BE_FILTER_UUID) {
+            ret = EINVAL;
+            state->err = "Invalid filter type";
+            goto done;
+        }
+
+        subreq = get_user_and_group_send(breq, be_ctx->ev, id_ctx,
+                                         sdom, conn,
+                                         ar->filter_value,
+                                         ar->filter_type,
+                                         ar->attr_type,
+                                         noexist_delete);
+        break;
+
     case BE_REQ_USER_AND_GROUP:
         if (!(ar->filter_type == BE_FILTER_NAME ||
               ar->filter_type == BE_FILTER_IDNUM)) {
@@ -1504,6 +1550,8 @@ sdap_handle_acct_req_done(struct tevent_req *subreq)
         break;
     case BE_REQ_BY_SECID:
         /* Fallthrough */
+    case BE_REQ_BY_UUID:
+        /* Fallthrough */
     case BE_REQ_USER_AND_GROUP:
         err = "Lookup by SID failed";
         ret = sdap_get_user_and_group_recv(subreq, &state->dp_error,
-- 
1.8.3.1

From c4999c38d1f24612d1b59f13135d14d07bb88f4a Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 7 Nov 2014 21:33:36 +0100
Subject: [PATCH 3/7] LDAP: always store UUID if available

Related to https://fedorahosted.org/sssd/ticket/2481
---
 src/providers/ldap/sdap_async_groups.c | 20 ++++++++++++++++++++
 src/providers/ldap/sdap_async_users.c  | 19 +++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/src/providers/ldap/sdap_async_groups.c 
b/src/providers/ldap/sdap_async_groups.c
index a82d2aa..dc1b60d 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -511,6 +511,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
     bool posix_group;
     bool use_id_mapping;
     char *sid_str;
+    const char *uuid;
     struct sss_domain_info *subdomain;
     int32_t ad_group_type;
 
@@ -547,6 +548,25 @@ static int sdap_save_group(TALLOC_CTX *memctx,
         sid_str = NULL;
     }
 
+    /* Always store UUID if available */
+    ret = sysdb_attrs_get_string(attrs,
+                                 opts->group_map[SDAP_AT_GROUP_UUID].sys_name,
+                                 &uuid);
+    if (ret == EOK) {
+        ret = sysdb_attrs_add_string(group_attrs, SYSDB_UUID, uuid);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_MINOR_FAILURE, "Could not add UUID string: [%s]\n",
+                                         strerror(ret));
+            goto done;
+        }
+    } else if (ret == ENOENT) {
+        DEBUG(SSSDBG_TRACE_ALL, "UUID not available for group [%s].\n",
+                                 group_name);
+    } else {
+        DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify UUID [%s]\n",
+                                     strerror(ret));
+    }
+
     /* If this object has a SID available, we will determine the correct
      * domain by its SID. */
     if (sid_str != NULL) {
diff --git a/src/providers/ldap/sdap_async_users.c 
b/src/providers/ldap/sdap_async_users.c
index 2331ba9..c6da5c1 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -140,6 +140,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
     TALLOC_CTX *tmpctx = NULL;
     bool use_id_mapping;
     char *sid_str;
+    const char *uuid;
     char *dom_sid_str = NULL;
     struct sss_domain_info *subdomain;
 
@@ -177,6 +178,24 @@ int sdap_save_user(TALLOC_CTX *memctx,
         sid_str = NULL;
     }
 
+    /* Always store UUID if available */
+    ret = sysdb_attrs_get_string(attrs,
+                                 opts->user_map[SDAP_AT_USER_UUID].sys_name,
+                                 &uuid);
+    if (ret == EOK) {
+        ret = sysdb_attrs_add_string(user_attrs, SYSDB_UUID, uuid);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_MINOR_FAILURE, "Could not add UUID string: [%s]\n",
+                                         strerror(ret));
+            goto done;
+        }
+    } else if (ret == ENOENT) {
+        DEBUG(SSSDBG_TRACE_ALL, "UUID not available for user.\n");
+    } else {
+        DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify UUID [%s]\n",
+                                     strerror(ret));
+    }
+
     /* If this object has a SID available, we will determine the correct
      * domain by its SID. */
     if (sid_str != NULL) {
-- 
1.8.3.1

From 0696db3558c817c61ffae5b00e34ad2a0be579f1 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 7 Nov 2014 15:05:41 +0100
Subject: [PATCH 4/7] ipa: add get_be_acct_req_for_uuid()

This new call creates the needs data for a lookup by UUID which is
needed when trying to find the original object for an IPA override
object.

Related to https://fedorahosted.org/sssd/ticket/2481
---
 src/providers/ipa/ipa_id.h    |  4 ++++
 src/providers/ipa/ipa_views.c | 42 ++++++++++++++++++++++++++++++++++++------
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
index 033ac40..890d00d 100644
--- a/src/providers/ipa/ipa_id.h
+++ b/src/providers/ipa/ipa_id.h
@@ -83,6 +83,10 @@ errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const 
char *sid,
                                 const char *domain_name,
                                 struct be_acct_req **_ar);
 
+errno_t get_be_acct_req_for_uuid(TALLOC_CTX *mem_ctx, const char *uuid,
+                                 const char *domain_name,
+                                 struct be_acct_req **_ar);
+
 struct tevent_req *ipa_get_ad_override_send(TALLOC_CTX *mem_ctx,
                                             struct tevent_context *ev,
                                             struct sdap_id_ctx *sdap_id_ctx,
diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
index 2eb7721..ee58689 100644
--- a/src/providers/ipa/ipa_views.c
+++ b/src/providers/ipa/ipa_views.c
@@ -140,9 +140,10 @@ static errno_t be_acct_req_to_override_filter(TALLOC_CTX 
*mem_ctx,
     return EOK;
 }
 
-errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
-                                const char *domain_name,
-                                struct be_acct_req **_ar)
+static errno_t get_be_acct_req_for_xyz(TALLOC_CTX *mem_ctx, const char *val,
+                                       const char *domain_name,
+                                       int type,
+                                       struct be_acct_req **_ar)
 {
     struct be_acct_req *ar;
 
@@ -152,9 +153,22 @@ errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const 
char *sid,
         return ENOMEM;
     }
 
-    ar->entry_type = BE_REQ_BY_SECID;
-    ar->filter_type = BE_FILTER_SECID;
-    ar->filter_value = talloc_strdup(ar, sid);
+    switch (type) {
+    case BE_REQ_BY_SECID:
+        ar->entry_type = BE_REQ_BY_SECID;
+        ar->filter_type = BE_FILTER_SECID;
+        break;
+    case BE_REQ_BY_UUID:
+        ar->entry_type = BE_REQ_BY_UUID;
+        ar->filter_type = BE_FILTER_UUID;
+        break;
+    default:
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported request type [%d].\n", type);
+        talloc_free(ar);
+        return EINVAL;
+    }
+
+    ar->filter_value = talloc_strdup(ar, val);
     ar->domain = talloc_strdup(ar, domain_name);
     if (ar->filter_value == NULL || ar->domain == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
@@ -168,6 +182,22 @@ errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const 
char *sid,
     return EOK;
 }
 
+errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
+                                const char *domain_name,
+                                struct be_acct_req **_ar)
+{
+    return get_be_acct_req_for_xyz(mem_ctx, sid, domain_name, BE_REQ_BY_SECID,
+                                   _ar);
+}
+
+errno_t get_be_acct_req_for_uuid(TALLOC_CTX *mem_ctx, const char *uuid,
+                                 const char *domain_name,
+                                 struct be_acct_req **_ar)
+{
+    return get_be_acct_req_for_xyz(mem_ctx, uuid, domain_name, BE_REQ_BY_UUID,
+                                   _ar);
+}
+
 struct ipa_get_ad_override_state {
     struct tevent_context *ev;
     struct sdap_id_ctx *sdap_id_ctx;
-- 
1.8.3.1

From c7d8a136959010d92cc733c6096e534c5aa3691f Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 7 Nov 2014 21:34:55 +0100
Subject: [PATCH 5/7] IPA: make get_object_from_cache() public

Related to https://fedorahosted.org/sssd/ticket/2481
---
 src/providers/ipa/ipa_id.h            | 5 +++++
 src/providers/ipa/ipa_subdomains_id.c | 9 +++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
index 890d00d..9d219f2 100644
--- a/src/providers/ipa/ipa_id.h
+++ b/src/providers/ipa/ipa_id.h
@@ -109,4 +109,9 @@ errno_t ipa_subdomain_account_recv(struct tevent_req *req, 
int *dp_error_out);
 
 errno_t split_ipa_anchor(TALLOC_CTX *mem_ctx, const char *anchor,
                          char **_anchor_domain, char **_ipa_uuid);
+
+errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
+                              struct sss_domain_info *dom,
+                              struct be_acct_req *ar,
+                              struct ldb_message **_msg);
 #endif
diff --git a/src/providers/ipa/ipa_subdomains_id.c 
b/src/providers/ipa/ipa_subdomains_id.c
index 0d00d09..dd1eae1 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -848,10 +848,10 @@ done:
     return ret;
 }
 
-static errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
-                                     struct sss_domain_info *dom,
-                                     struct be_acct_req *ar,
-                                     struct ldb_message **_msg)
+errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
+                              struct sss_domain_info *dom,
+                              struct be_acct_req *ar,
+                              struct ldb_message **_msg)
 {
     errno_t ret;
     uint32_t id;
@@ -861,6 +861,7 @@ static errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
                             SYSDB_UIDNUM,
                             SYSDB_SID_STR,
                             SYSDB_OBJECTCLASS,
+                            SYSDB_UUID,
                             NULL };
     char *name;
 
-- 
1.8.3.1

From 1463b471d3fc878c819ff04f08de0825ed637060 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Wed, 5 Nov 2014 15:58:04 +0100
Subject: [PATCH 6/7] IPA: check overrrides for IPA users as well

Currently overrides were only available for sub-domains, e.g. trusted AD
domains. With this patch overrides can be used for IPA users as well.

Related to https://fedorahosted.org/sssd/ticket/2481
---
 src/providers/ipa/ipa_id.c            | 405 +++++++++++++++++++++++++++++++++-
 src/providers/ipa/ipa_subdomains_id.c |  16 ++
 src/providers/ipa/ipa_views.c         |  15 ++
 3 files changed, 434 insertions(+), 2 deletions(-)

diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
index cd65f5b..a9606a9 100644
--- a/src/providers/ipa/ipa_id.c
+++ b/src/providers/ipa/ipa_id.c
@@ -56,6 +56,13 @@ static const char *ipa_account_info_error_text(int ret, int 
*dp_error,
     return default_text;
 }
 
+static struct tevent_req *
+ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
+                             struct ipa_id_ctx *ipa_ctx, struct be_req *be_req,
+                             struct be_acct_req *ar);
+
+static int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error);
+
 static struct tevent_req *ipa_id_get_netgroup_send(TALLOC_CTX *memctx,
                                                    struct tevent_context *ev,
                                                    struct ipa_id_ctx *ipa_ctx,
@@ -100,7 +107,9 @@ void ipa_account_info_handler(struct be_req *breq)
     } else {
         /* any account request is handled by sdap,
          * any invalid request is caught there. */
-        return sdap_handle_account_info(breq, ctx, ctx->conn);
+
+        req = ipa_id_get_account_info_send(breq, be_ctx->ev, ipa_ctx, breq,
+                                           ar);
     }
 
     if (!req) {
@@ -115,13 +124,18 @@ static void ipa_account_info_done(struct tevent_req *req)
     struct be_req *breq = tevent_req_callback_data(req, struct be_req);
     struct be_acct_req *ar = talloc_get_type(be_req_get_data(breq),
                                              struct be_acct_req);
+    struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
     const char *error_text;
     int ret, dp_error;
 
     if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) {
         ret = ipa_id_get_netgroup_recv(req, &dp_error);
     } else {
-        ret = ipa_subdomain_account_recv(req, &dp_error);
+        if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) {
+            ret = ipa_subdomain_account_recv(req, &dp_error);
+        } else {
+            ret = ipa_id_get_account_info_recv(req, &dp_error);
+        }
     }
     talloc_zfree(req);
 
@@ -130,6 +144,393 @@ static void ipa_account_info_done(struct tevent_req *req)
     sdap_handler_done(breq, dp_error, ret, error_text);
 }
 
+struct ipa_id_get_account_info_state {
+    struct tevent_context *ev;
+    struct ipa_id_ctx *ipa_ctx;
+    struct sdap_id_ctx *ctx;
+    struct sdap_id_op *op;
+    struct sysdb_ctx *sysdb;
+    struct sss_domain_info *domain;
+    struct be_req *be_req;
+    struct be_acct_req *ar;
+    const char *realm;
+
+    struct sysdb_attrs *override_attrs;
+    struct ldb_message *obj_msg;
+    int dp_error;
+};
+
+static void ipa_id_get_account_info_connected(struct tevent_req *subreq);
+static void ipa_id_get_account_info_got_override(struct tevent_req *subreq);
+static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req 
*req,
+                                                        struct be_acct_req 
*ar);
+static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq);
+static void ipa_id_get_account_info_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
+                             struct ipa_id_ctx *ipa_ctx, struct be_req *be_req,
+                             struct be_acct_req *ar)
+{
+    int ret;
+    struct tevent_req *req;
+    struct tevent_req *subreq;
+    struct ipa_id_get_account_info_state *state;
+
+    req = tevent_req_create(memctx, &state,
+                            struct ipa_id_get_account_info_state);
+    if (req == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
+        return NULL;
+    }
+
+    state->ev = ev;
+    state->ipa_ctx = ipa_ctx;
+    state->ctx = ipa_ctx->sdap_id_ctx;
+    state->dp_error = DP_ERR_FATAL;
+
+    state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
+    if (state->op == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    state->domain = find_domain_by_name(state->ctx->be->domain,
+                                        ar->domain, true);
+    if (state->domain == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
+        ret = ENOMEM;
+        goto fail;
+    }
+    state->sysdb = state->domain->sysdb;
+    state->be_req = be_req;
+    state->ar = ar;
+    state->realm = dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
+                                     IPA_KRB5_REALM);
+    if (state->realm == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
+        ret = EINVAL;
+        goto fail;
+    }
+
+    /* We can skip the override lookup and go directly to the original object
+     * if
+     * - the lookup is by SID
+     * - there is no view set of it is the default view
+     * - if the EXTRA_INPUT_MAYBE_WITH_VIEW flag is not set
+     */
+    if (state->ipa_ctx->view_name == NULL
+            || state->ar->filter_type == BE_FILTER_SECID
+            || strcmp(state->ipa_ctx->view_name,
+                      SYSDB_DEFAULT_VIEW_NAME) == 0
+            || strcmp(state->ar->extra_value,
+                      EXTRA_INPUT_MAYBE_WITH_VIEW) != 0 ) {
+        ret = ipa_id_get_account_info_get_original_step(req, ar);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "ipa_subdomain_account_get_original_step failed.\n");
+            goto fail;
+        }
+    } else {
+        subreq = sdap_id_op_connect_send(state->op, state, &ret);
+        if (subreq == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n");
+            goto fail;
+        }
+        tevent_req_set_callback(subreq, ipa_id_get_account_info_connected, 
req);
+    }
+
+    return req;
+
+fail:
+    tevent_req_error(req, ret);
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static void ipa_id_get_account_info_connected(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                struct tevent_req);
+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
+                                          struct 
ipa_id_get_account_info_state);
+    int dp_error = DP_ERR_FATAL;
+    int ret;
+
+    ret = sdap_id_op_connect_recv(subreq, &dp_error);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n");
+        goto fail;
+    }
+
+    subreq = ipa_get_ad_override_send(state, state->ev, state->ctx,
+                                      state->ipa_ctx->ipa_options, 
state->realm,
+                                      state->ipa_ctx->view_name, state->ar);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    tevent_req_set_callback(subreq, ipa_id_get_account_info_got_override, req);
+
+    return;
+
+fail:
+    state->dp_error = dp_error;
+    tevent_req_error(req, ret);
+    return;
+}
+
+static void ipa_id_get_account_info_got_override(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                struct tevent_req);
+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
+                                          struct 
ipa_id_get_account_info_state);
+    int dp_error = DP_ERR_FATAL;
+    int ret;
+    const char *anchor = NULL;
+    char *anchor_domain;
+    char *ipa_uuid;
+
+    ret = ipa_get_ad_override_recv(subreq, &dp_error, state,
+                                   &state->override_attrs);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
+        goto fail;
+    }
+
+    if (state->override_attrs != NULL) {
+        ret = sysdb_attrs_get_string(state->override_attrs,
+                                     SYSDB_OVERRIDE_ANCHOR_UUID,
+                                     &anchor);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
+            goto fail;
+        }
+
+        ret = split_ipa_anchor(state, anchor, &anchor_domain, &ipa_uuid);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Unsupported override anchor [%s].\n", anchor);
+            ret = EINVAL;
+            goto fail;
+        }
+
+        if (strcmp(state->ar->domain, anchor_domain) == 0) {
+
+            ret = get_be_acct_req_for_uuid(state, ipa_uuid,
+                                           state->ar->domain,
+                                           &state->ar);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
+                goto fail;
+            }
+        } else {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  "Anchor from a different domain [%s], expected [%s]. " \
+                  "This is currently not supported, continue lookup in " \
+                  "local IPA domain.\n",
+                  anchor_domain, state->ar->domain);
+        }
+    }
+
+    ret = ipa_id_get_account_info_get_original_step(req, state->ar);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "ipa_subdomain_account_get_original_step failed.\n");
+        goto fail;
+    }
+
+    return;
+
+fail:
+    state->dp_error = dp_error;
+    tevent_req_error(req, ret);
+    return;
+}
+
+static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req 
*req,
+                                                         struct be_acct_req 
*ar)
+{
+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
+                                          struct 
ipa_id_get_account_info_state);
+    struct tevent_req *subreq;
+    int ret;
+
+    subreq = sdap_handle_acct_req_send(state, state->be_req, ar,
+                                       state->ipa_ctx->sdap_id_ctx,
+                                       state->ipa_ctx->sdap_id_ctx->opts->sdom,
+                                       state->ipa_ctx->sdap_id_ctx->conn, 
true);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n");
+        return ENOMEM;
+    }
+    tevent_req_set_callback(subreq, ipa_id_get_account_info_orig_done, req);
+
+    return EOK;
+}
+
+static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                struct tevent_req);
+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
+                                          struct 
ipa_id_get_account_info_state);
+    int dp_error = DP_ERR_FATAL;
+    int ret;
+    const char *uuid;
+    const char *class;
+    enum sysdb_member_type type;
+
+    ret = sdap_handle_acct_req_recv(subreq, &dp_error, NULL, NULL);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret);
+        goto fail;
+    }
+
+    ret = get_object_from_cache(state, state->domain, state->ar,
+                                &state->obj_msg);
+    if (ret == ENOENT) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "Object not found, ending request\n");
+        tevent_req_done(req);
+        return;
+    } else if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
+        goto fail;
+    }
+
+    if (state->override_attrs == NULL) {
+        uuid = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_UUID, NULL);
+        if (uuid == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find a UUID.\n");
+            ret = EINVAL;
+            goto fail;
+        }
+
+        ret = get_be_acct_req_for_uuid(state, uuid, state->domain->name,
+                                       &state->ar);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
+            goto fail;
+        }
+
+        subreq = ipa_get_ad_override_send(state, state->ev,
+                                          state->ipa_ctx->sdap_id_ctx,
+                                          state->ipa_ctx->ipa_options,
+                                          state->realm,
+                                          state->ipa_ctx->view_name,
+                                          state->ar);
+        if (subreq == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
+            ret = ENOMEM;
+            goto fail;
+        }
+        tevent_req_set_callback(subreq, ipa_id_get_account_info_done, req);
+        return;
+    } else {
+        class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCLASS,
+                                            NULL);
+        if (class == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find an objectclass.\n");
+            ret = EINVAL;
+            goto fail;
+        }
+
+        if (strcmp(class, SYSDB_USER_CLASS) == 0) {
+            type = SYSDB_MEMBER_USER;
+        } else {
+            type = SYSDB_MEMBER_GROUP;
+        }
+
+        ret = sysdb_store_override(state->domain, state->ipa_ctx->view_name,
+                                   type,
+                                   state->override_attrs, state->obj_msg->dn);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
+            goto fail;
+        }
+    }
+
+    state->dp_error = DP_ERR_OK;
+    tevent_req_done(req);
+    return;
+
+fail:
+    state->dp_error = dp_error;
+    tevent_req_error(req, ret);
+    return;
+}
+
+static void ipa_id_get_account_info_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                struct tevent_req);
+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
+                                          struct 
ipa_id_get_account_info_state);
+    int dp_error = DP_ERR_FATAL;
+    int ret;
+    const char *class;
+    enum sysdb_member_type type;
+
+    ret = ipa_get_ad_override_recv(subreq, &dp_error, state,
+                                   &state->override_attrs);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
+        goto fail;
+    }
+
+    class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCLASS,
+                                        NULL);
+    if (class == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find an objectclass.\n");
+        ret = EINVAL;
+        goto fail;
+    }
+
+    if (strcmp(class, SYSDB_USER_CLASS) == 0) {
+        type = SYSDB_MEMBER_USER;
+    } else {
+        type = SYSDB_MEMBER_GROUP;
+    }
+
+    ret = sysdb_store_override(state->domain, state->ipa_ctx->view_name,
+                               type,
+                               state->override_attrs, state->obj_msg->dn);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
+        goto fail;
+    }
+
+    state->dp_error = DP_ERR_OK;
+    tevent_req_done(req);
+    return;
+
+fail:
+    state->dp_error = dp_error;
+    tevent_req_error(req, ret);
+    return;
+}
+
+static int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error)
+{
+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
+                                          struct 
ipa_id_get_account_info_state);
+
+    if (dp_error) {
+        *dp_error = state->dp_error;
+    }
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    return EOK;
+}
 
 /* Request for netgroups
  * - first start here and then go to ipa_netgroups.c
diff --git a/src/providers/ipa/ipa_subdomains_id.c 
b/src/providers/ipa/ipa_subdomains_id.c
index dd1eae1..2f74798 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -881,6 +881,22 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
+    if (ar->filter_type == BE_FILTER_UUID) {
+        ret = sysdb_search_object_by_uuid(mem_ctx, dom, ar->filter_value, 
attrs,
+                                          &res);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "Failed to make request to our cache: [%d]: [%s]\n",
+                   ret, sss_strerror(ret));
+            goto done;
+        }
+
+        *_msg = res->msgs[0];
+
+        ret = EOK;
+        goto done;
+    }
+
     if (ar->filter_type == BE_FILTER_IDNUM) {
         errno = 0;
         id = strtouint32(ar->filter_value, NULL, 10);
diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
index ee58689..c768186 100644
--- a/src/providers/ipa/ipa_views.c
+++ b/src/providers/ipa/ipa_views.c
@@ -125,6 +125,21 @@ static errno_t be_acct_req_to_override_filter(TALLOC_CTX 
*mem_ctx,
         }
         break;
 
+    case BE_FILTER_UUID:
+        if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_BY_UUID) {
+            filter = talloc_asprintf(mem_ctx, 
"(&(objectClass=%s)(%s=:IPA:%s:%s))",
+                       ipa_opts->override_map[IPA_OC_OVERRIDE].name,
+                       
ipa_opts->override_map[IPA_AT_OVERRIDE_ANCHOR_UUID].name,
+                       dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN),
+                       ar->filter_value);
+        } else {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Unexpected entry type [%d] for UUID filter.\n",
+                  ar->entry_type);
+            return EINVAL;
+        }
+        break;
+
     default:
         DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain filter type.\n");
         return EINVAL;
-- 
1.8.3.1

From cf23914f032c1271d46cac74d0947b019000329b Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 7 Nov 2014 21:36:12 +0100
Subject: [PATCH 7/7] Enable views for all domains

Currently views and overrides were only available for sub-domains, this
patch enables the lookup for the configured domains as well.

Related to https://fedorahosted.org/sssd/ticket/2481
---
 src/util/util.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/util/util.h b/src/util/util.h
index ffc8a87..7c335b9 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -574,8 +574,7 @@ errno_t sssd_domain_init(TALLOC_CTX *mem_ctx,
 
 #define IS_SUBDOMAIN(dom) ((dom)->parent != NULL)
 
-/* Currently views are only supported for subdomains */
-#define DOM_HAS_VIEWS(dom) ((dom)->has_views && IS_SUBDOMAIN(dom))
+#define DOM_HAS_VIEWS(dom) ((dom)->has_views)
 
 errno_t sss_write_domain_mappings(struct sss_domain_info *domain);
 
-- 
1.8.3.1

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to