Hi,

this patch set should solve https://fedorahosted.org/sssd/ticket/3018
by looking up the additional UPN suffixes on the IPA server. If some
were found, enterprise principals are enabled if they are not explicitly
disabled in sssd.conf.

The first patch read the attributes. The second and third patch store
the found suffixes in the cached object of the corresponding domain. So
far this is not strictly needed but maybe it might be handy at some
later time if this data is around. The fourth and fifth patch just add
some getter-calls because some internal data is needed to allow the
sub-domain provider to modify the configuration of the auth provider.
Finally the sixth patch sets the enterprise principal option to true if
there are UPN suffixes and enterprise principals are not explicitly
disabled in sssd.conf.

bye,
Sumit
From 90062aa7ee34b2883c4da81d18a4110410a6f43c Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Thu, 23 Jun 2016 11:58:30 +0200
Subject: [PATCH 1/6] IPA: read ipaNTAdditionalSuffixes for master and trusted
 domains

---
 src/providers/ipa/ipa_subdomains.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/providers/ipa/ipa_subdomains.c 
b/src/providers/ipa/ipa_subdomains.c
index 
cb443db9ca76d844b983e0fb28350a6a955df463..40de7da6e899f00d2b3fd8e44364fc4b00764ce8
 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -40,6 +40,7 @@
 #define IPA_SID "ipaNTSecurityIdentifier"
 #define IPA_TRUSTED_DOMAIN_SID "ipaNTTrustedDomainSID"
 #define IPA_RANGE_TYPE "ipaRangeType"
+#define IPA_ADDITIONAL_SUFFIXES "ipaNTAdditionalSuffixes"
 
 #define IPA_BASE_ID "ipaBaseID"
 #define IPA_ID_RANGE_SIZE "ipaIDRangeSize"
