[prev in list] [next in list] [prev in thread] [next in thread] 

List:       sssd-devel
Subject:    [SSSD]  [PATCH] AD: support gpo processing in offline mode
From:       Yassir Elley <yelley () redhat ! com>
Date:       2014-07-31 18:40:02
Message-ID: 2026195975.4404600.1406832002058.JavaMail.zimbra () redhat ! com
[Download RAW message or body]

Hi,

The attached patch adds support for gpo processing in offline mode. While the code \
for online mode uses LDAP to determine which gpo-guids are applicable (and then uses \
SMB to retrieve policy files), the code in offline mode simply retrieves all \
gpo-guids from the cache (and then retrieves locally cached per-gpo-guid policy \
files). Note that neither version checking nor the ad_gpo_cache_timeout option are \
relevant when in offline mode.

Unresolved issues
* if there are no gpo-guids in the cache, the code currently denies access; i suspect \
                we should be allowing access instead; agree?
* i don't think offline callbacks are needed, but i'm unclear about whether online \
callbacks are needed; i suspect they are not needed for the access provider (b/c I \
don't see them being used by the ad_access_filter code); should we trigger a fresh \
round of gpo processing when transitioning from offline to online?

Regards,
Yassir.


["0001-AD-GPO-Support-offline-mode.patch" (text/x-patch)]

From 99f1f669b20d9f101916ebcf70bd463343624fa1 Mon Sep 17 00:00:00 2001
From: Yassir Elley <yelley@redhat.com>
Date: Mon, 21 Jul 2014 15:56:56 -0400
Subject: [PATCH] AD-GPO: Support offline mode

---
 src/db/sysdb.h            |   7 ++-
 src/db/sysdb_gpo.c        |  58 +++++++++++++++++++-
 src/providers/ad/ad_gpo.c | 134 ++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 176 insertions(+), 23 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index addf13196352825009a4a4a0ebaed7e343c72a14..3cef1e66bdc5c3870ed1a349c797e66ac4ad3475 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -870,7 +870,8 @@ errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
 #define SYSDB_GPO_CONTAINER "cn=gpos,cn=ad,cn=custom"
 
 #define SYSDB_GPO_OC "gpo"
-#define SYSDB_GPO_FILTER "(&(objectClass="SYSDB_GPO_OC")("SYSDB_GPO_GUID_ATTR"=%s))"
+#define SYSDB_GPO_FILTER "(objectClass="SYSDB_GPO_OC")"
+#define SYSDB_GPO_GUID_FILTER "(&(objectClass="SYSDB_GPO_OC")("SYSDB_GPO_GUID_ATTR"=%s))"
 #define SYSDB_GPO_GUID_ATTR "gpoGUID"
 #define SYSDB_GPO_VERSION_ATTR "gpoVersion"
 #define SYSDB_GPO_TIMEOUT_ATTR "gpoPolicyFileTimeout"
@@ -896,4 +897,8 @@ errno_t sysdb_gpo_get_gpo_by_guid(TALLOC_CTX *mem_ctx,
                                   const char *gpo_guid,
                                   struct ldb_result **_result);
 
+errno_t sysdb_gpo_get_gpos(TALLOC_CTX *mem_ctx,
+                           struct sss_domain_info *domain,
+                           struct ldb_result **_result);
+
 #endif /* __SYS_DB_H__ */
diff --git a/src/db/sysdb_gpo.c b/src/db/sysdb_gpo.c
index 228f131ace761909c98e0c02fffc889599f86c07..7dd31d81a69c065fb03840ba9d2b7810abad4cad 100644
--- a/src/db/sysdb_gpo.c
+++ b/src/db/sysdb_gpo.c
@@ -265,7 +265,7 @@ sysdb_gpo_get_gpo_by_guid(TALLOC_CTX *mem_ctx,
     }
 
     lret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
-                      LDB_SCOPE_SUBTREE, attrs, SYSDB_GPO_FILTER, gpo_guid);
+                      LDB_SCOPE_SUBTREE, attrs, SYSDB_GPO_GUID_FILTER, gpo_guid);
     if (lret) {
         DEBUG(SSSDBG_MINOR_FAILURE,
               "Could not locate GPO: [%s]\n",
@@ -296,3 +296,59 @@ done:
     talloc_free(tmp_ctx);
     return ret;
 }
+
+errno_t
+sysdb_gpo_get_gpos(TALLOC_CTX *mem_ctx,
+                   struct sss_domain_info *domain,
+                   struct ldb_result **_result)
+{
+    errno_t ret;
+    int lret;
+    struct ldb_dn *base_dn;
+    TALLOC_CTX *tmp_ctx;
+    struct ldb_result *res;
+
+    const char *attrs[] = SYSDB_GPO_ATTRS;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) return ENOMEM;
+
+    DEBUG(SSSDBG_TRACE_FUNC, SYSDB_TMPL_GPO_BASE"\n", domain->name);
+
+    base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
+                             SYSDB_TMPL_GPO_BASE,
+                             domain->name);
+    if (!base_dn) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    lret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+                      LDB_SCOPE_SUBTREE, attrs, SYSDB_GPO_FILTER);
+    if (lret) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              "Could not locate GPOs: [%s]\n",
+              ldb_strerror(lret));
+        ret = sysdb_error_to_errno(lret);
+        goto done;
+    }
+
+    if (res->count == 0) {
+        ret = ENOENT;
+        goto done;
+    }
+
+    *_result = talloc_steal(mem_ctx, res);
+    ret = EOK;
+
+done:
+
+    if (ret == ENOENT) {
+        DEBUG(SSSDBG_TRACE_ALL, "No GPO entries.\n");
+    } else if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
+    }
+
+    talloc_free(tmp_ctx);
+    return ret;
+}
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index c26011d672886faadaf2bb60c4537c2de8bf6532..ab92c9a9e859c4fd8077118467948c50cc524f67 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -989,16 +989,67 @@ immediately:
     return req;
 }
 
