URL: https://github.com/SSSD/sssd/pull/5613
Author: pbrezina
 Title: #5613: ipa: read auto_private_groups from id range if available
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5613/head:pr5613
git checkout pr5613
From 8d20780fbe984f1ad47f9e832f772566d0f258a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Wed, 28 Apr 2021 14:17:40 +0200
Subject: [PATCH 1/2] ipa: read auto_private_groups from id range if available

Resolves: https://github.com/SSSD/sssd/issues/4216

:feature: `auto_private_groups` option can be set centrally through
  ID range setting in IPA (see `ipa idrange` commands family)
---
 src/confdb/confdb.h                |  1 +
 src/db/sysdb.h                     | 12 ++++++
 src/db/sysdb_ranges.c              | 46 +++++++++++++++++++++
 src/db/sysdb_subdomains.c          | 66 ++++++++++++++++++++++++++++++
 src/providers/ipa/ipa_common.h     |  1 +
 src/providers/ipa/ipa_idmap.c      | 10 +++++
 src/providers/ipa/ipa_subdomains.c | 54 ++++++++++++++++++------
 src/tests/cmocka/test_ipa_idmap.c  | 28 +++++++------
 src/util/domain_info_utils.c       |  5 +++
 9 files changed, 197 insertions(+), 26 deletions(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 437a473d5e..155b8a9f04 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -354,6 +354,7 @@ enum sss_domain_mpg_mode {
     MPG_DISABLED,
     MPG_ENABLED,
     MPG_HYBRID,
+    MPG_DEFAULT, /* Use default value for given id mapping. */
 };
 
 /**
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 0043ca01d8..94b91cf3fe 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -165,6 +165,7 @@
 #define SYSDB_SECONDARY_BASE_RID "secondaryBaseRID"
 #define SYSDB_DOMAIN_ID "domainID"
 #define SYSDB_ID_RANGE_TYPE "idRangeType"
+#define SYSDB_ID_RANGE_MPG "idRangeMPG"
 
 #define SYSDB_CERTMAP_PRIORITY "priority"
 #define SYSDB_CERTMAP_MATCHING_RULE "matchingRule"
@@ -344,6 +345,7 @@ struct range_info {
     uint32_t secondary_base_rid;
     char *trusted_dom_sid;
     char *range_type;
+    enum sss_domain_mpg_mode mpg_mode;
 };
 
 struct certmap_info {
@@ -563,6 +565,12 @@ errno_t sysdb_subdomain_delete(struct sysdb_ctx *sysdb, const char *name);
 errno_t sysdb_subdomain_content_delete(struct sysdb_ctx *sysdb,
                                        const char *name);
 
+errno_t
+sysdb_subdomain_get_id_by_name(TALLOC_CTX *mem_ctx,
+                               struct sysdb_ctx *sysdb,
+                               const char *name,
+                               const char **_id);
+
 /* The utility function to create a subdomain sss_domain_info object is handy
  * for unit tests, so it should be available in a headerr.
  */
@@ -584,6 +592,10 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
 errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
                              size_t *range_count,
                              struct range_info ***range_list);
+errno_t sysdb_get_range(TALLOC_CTX *mem_ctx,
+                        struct sysdb_ctx *sysdb,
+                        const char *forest,
+                        struct range_info **_range);
 errno_t sysdb_range_create(struct sysdb_ctx *sysdb, struct range_info *range);
 errno_t sysdb_update_ranges(struct sysdb_ctx *sysdb,
                             struct range_info **ranges);
diff --git a/src/db/sysdb_ranges.c b/src/db/sysdb_ranges.c
index be3a0d3722..3172a64939 100644
--- a/src/db/sysdb_ranges.c
+++ b/src/db/sysdb_ranges.c
@@ -54,6 +54,7 @@ errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
                            SYSDB_SECONDARY_BASE_RID,
                            SYSDB_DOMAIN_ID,
                            SYSDB_ID_RANGE_TYPE,
+                           SYSDB_ID_RANGE_MPG,
                            NULL};
     struct range_info **list;
     struct ldb_dn *basedn;
@@ -152,6 +153,9 @@ errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
             }
         }
 