@@ -785,7 +786,8 @@ ipa_subdomains_master_send(TALLOC_CTX *mem_ctx,
     struct tevent_req *subreq;
     struct tevent_req *req;
     errno_t ret;
-    const char *attrs[] = { IPA_CN, IPA_FLATNAME, IPA_SID, NULL };
+    const char *attrs[] = { IPA_CN, IPA_FLATNAME, IPA_SID,
+                            IPA_ADDITIONAL_SUFFIXES, NULL };
 
     req = tevent_req_create(mem_ctx, &state,
                             struct ipa_subdomains_master_state);
@@ -936,7 +938,8 @@ ipa_subdomains_slave_send(TALLOC_CTX *mem_ctx,
     struct tevent_req *req;
     errno_t ret;
     const char *attrs[] = { IPA_CN, IPA_FLATNAME, IPA_TRUSTED_DOMAIN_SID,
-                            IPA_TRUST_DIRECTION, NULL };
+                            IPA_TRUST_DIRECTION, IPA_ADDITIONAL_SUFFIXES,
+                            NULL };
 
     req = tevent_req_create(mem_ctx, &state,
                             struct ipa_subdomains_slave_state);
-- 
2.1.0

From 802cfa810009895f9d507a1d404d93fef9ca4aca Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Thu, 30 Jun 2016 13:48:58 +0200
Subject: [PATCH 2/6] sysdb: add UPN suffix support for the master domain

sysdb_master_domain_update() and sysdb_master_domain_add_info() are now
aware of the UPN suffix attribute.
---
 src/confdb/confdb.h                      |  1 +
 src/db/sysdb.h                           |  4 ++-
 src/db/sysdb_subdomains.c                | 49 ++++++++++++++++++++++++++++++--
 src/providers/ad/ad_id.c                 |  2 +-
 src/providers/ad/ad_subdomains.c         |  2 +-
 src/providers/ipa/ipa_subdomains.c       | 10 ++++++-
 src/tests/cmocka/test_sysdb_subdomains.c | 18 ++++++++----
 7 files changed, 74 insertions(+), 12 deletions(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 
b8ad827b796ecf88d3b8ff3e66e1ebd45913a880..cd5eb039836b53b874af5ceacd43ddbdf2e0fac7
 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -316,6 +316,7 @@ struct sss_domain_info {
      */
     char *forest;
     struct sss_domain_info *forest_root;
+    char **upn_suffixes;
 };
 
 /**
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 
2bc20ff97818655768b0f338e5cf7ed5222315f5..71717c3e11b642001405b9e7db6b556368742193
 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -147,6 +147,7 @@
 #define SYSDB_SUBDOMAIN_ENUM "enumerate"
 #define SYSDB_SUBDOMAIN_FOREST "memberOfForest"
 #define SYSDB_SUBDOMAIN_TRUST_DIRECTION "trustDirection"
+#define SYSDB_UPN_SUFFIXES "upnSuffixes"
 
 #define SYSDB_BASE_ID "baseID"
 #define SYSDB_ID_RANGE_SIZE "idRangeSize"
@@ -469,7 +470,8 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info 
*domain,
                                      const char *realm,
                                      const char *flat,
                                      const char *id,
-                                     const char* forest);
+                                     const char *forest,
+                                     struct ldb_message_element *alt_dom_suf);
 
 errno_t sysdb_subdomain_delete(struct sysdb_ctx *sysdb, const char *name);
 
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index 
456e6621b3434a9dbf2e611ad880facbc171c174..c0a190f36d886325a5be1e5d1145b6aef6860ffc
 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -448,6 +448,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info 
*domain)
     errno_t ret;
     TALLOC_CTX *tmp_ctx;
     const char *tmp_str;
+    struct ldb_message_element **tmp_el;
     struct ldb_dn *basedn;
     struct ldb_result *res;
     const char *attrs[] = {"cn",
@@ -455,6 +456,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info 
*domain)
                            SYSDB_SUBDOMAIN_FLAT,
                            SYSDB_SUBDOMAIN_ID,
                            SYSDB_SUBDOMAIN_FOREST,
+                           SYSDB_UPN_SUFFIXES,
                            NULL};
     char *view_name = NULL;
 
@@ -539,6 +541,19 @@ errno_t sysdb_master_domain_update(struct sss_domain_info 
*domain)
         }
     }
 
+    tmp_el = ldb_msg_find_element(res->msgs[0], SYSDB_UPN_SUFFIXES);
+    if (tmp_el != NULL) {
+        talloc_free(domain->upn_suffixes);
+        domain->upn_suffixes = sss_ldb_el_to_string_list(domain, tmp_el);
+        if (domain->upn_suffixes == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "sss_ldb_el_to_string_list failed.\n");
+            ret = ENOMEM;
+            goto done;
+        }
+    } else {
+        talloc_zfree(domain->upn_suffixes);
+    }
+
     ret = sysdb_get_view_name(tmp_ctx, domain->sysdb, &view_name);
     if (ret != EOK && ret != ENOENT) {
         DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name failed.\n");
@@ -633,7 +648,8 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info 
*domain,
                                      const char *realm,
                                      const char *flat,
                                      const char *id,
-                                     const char* forest)
+                                     const char *forest,
+                                     struct ldb_message_element *upn_suffixes)
 {
     TALLOC_CTX *tmp_ctx;
     struct ldb_message *msg;
@@ -720,7 +736,6 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info 
*domain,
             ret = sysdb_error_to_errno(ret);
             goto done;
         }
-
         ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_REALM, realm);
         if (ret != LDB_SUCCESS) {
             ret = sysdb_error_to_errno(ret);
@@ -730,6 +745,36 @@ errno_t sysdb_master_domain_add_info(struct 
sss_domain_info *domain,
         do_update = true;
     }
 
+    if (upn_suffixes != NULL) {
+        talloc_free(discard_const(upn_suffixes->name));
+        upn_suffixes->name = talloc_strdup(upn_suffixes, SYSDB_UPN_SUFFIXES);
+        if (upn_suffixes->name == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        ret = ldb_msg_add(msg, upn_suffixes, LDB_FLAG_MOD_REPLACE);
+        if (ret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        do_update = true;
+    } else {
+        /* Remove alternative_domain_suffixes from the cache */
+        if (domain->upn_suffixes != NULL) {
+            ret = ldb_msg_add_empty(msg, SYSDB_UPN_SUFFIXES,
+                                    LDB_FLAG_MOD_DELETE, NULL);
+            if (ret != LDB_SUCCESS) {
+                ret = sysdb_error_to_errno(ret);
+                goto done;
+            }
+        }
+
+        do_update = true;
+    }
+
     if (do_update == false) {
         ret = EOK;
         goto done;
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 
92ac4ab6a13d7094f7a663b4a070feea3be09571..98915b4b966e2665dbd34257e4002d72b95d76b2
 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -631,7 +631,7 @@ ad_enumeration_master_done(struct tevent_req *subreq)
     }
 
     ret = sysdb_master_domain_add_info(state->sdom->dom, state->realm,
-                                       flat_name, master_sid, forest);
+                                       flat_name, master_sid, forest, NULL);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "Cannot save master domain info\n");
         tevent_req_error(req, ret);
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index 
5b0bee86665a46f45fde5ec1034a9ccf8700d13a..8747d99113a07933e56b59f327f02d1aaf2f52d2
 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -1126,7 +1126,7 @@ static void ad_subdomains_refresh_master_done(struct 
tevent_req *subreq)
     }
 
     ret = sysdb_master_domain_add_info(state->be_ctx->domain, realm,
-                                       flat_name, master_sid, forest);
+                                       flat_name, master_sid, forest, NULL);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "Cannot save master domain info [%d]: %s\n",
               ret, sss_strerror(ret));