+static errno_t
+process_offline_gpo(TALLOC_CTX *mem_ctx,
+                    const char *user,
+                    enum gpo_access_control_mode gpo_mode,
+                    struct sss_domain_info *domain,
+                    struct ldb_message *gpo_cache_entry)
+{
+    const char *policy_filename = NULL;
+    const char *cached_gpo_guid;
+    char **allowed_sids;
+    int allowed_size;
+    char **denied_sids;
+    int denied_size;
+    int ret;
+
+    cached_gpo_guid = ldb_msg_find_attr_as_string(gpo_cache_entry,
+                                                  SYSDB_GPO_GUID_ATTR, NULL);
+
+    policy_filename = talloc_asprintf(mem_ctx,
+                                      GPO_CACHE_PATH"/%s/Policies/%s%s",
+                                      domain->name,
+                                      cached_gpo_guid,
+                                      GP_EXT_GUID_SECURITY_SUFFIX);
+
+    DEBUG(SSSDBG_TRACE_FUNC, "policy_filename:%s\n", policy_filename);
+
+    ret = ad_gpo_parse_policy_file(mem_ctx,
+                                   policy_filename,
+                                   &allowed_sids,
+                                   &allowed_size,
+                                   &denied_sids,
+                                   &denied_size);
+
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Cannot parse policy file: [%s][%d][%s]\n",
+              policy_filename, ret, strerror(ret));
+        goto done;
+    }
+
+    ret = ad_gpo_access_check
+        (mem_ctx, gpo_mode, user, domain,
+         allowed_sids, allowed_size, denied_sids, denied_size);
+
+ done:
+    return ret;
+}
+
 static void
 ad_gpo_connect_done(struct tevent_req *subreq)
 {
     struct tevent_req *req;
     struct ad_gpo_access_state *state;
-    char* filter;
+    char *filter;
     char *sam_account_name;
     char *domain_dn;
     int dp_error;
     errno_t ret;
+    struct ldb_result *res;
+    struct ldb_message *gpo_cache_entry;
+    int i;
 
     const char *attrs[] = {AD_AT_DN, AD_AT_UAC, NULL};
 
@@ -1009,20 +1060,60 @@ ad_gpo_connect_done(struct tevent_req *subreq)
     talloc_zfree(subreq);
 
     if (ret != EOK) {
-        /* TBD: handle (dp_error == DP_ERR_OFFLINE) case */
+        if (dp_error != DP_ERR_OFFLINE) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "Failed to connect to AD server: [%d](%s)\n",
+                  ret, strerror(ret));
+            goto done;
+        } else {
+            DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n");
 
-        DEBUG(SSSDBG_OP_FAILURE,
-              "Failed to connect to AD server: [%d](%s)\n",
-               ret, sss_strerror(ret));
+            ret = sysdb_gpo_get_gpos(state, state->domain, &res);
 
-        tevent_req_error(req, ret);
-        return;
+            if (ret != EOK) {
+                switch (ret) {
+                case ENOENT:
+                    DEBUG(SSSDBG_OP_FAILURE, "No GPOs available in cache\n");
+                    goto done;
+                default:
+                    DEBUG(SSSDBG_FATAL_FAILURE,
+                          "Could not read GPOs from cache: [%s]\n",
+                          strerror(ret));
+                    goto done;
+                }
+            }
+
+            DEBUG(SSSDBG_TRACE_FUNC, "Retrieving GPOs from cache\n");
+            DEBUG(SSSDBG_TRACE_FUNC, "Found %d GPO(s) in cache\n", res->count);
+
+            for (i = 0; i < res->count; i++){
+                gpo_cache_entry = res->msgs[i];
+                ret = process_offline_gpo(state,
+                                          state->user,
+                                          state->gpo_mode,
+                                          state->domain,
+                                          gpo_cache_entry);
+                if (ret != EOK) {
+                    DEBUG(SSSDBG_OP_FAILURE,
+                          "process_offline_gpo failed [%d](%s)\n",
+                          ret, sss_strerror(ret));
+                    goto done;
+                }
+            }
+
+            /* we have successfully processed all offline gpos */
+            if (ret == EOK) {
+                DEBUG(SSSDBG_TRACE_FUNC, "process_offline_gpo passed\n");
+                tevent_req_done(req);
+                goto done;
+            }
+        }
     }
 
     sam_account_name = talloc_asprintf(state, "%s$", state->ad_hostname);
     if (sam_account_name == NULL) {
-        tevent_req_error(req, ENOMEM);
-        return;
+        ret = ENOMEM;
+        goto done;
     }
 
     DEBUG(SSSDBG_TRACE_FUNC, "sam_account_name is %s\n", sam_account_name);
