Hi, The attached patch fixes ticket #2437 (conflicting gpo policy settings not being resolved correctly)
https://fedorahosted.org/sssd/ticket/2437 Regards, Yassir.
From a3e0abad5341b96aa1909082778bd1abb6746c5a Mon Sep 17 00:00:00 2001 From: Yassir Elley <yel...@redhat.com> Date: Tue, 9 Sep 2014 15:37:05 -0400 Subject: [PATCH] AD-GPO resolve conflicting policy settings correctly --- src/providers/ad/ad_gpo.c | 848 ++++++++++++++++++++++++++-------------------- 1 file changed, 474 insertions(+), 374 deletions(-) diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c index de4d44166b85ccd85ed36bcb11f0596e0020af11..f3a6ebfd53118a95ae866e159f91ea84ae949e46 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -176,9 +176,8 @@ 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 ==================================*/ @@ -1029,6 +1028,238 @@ check_rights(char **privilege_sids, return false; } + +static void dump_policy_file(enum gpo_map_type gpo_map_type, + char **allowed_sids, + int allowed_size, + char **denied_sids, + int denied_size) +{ + 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, "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, "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]); + } +} + +/* + * 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. If the allowed_sids input or denied_sids input + * has been set to NULL by the caller, then this function will not return the + * allowed_sids or denied_sids, respectively, from the filename. + */ +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; + } + + if (allowed_sids != NULL) { + 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; + } + + *allowed_sids = talloc_steal(mem_ctx, allow_sids); + *allowed_size = allow_size; + } + + if (denied_sids != NULL) { + 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; + } + + *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; +} + /* * This cse-specific function (GP_EXT_GUID_SECURITY) performs HBAC policy * application and determines whether logon access is granted or denied for @@ -1072,19 +1303,8 @@ 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, "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, "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]); - } + dump_policy_file(gpo_map_type, allowed_sids, allowed_size, + denied_sids, denied_size); ret = ad_gpo_get_sids(mem_ctx, user, domain, &user_sid, &group_sids, &group_size); @@ -1171,6 +1391,149 @@ static errno_t gpo_child_init(void) return EOK; } +/* + * 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 parses each of the input policy_filenames + * (extracting the allowed_sids and denied_sids for the input gpo_map_type), and + * determines the gpo_index of the last policy_filename which contains an allow + * policy setting (allowed_gpo_index), as well as the gpo_index of the last + * policy_filename which contains a deny policy setting (denied_gpo_index). + * + * Since the policy_filenames are in priority order (with the highest priority + * appearing last), this function is essentially implementing the + * "last policy wins" mechanism. Note that this conflict resolution mechanism + * ("last policy wins") applies per policy setting. In other words, if more + * than one policy_filename contains the SeInteractiveLogonRight, then the + * last policy_filename "overwrites" all previous settings of that key. + * Similarly, if more than one policy_filename contains the + * SeDenyInteractiveLogonRight, then the last policy_filename "overwrites" all + * previous settings of that key. + */ +static errno_t ad_gpo_perform_hbac_processing(TALLOC_CTX *mem_ctx, + int num_cse_filtered_gpos, + const char **policy_filenames, + enum gpo_access_control_mode gpo_mode, + enum gpo_map_type gpo_map_type, + const char *user, + struct sss_domain_info *domain) +{ + int i; + int ret; + char **allowed_sids_temp; + int allowed_size_temp; + char **denied_sids_temp; + int denied_size_temp; + char **allowed_sids_result; + int allowed_size_result; + int allowed_gpo_index = -1; + char **denied_sids_result; + int denied_size_result; + int denied_gpo_index = -1; + + /* + * for the given gpo_map_type, we parse each policy file, in priority order; + * we initialize the allowed_gpo_index and denied_gpo_index with -1; + * we keep track of the last gpo_index which has an allow policy setting; + * we keep track of the last gpo_index which has a deny policy setting; + */ + + for (i = 0; i < num_cse_filtered_gpos; i++) { + + ret = ad_gpo_parse_policy_file(mem_ctx, + policy_filenames[i], + gpo_map_type, + &allowed_sids_temp, + &allowed_size_temp, + &denied_sids_temp, + &denied_size_temp); + + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot parse policy file: [%s][%d][%s]\n", + policy_filenames[i], ret, strerror(ret)); + goto done; + } + + if (allowed_size_temp != 0) { + allowed_gpo_index = i; + } + + if (denied_size_temp != 0) { + denied_gpo_index = i; + } + + DEBUG(SSSDBG_TRACE_FUNC, "allowed_gpo_index: %d\n", allowed_gpo_index); + DEBUG(SSSDBG_TRACE_FUNC, "denied_gpo_index: %d\n", denied_gpo_index); + dump_policy_file(gpo_map_type, allowed_sids_temp, allowed_size_temp, + denied_sids_temp, denied_size_temp); + } + + /* + * if either gpo_index is -1, we set the corresponding size_result to 0; + * otherwise, we return the allowed and denied sids from the most + * recent gpo to have those settings (i.e. last gpo wins, since it has + * highest priority) + */ + if (allowed_gpo_index != -1) { + ret = ad_gpo_parse_policy_file(mem_ctx, + policy_filenames[allowed_gpo_index], + gpo_map_type, + &allowed_sids_result, + &allowed_size_result, + NULL, + 0); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot parse policy file: [%s][%d][%s]\n", + policy_filenames[allowed_gpo_index], ret, strerror(ret)); + goto done; + } + } else { + /* none of the policy files contained an allow key for the gpo map type */ + allowed_size_result = 0; + } + + if (denied_gpo_index != -1) { + ret = ad_gpo_parse_policy_file(mem_ctx, + policy_filenames[denied_gpo_index], + gpo_map_type, + NULL, + 0, + &denied_sids_result, + &denied_size_result); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot parse policy file: [%s][%d][%s]\n", + policy_filenames[denied_gpo_index], ret, strerror(ret)); + goto done; + } + } else { + /* none of the policy files contained a deny key for the gpo map type */ + denied_size_result = 0; + } + + /* perform the access check with the resultant allowed_sids and denied_sids */ + ret = ad_gpo_access_check + (mem_ctx, gpo_mode, gpo_map_type, user, + domain, allowed_sids_result, allowed_size_result, + denied_sids_result, denied_size_result); + + 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 { @@ -1193,6 +1556,7 @@ struct ad_gpo_access_state { struct gp_gpo **cse_filtered_gpos; int num_cse_filtered_gpos; int cse_gpo_index; + const char **policy_filenames; }; static void ad_gpo_connect_done(struct tevent_req *subreq); @@ -1361,78 +1725,18 @@ 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; + const char *cached_gpo_guid; errno_t ret; int i; + const char **policy_filenames; ret = sysdb_gpo_get_gpos(mem_ctx, domain, &res); @@ -1454,16 +1758,46 @@ process_offline_gpos(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_TRACE_FUNC, "Retrieving GPOs from cache\n"); DEBUG(SSSDBG_TRACE_FUNC, "Found %d GPO(s) in cache\n", res->count); + /* we create and populate an array of policy filenames */ + policy_filenames = talloc_array(mem_ctx, const char *, res->count); + if (policy_filenames == NULL) { + ret = ENOMEM; + goto done; + } + 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)); + 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; goto done; } + + policy_filenames[i] = talloc_asprintf(mem_ctx, + GPO_CACHE_PATH"/%s/Policies/%s%s", + domain->name, + cached_gpo_guid, + GP_EXT_GUID_SECURITY_SUFFIX); + if (policy_filenames[i] == NULL) { + ret = ENOMEM; + goto done; + } + } + + ret = ad_gpo_perform_hbac_processing(mem_ctx, + res->count, + policy_filenames, + gpo_mode, + gpo_map_type, + user, + domain); + + if (ret != EOK) { + 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 +2054,13 @@ 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. + * This function then removes any stale gpo cache entries (i.e. entries that + * have a gpo-guid that doesn't match any of the gpo-guids in the cse_guids list) + * to prevent "tattooing". + * + * 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) @@ -1821,6 +2160,14 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq) DEBUG(SSSDBG_TRACE_FUNC, "num_cse_filtered_gpos: %d\n", state->num_cse_filtered_gpos); + /* we create and populate an array of policy filenames */ + state->policy_filenames = + talloc_array(state, const char *, state->num_cse_filtered_gpos); + if (state->policy_filenames == NULL) { + ret = ENOMEM; + goto done; + } + /* * 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 @@ -1870,7 +2217,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 only 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", @@ -1886,6 +2233,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); + state->policy_filenames[state->cse_gpo_index] = + talloc_asprintf(state->policy_filenames, + GPO_CACHE_PATH"%s%s", + cse_filtered_gpo->smb_path, + GP_EXT_GUID_SECURITY_SUFFIX); + if (state->policy_filenames[state->cse_gpo_index] == 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); @@ -1946,13 +2302,9 @@ 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 files for all applicable GPOs have been + * downloaded. Once that happens, this functions performs HBAC processing. */ static void ad_gpo_cse_done(struct tevent_req *subreq) @@ -1960,12 +2312,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); @@ -1977,8 +2323,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); @@ -1988,35 +2333,26 @@ 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); - - 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 - (state, state->gpo_mode, state->gpo_map_type, state->user, - state->domain, allowed_sids, allowed_size, denied_sids, denied_size); - - 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); + if (ret == EOK) { + /* ret is EOK only after all GPO policy files have been downloaded */ + ret = ad_gpo_perform_hbac_processing(state, + state->num_cse_filtered_gpos, + state->policy_filenames, + 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; + } + + } + done: if (ret == EOK) { @@ -3550,207 +3886,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, @@ -3786,8 +3921,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; @@ -3836,9 +3969,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, @@ -3865,25 +4000,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; } @@ -4008,17 +4129,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, @@ -4035,19 +4145,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; } -- 1.8.5.3
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/sssd-devel