diff --git a/src/providers/ipa/ipa_subdomains.c 
b/src/providers/ipa/ipa_subdomains.c
index 
40de7da6e899f00d2b3fd8e44364fc4b00764ce8..9b9fe836dd28eb2deeb95d0f94e82120025cbb22
 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -852,6 +852,7 @@ static void ipa_subdomains_master_done(struct tevent_req 
*subreq)
     const char *flat = NULL;
     const char *id = NULL;
     const char *realm = NULL;
+    struct ldb_message_element *alternative_domain_suffixes = NULL;
     errno_t ret;
 
     req = tevent_req_callback_data(subreq, struct tevent_req);
@@ -876,6 +877,12 @@ static void ipa_subdomains_master_done(struct tevent_req 
*subreq)
         if (ret != EOK) {
             goto done;
         }
+
+        ret = sysdb_attrs_get_el_ext(reply[0], IPA_ADDITIONAL_SUFFIXES, false,
+                                     &alternative_domain_suffixes);
+        if (ret != EOK && ret != ENOENT) {
+            goto done;
+        }
     } else {
         /* All search paths are searched and no master domain record was
          * found.
@@ -893,7 +900,8 @@ static void ipa_subdomains_master_done(struct tevent_req 
*subreq)
         goto done;
     }
 
-    ret = sysdb_master_domain_add_info(state->domain, realm, flat, id, NULL);
+    ret = sysdb_master_domain_add_info(state->domain, realm, flat, id, NULL,
+                                       alternative_domain_suffixes);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add master domain info "
               "[%d]: %s\n", ret, sss_strerror(ret));
diff --git a/src/tests/cmocka/test_sysdb_subdomains.c 
b/src/tests/cmocka/test_sysdb_subdomains.c
index 
f55c2918015900351483e3471bf946ea60872dae..6d1ec884284487a12bcbfad77c00cd6c30f67707
 100644
--- a/src/tests/cmocka/test_sysdb_subdomains.c
+++ b/src/tests/cmocka/test_sysdb_subdomains.c
@@ -165,7 +165,8 @@ static void test_sysdb_master_domain_ops(void **state)
         talloc_get_type(*state, struct subdom_test_ctx);
 
     ret = sysdb_master_domain_add_info(test_ctx->tctx->dom,
-                                       "realm1", "flat1", "id1", "forest1");
+                                       "realm1", "flat1", "id1", "forest1",
+                                       NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_master_domain_update(test_ctx->tctx->dom);
@@ -177,7 +178,8 @@ static void test_sysdb_master_domain_ops(void **state)
     assert_string_equal(test_ctx->tctx->dom->forest, "forest1");
 
     ret = sysdb_master_domain_add_info(test_ctx->tctx->dom,
-                                       "realm2", "flat2", "id2", "forest2");
+                                       "realm2", "flat2", "id2", "forest2",
+                                       NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_master_domain_update(test_ctx->tctx->dom);
@@ -298,7 +300,8 @@ static void test_sysdb_link_forest_root_ad(void **state)
                                        TEST_REALM,
                                        TEST_FLAT_NAME,
                                        TEST_SID,
-                                       TEST_FOREST);
+                                       TEST_FOREST,
+                                       NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
@@ -374,7 +377,8 @@ static void test_sysdb_link_forest_member_ad(void **state)
                                        child_dom[1],
                                        child_dom[2],
                                        child_dom[3],
-                                       TEST_FOREST);
+                                       TEST_FOREST,
+                                       NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
@@ -457,7 +461,8 @@ static void test_sysdb_link_ad_multidom(void **state)
                                        TEST_REALM,
                                        TEST_FLAT_NAME,
                                        TEST_SID,
-                                       TEST_FOREST);
+                                       TEST_FOREST,
+                                       NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(main_dom1->sysdb,
@@ -477,7 +482,8 @@ static void test_sysdb_link_ad_multidom(void **state)
                                        TEST_REALM2,
                                        TEST_FLAT_NAME2,
                                        TEST_SID2,
-                                       TEST_FOREST2);
+                                       TEST_FOREST2,
+                                       NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(main_dom2->sysdb,
-- 
2.1.0

From ecb154f8bbf364026fd6909e89a8dd11ad4ea27c Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 1 Jul 2016 12:54:39 +0200
Subject: [PATCH 3/6] sysdb: make subdomain calls aware of upn_suffixes

sysdb_subdomain_store() and sysdb_update_subdomains() can now update
upn_suffixes as well.
---
 src/confdb/confdb.h                           |  2 +-
 src/db/sysdb.h                                |  3 +-
 src/db/sysdb_subdomains.c                     | 56 +++++++++++++++++++++++++--
 src/providers/ad/ad_subdomains.c              |  2 +-
 src/providers/ipa/ipa_subdomains.c            |  9 ++++-
 src/tests/cmocka/test_ipa_subdomains_server.c |  4 +-
 src/tests/cmocka/test_nss_srv.c               |  2 +-
 src/tests/cmocka/test_sysdb_subdomains.c      | 28 +++++++-------
 src/tests/sysdb-tests.c                       |  6 +--
 9 files changed, 85 insertions(+), 27 deletions(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 
cd5eb039836b53b874af5ceacd43ddbdf2e0fac7..4f4d2fb87f75d77231d401ddc0a91c7a8e6b0de2
 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -316,7 +316,7 @@ struct sss_domain_info {
      */
     char *forest;
     struct sss_domain_info *forest_root;
-    char **upn_suffixes;
+    const char **upn_suffixes;
 };
 
 /**
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 
71717c3e11b642001405b9e7db6b556368742193..9d94ba8b5a92099cbaca5ab191a5d274c19fc0a4
 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -460,7 +460,8 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
                               const char *name, const char *realm,
                               const char *flat_name, const char *domain_id,
                               bool mpg, bool enumerate, const char *forest,
-                              uint32_t trust_direction);
+                              uint32_t trust_direction,
+                              struct ldb_message_element *upn_suffixes);
 
 errno_t sysdb_update_subdomains(struct sss_domain_info *domain);
 
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index 
c0a190f36d886325a5be1e5d1145b6aef6860ffc..02206e470e8e035cc05848137df6a1eb04806869
 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -237,6 +237,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info 
*domain)
                            SYSDB_SUBDOMAIN_ENUM,
                            SYSDB_SUBDOMAIN_FOREST,
                            SYSDB_SUBDOMAIN_TRUST_DIRECTION,
+                           SYSDB_UPN_SUFFIXES,
                            NULL};
     struct sss_domain_info *dom;
     struct ldb_dn *basedn;
@@ -248,6 +249,8 @@ errno_t sysdb_update_subdomains(struct sss_domain_info 
*domain)
     bool mpg;
     bool enumerate;
     uint32_t trust_direction;
+    struct ldb_message_element *tmp_el;
+    const char **upn_suffixes;
 
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
@@ -308,6 +311,17 @@ errno_t sysdb_update_subdomains(struct sss_domain_info 
*domain)
         forest = ldb_msg_find_attr_as_string(res->msgs[i],
                                              SYSDB_SUBDOMAIN_FOREST, NULL);
 
+        upn_suffixes = NULL;
+        tmp_el = ldb_msg_find_element(res->msgs[0], SYSDB_UPN_SUFFIXES);
+        if (tmp_el != NULL) {
+            upn_suffixes = sss_ldb_el_to_string_list(tmp_ctx, tmp_el);
+            if (upn_suffixes == NULL) {
+                DEBUG(SSSDBG_OP_FAILURE, "sss_ldb_el_to_string_list 
failed.\n");
+                ret = ENOMEM;
+                goto done;
+            }
+        }
+
         trust_direction = ldb_msg_find_attr_as_int(res->msgs[i],
                                              SYSDB_SUBDOMAIN_TRUST_DIRECTION,
                                              0);
@@ -382,6 +396,9 @@ errno_t sysdb_update_subdomains(struct sss_domain_info 
*domain)
                     }
                 }
 
+                talloc_zfree(dom->upn_suffixes);
+                dom->upn_suffixes = talloc_steal(dom, upn_suffixes);
+
                 if (!dom->has_views && dom->view_name == NULL) {
                     /* maybe views are not initialized, copy from parent */
                     dom->has_views = dom->parent->has_views;
@@ -448,7 +465,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info 
*domain)
     errno_t ret;
     TALLOC_CTX *tmp_ctx;
     const char *tmp_str;
-    struct ldb_message_element **tmp_el;
+    struct ldb_message_element *tmp_el;
     struct ldb_dn *basedn;
     struct ldb_result *res;
     const char *attrs[] = {"cn",
@@ -806,7 +823,8 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
                               const char *name, const char *realm,
                               const char *flat_name, const char *domain_id,
                               bool mpg, bool enumerate, const char *forest,
-                              uint32_t trust_direction)
+                              uint32_t trust_direction,
+                              struct ldb_message_element *upn_suffixes)
 {
     TALLOC_CTX *tmp_ctx;
     struct ldb_message *msg;
@@ -820,8 +838,10 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
                            SYSDB_SUBDOMAIN_ENUM,
                            SYSDB_SUBDOMAIN_FOREST,
                            SYSDB_SUBDOMAIN_TRUST_DIRECTION,
+                           SYSDB_UPN_SUFFIXES,
                            NULL};
     const char *tmp_str;
+    struct ldb_message_element *tmp_el;
     bool tmp_bool;
     bool store = false;
     int realm_flags = 0;
@@ -831,6 +851,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
     int enum_flags = 0;
     int forest_flags = 0;
     int td_flags = 0;
+    int upn_flags = 0;
     uint32_t tmp_td;
     int ret;
 
@@ -864,6 +885,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
         enum_flags = LDB_FLAG_MOD_ADD;
         if (forest) forest_flags = LDB_FLAG_MOD_ADD;
         if (trust_direction) td_flags = LDB_FLAG_MOD_ADD;