@@ -1033,8 +1124,7 @@ ad_gpo_connect_done(struct tevent_req *subreq)
         DEBUG(SSSDBG_OP_FAILURE,
               "Cannot convert domain name [%s] to base DN [%d]: %s\n",
                state->domain->name, ret, sss_strerror(ret));
-        tevent_req_error(req, ret);
-        return;
+        goto done;
     }
 
     /* SDAP_OC_USER objectclass covers both users and computers */
@@ -1045,8 +1135,8 @@ ad_gpo_connect_done(struct tevent_req *subreq)
                              sam_account_name);
 
     if (filter == NULL) {
-        tevent_req_error(req, ENOMEM);
-        return;
+        ret = ENOMEM;
+        goto done;
     }
 
     subreq = sdap_get_generic_send(state, state->ev, state->opts,
@@ -1058,11 +1148,19 @@ ad_gpo_connect_done(struct tevent_req *subreq)
 
     if (subreq == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
-        tevent_req_error(req, EIO);
-        return;
+        ret = EIO;
+        goto done;
     }
 
     tevent_req_set_callback(subreq, ad_gpo_target_dn_retrieval_done, req);
+
+    ret = EOK;
+
+ done:
+
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+    }
 }
 
 static void
@@ -1084,7 +1182,6 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq)
     talloc_zfree(subreq);
     if (ret != EOK) {
         ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
-        /* TBD: handle (dp_error == DP_ERR_OFFLINE) case */
 
         DEBUG(SSSDBG_OP_FAILURE,
               "Unable to get policy target's DN: [%d](%s)\n",
@@ -1238,8 +1335,6 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq)
     ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
 
     if (ret != EOK) {
-        /* TBD: handle (dp_error == DP_ERR_OFFLINE) case */
-
         DEBUG(SSSDBG_OP_FAILURE,
               "Unable to get GPO list: [%d](%s)\n",
               ret, sss_strerror(ret));
@@ -1950,7 +2045,6 @@ ad_gpo_site_dn_retrieval_done(struct tevent_req *subreq)
     talloc_zfree(subreq);
     if (ret != EOK) {
         ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
-        /* TBD: handle (dp_error == DP_ERR_OFFLINE) case */
 
         DEBUG(SSSDBG_OP_FAILURE,
               "Unable to get configNC: [%d](%s)\n", ret, sss_strerror(ret));
@@ -2080,7 +2174,6 @@ ad_gpo_get_som_attrs_done(struct tevent_req *subreq)
 
     if (ret != EOK) {
         ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
-        /* TBD: handle (dp_error == DP_ERR_OFFLINE) case */
 
         DEBUG(SSSDBG_OP_FAILURE,
               "Unable to get SOM attributes: [%d](%s)\n",
@@ -2749,7 +2842,6 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq)
 
     if (ret != EOK) {
         ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
-        /* TBD: handle (dp_error == DP_ERR_OFFLINE) case */
 
         DEBUG(SSSDBG_OP_FAILURE,
               "Unable to get GPO attributes: [%d](%s)\n",
-- 
1.8.5.3


[Attachment #4 (text/plain)]

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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic