>From 9e74d52391de5b0a19036dbeb1f10ce79ea4d15a Mon Sep 17 00:00:00 2001
From: Pavel Reichl <pavel.reichl@redhat.com>
Date: Tue, 17 Dec 2013 17:32:04 +0000
Subject: [PATCH] responder: Set forest attribute in AD domains

Resolves:
https://fedorahosted.org/sssd/ticket/2160
---
 src/db/sysdb.h                     |  3 ++-
 src/db/sysdb_subdomains.c          | 35 ++++++++++++++++++++++++++++-
 src/providers/ad/ad_domain_info.c  | 46 +++++++++++++++++++++++++++++++-------
 src/providers/ad/ad_domain_info.h  |  3 ++-
 src/providers/ad/ad_id.c           |  5 +++--
 src/providers/ad/ad_subdomains.c   |  7 ++++--
 src/providers/ipa/ipa_subdomains.c |  2 +-
 src/providers/ldap/sdap_access.c   |  2 +-
 8 files changed, 86 insertions(+), 17 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 63a1fab8b26c1cf62b9a8aa4bfc22dc4b0bd175d..3fa533a75ae48e9ba05c6f0d970329f9829450c5 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -380,7 +380,8 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain);
 errno_t sysdb_master_domain_update(struct sss_domain_info *domain);
 
 errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain,
-                                     const char *flat, const char *id);
+                                     const char *flat, const char *id,
+                                     const char* forest);
 
 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 43c75799cdc2856916b2dc95c3a544ef99b56081..9c2926c00b0cc08cb8e317ae838e26c82506ee37 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -208,6 +208,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain)
                            SYSDB_SUBDOMAIN_REALM,
                            SYSDB_SUBDOMAIN_FLAT,
                            SYSDB_SUBDOMAIN_ID,
+                           SYSDB_SUBDOMAIN_FOREST,
                            NULL};
 
     tmp_ctx = talloc_new(NULL);
@@ -278,13 +279,27 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain)
         }
     }
 
+    tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FOREST,
+                                          NULL);
+    if (tmp_str != NULL &&
+        (domain->forest == NULL ||
+         strcasecmp(tmp_str, domain->forest) != 0)) {
+        talloc_free(domain->forest);
+        domain->forest = talloc_strdup(domain, tmp_str);
+        if (domain->forest == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
 done:
     talloc_free(tmp_ctx);
     return ret;
 }
 
 errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain,
-                                     const char *flat, const char *id)
+                                     const char *flat, const char *id,
+                                     const char* forest)
 {
     TALLOC_CTX *tmp_ctx;
     struct ldb_message *msg;
@@ -345,6 +360,24 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain,
         do_update = true;
     }
 
+   if (forest != NULL && (domain->forest == NULL ||
+                       strcmp(domain->forest, forest) != 0)) {
+        ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST,
+                                LDB_FLAG_MOD_REPLACE, NULL);
+        if (ret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest);
+        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_domain_info.c b/src/providers/ad/ad_domain_info.c
index c24da939feaa061e8f8bcc83813eb64f14523df0..e8987a482a6de373c037dd758b2e464f4fcc3686 100644
--- a/src/providers/ad/ad_domain_info.c
+++ b/src/providers/ad/ad_domain_info.c
@@ -42,9 +42,9 @@
 #define MASTER_DOMAIN_SID_FILTER "objectclass=domain"
 
 static errno_t