+        tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], SYSDB_ID_RANGE_MPG,
+                                              "default");
+        list[c]->mpg_mode = str_to_domain_mpg_mode(tmp_str);
     }
     list[res->count] = NULL;
 
@@ -164,6 +168,44 @@ errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
     return ret;
 }
 
+errno_t sysdb_get_range(TALLOC_CTX *mem_ctx,
+                        struct sysdb_ctx *sysdb,
+                        const char *forest,
+                        struct range_info **_range)
+{
+    struct range_info **list;
+    struct range_info *range;
+    size_t count;
+    size_t i;
+    errno_t ret;
+
+    ret = sysdb_get_ranges(NULL, sysdb, &count, &list);
+    if (ret != EOK) {
+        return ret;
+    }
+
+    for (i = 0; i < count; i++) {
+        range = list[i];
+        if (range->trusted_dom_sid == NULL) {
+            continue;
+        }
+
+        if (strcmp(range->trusted_dom_sid, forest) != 0) {
+            continue;
+        }
+
+        *_range = talloc_steal(mem_ctx, range);
+        ret = EOK;
+        goto done;
+    }
+
+    ret = ENOENT;
+
+done:
+    talloc_free(list);
+    return ret;
+}
+
 errno_t sysdb_range_create(struct sysdb_ctx *sysdb, struct range_info *range)
 {
     struct ldb_message *msg;
@@ -239,6 +281,10 @@ errno_t sysdb_range_create(struct sysdb_ctx *sysdb, struct range_info *range)
     ret = sysdb_add_string(msg, SYSDB_ID_RANGE_TYPE, range->range_type);
     if (ret) goto done;
 
+    ret = sysdb_add_string(msg, SYSDB_ID_RANGE_MPG,
+                           str_domain_mpg_mode(range->mpg_mode));
+    if (ret) goto done;
+
     ret = ldb_add(sysdb->ldb, msg);
     if (ret) goto done;
 
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index 348f242d08..27c47b2512 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -1130,6 +1130,11 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
                 mpg_flags = LDB_FLAG_MOD_REPLACE;
             }
             break;
+        case MPG_DEFAULT:
+            if (strcasecmp(tmp_str, "default") != 0) {
+                mpg_flags = LDB_FLAG_MOD_REPLACE;
+            }
+            break;
         }
 
         tmp_bool = ldb_msg_find_attr_as_bool(res->msgs[0], SYSDB_SUBDOMAIN_ENUM,
@@ -1394,6 +1399,67 @@ errno_t sysdb_subdomain_content_delete(struct sysdb_ctx *sysdb,
     return sysdb_subdomain_delete_with_filter(sysdb, name, filter);
 }
 
+errno_t
+sysdb_subdomain_get_id_by_name(TALLOC_CTX *mem_ctx,
+                               struct sysdb_ctx *sysdb,
+                               const char *name,
+                               const char **_id)
+{
+    TALLOC_CTX *tmp_ctx;
+    struct ldb_dn *base_dn;
+    const char *attrs[] = {SYSDB_DOMAIN_ID, NULL};
+    struct ldb_message **msgs;
+    const char *id;
+    char *filter;
+    size_t count;
+    errno_t ret;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    base_dn = sysdb_base_dn(sysdb, tmp_ctx);
+    if (base_dn == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    filter = talloc_asprintf(tmp_ctx,
+        "(&(" SYSDB_OBJECTCLASS "=" SYSDB_SUBDOMAIN_CLASS ")(cn=%s))", name);
+    if (filter == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn, LDB_SCOPE_ONELEVEL,
+                             filter, attrs, &count, &msgs);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    if (count != 1) {
+        ret = ERR_MULTIPLE_ENTRIES;
+        goto done;
+    }
+
+    id = ldb_msg_find_attr_as_string(msgs[0], SYSDB_DOMAIN_ID, NULL);
+    if (id == NULL) {
+        ret = ENOENT;
+        goto done;
+    }
+
+    *_id = talloc_steal(mem_ctx, id);
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
+
 errno_t
 sysdb_domain_get_domain_resolution_order(TALLOC_CTX *mem_ctx,
                                          struct sysdb_ctx *sysdb,
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index db382ab8ba..480f7b6644 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -36,6 +36,7 @@
 #define IPA_ID_RANGE_SIZE "ipaIDRangeSize"
 #define IPA_BASE_RID "ipaBaseRID"
 #define IPA_SECONDARY_BASE_RID "ipaSecondaryBaseRID"
+#define IPA_ID_RANGE_MPG "ipaAutoPrivateGroups"
 
 struct ipa_service {
     struct sdap_service *sdap;
diff --git a/src/providers/ipa/ipa_idmap.c b/src/providers/ipa/ipa_idmap.c
index 7e65ed02a4..5d8d56b856 100644
--- a/src/providers/ipa/ipa_idmap.c
+++ b/src/providers/ipa/ipa_idmap.c
@@ -333,6 +333,16 @@ errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx,
             goto done;
         }
 
+        ret = sysdb_attrs_get_string(reply[c], IPA_ID_RANGE_MPG, &value);
+        if (ret == EOK) {
+            r->mpg_mode = str_to_domain_mpg_mode(value);
+        } else if (ret == ENOENT) {
+            r->mpg_mode = MPG_DEFAULT;
+        } else {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
+            goto done;
+        }
+
         ret = get_idmap_data_from_range(r, domain_name, &name1, &sid1, &rid1,
                                         &range1, &mapping1);
         if (ret == ERR_UNSUPPORTED_RANGE_TYPE) {
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 252c25efc9..39b7cf6624 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -408,6 +408,8 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent,
     bool enumerate;
     uint32_t direction;
     struct ldb_message_element *alternative_domain_suffixes = NULL;
+    struct range_info *range;
+    const char *forest_id;
 
     tmp_ctx = talloc_new(parent);
     if (tmp_ctx == NULL) {
@@ -444,18 +446,6 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent,
         goto done;
     }
 
-    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx,
-                                                               name, id);
-    if (use_id_mapping == true) {
-        mpg_mode = MPG_ENABLED;
-    } else {
-        /* Domains that use the POSIX attributes set by the admin must
-         * inherit the MPG setting from the parent domain so that the
-         * auto_private_groups options works for trusted domains as well
-         */
-        mpg_mode = get_domain_mpg_mode(parent);
-    }
-
     ret = ipa_subdom_get_forest(tmp_ctx, sysdb_ctx_get_ldb(parent->sysdb),
                                 attrs, &forest);
     if (ret != EOK) {
@@ -481,6 +471,44 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent,
               "Trust type of [%s]: %s\n", name, ipa_trust_dir2str(direction));
     }
 
+    /* First see if there is an ID range for the domain. */
+    ret = sysdb_get_range(tmp_ctx, parent->sysdb, id, &range);
+    if (ret == ENOENT) {
+        /* Check if there is ID range for the forest root. We need to find the
+         * domain in sysdb since the sss_domain_info object might not be yet
+         * created. */
+        ret = sysdb_subdomain_get_id_by_name(tmp_ctx, parent->sysdb, forest,
+                                             &forest_id);
+        if (ret == EOK) {
+            ret = sysdb_get_range(tmp_ctx, parent->sysdb, forest_id, &range);
+        }
+    }
+    if (ret != EOK && ret != ENOENT) {
+        DEBUG(SSSDBG_TRACE_FUNC, "Unable to find ID range for [%s] [%d]: %s\n",
+              name, ret, sss_strerror(ret));
+    }
+    mpg_mode = ret == EOK ? range->mpg_mode : MPG_DEFAULT;
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Range mpg mode for %s: %s\n",
+          name, str_domain_mpg_mode(mpg_mode));
+
+    if (mpg_mode == MPG_DEFAULT) {
+        use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
+                                                    sdap_idmap_ctx, name, id);
+        if (use_id_mapping == true) {
+            mpg_mode = MPG_ENABLED;
+        } else {
+            /* Domains that use the POSIX attributes set by the admin must
+            * inherit the MPG setting from the parent domain so that the
+            * auto_private_groups options works for trusted domains as well
+            */
+            mpg_mode = get_domain_mpg_mode(parent);
+        }
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Domain mpg mode for %s: %s\n",
+          name, str_domain_mpg_mode(mpg_mode));
+
     ret = sysdb_subdomain_store(parent->sysdb, name, realm, flat,
                                 id, mpg_mode, enumerate, forest,
                                 direction, alternative_domain_suffixes);
@@ -948,7 +976,7 @@ ipa_subdomains_ranges_send(TALLOC_CTX *mem_ctx,
     const char *attrs[] = { OBJECTCLASS, IPA_CN,
                             IPA_BASE_ID, IPA_BASE_RID, IPA_SECONDARY_BASE_RID,
                             IPA_ID_RANGE_SIZE, IPA_TRUSTED_DOMAIN_SID,
-                            IPA_RANGE_TYPE, NULL };
+                            IPA_RANGE_TYPE, IPA_ID_RANGE_MPG, NULL };
 
     req = tevent_req_create(mem_ctx, &state,
                             struct ipa_subdomains_ranges_state);
diff --git a/src/tests/cmocka/test_ipa_idmap.c b/src/tests/cmocka/test_ipa_idmap.c
index dd15b5b132..44418278cb 100644
--- a/src/tests/cmocka/test_ipa_idmap.c
+++ b/src/tests/cmocka/test_ipa_idmap.c
@@ -57,33 +57,35 @@ void test_get_idmap_data_from_range(void **state)
     } d[] = {
         /* working IPA_RANGE_LOCAL range */
         {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, SECONDARY_BASE_RID,
-          NULL, discard_const(IPA_RANGE_LOCAL)},
+          NULL, discard_const(IPA_RANGE_LOCAL), MPG_DEFAULT},
          EOK, DOMAIN_NAME, NULL, 0, {BASE_ID, RANGE_MAX}, true},
         /* working old-style IPA_RANGE_LOCAL range without range type */
         {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, SECONDARY_BASE_RID,
-          NULL, NULL},
+          NULL, NULL, MPG_DEFAULT},
          EOK, DOMAIN_NAME, NULL, 0, {BASE_ID, RANGE_MAX}, true},
         /* old-style IPA_RANGE_LOCAL without SID and secondary base rid */
-        {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, NULL, NULL},
+        {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, NULL, NULL,
+          MPG_DEFAULT},
          EINVAL, NULL, NULL, 0, {0, 0}, false},
         /* old-style range with SID and secondary base rid */
         {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, SECONDARY_BASE_RID,
-          DOMAIN_SID, NULL},
+          DOMAIN_SID, NULL, MPG_DEFAULT},
          EINVAL, NULL, NULL, 0, {0, 0}, false},
         /* working IPA_RANGE_AD_TRUST range */
         {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, DOMAIN_SID,
-          discard_const(IPA_RANGE_AD_TRUST)},
+          discard_const(IPA_RANGE_AD_TRUST), MPG_DEFAULT},
          EOK, DOMAIN_SID, DOMAIN_SID, BASE_RID, {BASE_ID, RANGE_MAX}, false},
         /* working old-style IPA_RANGE_AD_TRUST range without range type */
-        {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, DOMAIN_SID, NULL},
+        {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, DOMAIN_SID, NULL,
+          MPG_DEFAULT},
          EOK, DOMAIN_SID, DOMAIN_SID, BASE_RID, {BASE_ID, RANGE_MAX}, false},
         /* working IPA_RANGE_AD_TRUST_POSIX range */
         {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, DOMAIN_SID,
-          discard_const(IPA_RANGE_AD_TRUST_POSIX)},
+          discard_const(IPA_RANGE_AD_TRUST_POSIX), MPG_DEFAULT},
          EOK, DOMAIN_SID, DOMAIN_SID, 0, {BASE_ID, RANGE_MAX}, true},
         /* IPA_RANGE_AD_TRUST range  with unsupported type */
         {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, DOMAIN_SID,
-          discard_const("unsupported-range")},
+          discard_const("unsupported-range"), MPG_DEFAULT},
          ERR_UNSUPPORTED_RANGE_TYPE, NULL, NULL, 0, {0, 0}, false},
         {{0}, 0, NULL, NULL, 0, {0, 0}, false}
     };
@@ -275,11 +277,11 @@ void test_ipa_ranges_parse_results(void **state)
     struct sysdb_attrs *reply[5];
     struct range_info **range_list;
     struct range_info r[5] = {
-        { discard_const("range1"), 1000, 500, 0, 1000, discard_const("S-1-2-1"), discard_const(IPA_RANGE_AD_TRUST) },
-        { discard_const("range2"), 2000, 500, 0, 2000, discard_const("S-1-2-2"), discard_const(IPA_RANGE_AD_TRUST) },
-        { discard_const("range3"), 3000, 500, 0, 3000, discard_const("S-1-2-3"), discard_const("unsupported-type") },
-        { discard_const("range4"), 4000, 500, 0, 4000, discard_const("S-1-2-4"), discard_const(IPA_RANGE_AD_TRUST) },
-        { discard_const("range5"), 5000, 500, 0, 5000, discard_const("S-1-2-5"), discard_const(IPA_RANGE_AD_TRUST) }
+        { discard_const("range1"), 1000, 500, 0, 1000, discard_const("S-1-2-1"), discard_const(IPA_RANGE_AD_TRUST), MPG_DEFAULT },
+        { discard_const("range2"), 2000, 500, 0, 2000, discard_const("S-1-2-2"), discard_const(IPA_RANGE_AD_TRUST), MPG_DEFAULT },
+        { discard_const("range3"), 3000, 500, 0, 3000, discard_const("S-1-2-3"), discard_const("unsupported-type"), MPG_DEFAULT },
+        { discard_const("range4"), 4000, 500, 0, 4000, discard_const("S-1-2-4"), discard_const(IPA_RANGE_AD_TRUST), MPG_DEFAULT },
+        { discard_const("range5"), 5000, 500, 0, 5000, discard_const("S-1-2-5"), discard_const(IPA_RANGE_AD_TRUST), MPG_DEFAULT }
     };
 
     for (c = 0; c < count; c++) {
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 57157861ea..26e3ed054e 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -980,6 +980,8 @@ const char *str_domain_mpg_mode(enum sss_domain_mpg_mode mpg_mode)
         return "false";
     case MPG_HYBRID:
         return "hybrid";
+    case MPG_DEFAULT:
+        return "default";
     }
 
     return NULL;
@@ -993,8 +995,11 @@ enum sss_domain_mpg_mode str_to_domain_mpg_mode(const char *str_mpg_mode)
         return MPG_ENABLED;
     } else if (strcasecmp(str_mpg_mode, "HYBRID") == 0) {
         return MPG_HYBRID;
+    } else if (strcasecmp(str_mpg_mode, "DEFAULT") == 0) {
+        return MPG_DEFAULT;
     }
 
+
     DEBUG(SSSDBG_MINOR_FAILURE,
           "Invalid value for %s\n, assuming disabled",
           SYSDB_SUBDOMAIN_MPG);

From ad6ba7aec2c76b4e77323f26861914cf4a99b5ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Fri, 14 May 2021 15:16:04 +0200
Subject: [PATCH 2/2] cache_req: consider mpg_mode of each domain

Before this patch the mpg_mode == hybrid was used only if the main domain
had this mode set. This fails in multi domain environments as well as with
subdomains.

Now we lookup the hybrid object in each domain that has the hybrid mode
enabled.
---
 src/responder/common/cache_req/cache_req.c    |  5 +++++
 src/responder/common/cache_req/cache_req.h    |  4 ++++
 .../common/cache_req/cache_req_data.c         | 13 ++++++++++++
 .../common/cache_req/cache_req_private.h      |  3 +++
 src/responder/nss/nss_get_object.c            | 21 ++++++++++++++++++-
 5 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c
index abff0d4957..f1b63d9de1 100644
--- a/src/responder/common/cache_req/cache_req.c
+++ b/src/responder/common/cache_req/cache_req.c
@@ -259,6 +259,11 @@ cache_req_validate_domain(struct cache_req *cr,
         return false;
     }
 
+    ok = !cr->data->hybrid_lookup || domain->mpg_mode == MPG_HYBRID;
+    if (ok == false) {
+        return false;
+    }
+
     return true;
 }
 
diff --git a/src/responder/common/cache_req/cache_req.h b/src/responder/common/cache_req/cache_req.h
index d301a076e4..d5c25ccf04 100644
--- a/src/responder/common/cache_req/cache_req.h
+++ b/src/responder/common/cache_req/cache_req.h
@@ -175,6 +175,10 @@ void
 cache_req_data_set_propogate_offline_status(struct cache_req_data *data,
                                             bool propogate_offline_status);
 
