diff options
author | Yassir Elley <yelley@redhat.com> | 2014-07-05 15:37:23 -0400 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-07-20 21:29:26 +0200 |
commit | 32381402a4a9afc003782c9e2301fc59c9bda2a9 (patch) | |
tree | a1a37e17a18de49be0fd1df6e94feff1b98ab566 /src/providers/ad/ad_gpo.c | |
parent | b31b0a468ddbc9be4fc78289e5a0a108c31ec620 (diff) | |
download | sssd-32381402a4a9afc003782c9e2301fc59c9bda2a9.tar.gz sssd-32381402a4a9afc003782c9e2301fc59c9bda2a9.tar.xz sssd-32381402a4a9afc003782c9e2301fc59c9bda2a9.zip |
AD-GPO: Store policy settings in local files
Reviewed-by: Sumit Bose <sbose@redhat.com>
Diffstat (limited to 'src/providers/ad/ad_gpo.c')
-rw-r--r-- | src/providers/ad/ad_gpo.c | 366 |
1 files changed, 264 insertions, 102 deletions
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c index 32ef852f3..e33ea72e9 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -33,6 +33,8 @@ #include <security/pam_modules.h> #include <syslog.h> +#include <fcntl.h> +#include <ini_configobj.h> #include "util/util.h" #include "util/strtonum.h" #include "util/child_common.h" @@ -74,10 +76,15 @@ /* == gpo-smb constants ==================================================== */ #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_LOCALLY "SeInteractiveLogonRight" +#define DENY_LOGON_LOCALLY "SeDenyInteractiveLogonRight" + #define GP_EXT_GUID_SECURITY "{827D319E-6EAC-11D2-A4EA-00C04F79F83A}" #define GP_EXT_GUID_SECURITY_SUFFIX "/Microsoft/Windows NT/SecEdit/GptTmpl.inf" @@ -109,6 +116,7 @@ struct gp_gpo { const char *gpo_guid; const char *gpo_display_name; const char *gpo_file_sys_path; + const char *gpo_unix_path; uint32_t gpo_container_version; const char **gpo_cse_guids; int num_gpo_cse_guids; @@ -148,7 +156,8 @@ int ad_gpo_process_gpo_recv(struct tevent_req *req, int *num_candidate_gpos); struct tevent_req *ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - char *smb_uri); + char *cse_smb_uri, + char *cse_unix_path); int ad_gpo_process_cse_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, int *_allowed_size, @@ -1289,7 +1298,8 @@ ad_gpo_cse_step(struct tevent_req *req) { struct tevent_req *subreq; struct ad_gpo_access_state *state; - char *smb_uri; + char *cse_smb_uri; + char *cse_unix_path; int i = 0; state = tevent_req_data(req, struct ad_gpo_access_state); @@ -1303,19 +1313,21 @@ ad_gpo_cse_step(struct tevent_req *req) DEBUG(SSSDBG_TRACE_FUNC, "cse filtered_gpos[%d]->gpo_guid is %s\n", state->cse_gpo_index, cse_filtered_gpo->gpo_guid); - DEBUG(SSSDBG_TRACE_FUNC, "cse filtered_gpos[%d]->file_sys_path is %s\n", - state->cse_gpo_index, cse_filtered_gpo->gpo_file_sys_path); for (i = 0; i < cse_filtered_gpo->num_gpo_cse_guids; i++) { DEBUG(SSSDBG_TRACE_ALL, "cse_filtered_gpos[%d]->gpo_cse_guids[%d]->gpo_guid is %s\n", state->cse_gpo_index, i, cse_filtered_gpo->gpo_cse_guids[i]); } - smb_uri = talloc_asprintf(state, "%s%s", - cse_filtered_gpo->gpo_file_sys_path, - GP_EXT_GUID_SECURITY_SUFFIX); + cse_smb_uri = talloc_asprintf(state, "%s%s", + cse_filtered_gpo->gpo_file_sys_path, + GP_EXT_GUID_SECURITY_SUFFIX); + + cse_unix_path = talloc_asprintf(state, "%s%s", + cse_filtered_gpo->gpo_unix_path, + GP_EXT_GUID_SECURITY_SUFFIX); - subreq = ad_gpo_process_cse_send(state, state->ev, smb_uri); + subreq = ad_gpo_process_cse_send(state, state->ev, cse_smb_uri, cse_unix_path); tevent_req_set_callback(subreq, ad_gpo_cse_done, req); return EAGAIN; @@ -1344,8 +1356,8 @@ ad_gpo_cse_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_gpo_access_state); - ret = ad_gpo_process_cse_recv(subreq, state, &allowed_size, &allowed_sids, - &denied_size, &denied_sids); + ret = ad_gpo_process_cse_recv(subreq, state, &allowed_size, + &allowed_sids, &denied_size, &denied_sids); talloc_zfree(subreq); @@ -2262,39 +2274,48 @@ ad_gpo_populate_candidate_gpos(TALLOC_CTX *mem_ctx, } /* - * This function converts the input_path to an smb uri, which is used to - * populate the _converted_path output parameter. The output is constructed by - * concatenating the following elements: + * This function converts the input_path to an smb uri and a unix_path, which + * are used to populate the _smb_uri and _unix_path output parameters, + * respectively. + * + * The smb_path starts with the slash immediately after the domain name, while + * the unix_path starts with the following slash (immediately after the share name). + * + * The _smb_uri output is constructed by concatenating the following elements: * - SMB_STANDARD_URI ("smb://") * - server_hostname (which replaces domain_name in input path) - * - smb_path (which starts with the slash immediately after the domain name + * - smb_path * Additionally, each forward slash ('\') is replaced with a back slash ('/') * * Example: if input_path = "\\foo.com\SysVol\foo.com\..." and - * server_hostname = "adserver.foo.com", then _converted_path would be - * "smb://adserver.foo.com/SysVol/foo.com/..." + * server_hostname = "adserver.foo.com", then + * _smb_uri = "smb://adserver.foo.com/SysVol/foo.com/..."; and + * _unix_path = "/foo.com/..." * - * Note that the input_path must have at least three forward slash separators. - * For example, input_path = "\\foo.com" is not a valid input_path, because - * it has only two forward slash separators. + * Note that the input_path must have at least four forward slash separators. + * For example, input_path = "\\foo.com\SysVol" is not a valid input_path, + * because it has only three forward slash separators. */ static errno_t ad_gpo_convert_to_smb_uri(TALLOC_CTX *mem_ctx, char *server_hostname, char *input_path, - const char **_converted_path) + const char **_smb_uri, + const char **_unix_path) { char *ptr; const char delim = '\\'; int ret; int num_seps = 0; char *smb_path = NULL; + char *unix_path = NULL; DEBUG(SSSDBG_TRACE_ALL, "input_path: %s\n", input_path); if (input_path == NULL || *input_path == '\0' || - _converted_path == NULL) { + _smb_uri == NULL || + _unix_path == NULL) { ret = EINVAL; goto done; } @@ -2305,6 +2326,9 @@ ad_gpo_convert_to_smb_uri(TALLOC_CTX *mem_ctx, if (num_seps == 3) { /* keep track of path from third slash onwards (after domain name) */ smb_path = ptr; + } else if (num_seps == 4) { + /* keep track of path from fourth slash onwards (after share name) */ + unix_path = ptr; } *ptr = '/'; ptr++; @@ -2315,15 +2339,19 @@ ad_gpo_convert_to_smb_uri(TALLOC_CTX *mem_ctx, goto done; } - if (smb_path == NULL) { + if (smb_path == NULL || unix_path == NULL) { ret = EINVAL; goto done; } - *_converted_path = talloc_asprintf(mem_ctx, "%s%s%s", - SMB_STANDARD_URI, - server_hostname, - smb_path); + + *_smb_uri = talloc_asprintf(mem_ctx, "%s%s%s", + SMB_STANDARD_URI, + server_hostname, + smb_path); + + *_unix_path = talloc_strdup(mem_ctx, unix_path); + ret = EOK; done: @@ -2595,6 +2623,7 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq) struct ldb_message_element *el = NULL; const char *gpo_guid = NULL; const char *smb_uri = NULL; + const char *unix_path = NULL; const char *gpo_display_name = NULL; const char *raw_file_sys_path = NULL; char *file_sys_path = NULL; @@ -2681,7 +2710,7 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq) file_sys_path = talloc_strdup(gp_gpo, raw_file_sys_path); ad_gpo_convert_to_smb_uri(state, state->server_hostname, file_sys_path, - &smb_uri); + &smb_uri, &unix_path); gp_gpo->gpo_file_sys_path = talloc_asprintf(gp_gpo, "%s/Machine", smb_uri); @@ -2693,6 +2722,16 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq) DEBUG(SSSDBG_TRACE_FUNC, "gpo_file_sys_path: %s\n", gp_gpo->gpo_file_sys_path); + gp_gpo->gpo_unix_path = talloc_asprintf(gp_gpo, "%s/Machine", + unix_path); + if (gp_gpo->gpo_unix_path == NULL) { + ret = ENOMEM; + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "gpo_unix_path: %s\n", + gp_gpo->gpo_unix_path); + /* retrieve AD_AT_VERSION_NUMBER */ ret = sysdb_attrs_get_uint32_t(results[0], AD_AT_VERSION_NUMBER, &gp_gpo->gpo_container_version); @@ -2807,17 +2846,17 @@ ad_gpo_process_gpo_recv(struct tevent_req *req, static errno_t create_cse_send_buffer(TALLOC_CTX *mem_ctx, - char *smb_uri, + char *cse_smb_uri, + char *cse_unix_path, struct io_buffer **io_buf) { struct io_buffer *buf; size_t rp; - int smb_uri_length; - - smb_uri_length = strlen(smb_uri); + int cse_smb_uri_length; + int cse_unix_path_length; - DEBUG(SSSDBG_TRACE_FUNC, "smb_uri: %s\n", smb_uri); - DEBUG(SSSDBG_TRACE_FUNC, "strlen(smb_uri): %d\n", smb_uri_length); + cse_smb_uri_length = strlen(cse_smb_uri); + cse_unix_path_length = strlen(cse_unix_path); buf = talloc(mem_ctx, struct io_buffer); if (buf == NULL) { @@ -2825,8 +2864,8 @@ create_cse_send_buffer(TALLOC_CTX *mem_ctx, return ENOMEM; } - buf->size = 1 * sizeof(uint32_t); - buf->size += smb_uri_length; + buf->size = 2 * sizeof(uint32_t); + buf->size += cse_smb_uri_length + cse_unix_path_length; DEBUG(SSSDBG_TRACE_ALL, "buffer size: %zu\n", buf->size); @@ -2838,31 +2877,38 @@ create_cse_send_buffer(TALLOC_CTX *mem_ctx, } rp = 0; - /* smb_uri */ - SAFEALIGN_SET_UINT32(&buf->data[rp], smb_uri_length, &rp); - safealign_memcpy(&buf->data[rp], smb_uri, smb_uri_length, &rp); + /* cse_smb_uri */ + SAFEALIGN_SET_UINT32(&buf->data[rp], cse_smb_uri_length, &rp); + safealign_memcpy(&buf->data[rp], cse_smb_uri, cse_smb_uri_length, &rp); + + /* cse_unix_path */ + SAFEALIGN_SET_UINT32(&buf->data[rp], cse_unix_path_length, &rp); + safealign_memcpy(&buf->data[rp], cse_unix_path, cse_unix_path_length, &rp); *io_buf = buf; 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. The input name can be either + * ALLOW_LOGON_LOCALLY or DENY_LOGON_LOCALLY. + */ static errno_t -parse_gpo_child_response(TALLOC_CTX *mem_ctx, - uint8_t *buf, ssize_t size, - char ***_allowed_sids, - int *_allowed_size, - char ***_denied_sids, - int *_denied_size) +parse_logon_right_with_libini(TALLOC_CTX *mem_ctx, + struct ini_cfgobj *ini_config, + const char *name, + int *_size, + char ***_sids) { - size_t p = 0; - uint32_t res; - errno_t ret; - int allowed_size = 0; - int denied_size = 0; - int i = 0; - int sid_len = 0; - char **allowed_sids; - char **denied_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); @@ -2871,77 +2917,175 @@ parse_gpo_child_response(TALLOC_CTX *mem_ctx, goto done; } - /* operation result code */ - SAFEALIGN_COPY_UINT32_CHECK(&res, buf + p, size, &p); + 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); - /* allowed_size */ - SAFEALIGN_COPY_UINT32_CHECK(&allowed_size, buf + p, size, &p); - DEBUG(SSSDBG_TRACE_FUNC, "child response allowed_size: %d\n", allowed_size); + if (ret != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "ini_get_string_config_array failed [%d][%s]\n", ret, strerror(ret)); + goto done; + } - allowed_sids = talloc_array(tmp_ctx, char *, allowed_size); - if (allowed_sids == NULL) { + sids = talloc_array(tmp_ctx, char *, num_ini_sids + 1); + if (sids == NULL) { ret = ENOMEM; goto done; } - for (i = 0; i < allowed_size; i++) { - SAFEALIGN_COPY_UINT32_CHECK(&sid_len, buf + p, size, &p); - if ((p + sid_len ) > size) { - ret = EINVAL; - 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++; } - allowed_sids[i] = talloc_strndup(allowed_sids, - (const char *)buf + p, - sid_len); - if (allowed_sids[i] == NULL) { + sids[i] = talloc_strdup(sids, ini_sid); + if (sids[i] == NULL) { ret = ENOMEM; goto done; } - p += sid_len; } + sids[i] = NULL; + + *_size = num_ini_sids; + *_sids = talloc_steal(mem_ctx, sids); + + ret = EOK; - /* denied_size */ - SAFEALIGN_COPY_UINT32_CHECK(&denied_size, buf + p, size, &p); - DEBUG(SSSDBG_TRACE_FUNC, "child response denied_size: %d\n", denied_size); + done: - denied_sids = talloc_array(tmp_ctx, char *, denied_size); - if (denied_sids == NULL) { + 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_security_cse_buffer(TALLOC_CTX *mem_ctx, + const char *filename, + 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 *key = NULL; + TALLOC_CTX *tmp_ctx = NULL; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { ret = ENOMEM; goto done; } - for (i = 0; i < denied_size; i++) { - SAFEALIGN_COPY_UINT32_CHECK(&sid_len, buf + p, size, &p); - if ((p + sid_len ) > size) { - ret = EINVAL; - goto done; - } - denied_sids[i] = talloc_strndup(denied_sids, - (const char *)buf + p, - sid_len); - if (denied_sids[i] == NULL) { - ret = ENOMEM; - goto done; - } - p += sid_len; + 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; } - *_allowed_size = allowed_size; - *_allowed_sids = talloc_steal(mem_ctx, allowed_sids); - *_denied_size = denied_size; - *_denied_sids = talloc_steal(mem_ctx, denied_sids); + 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 = EOK; + 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; + } + + key = ALLOW_LOGON_LOCALLY; + ret = parse_logon_right_with_libini(tmp_ctx, + ini_config, + key, + &allow_size, + &allow_sids); + if (ret != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "parse_logon_right_with_libini failed for %s [%d][%s]\n", + key, ret, strerror(ret)); + goto done; + } + + key = DENY_LOGON_LOCALLY; + ret = parse_logon_right_with_libini(tmp_ctx, + ini_config, + DENY_LOGON_LOCALLY, + &deny_size, + &deny_sids); + if (ret != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "parse_logon_right_with_libini failed for %s [%d][%s]\n", + 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, ssize_t size, uint32_t *_result) +{ + + int ret; + size_t p = 0; + uint32_t result; + + /* operation result code */ + SAFEALIGN_COPY_UINT32_CHECK(&result, buf + p, size, &p); + + *_result = result; + ret = EOK; + return ret; +} + /* == ad_gpo_process_cse_send/recv implementation ========================== */ struct ad_gpo_process_cse_state { struct tevent_context *ev; + const char *cse_unix_path; pid_t child_pid; uint8_t *buf; ssize_t len; @@ -2997,7 +3141,8 @@ static void gpo_cse_done(struct tevent_req *subreq); struct tevent_req * ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - char *smb_uri) + char *cse_smb_uri, + char *cse_unix_path) { struct tevent_req *req; struct tevent_req *subreq; @@ -3012,6 +3157,7 @@ ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx, } state->ev = ev; + state->cse_unix_path = cse_unix_path; state->buf = NULL; state->len = 0; @@ -3027,7 +3173,7 @@ ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx, talloc_set_destructor((void *) state->io, gpo_child_io_destructor); /* prepare the data to pass to child */ - ret = create_cse_send_buffer(state, smb_uri, &buf); + ret = create_cse_send_buffer(state, cse_smb_uri, cse_unix_path, &buf); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "create_cse_send_buffer failed.\n"); goto fail; @@ -3114,25 +3260,41 @@ int ad_gpo_process_cse_recv(struct tevent_req *req, char ***_denied_sids) { int ret; + uint32_t result; char **allowed_sids; int allowed_size; char **denied_sids; int denied_size; struct ad_gpo_process_cse_state *state; + const char *filename = NULL; state = tevent_req_data(req, struct ad_gpo_process_cse_state); TEVENT_REQ_RETURN_ON_ERROR(req); - ret = parse_gpo_child_response(mem_ctx, state->buf, state->len, - &allowed_sids, - &allowed_size, - &denied_sids, - &denied_size); + ret = ad_gpo_parse_gpo_child_response(state, state->buf, state->len, &result); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "ad_gpo_parse_gpo_child_response failed: [%d][%s]\n", ret, strerror(ret)); + return ret; + } else if (result != 0){ + DEBUG(SSSDBG_CRIT_FAILURE, + "Error in gpo_child: [%d][%s]\n", result, strerror(result)); + return result; + } + + filename = talloc_asprintf(mem_ctx, GPO_CACHE_PATH"%s", state->cse_unix_path); + + ret = ad_gpo_parse_security_cse_buffer(state, + filename, + &allowed_sids, + &allowed_size, + &denied_sids, + &denied_size); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, - "Cannot parse child response: [%d][%s]\n", ret, strerror(ret)); + "ad_gpo_parse_security_cse_buffer failed: [%d][%s]\n", ret, strerror(ret)); return ret; } |