-netlogon_get_flat_name(TALLOC_CTX *mem_ctx,
-                       struct sysdb_attrs *reply,
-                       char **_flat_name)
+netlogon_get_domain_info(TALLOC_CTX *mem_ctx,
+                         struct sysdb_attrs *reply,
+                         char **_flat_name, char **_forest)
 {
     errno_t ret;
     struct ldb_message_element *el;
@@ -53,6 +53,7 @@ netlogon_get_flat_name(TALLOC_CTX *mem_ctx,
     enum ndr_err_code ndr_err;
     struct netlogon_samlogon_response response;
     const char *flat_name;
+    const char *forest;
 
     ret = sysdb_attrs_get_el(reply, AD_AT_NETLOGON, &el);
     if (ret != EOK) {
@@ -93,11 +94,13 @@ netlogon_get_flat_name(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
+    /* get flat name */
     if (response.data.nt5_ex.domain_name != NULL &&
         *response.data.nt5_ex.domain_name != '\0') {
         flat_name = response.data.nt5_ex.domain_name;
     } else {
-        DEBUG(SSSDBG_MINOR_FAILURE, ("No netlogon data available\n"));
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              ("No netlogon domain name data available\n"));
         ret = ENOENT;
         goto done;
     }
@@ -108,6 +111,24 @@ netlogon_get_flat_name(TALLOC_CTX *mem_ctx,
         ret = ENOMEM;
         goto done;
     }
+
+    /* get forest */
+    if (response.data.nt5_ex.forest != NULL &&
+        *response.data.nt5_ex.forest != '\0') {
+        forest = response.data.nt5_ex.forest;
+    } else {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("No netlogon forest data available\n"));
+        ret = ENOENT;
+        goto done;
+    }
+
+    *_forest = talloc_strdup(mem_ctx, forest);
+    if (*_forest == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
     ret = EOK;
 done:
     talloc_free(ndr_pull);
@@ -125,6 +146,7 @@ struct ad_master_domain_state {
     int base_iter;
 
     char *flat;
+    char *forest;
     char *sid;
 };
 
@@ -339,14 +361,17 @@ ad_master_domain_netlogon_done(struct tevent_req *subreq)
 
     /* Exactly one flat name. Carry on */
 
-    ret = netlogon_get_flat_name(state, reply[0], &state->flat);
+    ret = netlogon_get_domain_info(state, reply[0], &state->flat,
+                                   &state->forest);
     if (ret != EOK) {
-        DEBUG(SSSDBG_MINOR_FAILURE, ("Could not get the flat name\n"));
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              ("Could not get the flat name or forest\n"));
         /* Not fatal. Just quit. */
         goto done;
     }
-
     DEBUG(SSSDBG_TRACE_FUNC, ("Found flat name [%s].\n", state->flat));
+    DEBUG(SSSDBG_TRACE_FUNC, ("Found forest [%s].\n", state->forest));
+
 done:
     tevent_req_done(req);
     return;
@@ -356,7 +381,8 @@ errno_t
 ad_master_domain_recv(struct tevent_req *req,
                       TALLOC_CTX *mem_ctx,
                       char **_flat,
-                      char **_id)
+                      char **_id,
+                      char **_forest)
 {
     struct ad_master_domain_state *state = tevent_req_data(req,
                                               struct ad_master_domain_state);
@@ -367,6 +393,10 @@ ad_master_domain_recv(struct tevent_req *req,
         *_flat = talloc_steal(mem_ctx, state->flat);
     }
 
+    if (_forest) {
+        *_forest = talloc_steal(mem_ctx, state->forest);
+    }
+
     if (_id) {
         *_id = talloc_steal(mem_ctx, state->sid);
     }
diff --git a/src/providers/ad/ad_domain_info.h b/src/providers/ad/ad_domain_info.h
index d21706396034509a498391e666e03a8e2eda8e08..d3a6416cebd07b524aceedcb63a18c4467e3dc4e 100644
--- a/src/providers/ad/ad_domain_info.h
+++ b/src/providers/ad/ad_domain_info.h
@@ -36,6 +36,7 @@ errno_t
 ad_master_domain_recv(struct tevent_req *req,
                       TALLOC_CTX *mem_ctx,
                       char **_flat,
-                      char **_id);
+                      char **_id,
+                      char **_forest);
 
 #endif /* _AD_MASTER_DOMAIN_H_ */
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 242e962fba2d63bf9132daff84a690489afd862e..7a855f00209326fdfb1810c96ac1b7fb3d7ae244 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -531,9 +531,10 @@ ad_enumeration_master_done(struct tevent_req *subreq)
                                                 struct ad_enumeration_state);
     char *flat_name;
     char *master_sid;
+    char *forest;
 
     ret = ad_master_domain_recv(subreq, state,
-                                &flat_name, &master_sid);
+                                &flat_name, &master_sid, &forest);
     talloc_zfree(subreq);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, ("Cannot retrieve master domain info\n"));
@@ -542,7 +543,7 @@ ad_enumeration_master_done(struct tevent_req *subreq)
     }
 
     ret = sysdb_master_domain_add_info(state->sdom->dom,
-                                       flat_name, master_sid);
+                                       flat_name, master_sid, forest);
     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 73190faa1e7e995123f12e2200ab00fb40f3b256..31b317fb32a61cb6741adbc512d2205675365816 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -83,6 +83,7 @@ struct ad_subdomains_req_ctx {
 
     char *master_sid;
     char *flat_name;
+    char *forest;
 };
 
 static errno_t
@@ -384,7 +385,8 @@ static void ad_subdomains_master_dom_done(struct tevent_req *req)
     ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
 
     ret = ad_master_domain_recv(req, ctx,
-                                &ctx->flat_name, &ctx->master_sid);
+                                &ctx->flat_name, &ctx->master_sid,
+                                &ctx->forest);
     talloc_zfree(req);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, ("Cannot retrieve master domain info\n"));
@@ -392,7 +394,8 @@ static void ad_subdomains_master_dom_done(struct tevent_req *req)
     }
 
     ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
-                                       ctx->flat_name, ctx->master_sid);
+                                       ctx->flat_name, ctx->master_sid,
+                                       ctx->forest);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, ("Cannot save master domain info\n"));
         goto done;
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 4f7627eddb9c54d68e45be876157057f3c30b422..7087e8b2d09311d3f3d16d52109930dacfc3d4c5 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -1062,7 +1062,7 @@ static void ipa_subdomains_handler_master_done(struct tevent_req *req)
         }
 
         ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
-                                           flat, id);
+                                           flat, id, NULL);
     } else {
         ctx->search_base_iter++;
         ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_MASTER);
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index e93400db1c33b04a5c7bf5cd01eca5c9325a4593..91a1807648f4d90ff638f9b87d474e3d950f85b3 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -213,7 +213,7 @@ static void sdap_access_filter_done(struct tevent_req *subreq)
     ret = sdap_access_filter_recv(subreq);
     talloc_zfree(subreq);
     if (ret != EOK) {
-        DEBUG(1, ("Error retrieving access check result.\n"));
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Error retrieving access check result.\n"));
         tevent_req_error(req, ret);
         return;
     }
-- 
1.8.3.1