+void
+cache_req_data_set_hybrid_lookup(struct cache_req_data *data,
+                                 bool hybrid_lookup);
+
 enum cache_req_type
 cache_req_data_get_type(struct cache_req_data *data);
 
diff --git a/src/responder/common/cache_req/cache_req_data.c b/src/responder/common/cache_req/cache_req_data.c
index fe9f3db298..b82688bdca 100644
--- a/src/responder/common/cache_req/cache_req_data.c
+++ b/src/responder/common/cache_req/cache_req_data.c
@@ -467,6 +467,19 @@ cache_req_data_set_propogate_offline_status(struct cache_req_data *data,
     data->propogate_offline_status = propogate_offline_status;
 }
 
+void
+cache_req_data_set_hybrid_lookup(struct cache_req_data *data,
+                                 bool hybrid_lookup)
+{
+    if (data == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "cache_req_data should never be NULL\n");
+        return;
+    }
+
+    data->hybrid_lookup = hybrid_lookup;
+}
+
+
 enum cache_req_type
 cache_req_data_get_type(struct cache_req_data *data)
 {
diff --git a/src/responder/common/cache_req/cache_req_private.h b/src/responder/common/cache_req/cache_req_private.h
index 2d52e7600b..8ce10c2fbd 100644
--- a/src/responder/common/cache_req/cache_req_private.h
+++ b/src/responder/common/cache_req/cache_req_private.h
@@ -106,6 +106,9 @@ struct cache_req_data {
 
     /* if set, ERR_OFFLINE is returned if data provider is offline */
     bool propogate_offline_status;
+
+    /* if set, only domains with MPG_HYBRID are searched */
+    bool hybrid_lookup;
 };
 
 struct tevent_req *
diff --git a/src/responder/nss/nss_get_object.c b/src/responder/nss/nss_get_object.c
index 3a8a7c3ea5..30d8cb7e15 100644
--- a/src/responder/nss/nss_get_object.c
+++ b/src/responder/nss/nss_get_object.c
@@ -171,6 +171,8 @@ hybrid_domain_retry_data(TALLOC_CTX *mem_ctx,
                                           input_name);
     }
 
+    cache_req_data_set_hybrid_lookup(hybrid_data, true);
+
     return hybrid_data;
 }
 
@@ -255,6 +257,7 @@ struct nss_get_object_state {
 };
 
 static void nss_get_object_done(struct tevent_req *subreq);
+static bool nss_is_hybrid_object_enabled(struct sss_domain_info *domains);
 static errno_t nss_get_hybrid_object_step(struct tevent_req *req);
 static void nss_get_hybrid_object_done(struct tevent_req *subreq);
 static void nss_get_hybrid_gid_verify_done(struct tevent_req *subreq);
@@ -335,8 +338,10 @@ static void nss_get_object_done(struct tevent_req *subreq)
     ret = cache_req_single_domain_recv(state, subreq, &state->result);
     talloc_zfree(subreq);
 
+    /* Try to process hybrid object if any domain enables it. This will issue a
+     * cache_req that will iterate only over domains with MPG_HYBRID. */
     if (ret == ENOENT
-            && state->nss_ctx->rctx->domains->mpg_mode == MPG_HYBRID) {
+            && nss_is_hybrid_object_enabled(state->nss_ctx->rctx->domains)) {
         retry_ret = nss_get_hybrid_object_step(req);
         if (retry_ret == EAGAIN) {
             /* Retrying hybrid search */
@@ -387,6 +392,20 @@ static void nss_get_object_finish_req(struct tevent_req *req,
     }
 }
 
+static bool nss_is_hybrid_object_enabled(struct sss_domain_info *domains)
+{
+    struct sss_domain_info *dom;
+
+    for (dom = domains; dom != NULL;
+             dom = get_next_domain(dom, SSS_GND_DESCEND)) {
+        if (dom->mpg_mode == MPG_HYBRID) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 static errno_t nss_get_hybrid_object_step(struct tevent_req *req)
 {
     struct tevent_req *subreq;
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to