+        if (upn_suffixes) upn_flags = LDB_FLAG_MOD_ADD;
     } else if (res->count != 1) {
         ret = EINVAL;
         goto done;
@@ -915,11 +937,21 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
         if (tmp_td != trust_direction) {
             td_flags = LDB_FLAG_MOD_REPLACE;
         }
+
+        if (upn_suffixes) {
+            tmp_el = ldb_msg_find_element(res->msgs[0], SYSDB_UPN_SUFFIXES);
+            /* Luckily ldb_msg_element_compare() only compares the values and
+             * not the name. */
+            if (tmp_el == NULL
+                    || ldb_msg_element_compare(upn_suffixes, tmp_el) != 0) {
+                upn_flags = LDB_FLAG_MOD_REPLACE;
+            }
+        }
     }
 
     if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0
             && mpg_flags == 0 && enum_flags == 0 && forest_flags == 0
-            && td_flags == 0) {
+            && td_flags == 0 && upn_flags == 0) {
         ret = EOK;
         goto done;
     }
@@ -1048,6 +1080,24 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
         }
     }
 
+    if (upn_flags) {
+        tmp_el = talloc_zero(tmp_ctx, struct ldb_message_element);
+        if (tmp_el == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        tmp_el->name = SYSDB_UPN_SUFFIXES;
+        tmp_el->num_values = upn_suffixes->num_values;
+        tmp_el->values = upn_suffixes->values;
+        ret = ldb_msg_add(msg, tmp_el, upn_flags);
+        if (ret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+    }
+
     ret = ldb_modify(sysdb->ldb, msg);
     if (ret != LDB_SUCCESS) {
         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add subdomain attributes to "
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index 
8747d99113a07933e56b59f327f02d1aaf2f52d2..4a858fd4db6f3075ad908bfde6b077363f284fde
 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -252,7 +252,7 @@ ad_subdom_store(struct sdap_idmap_ctx *idmap_ctx,
     mpg = sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx, name, sid_str);
 
     ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str,
-                                mpg, enumerate, domain->forest, 0);
+                                mpg, enumerate, domain->forest, 0, NULL);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
         goto done;
diff --git a/src/providers/ipa/ipa_subdomains.c 
b/src/providers/ipa/ipa_subdomains.c
index 
9b9fe836dd28eb2deeb95d0f94e82120025cbb22..74d71f3e3dcc740fb3e4075b48f7e5460e76239d
 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -372,6 +372,7 @@ static errno_t ipa_subdom_store(struct sss_domain_info 
*parent,
     bool mpg;
     bool enumerate;
     uint32_t direction;
+    struct ldb_message_element *alternative_domain_suffixes = NULL;
 
     tmp_ctx = talloc_new(parent);
     if (tmp_ctx == NULL) {
@@ -402,6 +403,12 @@ static errno_t ipa_subdom_store(struct sss_domain_info 
*parent,
         goto done;
     }
 
+    ret = sysdb_attrs_get_el_ext(attrs, IPA_ADDITIONAL_SUFFIXES, false,
+                                 &alternative_domain_suffixes);
+    if (ret != EOK && ret != ENOENT) {
+        goto done;
+    }
+
     mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, name, id);
 
     ret = ipa_subdom_get_forest(tmp_ctx, sysdb_ctx_get_ldb(parent->sysdb),
@@ -428,7 +435,7 @@ static errno_t ipa_subdom_store(struct sss_domain_info 
*parent,
           "Trust direction of %s is %s\n", name, ipa_trust_dir2str(direction));
     ret = sysdb_subdomain_store(parent->sysdb, name, realm, flat,
                                 id, mpg, enumerate, forest,
-                                direction);
+                                direction, alternative_domain_suffixes);
     if (ret) {
         DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
         goto done;
diff --git a/src/tests/cmocka/test_ipa_subdomains_server.c 
b/src/tests/cmocka/test_ipa_subdomains_server.c
index 
0fddc951894dee45658497851473b9bddbba0ef7..123cf11c01ef4687eecad31a9d73120a87c643e1
 100644
--- a/src/tests/cmocka/test_ipa_subdomains_server.c
+++ b/src/tests/cmocka/test_ipa_subdomains_server.c
@@ -253,14 +253,14 @@ static void add_test_subdomains(struct trust_test_ctx 
*test_ctx,
                                 SUBDOM_NAME, SUBDOM_REALM,
                                 NULL, SUBDOM_SID,
                                 true, false, SUBDOM_REALM,
-                                direction);
+                                direction, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 CHILD_NAME, CHILD_REALM,
                                 CHILD_FLAT, CHILD_SID,
                                 true, false, SUBDOM_REALM,
-                                direction);
+                                direction, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_update_subdomains(test_ctx->tctx->dom);
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index 
945e2b0c23b246aa00ffef73b17a19e06d353632..58f5b175b08aaffd2fc7128bbeb782ac4f081d12
 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -2709,7 +2709,7 @@ static int nss_subdom_test_setup(void **state)
 
     ret = sysdb_subdomain_store(nss_test_ctx->tctx->sysdb,
                                 testdom[0], testdom[1], testdom[2], testdom[3],
-                                false, false, NULL, 0);
+                                false, false, NULL, 0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_update_subdomains(nss_test_ctx->tctx->dom);
diff --git a/src/tests/cmocka/test_sysdb_subdomains.c 
b/src/tests/cmocka/test_sysdb_subdomains.c
index 
6d1ec884284487a12bcbfad77c00cd6c30f67707..c9db56841e841472c81d00a79f475dbbd975ccb0
 100644
--- a/src/tests/cmocka/test_sysdb_subdomains.c
+++ b/src/tests/cmocka/test_sysdb_subdomains.c
@@ -103,7 +103,7 @@ static void test_sysdb_subdomain_create(void **state)
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 dom1[0], dom1[1], dom1[2], dom1[3],
-                                false, false, NULL, 0);
+                                false, false, NULL, 0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_update_subdomains(test_ctx->tctx->dom);
@@ -115,7 +115,7 @@ static void test_sysdb_subdomain_create(void **state)
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 dom2[0], dom2[1], dom2[2], dom2[3],
-                                false, false, NULL, 1);
+                                false, false, NULL, 1, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_update_subdomains(test_ctx->tctx->dom);
@@ -128,12 +128,12 @@ static void test_sysdb_subdomain_create(void **state)
     /* Reverse the trust directions */
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 dom1[0], dom1[1], dom1[2], dom1[3],
-                                false, false, NULL, 1);
+                                false, false, NULL, 1, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 dom2[0], dom2[1], dom2[2], dom2[3],
-                                false, false, NULL, 0);
+                                false, false, NULL, 0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_update_subdomains(test_ctx->tctx->dom);
@@ -215,27 +215,27 @@ static void test_sysdb_link_forest_root_ipa(void **state)
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 dom1[0], dom1[1], dom1[2], dom1[3],
-                                false, false, dom1[4], 0);
+                                false, false, dom1[4], 0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 child_dom1[0], child_dom1[1],
                                 child_dom1[2], child_dom1[3],
                                 false, false, child_dom1[4],
-                                0);
+                                0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 dom2[0], dom2[1], dom2[2], dom2[3],
                                 false, false, dom2[4],
-                                0);
+                                0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 child_dom2[0], child_dom2[1],
                                 child_dom2[2], child_dom2[3],
                                 false, false, child_dom2[4],
-                                0);
+                                0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_update_subdomains(test_ctx->tctx->dom);
@@ -308,14 +308,14 @@ static void test_sysdb_link_forest_root_ad(void **state)
                                 child_dom[0], child_dom[1],
                                 child_dom[2], child_dom[3],
                                 false, false, child_dom[4],
-                                0);
+                                0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 sub_dom[0], sub_dom[1],
                                 sub_dom[2], sub_dom[3],
                                 false, false, sub_dom[4],
-                                0);
+                                0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_update_subdomains(test_ctx->tctx->dom);
@@ -385,14 +385,14 @@ static void test_sysdb_link_forest_member_ad(void **state)
                                 sub_dom[0], sub_dom[1],
                                 sub_dom[2], sub_dom[3],
                                 false, false, sub_dom[4],
-                                0);
+                                0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_subdomain_store(test_ctx->tctx->sysdb,
                                 forest_root[0], forest_root[1],
                                 forest_root[2], forest_root[3],
                                 false, false, forest_root[4],
-                                0);
+                                0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_master_domain_update(test_ctx->tctx->dom);
@@ -469,7 +469,7 @@ static void test_sysdb_link_ad_multidom(void **state)
                                 child_dom[0], child_dom[1],
                                 child_dom[2], child_dom[3],
                                 false, false, child_dom[4],
-                                0);
+                                0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_master_domain_update(main_dom1);
@@ -489,7 +489,7 @@ static void test_sysdb_link_ad_multidom(void **state)
     ret = sysdb_subdomain_store(main_dom2->sysdb,
                                 dom2_forest_root[0], dom2_forest_root[1],
                                 dom2_forest_root[2], dom2_forest_root[3],
-                                false, false, dom2_forest_root[4], 0);
+                                false, false, dom2_forest_root[4], 0, NULL);
     assert_int_equal(ret, EOK);
 
     ret = sysdb_master_domain_update(main_dom2);
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 
05017e4c0b5b5e98b810cdf3d3bd6b6cdbc3e364..7487f2a86d5ee5380fd4a924c200c932a9895f4e
 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -5397,7 +5397,7 @@ START_TEST(test_sysdb_subdomain_store_user)
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
                                 testdom[0], testdom[1], testdom[2], testdom[3],
-                                false, false, NULL, 0);
+                                false, false, NULL, 0, NULL);
     fail_if(ret != EOK, "Could not set up the test (test subdom)");
 
     ret = sysdb_update_subdomains(test_ctx->domain);
@@ -5468,7 +5468,7 @@ START_TEST(test_sysdb_subdomain_user_ops)
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
                                 testdom[0], testdom[1], testdom[2], testdom[3],
-                                false, false, NULL, 0);
+                                false, false, NULL, 0, NULL);
     fail_if(ret != EOK, "Could not set up the test (test subdom)");
 
     ret = sysdb_update_subdomains(test_ctx->domain);
@@ -5523,7 +5523,7 @@ START_TEST(test_sysdb_subdomain_group_ops)
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
                                 testdom[0], testdom[1], testdom[2], testdom[3],
-                                false, false, NULL, 0);
+                                false, false, NULL, 0, NULL);
     fail_if(ret != EOK, "Could not set up the test (test subdom)");
 
     ret = sysdb_update_subdomains(test_ctx->domain);
-- 
2.1.0

From c67a021f6912cedbaaa91cdd749f0fb2404e70a8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 1 Jul 2016 17:57:31 +0200
Subject: [PATCH 4/6] DP: add dp_get_module_data()

---
 src/providers/data_provider/dp.h         | 2 ++
 src/providers/data_provider/dp_targets.c | 5 +++++
 2 files changed, 7 insertions(+)

diff --git a/src/providers/data_provider/dp.h b/src/providers/data_provider/dp.h
index 
8cdbd7768a0b3f7f234b6bce6abab02419b3b9d1..5b36baf3489be4cce463dfb42c65a0b7f7ece9ef
 100644
