summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYassir Elley <yelley@redhat.com>2014-09-09 15:37:05 -0400
committerJakub Hrozek <jhrozek@redhat.com>2014-10-02 14:13:39 +0200
commit4611802d41d8954a3040f39403590adb920ca521 (patch)
tree57277a84018e0a3796c1dc6cc56767372beed87b
parent7f4270ee333c1128a87fce6e6a3de64d263733e1 (diff)
downloadsssd-4611802d41d8954a3040f39403590adb920ca521.tar.gz
sssd-4611802d41d8954a3040f39403590adb920ca521.tar.xz
sssd-4611802d41d8954a3040f39403590adb920ca521.zip
AD-GPO resolve conflicting policy settings correctly
Resolves: https://fedorahosted.org/sssd/ticket/2437 Reviewed-by: Stephen Gallagher <sgallagh@redhat.com>
-rw-r--r--src/db/sysdb.h29
-rw-r--r--src/db/sysdb_gpo.c357
-rw-r--r--src/providers/ad/ad_gpo.c911
-rw-r--r--src/tests/cmocka/test_ad_gpo.c1
4 files changed, 743 insertions, 555 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 901b6129b..81b39252c 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -876,6 +876,8 @@ errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
#define SYSDB_GPO_CONTAINER "cn=gpos,cn=ad,cn=custom"
+/* === Functions related to GPO entries === */
+
#define SYSDB_GPO_OC "gpo"
#define SYSDB_GPO_FILTER "(objectClass="SYSDB_GPO_OC")"
#define SYSDB_GPO_GUID_FILTER "(&(objectClass="SYSDB_GPO_OC")("SYSDB_GPO_GUID_ATTR"=%s))"
@@ -908,9 +910,28 @@ errno_t sysdb_gpo_get_gpos(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
struct ldb_result **_result);
-errno_t sysdb_gpo_delete_stale_gpos(TALLOC_CTX *mem_ctx,
- struct sss_domain_info *domain,
- const char **gpo_guid_list,
- int num_gpos);
+/* === Functions related to GPO Result object === */
+
+#define SYSDB_GPO_RESULT_OC "gpo_result"
+#define SYSDB_GPO_RESULT_FILTER "(objectClass="SYSDB_GPO_RESULT_OC")"
+
+#define SYSDB_TMPL_GPO_RESULT_BASE SYSDB_GPO_CONTAINER","SYSDB_DOM_BASE
+#define SYSDB_TMPL_GPO_RESULT "cn=%s,"SYSDB_TMPL_GPO_RESULT_BASE
+
+errno_t sysdb_gpo_get_gpo_result_object(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ struct ldb_result **_result);
+
+errno_t sysdb_gpo_delete_gpo_result_object(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain);
+
+errno_t sysdb_gpo_store_gpo_result_setting(struct sss_domain_info *domain,
+ const char *policy_setting_key,
+ const char *policy_setting_value);
+
+errno_t sysdb_gpo_get_gpo_result_setting(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *policy_setting_key,
+ const char **policy_setting_value);
#endif /* __SYS_DB_H__ */
diff --git a/src/db/sysdb_gpo.c b/src/db/sysdb_gpo.c
index e0b9bb9f0..92559d41e 100644
--- a/src/db/sysdb_gpo.c
+++ b/src/db/sysdb_gpo.c
@@ -37,7 +37,7 @@ sysdb_gpo_dn(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain,
return NULL;
}
- DEBUG(SSSDBG_TRACE_FUNC, SYSDB_TMPL_GPO"\n", clean_gpo_guid, domain->name);
+ DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_GPO"\n", clean_gpo_guid, domain->name);
dn = ldb_dn_new_fmt(mem_ctx, domain->sysdb->ldb, SYSDB_TMPL_GPO,
clean_gpo_guid, domain->name);
@@ -172,8 +172,7 @@ sysdb_gpo_store_gpo(struct sss_domain_info *domain,
} else if (ret == EOK && count == 1) {
/* Update the existing GPO */
- DEBUG(SSSDBG_TRACE_FUNC,
- "Updating new GPO [%s][%s]\n", domain->name, gpo_guid);
+ DEBUG(SSSDBG_TRACE_ALL, "Updating new GPO [%s][%s]\n", domain->name, gpo_guid);
/* Add the Version */
lret = ldb_msg_add_empty(update_msg, SYSDB_GPO_VERSION_ATTR,
@@ -254,7 +253,7 @@ sysdb_gpo_get_gpo_by_guid(TALLOC_CTX *mem_ctx,
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return ENOMEM;
- DEBUG(SSSDBG_TRACE_FUNC, SYSDB_TMPL_GPO_BASE"\n", domain->name);
+ DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_GPO_BASE"\n", domain->name);
base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
SYSDB_TMPL_GPO_BASE,
@@ -313,7 +312,7 @@ sysdb_gpo_get_gpos(TALLOC_CTX *mem_ctx,
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return ENOMEM;
- DEBUG(SSSDBG_TRACE_FUNC, SYSDB_TMPL_GPO_BASE"\n", domain->name);
+ DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_GPO_BASE"\n", domain->name);
base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
SYSDB_TMPL_GPO_BASE,
@@ -353,32 +352,59 @@ done:
return ret;
}
-static inline bool
-sysdb_gpo_guid_in_list(const char **gpo_guid_list, int num_gpos, const char *gpo_guid)
+/* GPO Result */
+
+static struct ldb_dn *
+sysdb_gpo_result_dn(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *result_name)
{
- size_t i;
+ errno_t ret;
+ char *clean_result_name;
+ struct ldb_dn *dn;
- for (i = 0; i < num_gpos; i++) {
- if (strcasecmp(gpo_guid_list[i], gpo_guid) == 0) {
- break;
- }
+ ret = sysdb_dn_sanitize(NULL, result_name, &clean_result_name);
+ if (ret != EOK) {
+ return NULL;
}
- return (i < num_gpos) ? true : false;
+ DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_GPO_RESULT"\n",
+ clean_result_name, domain->name);
+
+ dn = ldb_dn_new_fmt(mem_ctx, domain->sysdb->ldb, SYSDB_TMPL_GPO_RESULT,
+ clean_result_name, domain->name);
+ talloc_free(clean_result_name);
+
+ return dn;
}
errno_t
-sysdb_gpo_delete_stale_gpos(TALLOC_CTX *mem_ctx,
- struct sss_domain_info *domain,
- const char **gpo_guid_list,
- int num_gpos)
+sysdb_gpo_store_gpo_result_setting(struct sss_domain_info *domain,
+ const char *ini_key,
+ const char *ini_value)
{
- struct ldb_result *res;
errno_t ret, sret;
- int i;
+ int lret;
+ struct ldb_message *update_msg;
+ struct ldb_message **msgs;
+ size_t count;
bool in_transaction = false;
- const char *cached_gpo_guid;
- bool stale_gpo_found = false;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) return ENOMEM;
+
+ update_msg = ldb_msg_new(tmp_ctx);
+ if (!update_msg) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ update_msg->dn = sysdb_gpo_result_dn(update_msg, domain, "gpo_result");
+ if (!update_msg->dn) {
+ ret = ENOMEM;
+ goto done;
+ }
ret = sysdb_transaction_start(domain->sysdb);
if (ret != EOK) {
@@ -388,43 +414,272 @@ sysdb_gpo_delete_stale_gpos(TALLOC_CTX *mem_ctx,
in_transaction = true;
- ret = sysdb_gpo_get_gpos(mem_ctx, domain, &res);
- if (ret != EOK && ret != ENOENT) {
- goto done;
- } else if (ret != ENOENT) {
- for (i = 0; i < res->count; i++) {
- cached_gpo_guid = ldb_msg_find_attr_as_string(res->msgs[i],
- SYSDB_GPO_GUID_ATTR,
- NULL);
- if (cached_gpo_guid == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "No gpo_guid attribute found in gpo cache entry\n");
- ret = EFAULT;
+ /* Check for an existing GPO Result object */
+ ret = sysdb_search_entry(tmp_ctx, domain->sysdb, update_msg->dn,
+ LDB_SCOPE_BASE, NULL, NULL, &count, &msgs);
+
+ if (ret == ENOENT) {
+ /* Create new GPO Result object */
+ DEBUG(SSSDBG_TRACE_FUNC, "Storing setting: key [%s] value [%s]\n",
+ ini_key, ini_value);
+
+ /* Add the objectClass */
+ lret = ldb_msg_add_empty(update_msg, SYSDB_OBJECTCLASS,
+ LDB_FLAG_MOD_ADD,
+ NULL);
+ if (lret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(lret);
+ goto done;
+ }
+
+ lret = ldb_msg_add_string(update_msg, SYSDB_OBJECTCLASS,
+ SYSDB_GPO_RESULT_OC);
+ if (lret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(lret);
+ goto done;
+ }
+
+ /* Store the policy_setting if it is non-NULL */
+ if (ini_value) {
+ lret = ldb_msg_add_empty(update_msg, ini_key,
+ LDB_FLAG_MOD_ADD,
+ NULL);
+ if (lret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(lret);
+ goto done;
+ }
+
+ lret = ldb_msg_add_string(update_msg, ini_key, ini_value);
+ if (lret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(lret);
+ goto done;
+ }
+ }
+
+ lret = ldb_add(domain->sysdb->ldb, update_msg);
+ if (lret != LDB_SUCCESS) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Failed to add GPO Result: [%s]\n",
+ ldb_strerror(lret));
+ ret = sysdb_error_to_errno(lret);
+ goto done;
+ }
+ } else if (ret == EOK && count == 1) {
+ /* Update existing GPO Result object*/
+ if (ini_value) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Updating setting: key [%s] value [%s]\n",
+ ini_key, ini_value);
+ /* Update the policy setting */
+ lret = ldb_msg_add_empty(update_msg, ini_key,
+ LDB_FLAG_MOD_REPLACE,
+ NULL);
+ if (lret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(lret);
goto done;
}
- if (sysdb_gpo_guid_in_list(gpo_guid_list, num_gpos, cached_gpo_guid)) {
- /* the cached_gpo_guid is still applicable, skip it */
- continue;
- } else {
- stale_gpo_found = true;
- /* the cached_gpo_guid is no longer applicable, delete it */
- DEBUG(SSSDBG_TRACE_FUNC, "Deleting stale GPO [gpo_guid:%s]\n",
- cached_gpo_guid);
-
- ret = sysdb_delete_entry(domain->sysdb, res->msgs[i]->dn, true);
- if (ret != EOK) {
- DEBUG(SSSDBG_MINOR_FAILURE,
- "Could not delete GPO cache entry [gpo_guid:%s]\n",
- cached_gpo_guid);
- goto done;
- }
+ lret = ldb_msg_add_fmt(update_msg, ini_key, "%s", ini_value);
+ if (lret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(lret);
+ goto done;
}
+ } else {
+ /* If the value is NULL, we need to remove it from the cache */
+ DEBUG(SSSDBG_TRACE_FUNC, "Removing setting: key [%s]\n", ini_key);
+
+ /* Update the policy setting */
+ lret = ldb_msg_add_empty(update_msg, ini_key,
+ LDB_FLAG_MOD_DELETE,
+ NULL);
+ if (lret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(lret);
+ goto done;
+ }
+ }
+
+ lret = ldb_modify(domain->sysdb->ldb, update_msg);
+ if (lret != LDB_SUCCESS) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Failed to modify GPO Result: [%s]\n", ldb_strerror(lret));
+ ret = sysdb_error_to_errno(lret);
+ goto done;
}
+ } else {
+ ret = EIO;
+ goto done;
}
- if (!stale_gpo_found) {
- DEBUG(SSSDBG_TRACE_FUNC, "No stale GPOs found\n");
+ ret = sysdb_transaction_commit(domain->sysdb);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Could not commit transaction: [%s]\n", strerror(ret));
+ goto done;
+ }
+ in_transaction = false;
+
+done:
+ if (in_transaction) {
+ sret = sysdb_transaction_cancel(domain->sysdb);
+ if (sret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
+ }
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+errno_t
+sysdb_gpo_get_gpo_result_setting(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *ini_key,
+ const char **_ini_value)
+{
+ errno_t ret;
+ int lret;
+ struct ldb_dn *base_dn;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_result *res;
+ const char *ini_value;
+
+ const char *attrs[] = {ini_key, NULL};
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) return ENOMEM;
+
+ DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_GPO_RESULT_BASE"\n", domain->name);
+
+ base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
+ SYSDB_TMPL_GPO_RESULT_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_RESULT_FILTER);
+ if (lret) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Could not locate GPO Result: [%s]\n",
+ ldb_strerror(lret));
+ ret = sysdb_error_to_errno(lret);
+ goto done;
+ }
+
+ if (res->count == 0) {
+ ret = ENOENT;
+ goto done;
+ }
+
+ ini_value = ldb_msg_find_attr_as_string(res->msgs[0],
+ ini_key,
+ NULL);
+ DEBUG(SSSDBG_TRACE_FUNC, "key [%s] value [%s]\n", ini_key, ini_value);
+
+ *_ini_value = talloc_strdup(mem_ctx, ini_value);
+ if (!*_ini_value && ini_value) {
+ /* If ini_value was NULL, this is expected to also be NULL */
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+
+ if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_ALL, "No setting for key [%s].\n", ini_key);
+ } else if (ret) {
+ DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
+ }
+
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
+errno_t
+sysdb_gpo_get_gpo_result_object(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;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) return ENOMEM;
+
+ DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_GPO_RESULT_BASE"\n", domain->name);
+
+ base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
+ SYSDB_TMPL_GPO_RESULT_BASE,
+ domain->name);
+ if (!base_dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ lret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+ LDB_SCOPE_SUBTREE, NULL, SYSDB_GPO_RESULT_FILTER);
+ if (lret) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Could not locate GPO Result object: [%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 Result object.\n");
+ } else if (ret) {
+ DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
+ }
+
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
+errno_t sysdb_gpo_delete_gpo_result_object(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain)
+{
+ struct ldb_result *res;
+ errno_t ret, sret;
+ bool in_transaction = false;
+
+ ret = sysdb_transaction_start(domain->sysdb);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
+ goto done;
+ }
+
+ in_transaction = true;
+
+ ret = sysdb_gpo_get_gpo_result_object(mem_ctx, domain, &res);
+ if (ret != EOK && ret != ENOENT) {
+ goto done;
+ } else if (ret != ENOENT) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Deleting GPO Result object\n");
+
+ ret = sysdb_delete_entry(domain->sysdb, res->msgs[0]->dn, true);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Could not delete GPO Result cache entry\n");
+ goto done;
+ }
}
ret = sysdb_transaction_commit(domain->sysdb);
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index 7cb9619ca..cf6023a35 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -61,11 +61,8 @@
#define AD_AT_GPOPTIONS "gpOptions"
#define AD_AT_NT_SEC_DESC "nTSecurityDescriptor"
#define AD_AT_CN "cn"
-#define AD_AT_DISPLAY_NAME "displayName"
#define AD_AT_FILE_SYS_PATH "gPCFileSysPath"
-#define AD_AT_VERSION_NUMBER "versionNumber"
#define AD_AT_MACHINE_EXT_NAMES "gPCMachineExtensionNames"
-#define AD_AT_USER_EXT_NAMES "gPCUserExtensionNames"
#define AD_AT_FUNC_VERSION "gPCFunctionalityVersion"
#define AD_AT_FLAGS "flags"
@@ -78,9 +75,6 @@
#define SMB_STANDARD_URI "smb://"
#define BUFSIZE 65536
-#define GPO_VERSION_USER(x) (x >> 16)
-#define GPO_VERSION_MACHINE(x) (x & 0xffff)
-
#define RIGHTS_SECTION "Privilege Rights"
#define ALLOW_LOGON_INTERACTIVE "SeInteractiveLogonRight"
#define DENY_LOGON_INTERACTIVE "SeDenyInteractiveLogonRight"
@@ -91,7 +85,7 @@
#define ALLOW_LOGON_BATCH "SeBatchLogonRight"
#define DENY_LOGON_BATCH "SeDenyBatchLogonRight"
#define ALLOW_LOGON_SERVICE "SeServiceLogonRight"
-#define DENY_LOGON_SERVICE "SeServiceBatchLogonRight"
+#define DENY_LOGON_SERVICE "SeDenyServiceLogonRight"
#define GP_EXT_GUID_SECURITY "{827D319E-6EAC-11D2-A4EA-00C04F79F83A}"
#define GP_EXT_GUID_SECURITY_SUFFIX "/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf"
@@ -122,16 +116,15 @@ struct gp_gpo {
struct security_descriptor *gpo_sd;
const char *gpo_dn;
const char *gpo_guid;
- const char *gpo_display_name;
const char *smb_server;
const char *smb_share;
const char *smb_path;
- uint32_t gpc_version;
const char **gpo_cse_guids;
int num_gpo_cse_guids;
int gpo_func_version;
int gpo_flags;
bool send_to_child;
+ const char *policy_filename;
};
enum ace_eval_status {
@@ -164,6 +157,7 @@ int ad_gpo_process_gpo_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct gp_gpo ***candidate_gpos,
int *num_candidate_gpos);
+
struct tevent_req *ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
bool send_to_child,
@@ -176,9 +170,7 @@ struct tevent_req *ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
int cached_gpt_version,
int gpo_timeout_option);
int ad_gpo_process_cse_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- int *_sysvol_gpt_version,
- const char **_policy_filename);
+ TALLOC_CTX *mem_ctx);
/* == ad_gpo_parse_map_options and helpers ==================================*/
@@ -200,6 +192,8 @@ struct gpo_map_option_entry {
enum gpo_map_type gpo_map_type;
enum ad_basic_opt ad_basic_opt;
const char **gpo_map_defaults;
+ const char *allow_key;
+ const char *deny_key;
};
const char *gpo_map_interactive_defaults[] =
@@ -213,17 +207,21 @@ const char *gpo_map_permit_defaults[] = {GPO_SUDO, GPO_SUDO_I, NULL};
const char *gpo_map_deny_defaults[] = {NULL};
struct gpo_map_option_entry gpo_map_option_entries[] = {
- {GPO_MAP_INTERACTIVE, AD_GPO_MAP_INTERACTIVE, gpo_map_interactive_defaults},
+ {GPO_MAP_INTERACTIVE, AD_GPO_MAP_INTERACTIVE, gpo_map_interactive_defaults,
+ ALLOW_LOGON_INTERACTIVE, DENY_LOGON_INTERACTIVE},
{GPO_MAP_REMOTE_INTERACTIVE, AD_GPO_MAP_REMOTE_INTERACTIVE,
- gpo_map_remote_interactive_defaults},
- {GPO_MAP_NETWORK, AD_GPO_MAP_NETWORK, gpo_map_network_defaults},
- {GPO_MAP_BATCH, AD_GPO_MAP_BATCH, gpo_map_batch_defaults},
- {GPO_MAP_SERVICE, AD_GPO_MAP_SERVICE, gpo_map_service_defaults},
- {GPO_MAP_PERMIT, AD_GPO_MAP_PERMIT, gpo_map_permit_defaults},
- {GPO_MAP_DENY, AD_GPO_MAP_DENY, gpo_map_deny_defaults},
+ gpo_map_remote_interactive_defaults,
+ ALLOW_LOGON_REMOTE_INTERACTIVE, DENY_LOGON_REMOTE_INTERACTIVE},
+ {GPO_MAP_NETWORK, AD_GPO_MAP_NETWORK, gpo_map_network_defaults,
+ ALLOW_LOGON_NETWORK, DENY_LOGON_NETWORK},
+ {GPO_MAP_BATCH, AD_GPO_MAP_BATCH, gpo_map_batch_defaults,
+ ALLOW_LOGON_BATCH, DENY_LOGON_BATCH},
+ {GPO_MAP_SERVICE, AD_GPO_MAP_SERVICE, gpo_map_service_defaults,
+ ALLOW_LOGON_SERVICE, DENY_LOGON_SERVICE},
+ {GPO_MAP_PERMIT, AD_GPO_MAP_PERMIT, gpo_map_permit_defaults, NULL, NULL},
+ {GPO_MAP_DENY, AD_GPO_MAP_DENY, gpo_map_deny_defaults, NULL, NULL},
};
-
const char* gpo_map_type_string(int gpo_map_type)
{
switch(gpo_map_type) {
@@ -252,7 +250,6 @@ ad_gpo_service_in_list(char **list, size_t nlist, const char *str)
return (i < nlist) ? true : false;
}
-
errno_t
ad_gpo_parse_map_option_helper(enum gpo_map_type gpo_map_type,
hash_key_t key,
@@ -326,7 +323,7 @@ ad_gpo_parse_map_option(TALLOC_CTX *mem_ctx,
goto done;
}
- DEBUG(SSSDBG_TRACE_FUNC, "gpo_map_type: %s\n",
+ DEBUG(SSSDBG_TRACE_ALL, "gpo_map_type: %s\n",
gpo_map_type_string(gpo_map_type));
if (conf_str) {
@@ -383,7 +380,7 @@ ad_gpo_parse_map_option(TALLOC_CTX *mem_ctx,
goto done;
}
- DEBUG(SSSDBG_TRACE_FUNC, "Explicitly added service: %s\n", key.str);
+ DEBUG(SSSDBG_TRACE_ALL, "Explicitly added service: %s\n", key.str);
}
/* Add defaults to hashtable */
@@ -402,7 +399,7 @@ ad_gpo_parse_map_option(TALLOC_CTX *mem_ctx,
goto done;
}
- DEBUG(SSSDBG_TRACE_FUNC, "Default service (not explicitly removed): %s\n",
+ DEBUG(SSSDBG_TRACE_ALL, "Default service (not explicitly removed): %s\n",
key.str);
}
@@ -442,7 +439,7 @@ ad_gpo_parse_map_options(struct ad_access_ctx *access_ctx)
gpo_default_right_config =
dp_opt_get_string(access_ctx->ad_options, AD_GPO_DEFAULT_RIGHT);
- DEBUG(SSSDBG_TRACE_FUNC, "gpo_default_right_config: %s\n",
+ DEBUG(SSSDBG_TRACE_ALL, "gpo_default_right_config: %s\n",
gpo_default_right_config);
/* if default right not set in config, set them to DENY */
@@ -474,7 +471,7 @@ ad_gpo_parse_map_options(struct ad_access_ctx *access_ctx)
goto fail;
}
- DEBUG(SSSDBG_TRACE_FUNC, "gpo_default_right: %d\n", gpo_default_right);
+ DEBUG(SSSDBG_TRACE_ALL, "gpo_default_right: %d\n", gpo_default_right);
access_ctx->gpo_default_right = gpo_default_right;
fail:
@@ -791,7 +788,6 @@ static errno_t ad_gpo_evaluate_dacl(struct security_acl *dacl,
* _dacl_filtered_gpos output parameter. The filtering algorithm is
* defined in [MS-GPOL] 3.2.5.1.6
*/
-
static errno_t
ad_gpo_filter_gpos_by_dacl(TALLOC_CTX *mem_ctx,
const char *user,
@@ -1002,9 +998,9 @@ ad_gpo_filter_gpos_by_cse_guid(TALLOC_CTX *mem_ctx,
}
/*
- * This cse-specific function (GP_EXT_GUID_SECURITY) populates the output
- * parameter (found) based on whether the input user_sid or any of the input
- * group_sids appear in the input list of privilege_sids.
+ * This cse-specific function (GP_EXT_GUID_SECURITY) returns a boolean value
+ * based on whether the input user_sid or any of the input group_sids appear
+ * in the input list of privilege_sids.
*/
static bool
check_rights(char **privilege_sids,
@@ -1030,8 +1026,167 @@ check_rights(char **privilege_sids,
}
/*
- * This cse-specific function (GP_EXT_GUID_SECURITY) performs HBAC policy
- * application and determines whether logon access is granted or denied for
+ * This function parses the input ini_config object (which represents
+ * the cse-specific filename), and returns the policy_setting_value
+ * corresponding to the input policy_setting_key.
+ */
+static errno_t
+ad_gpo_extract_policy_setting(TALLOC_CTX *mem_ctx,
+ struct ini_cfgobj *ini_config,
+ const char *policy_setting_key,
+ char **_policy_setting_value)
+{
+ struct value_obj *vobj = NULL;
+ int ret;
+ const char *policy_setting_value;
+
+ ret = ini_get_config_valueobj(RIGHTS_SECTION, policy_setting_key, ini_config,
+ INI_GET_FIRST_VALUE, &vobj);
+ if (ret != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "ini_get_config_valueobj failed [%d][%s]\n", ret, strerror(ret));
+ goto done;
+ }
+ if (vobj == NULL) {
+ DEBUG(SSSDBG_TRACE_ALL, "section/name not found: [%s][%s]\n",
+ RIGHTS_SECTION, policy_setting_key);
+ ret = ENOENT;
+ goto done;
+ }
+ policy_setting_value = ini_get_string_config_value(vobj, &ret);
+ if (ret != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "ini_get_string_config_value failed [%d][%s]\n",
+ ret, strerror(ret));
+ goto done;
+ }
+
+ if (policy_setting_value[0]) {
+ *_policy_setting_value = talloc_strdup(mem_ctx, policy_setting_value);
+ if (!*_policy_setting_value) {
+ ret = ENOMEM;
+ goto done;
+ }
+ } else {
+ /* This is an explicitly empty policy setting.
+ * We need to remove this from the LDB.
+ */
+ *_policy_setting_value = NULL;
+ }
+
+ ret = EOK;
+
+ done:
+
+ return ret;
+}
+
+/*
+ * This function parses the cse-specific (GP_EXT_GUID_SECURITY) filename,
+ * and stores the allow_key and deny_key of all of the gpo_map_types present
+ * in the file (as part of the GPO Result object in the sysdb cache).
+ */
+static errno_t
+ad_gpo_store_policy_settings(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *filename)
+{
+ struct ini_cfgfile *file_ctx = NULL;
+ struct ini_cfgobj *ini_config = NULL;
+ int ret;
+ int i;
+ char *allow_value = NULL;
+ char *deny_value = NULL;
+ const char *allow_key = NULL;
+ const char *deny_key = NULL;
+ TALLOC_CTX *tmp_ctx = NULL;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ini_config_create(&ini_config);
+ if (ret != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "ini_config_create failed [%d][%s]\n", ret, strerror(ret));
+ goto done;
+ }
+
+ ret = ini_config_file_open(filename, 0, &file_ctx);
+ if (ret != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "ini_config_file_open failed [%d][%s]\n", ret, strerror(ret));
+ goto done;
+ }
+
+ ret = ini_config_parse(file_ctx, INI_STOP_ON_NONE, 0, 0, ini_config);
+ if (ret != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "ini_config_parse failed [%d][%s]\n", ret, strerror(ret));
+ goto done;
+ }
+
+ for (i = 0; i < GPO_MAP_NUM_OPTS; i++) {
+
+ struct gpo_map_option_entry entry = gpo_map_option_entries[i];
+
+ allow_key = entry.allow_key;
+ if (allow_key != NULL) {
+ DEBUG(SSSDBG_TRACE_ALL, "allow_key = %s\n", allow_key);
+ ret = ad_gpo_extract_policy_setting(tmp_ctx,
+ ini_config,
+ allow_key,
+ &allow_value);
+ if (ret != EOK && ret != ENOENT) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "ad_gpo_extract_policy_setting failed for %s [%d][%s]\n",
+ allow_key, ret, strerror(ret));
+ goto done;
+ } else if (ret != ENOENT) {
+ ret = sysdb_gpo_store_gpo_result_setting(domain,
+ allow_key,
+ allow_value);
+ }
+ }
+
+ deny_key = entry.deny_key;
+ if (deny_key != NULL) {
+ DEBUG(SSSDBG_TRACE_ALL, "deny_key = %s\n", deny_key);
+ ret = ad_gpo_extract_policy_setting(tmp_ctx,
+ ini_config,
+ deny_key,
+ &deny_value);
+ if (ret != EOK && ret != ENOENT) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "ad_gpo_extract_policy_setting failed for %s [%d][%s]\n",
+ deny_key, ret, strerror(ret));
+ goto done;
+ } else if (ret != ENOENT) {
+ ret = sysdb_gpo_store_gpo_result_setting(domain,
+ deny_key,
+ deny_value);
+ }
+ }
+ }
+
+ ret = EOK;
+
+ done:
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Error encountered: %d.\n", ret);
+ }
+ ini_config_file_destroy(file_ctx);
+ ini_config_destroy(ini_config);
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ * This cse-specific function (GP_EXT_GUID_SECURITY) performs the access
+ * check for determining whether logon access is granted or denied for
* the {user,domain} tuple specified in the inputs. This function returns EOK
* to indicate that access is granted. Any other return value indicates that
* access is denied.
@@ -1047,7 +1202,7 @@ check_rights(char **privilege_sids,
* appear in denied_sids
*
* Note that a deployment that is unaware of GPO-based access-control policy
- * settings is unaffected by them (b/c the absence of allowed_sids grants access).
+ * settings is unaffected by them (b/c absence of allowed_sids grants access).
*
* Note that if a principal_sid appears in both allowed_sids and denied_sids,
* the "allowed_sids_condition" is met, but the "denied_sids_condition" is not.
@@ -1072,18 +1227,17 @@ ad_gpo_access_check(TALLOC_CTX *mem_ctx,
int ret;
int j;
- DEBUG(SSSDBG_TRACE_FUNC, "POLICY FILE:\n");
- DEBUG(SSSDBG_TRACE_FUNC, "gpo_map_type: %d\n", gpo_map_type);
+ DEBUG(SSSDBG_TRACE_FUNC, "RESULTANT POLICY:\n");
+ DEBUG(SSSDBG_TRACE_FUNC, "gpo_map_type: %s\n",
+ gpo_map_type_string(gpo_map_type));
DEBUG(SSSDBG_TRACE_FUNC, "allowed_size = %d\n", allowed_size);
for (j= 0; j < allowed_size; j++) {
- DEBUG(SSSDBG_TRACE_FUNC, "allowed_sids[%d] = %s\n", j,
- allowed_sids[j]);
+ DEBUG(SSSDBG_TRACE_FUNC, "allowed_sids[%d] = %s\n", j, allowed_sids[j]);
}
DEBUG(SSSDBG_TRACE_FUNC, "denied_size = %d\n", denied_size);
for (j= 0; j < denied_size; j++) {
- DEBUG(SSSDBG_TRACE_FUNC, " denied_sids[%d] = %s\n", j,
- denied_sids[j]);
+ DEBUG(SSSDBG_TRACE_FUNC, " denied_sids[%d] = %s\n", j, denied_sids[j]);
}
ret = ad_gpo_get_sids(mem_ctx, user, domain, &user_sid,
@@ -1103,8 +1257,6 @@ ad_gpo_access_check(TALLOC_CTX *mem_ctx,
group_sids[j]);
}
- DEBUG(SSSDBG_TRACE_FUNC, "gpo_map_type: %d\n", gpo_map_type);
-
if (allowed_size == 0) {
access_granted = true;
} else {
@@ -1112,6 +1264,8 @@ ad_gpo_access_check(TALLOC_CTX *mem_ctx,
group_sids, group_size);
}
+ DEBUG(SSSDBG_TRACE_FUNC, "POLICY DECISION:\n");
+
DEBUG(SSSDBG_TRACE_FUNC, " access_granted = %d\n", access_granted);
access_denied = check_rights(denied_sids, denied_size, user_sid,
@@ -1171,6 +1325,124 @@ static errno_t gpo_child_init(void)
return EOK;
}
+/*
+ * This function retrieves the raw policy_setting_value for the input key from
+ * the GPO_Result object in the sysdb cache. It then parses the raw value and
+ * uses the results to populate the output parameters with the sids_list and
+ * the size of the sids_list.
+ */
+errno_t
+parse_policy_setting_value(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *key,
+ char ***_sids_list,
+ int *_sids_list_size)
+{
+ int ret;
+ int i;
+ const char *value;
+ int sids_list_size;
+ char **sids_list = NULL;
+
+ ret = sysdb_gpo_get_gpo_result_setting(mem_ctx, domain, key, &value);
+
+ if (value == NULL) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "No value for key [%s] found in gpo result\n", key);
+ sids_list_size = 0;
+ } else {
+ ret = split_on_separator(mem_ctx, value, ',', true, true,
+ &sids_list, &sids_list_size);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Cannot parse list of sids %s: %d\n", value, ret);
+ ret = EINVAL;
+ goto done;
+ }
+
+ for (i = 0; i < sids_list_size; i++) {
+ /* remove the asterisk prefix found on sids */
+ sids_list[i]++;
+ }
+ }
+
+ *_sids_list = talloc_steal(mem_ctx, sids_list);
+ *_sids_list_size = sids_list_size;
+
+ ret = EOK;
+
+ done:
+ return ret;
+}
+
+/*
+ * This cse-specific function (GP_EXT_GUID_SECURITY) performs HBAC policy
+ * processing and determines whether logon access is granted or denied for
+ * the {user,domain} tuple specified in the inputs. This function returns EOK
+ * to indicate that access is granted. Any other return value indicates that
+ * access is denied.
+ *
+ * Internally, this function retrieves the allow_value and deny_value for the
+ * input gpo_map_type from the GPO Result object in the sysdb cache, parses
+ * the values into allow_sids and deny_sids, and executes the access control
+ * algorithm which compares the allow_sids and deny_sids against the user_sid
+ * and group_sids for the input user.
+ */
+static errno_t
+ad_gpo_perform_hbac_processing(TALLOC_CTX *mem_ctx,
+ enum gpo_access_control_mode gpo_mode,
+ enum gpo_map_type gpo_map_type,
+ const char *user,
+ struct sss_domain_info *domain)
+{
+ int ret;
+ const char *allow_key = NULL;
+ char **allow_sids;
+ int allow_size ;
+ const char *deny_key = NULL;
+ char **deny_sids;
+ int deny_size;
+
+ allow_key = gpo_map_option_entries[gpo_map_type].allow_key;
+ DEBUG(SSSDBG_TRACE_ALL, "allow_key: %s\n", allow_key);
+ deny_key = gpo_map_option_entries[gpo_map_type].deny_key;
+ DEBUG(SSSDBG_TRACE_ALL, "deny_key: %s\n", deny_key);
+
+ ret = parse_policy_setting_value(mem_ctx, domain, allow_key,
+ &allow_sids, &allow_size);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "parse_policy_setting_value failed; allow_size %d: %d\n",
+ allow_size, ret);
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = parse_policy_setting_value(mem_ctx, domain, deny_key,
+ &deny_sids, &deny_size);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "parse_policy_setting_value failed; deny_size %d: %d\n",
+ deny_size, ret);
+ ret = EINVAL;
+ goto done;
+ }
+
+ /* perform access check with the final resultant allow_sids and deny_sids */
+ ret = ad_gpo_access_check(mem_ctx, gpo_mode, gpo_map_type, user, domain,
+ allow_sids, allow_size, deny_sids, deny_size);
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "GPO access check failed: [%d](%s)\n",
+ ret, strerror(ret));
+ goto done;
+ }
+
+ done:
+ return ret;
+}
+
/* == ad_gpo_access_send/recv implementation ================================*/
struct ad_gpo_access_state {
@@ -1201,13 +1473,6 @@ static void ad_gpo_process_som_done(struct tevent_req *subreq);
static void ad_gpo_process_gpo_done(struct tevent_req *subreq);
static errno_t ad_gpo_cse_step(struct tevent_req *req);
-static errno_t ad_gpo_parse_policy_file(TALLOC_CTX *mem_ctx,
- const char *filename,
- enum gpo_map_type gpo_map_type,
- char ***allowed_sids,
- int *allowed_size,
- char ***denied_sids,
- int *denied_size);
static void ad_gpo_cse_done(struct tevent_req *subreq);
struct tevent_req *
@@ -1361,109 +1626,24 @@ immediately:
}
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,
- enum gpo_map_type gpo_map_type)
-{
- 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);
-
- if (cached_gpo_guid == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "No gpo_guid attribute found in gpo cache entry\n");
- ret = EFAULT;
- goto done;
- }
-
- policy_filename = talloc_asprintf(mem_ctx,
- GPO_CACHE_PATH"/%s/Policies/%s%s",
- domain->name,
- cached_gpo_guid,
- GP_EXT_GUID_SECURITY_SUFFIX);
-
- if (policy_filename == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- DEBUG(SSSDBG_TRACE_FUNC, "policy_filename:%s\n", policy_filename);
-
- ret = ad_gpo_parse_policy_file(mem_ctx,
- policy_filename,
- gpo_map_type,
- &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, gpo_map_type, user, domain,
- allowed_sids, allowed_size, denied_sids, denied_size);
-
- done:
- return ret;
-}
-
-static errno_t
process_offline_gpos(TALLOC_CTX *mem_ctx,
const char *user,
enum gpo_access_control_mode gpo_mode,
struct sss_domain_info *domain,
enum gpo_map_type gpo_map_type)
+
{
- struct ldb_result *res;
- struct ldb_message *gpo_cache_entry;
errno_t ret;
- int i;
-
- ret = sysdb_gpo_get_gpos(mem_ctx, domain, &res);
+ ret = ad_gpo_perform_hbac_processing(mem_ctx,
+ gpo_mode,
+ gpo_map_type,
+ user,
+ domain);
if (ret != EOK) {
- switch (ret) {
- case ENOENT:
- DEBUG(SSSDBG_OP_FAILURE, "No GPOs available in cache\n");
- /* if there are no GPOs available, we allow access by default */
- ret = EOK;
- 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(mem_ctx, user, gpo_mode, domain,
- gpo_cache_entry, gpo_map_type);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "process_offline_gpo failed [%d](%s)\n",
- ret, sss_strerror(ret));
- goto done;
- }
+ DEBUG(SSSDBG_OP_FAILURE, "HBAC processing failed: [%d](%s}\n",
+ ret, sss_strerror(ret));
+ goto done;
}
/* we have successfully processed all offline gpos */
@@ -1720,8 +1900,9 @@ ad_gpo_process_som_done(struct tevent_req *subreq)
* reduces it to a list of cse_filtered_gpos, based on whether each GPO's list
* of cse_guids includes the "SecuritySettings" CSE GUID (used for HBAC).
*
- * This function then sends each cse_filtered_gpo to the CSE processing engine
- * for policy application, which currently consists of HBAC functionality.
+ * Ultimately, this function then sends each cse_filtered_gpo to the gpo_child,
+ * which retrieves the GPT.INI and policy files (as needed). Once all files
+ * have been downloaded, the ad_gpo_cse_done function performs HBAC processing.
*/
static void
ad_gpo_process_gpo_done(struct tevent_req *subreq)
@@ -1822,22 +2003,20 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq)
state->num_cse_filtered_gpos);
/*
- * we now have the array of applicable gpos in hand; however, since we
- * may have cached a larger set of gpo-guids previously, we delete
- * all stale gpo cache entries (i.e. entries that have a gpo-guid that
- * doesn't match any of the gpo-guids in the cse_filtered_gpo_guids list)
+ * before we start processing each gpo, we delete the GPO Result object
+ * from the sysdb cache so that any previous policy settings are cleared;
+ * subsequent functions will add the GPO Result object (and populate it
+ * with resultant policy settings) for this policy application
*/
- ret = sysdb_gpo_delete_stale_gpos(state, state->domain,
- cse_filtered_gpo_guids,
- state->num_cse_filtered_gpos);
+ ret = sysdb_gpo_delete_gpo_result_object(state, state->domain);
if (ret != EOK) {
switch (ret) {
case ENOENT:
- DEBUG(SSSDBG_TRACE_FUNC, "No GPOs available in cache\n");
+ DEBUG(SSSDBG_TRACE_FUNC, "No GPO Result available in cache\n");
break;
default:
DEBUG(SSSDBG_FATAL_FAILURE,
- "Could not delete stale GPOs from cache: [%s]\n",
+ "Could not delete GPO Result from cache: [%s]\n",
strerror(ret));
goto done;
}
@@ -1871,7 +2050,7 @@ ad_gpo_cse_step(struct tevent_req *req)
struct gp_gpo *cse_filtered_gpo =
state->cse_filtered_gpos[state->cse_gpo_index];
- /* cse_filtered_gpo is NULL only after all GPOs have been processed */
+ /* cse_filtered_gpo is NULL after all GPO policy files have been downloaded */
if (cse_filtered_gpo == NULL) return EOK;
DEBUG(SSSDBG_TRACE_FUNC, "cse filtered_gpos[%d]->gpo_guid is %s\n",
@@ -1887,6 +2066,15 @@ ad_gpo_cse_step(struct tevent_req *req)
DEBUG(SSSDBG_TRACE_FUNC, "smb_path: %s\n", cse_filtered_gpo->smb_path);
DEBUG(SSSDBG_TRACE_FUNC, "gpo_guid: %s\n", cse_filtered_gpo->gpo_guid);
+ cse_filtered_gpo->policy_filename =
+ talloc_asprintf(state,
+ GPO_CACHE_PATH"%s%s",
+ cse_filtered_gpo->smb_path,
+ GP_EXT_GUID_SECURITY_SUFFIX);
+ if (cse_filtered_gpo->policy_filename == NULL) {
+ return ENOMEM;
+ }
+
/* retrieve gpo cache entry; set cached_gpt_version to -1 if unavailable */
DEBUG(SSSDBG_TRACE_FUNC, "retrieving GPO from cache [%s]\n",
cse_filtered_gpo->gpo_guid);
@@ -1947,13 +2135,12 @@ ad_gpo_cse_step(struct tevent_req *req)
}
/*
- * This cse-specific function (GP_EXT_GUID_SECURITY) retrieves a list of
- * allowed_sids and denied_sids, and uses them to determine whether logon
- * access is granted or denied for the state's {user, domain} tuple.
- *
- * If it is determined that the current cse_filtered_gpo grants access, then
- * we process the next cse_filtered_gpo in the list. At any time, if access is
- * denied, we return immediately with an error.
+ * This cse-specific function (GP_EXT_GUID_SECURITY) increments the
+ * cse_gpo_index until the policy settings for all applicable GPOs have been
+ * stored as part of the GPO Result object in the sysdb cache. Once all
+ * GPOs have been processed, this functions performs HBAC processing by
+ * comparing the resultant policy setting values in the GPO Result object
+ * with the user_sid/group_sids of interest.
*/
static void
ad_gpo_cse_done(struct tevent_req *subreq)
@@ -1961,12 +2148,6 @@ ad_gpo_cse_done(struct tevent_req *subreq)
struct tevent_req *req;
struct ad_gpo_access_state *state;
int ret;
- int sysvol_gpt_version;
- const char *policy_filename = NULL;
- char **allowed_sids;
- int allowed_size;
- char **denied_sids;
- int denied_size;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_gpo_access_state);
@@ -1978,8 +2159,7 @@ ad_gpo_cse_done(struct tevent_req *subreq)
DEBUG(SSSDBG_TRACE_FUNC, "gpo_guid: %s\n", gpo_guid);
- ret = ad_gpo_process_cse_recv(subreq, state, &sysvol_gpt_version,
- &policy_filename);
+ ret = ad_gpo_process_cse_recv(subreq, state);
talloc_zfree(subreq);
@@ -1989,35 +2169,32 @@ ad_gpo_cse_done(struct tevent_req *subreq)
goto done;
}
- ret = ad_gpo_parse_policy_file(state,
- policy_filename,
- state->gpo_map_type,
- &allowed_sids,
- &allowed_size,
- &denied_sids,
- &denied_size);
+ /*
+ * now that the policy file for this gpo have been downloaded to the
+ * GPO CACHE, we store all of the supported keys present in the file
+ * (as part of the GPO Result object in the sysdb cache).
+ */
+ ret = ad_gpo_store_policy_settings(state, state->domain,
+ cse_filtered_gpo->policy_filename);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Cannot parse policy file: [%s][%d][%s]\n",
- policy_filename, ret, strerror(ret));
- goto done;
- }
+ state->cse_gpo_index++;
+ ret = ad_gpo_cse_step(req);
- ret = ad_gpo_access_check
- (state, state->gpo_mode, state->gpo_map_type, state->user,
- state->domain, allowed_sids, allowed_size, denied_sids, denied_size);
+ if (ret == EOK) {
+ /* ret is EOK only after all GPO policy files have been downloaded */
+ ret = ad_gpo_perform_hbac_processing(state,
+ state->gpo_mode,
+ state->gpo_map_type,
+ state->user,
+ state->domain);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "HBAC processing failed: [%d](%s}\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "GPO access check failed: [%d](%s)\n",
- ret, strerror(ret));
- goto done;
}
- state->cse_gpo_index++;
- ret = ad_gpo_cse_step(req);
-
done:
if (ret == EOK) {
@@ -2213,7 +2390,7 @@ ad_gpo_populate_gplink_list(TALLOC_CTX *mem_ctx,
return EINVAL;
}
- DEBUG(SSSDBG_TRACE_ALL, "som_dn: %s\n", som_dn);
+ DEBUG(SSSDBG_TRACE_FUNC, "som_dn: %s\n", som_dn);
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
ret = ENOMEM;
@@ -2228,7 +2405,7 @@ ad_gpo_populate_gplink_list(TALLOC_CTX *mem_ctx,
}
if (gplink_count == 0) {
- ret = EINVAL;
+ ret = EOK;
goto done;
}
@@ -3236,8 +3413,7 @@ immediately:
static errno_t
ad_gpo_get_gpo_attrs_step(struct tevent_req *req)
{
- const char *attrs[] = {AD_AT_NT_SEC_DESC, AD_AT_CN, AD_AT_DISPLAY_NAME,
- AD_AT_FILE_SYS_PATH, AD_AT_VERSION_NUMBER,
+ const char *attrs[] = {AD_AT_NT_SEC_DESC, AD_AT_CN, AD_AT_FILE_SYS_PATH,
AD_AT_MACHINE_EXT_NAMES, AD_AT_FUNC_VERSION,
AD_AT_FLAGS, NULL};
struct tevent_req *subreq;
@@ -3276,7 +3452,6 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq)
struct sysdb_attrs **results;
struct ldb_message_element *el = NULL;
const char *gpo_guid = NULL;
- const char *gpo_display_name = NULL;
const char *raw_file_sys_path = NULL;
char *file_sys_path = NULL;
uint8_t *raw_machine_ext_names = NULL;
@@ -3329,25 +3504,6 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq)
DEBUG(SSSDBG_TRACE_ALL, "populating attrs for gpo_guid: %s\n",
gp_gpo->gpo_guid);
- /* retrieve AD_AT_DISPLAY_NAME */
- ret = sysdb_attrs_get_string(results[0], AD_AT_DISPLAY_NAME,
- &gpo_display_name);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sysdb_attrs_get_string failed: [%d](%s)\n",
- ret, sss_strerror(ret));
- goto done;
- }
-
- gp_gpo->gpo_display_name = talloc_steal(gp_gpo, gpo_display_name);
- if (gp_gpo->gpo_display_name == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- DEBUG(SSSDBG_TRACE_ALL, "gpo_display_name: %s\n",
- gp_gpo->gpo_display_name);
-
/* retrieve AD_AT_FILE_SYS_PATH */
ret = sysdb_attrs_get_string(results[0],
AD_AT_FILE_SYS_PATH,
@@ -3376,43 +3532,6 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq)
DEBUG(SSSDBG_TRACE_ALL, "smb_share: %s\n", gp_gpo->smb_share);
DEBUG(SSSDBG_TRACE_ALL, "smb_path: %s\n", gp_gpo->smb_path);
- /* retrieve AD_AT_VERSION_NUMBER */
- ret = sysdb_attrs_get_uint32_t(results[0], AD_AT_VERSION_NUMBER,
- &gp_gpo->gpc_version);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sysdb_attrs_get_uint32_t failed: [%d](%s)\n",
- ret, sss_strerror(ret));
- goto done;
- }
-
- DEBUG(SSSDBG_TRACE_ALL, "gpc_version: %d\n", gp_gpo->gpc_version);
-
- /* retrieve AD_AT_MACHINE_EXT_NAMES */
- ret = sysdb_attrs_get_el(results[0], AD_AT_MACHINE_EXT_NAMES, &el);
- if (ret != EOK && ret != ENOENT) {
- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el() failed\n");
- goto done;
- }
- if ((ret == ENOENT) || (el->num_values == 0)) {
- DEBUG(SSSDBG_OP_FAILURE,
- "machine_ext_names not found or has no value\n");
- ret = ENOENT;
- goto done;
- }
-
- raw_machine_ext_names = el[0].values[0].data;
-
- ret = ad_gpo_parse_machine_ext_names(gp_gpo,
- (char *)raw_machine_ext_names,
- &gp_gpo->gpo_cse_guids,
- &gp_gpo->num_gpo_cse_guids);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "ad_gpo_parse_machine_ext_names() failed\n");
- goto done;
- }
-
/* retrieve AD_AT_FUNC_VERSION */
ret = sysdb_attrs_get_int32_t(results[0], AD_AT_FUNC_VERSION,
&gp_gpo->gpo_func_version);
@@ -3458,7 +3577,37 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq)
goto done;
}
- state->gpo_index++;
+ /* retrieve AD_AT_MACHINE_EXT_NAMES */
+ ret = sysdb_attrs_get_el(results[0], AD_AT_MACHINE_EXT_NAMES, &el);
+ if (ret != EOK && ret != ENOENT) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el() failed\n");
+ goto done;
+ }
+
+ if ((ret == ENOENT) || (el->num_values == 0)) {
+ /*
+ * if gpo has no machine_ext_names (which is perfectly valid: it could
+ * have only user_ext_names, for example), we continue to next gpo
+ */
+ DEBUG(SSSDBG_TRACE_ALL,
+ "machine_ext_names attribute not found or has no value\n");
+ state->gpo_index++;
+ } else {
+ raw_machine_ext_names = el[0].values[0].data;
+
+ ret = ad_gpo_parse_machine_ext_names(gp_gpo,
+ (char *)raw_machine_ext_names,
+ &gp_gpo->gpo_cse_guids,
+ &gp_gpo->num_gpo_cse_guids);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "ad_gpo_parse_machine_ext_names() failed\n");
+ goto done;
+ }
+
+ state->gpo_index++;
+ }
+
ret = ad_gpo_get_gpo_attrs_step(req);
done:
@@ -3551,207 +3700,6 @@ create_cse_send_buffer(TALLOC_CTX *mem_ctx,
return EOK;
}
-/*
- * This function uses the input ini_config object to parse the logon right value
- * associated with the input name. This value is a list of sids, and is used
- * to populate the output parameters.
- */
-static errno_t
-parse_logon_right_with_libini(TALLOC_CTX *mem_ctx,
- struct ini_cfgobj *ini_config,
- const char *name,
- int *_size,
- char ***_sids)
-{
- int ret = 0;
- struct value_obj *vobj = NULL;
- char **ini_sids = NULL;
- char *ini_sid = NULL;
- int num_ini_sids = 0;
- char **sids = NULL;
- int i;
- TALLOC_CTX *tmp_ctx = NULL;
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- ret = ini_get_config_valueobj(RIGHTS_SECTION, name, ini_config,
- INI_GET_FIRST_VALUE, &vobj);
- if (ret != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "ini_get_config_valueobj failed [%d][%s]\n", ret, strerror(ret));
- goto done;
- }
- if (vobj == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "section/name not found: [%s][%s]\n",
- RIGHTS_SECTION, name);
- ret = EOK;
- goto done;
- }
- ini_sids = ini_get_string_config_array(vobj, NULL, &num_ini_sids, &ret);
-
- if (ret != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "ini_get_string_config_array failed [%d][%s]\n",
- ret, strerror(ret));
- goto done;
- }
-
- sids = talloc_array(tmp_ctx, char *, num_ini_sids + 1);
- if (sids == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- for (i = 0; i < num_ini_sids; i++) {
- ini_sid = ini_sids[i];
-
- /* remove the asterisk prefix found on sids in the .inf policy file */
- if (ini_sid[0] == '*') {
- ini_sid++;
- }
- sids[i] = talloc_strdup(sids, ini_sid);
- if (sids[i] == NULL) {
- ret = ENOMEM;
- goto done;
- }
- }
- sids[i] = NULL;
-
- *_size = num_ini_sids;
- *_sids = talloc_steal(mem_ctx, sids);
-
- ret = EOK;
-
- done:
-
- ini_free_string_config_array(ini_sids);
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/*
- * This function parses the cse-specific (GP_EXT_GUID_SECURITY) input data_buf,
- * and uses the results to populate the output parameters with the list of
- * allowed_sids and denied_sids
- */
-static errno_t
-ad_gpo_parse_policy_file(TALLOC_CTX *mem_ctx,
- const char *filename,
- enum gpo_map_type gpo_map_type,
- char ***allowed_sids,
- int *allowed_size,
- char ***denied_sids,
- int *denied_size)
-{
- struct ini_cfgfile *file_ctx = NULL;
- struct ini_cfgobj *ini_config = NULL;
- int ret;
- char **allow_sids = NULL;
- char **deny_sids = NULL;
- int allow_size = 0;
- int deny_size = 0;
- const char *allow_key = NULL;
- const char *deny_key = NULL;
- TALLOC_CTX *tmp_ctx = NULL;
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- ret = ini_config_create(&ini_config);
- if (ret != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "ini_config_create failed [%d][%s]\n", ret, strerror(ret));
- goto done;
- }
-
- ret = ini_config_file_open(filename, 0, &file_ctx);
- if (ret != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "ini_config_file_open failed [%d][%s]\n", ret, strerror(ret));
- goto done;
- }
-
- ret = ini_config_parse(file_ctx, INI_STOP_ON_NONE, 0, 0, ini_config);
- if (ret != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "ini_config_parse failed [%d][%s]\n", ret, strerror(ret));
- goto done;
- }
-
- switch (gpo_map_type) {
- case GPO_MAP_INTERACTIVE:
- allow_key = ALLOW_LOGON_INTERACTIVE;
- deny_key = DENY_LOGON_INTERACTIVE;
- break;
- case GPO_MAP_REMOTE_INTERACTIVE:
- allow_key = ALLOW_LOGON_REMOTE_INTERACTIVE;
- deny_key = DENY_LOGON_REMOTE_INTERACTIVE;
- break;
- case GPO_MAP_NETWORK:
- allow_key = ALLOW_LOGON_NETWORK;
- deny_key = DENY_LOGON_NETWORK;
- break;
- case GPO_MAP_BATCH:
- allow_key = ALLOW_LOGON_BATCH;
- deny_key = DENY_LOGON_BATCH;
- break;
- case GPO_MAP_SERVICE:
- allow_key = ALLOW_LOGON_SERVICE;
- deny_key = DENY_LOGON_SERVICE;
- break;
- default:
- ret = EINVAL;
- goto done;
- }
-
- ret = parse_logon_right_with_libini(tmp_ctx,
- ini_config,
- allow_key,
- &allow_size,
- &allow_sids);
- if (ret != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "parse_logon_right_with_libini failed for %s [%d][%s]\n",
- allow_key, ret, strerror(ret));
- goto done;
- }
-
- ret = parse_logon_right_with_libini(tmp_ctx,
- ini_config,
- deny_key,
- &deny_size,
- &deny_sids);
- if (ret != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "parse_logon_right_with_libini failed for %s [%d][%s]\n",
- deny_key, ret, strerror(ret));
- goto done;
- }
-
- *allowed_sids = talloc_steal(mem_ctx, allow_sids);
- *allowed_size = allow_size;
- *denied_sids = talloc_steal(mem_ctx, deny_sids);
- *denied_size = deny_size;
-
- done:
-
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Error encountered: %d.\n", ret);
- }
-
- ini_config_file_destroy(file_ctx);
- ini_config_destroy(ini_config);
- talloc_free(tmp_ctx);
- return ret;
-}
-
static errno_t
ad_gpo_parse_gpo_child_response(TALLOC_CTX *mem_ctx,
uint8_t *buf,
@@ -3787,8 +3735,6 @@ struct ad_gpo_process_cse_state {
const char *gpo_guid;
const char *smb_path;
const char *smb_cse_suffix;
- int sysvol_gpt_version;
- const char *policy_filename;
pid_t child_pid;
uint8_t *buf;
ssize_t len;
@@ -3837,9 +3783,11 @@ static void gpo_cse_step(struct tevent_req *subreq);
static void gpo_cse_done(struct tevent_req *subreq);
/*
- * This cse-specific function (GP_EXT_GUID_SECURITY) retrieves the data
- * referenced by the input smb_uri, and uses the parsed results to populate the
- * state's list of allowed_sids and denied_sids.
+ * This cse-specific function (GP_EXT_GUID_SECURITY) sends the input smb uri
+ * components and cached_gpt_version to the gpo child, which, in turn,
+ * will download the GPT.INI file and policy files (as needed) and store
+ * them in the GPO_CACHE directory. Note that if the send_to_child input is
+ * false, this function simply completes the request.
*/
struct tevent_req *
ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
@@ -3866,25 +3814,11 @@ ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
return NULL;
}
- state->sysvol_gpt_version = -1;
-
if (!send_to_child) {
/*
- * if we don't need to talk to child (b/c cache timeout is valid),
- * we simply set the policy_filename and complete the request
+ * if we don't need to talk to child (b/c cache timeout is still valid),
+ * we simply complete the request
*/
- state->policy_filename =
- talloc_asprintf(state,
- GPO_CACHE_PATH"/%s/Policies/%s%s",
- domain->name,
- gpo_guid,
- GP_EXT_GUID_SECURITY_SUFFIX);
- if (state->policy_filename == NULL) {
- ret = ENOMEM;
- goto immediately;
- }
-
- DEBUG(SSSDBG_TRACE_FUNC, "policy_filename:%s\n", state->policy_filename);
ret = EOK;
goto immediately;
}
@@ -4009,17 +3943,6 @@ static void gpo_cse_done(struct tevent_req *subreq)
tevent_req_error(req, child_result);
}
- state->sysvol_gpt_version = sysvol_gpt_version;
- state->policy_filename = talloc_asprintf(state,
- GPO_CACHE_PATH"%s%s",
- state->smb_path,
- state->smb_cse_suffix);
- if (state->policy_filename == NULL) {
- tevent_req_error(req, ENOMEM);
- }
-
- DEBUG(SSSDBG_TRACE_FUNC, "policy_filename:%s\n", state->policy_filename);
-
now = time(NULL);
DEBUG(SSSDBG_TRACE_FUNC, "sysvol_gpt_version: %d\n", sysvol_gpt_version);
ret = sysdb_gpo_store_gpo(state->domain, state->gpo_guid, sysvol_gpt_version,
@@ -4036,19 +3959,9 @@ static void gpo_cse_done(struct tevent_req *subreq)
}
int ad_gpo_process_cse_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- int *_sysvol_gpt_version,
- const char **_policy_filename)
+ TALLOC_CTX *mem_ctx)
{
- struct ad_gpo_process_cse_state *state;
-
- state = tevent_req_data(req, struct ad_gpo_process_cse_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
-
- *_sysvol_gpt_version = state->sysvol_gpt_version;
- *_policy_filename = talloc_steal(mem_ctx, state->policy_filename);
-
return EOK;
}
diff --git a/src/tests/cmocka/test_ad_gpo.c b/src/tests/cmocka/test_ad_gpo.c
index e6319118e..4753c95d3 100644
--- a/src/tests/cmocka/test_ad_gpo.c
+++ b/src/tests/cmocka/test_ad_gpo.c
@@ -256,7 +256,6 @@ void test_populate_gplink_list_malformed(void **state)
};
test_populate_gplink_list(NULL, false, &expected);
- test_populate_gplink_list("[malformed", false, &expected);
test_populate_gplink_list("[malformed]", false, &expected);
/* the GPLinkOptions value (after semicolon) must be between 0 and 3 */
test_populate_gplink_list("[gpo_dn; 4]", false, &expected);