--- a/src/providers/data_provider/dp.h
+++ b/src/providers/data_provider/dp.h
@@ -118,6 +118,8 @@ bool _dp_target_enabled(struct data_provider *provider,
 struct dp_module *dp_target_module(struct data_provider *provider,
                                    enum dp_targets target);
 
+void *dp_get_module_data(struct dp_module *dp_module);
+
 void _dp_set_method(struct dp_method *methods,
                     enum dp_methods method,
                     dp_req_send_fn send_fn,
diff --git a/src/providers/data_provider/dp_targets.c 
b/src/providers/data_provider/dp_targets.c
index 
e19cf93a3693dede98567d2105021488380b5408..87ecfe55daa805eec0265795ef76751a1568c474
 100644
--- a/src/providers/data_provider/dp_targets.c
+++ b/src/providers/data_provider/dp_targets.c
@@ -88,6 +88,11 @@ struct dp_module *dp_target_module(struct data_provider 
*provider,
     return provider->targets[target]->module;
 }
 
+void *dp_get_module_data(struct dp_module *dp_module)
+{
+    return dp_module == NULL ? NULL : dp_module->module_data;
+}
+
 const char *dp_target_to_string(enum dp_targets target)
 {
     switch (target) {
-- 
2.1.0

From d6511e4f261f657a12120a67dcc5be7e92ea117f Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 1 Jul 2016 17:58:02 +0200
Subject: [PATCH 5/6] IPA: add ipa_init_get_krb5_auth_ctx()

---
 src/providers/ipa/ipa_common.h |  5 +++++
 src/providers/ipa/ipa_init.c   | 13 +++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 
939c898e1a690806abd37493aabfb7bdec3e87a9..add9df87692c732b3567eee5584e7698991c66ca
 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -34,6 +34,8 @@ struct ipa_service {
     struct krb5_service *krb5_service;
 };
 
+struct ipa_init_ctx;
+
 enum ipa_basic_opt {
     IPA_DOMAIN = 0,
     IPA_SERVER,
@@ -287,4 +289,7 @@ errno_t ipa_idmap_get_ranges_from_sysdb(struct 
sdap_idmap_ctx *idmap_ctx,
 errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx,
                        struct sdap_id_ctx *id_ctx,
                        struct sdap_idmap_ctx **_idmap_ctx);
+
+
+struct krb5_ctx *ipa_init_get_krb5_auth_ctx(void *data);
 #endif /* _IPA_COMMON_H_ */
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 
d3093b3b5d269e6acd29f35560cf8299017c72b5..959cdb4a7c40c1be03dd1e7c66dee6e65ca76607
 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -58,6 +58,19 @@ struct ipa_init_ctx {
     struct ipa_auth_ctx *auth_ctx;
 };
 
+
+struct krb5_ctx *ipa_init_get_krb5_auth_ctx(void *data)
+{
+    struct ipa_init_ctx *ipa_init_ctx;
+
+    ipa_init_ctx = talloc_get_type(data, struct ipa_init_ctx);
+    if (ipa_init_ctx == NULL || ipa_init_ctx->auth_ctx == NULL) {
+        return NULL;
+    }
+
+    return ipa_init_ctx->auth_ctx->krb5_auth_ctx;
+}
+
 static bool srv_in_server_list(const char *servers)
 {
     TALLOC_CTX *tmp_ctx;
-- 
2.1.0

From d2c50ee770f0f0c95b6b1a41ada99d4db55c5c77 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 1 Jul 2016 18:18:14 +0200
Subject: [PATCH 6/6] IPA: enable enterprise principals if server supports them

If there are alternative UPN suffixes found on the server we can safely
assume that the IPA server supports enterprise principals.

Resolves https://fedorahosted.org/sssd/ticket/3018
---
 src/man/sssd-krb5.5.xml            |  6 +++
 src/providers/ipa/ipa_subdomains.c | 87 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml
index 
e7fdd19e07db99314a9491faff9974d7d5e617e6..60b7dfb508c0d054a421fd46957574f52e0333d7
 100644
--- a/src/man/sssd-krb5.5.xml
+++ b/src/man/sssd-krb5.5.xml
@@ -513,6 +513,12 @@
                         <para>
                             Default: false (AD provider: true)
                         </para>
+                        <para>
+                            The IPA provider will set to option to 'true' if it
+                            detects that the server is capable of handling
+                            enterprise principals and the option is not set
+                            explicitly in the config file.
+                        </para>
                     </listitem>
                 </varlistentry>
 
diff --git a/src/providers/ipa/ipa_subdomains.c 
b/src/providers/ipa/ipa_subdomains.c
index 
74d71f3e3dcc740fb3e4075b48f7e5460e76239d..f36e1bc691bc637518f34f78e64c0fe4c25cf6d1
 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -28,6 +28,7 @@
 #include "providers/ipa/ipa_subdomains.h"
 #include "providers/ipa/ipa_common.h"
 #include "providers/ipa/ipa_id.h"
+#include "providers/ipa/ipa_opts.h"
 
 #include <ctype.h>
 
@@ -996,6 +997,85 @@ immediately:
     return req;
 }
 
+static errno_t ipa_enable_enterprise_principals(struct be_ctx *be_ctx)
+{
+    int ret;
+    struct sss_domain_info *d;
+    TALLOC_CTX *tmp_ctx;
+    char **vals = NULL;
+    struct dp_module *auth;
+    struct ipa_init_ctx *ipa_init_ctx;
+    struct krb5_ctx *krb5_auth_ctx;
+
+    d = get_domains_head(be_ctx->domain);
+
+    while (d != NULL) {
+        DEBUG(SSSDBG_TRACE_ALL, "checking [%s].\n", d->name);
+        if (d->upn_suffixes != NULL) {
+            break;
+        }
+        d = get_next_domain(d, SSS_GND_DESCEND);
+    }
+
+    if (d == NULL) {
+        DEBUG(SSSDBG_TRACE_ALL,
+              "No UPN suffixes found, "
+              "no need to enable enterprise principals.\n");
+        return EOK;
+    }
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    ret = confdb_get_param(be_ctx->cdb, tmp_ctx, be_ctx->conf_path,
+                     ipa_def_krb5_opts[KRB5_USE_ENTERPRISE_PRINCIPAL].opt_name,
+                     &vals);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "confdb_get_param failed.\n");
+        goto done;
+    }
+
+    if (vals[0]) {
+        DEBUG(SSSDBG_CONF_SETTINGS,
+              "Parameter [%s] set in config file and will not be changed.\n",
+              ipa_def_krb5_opts[KRB5_USE_ENTERPRISE_PRINCIPAL].opt_name);
+        return EOK;
+    }
+
+    auth = dp_target_module(be_ctx->provider, DPT_AUTH);
+    if (auth == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to find auth proivder.\n");
+        ret = EINVAL;
+        goto done;
+    }
+
+    krb5_auth_ctx = ipa_init_get_krb5_auth_ctx(dp_get_module_data(auth));
+    if (krb5_auth_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to find auth proivder data.\n");
+        ret = EINVAL;
+        goto done;
+    }
+
+    ret = dp_opt_set_bool(krb5_auth_ctx->opts,
+                          KRB5_USE_ENTERPRISE_PRINCIPAL, true);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "dp_opt_set_bool failed.\n");
+        goto done;
+    }
+
+    DEBUG(SSSDBG_CONF_SETTINGS, "Enterprise principals enabled.\n");
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
 static void ipa_subdomains_slave_search_done(struct tevent_req *subreq)
 {
     struct ipa_subdomains_slave_state *state;
@@ -1034,6 +1114,13 @@ static void ipa_subdomains_slave_search_done(struct 
tevent_req *subreq)
         goto done;
     }
 
+    ret = ipa_enable_enterprise_principals(state->sd_ctx->be_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "ipa_enable_enterprise_principals failed. "
+                                 "Enterprise principals might not work as "
+                                 "expected.\n");
+    }
+
     if (state->sd_ctx->ipa_id_ctx->server_mode == NULL) {
         ret = EOK;
         goto done;
-- 
2.1.0

_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/admin/lists/[email protected]

Reply via email to