diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | contrib/sssd.spec.in | 3 | ||||
-rw-r--r-- | src/conf_macros.m4 | 17 | ||||
-rw-r--r-- | src/providers/ad/ad_gpo.c | 366 | ||||
-rw-r--r-- | src/providers/ad/ad_gpo_child.c | 387 |
6 files changed, 426 insertions, 350 deletions
diff --git a/Makefile.am b/Makefile.am index 8d3d366b4..e3592868c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,6 +61,7 @@ systemdunitdir = @systemdunitdir@ systemdconfdir = @systemdconfdir@ logpath = @logpath@ pubconfpath = @pubconfpath@ +gpocachepath = @gpocachepath@ pkgconfigdir = $(libdir)/pkgconfig krb5rcachedir = @krb5rcachedir@ sudolibdir = @sudolibpath@ @@ -2606,6 +2607,7 @@ installsssddirs:: $(DESTDIR)$(logpath) \ $(DESTDIR)$(pubconfpath) \ $(DESTDIR)$(pubconfpath)/krb5.include.d \ + $(DESTDIR)$(gpocachepath) \ $(DESTDIR)$(sudolibdir) \ $(DESTDIR)$(autofslibdir) diff --git a/configure.ac b/configure.ac index b184b86a3..38654219b 100644 --- a/configure.ac +++ b/configure.ac @@ -112,6 +112,7 @@ WITH_CIFS_PLUGIN_PATH WITH_SELINUX WITH_NSCD WITH_SEMANAGE +WITH_GPO_CACHE_PATH WITH_NOLOGIN_SHELL WITH_APP_LIBS WITH_SUDO diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index fb5500221..82d8e895c 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -77,6 +77,7 @@ Requires: python-sssdconfig = %{version}-%{release} %global pipepath %{sssdstatedir}/pipes %global mcpath %{sssdstatedir}/mc %global pubconfpath %{sssdstatedir}/pubconf +%global gpocachepath %{sssdstatedir}/gpo_cache ### Build Dependencies ### @@ -447,6 +448,7 @@ autoreconf -ivf --with-mcache-path=%{mcpath} \ --with-pipe-path=%{pipepath} \ --with-pubconf-path=%{pubconfpath} \ + --with-gpo-cache-path=%{gpocachepath} \ --with-init-dir=%{_initrddir} \ --with-krb5-rcache-dir=%{_localstatedir}/cache/krb5rcache \ --enable-nsslibdir=/%{_lib} \ @@ -615,6 +617,7 @@ rm -rf $RPM_BUILD_ROOT %ghost %attr(0644,root,root) %verify(not md5 size mtime) %{mcpath}/group %attr(755,root,root) %dir %{pipepath} %attr(755,root,root) %dir %{pubconfpath} +%attr(755,root,root) %dir %{gpocachepath} %attr(700,root,root) %dir %{pipepath}/private %attr(750,root,root) %dir %{_var}/log/%{name} %attr(711,root,root) %dir %{_sysconfdir}/sssd diff --git a/src/conf_macros.m4 b/src/conf_macros.m4 index 3a042a81b..3c9827b4d 100644 --- a/src/conf_macros.m4 +++ b/src/conf_macros.m4 @@ -453,6 +453,23 @@ AC_DEFUN([WITH_SEMANAGE], AM_CONDITIONAL([BUILD_SEMANAGE], [test x"$with_semanage" = xyes]) ]) +AC_DEFUN([WITH_GPO_CACHE_PATH], + [ AC_ARG_WITH([gpo-cache-path], + [AC_HELP_STRING([--with-gpo-cache-path=PATH], + [Where to store GPO policy files [/var/lib/sss/gpo_cache]] + ) + ] + ) + config_gpocachepath="\"VARDIR\"/lib/sss/gpo_cache" + gpocachepath="${localstatedir}/lib/sss/gpo_cache" + if test x"$with_gpo_cache_path" != x; then + config_gpocachepath=$with_gpo_cache_path + gpocachepath=$with_gpo_cache_path + fi + AC_SUBST(gpocachepath) + AC_DEFINE_UNQUOTED(GPO_CACHE_PATH, "$config_gpocachepath", [Where to store GPO policy files]) + ]) + AC_DEFUN([WITH_LIBNL], [ AC_ARG_WITH([libnl], [AC_HELP_STRING([--with-libnl], 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; } diff --git a/src/providers/ad/ad_gpo_child.c b/src/providers/ad/ad_gpo_child.c index 31c5c99b1..22b8b5204 100644 --- a/src/providers/ad/ad_gpo_child.c +++ b/src/providers/ad/ad_gpo_child.c @@ -27,7 +27,6 @@ #include <sys/stat.h> #include <popt.h> #include <libsmbclient.h> -#include <ini_configobj.h> #include <security/pam_modules.h> #include "util/util.h" @@ -42,6 +41,7 @@ struct input_buffer { const char *smb_uri; + const char *unix_path; }; static errno_t @@ -52,12 +52,10 @@ unpack_buffer(uint8_t *buf, size_t p = 0; uint32_t len; - DEBUG(SSSDBG_TRACE_FUNC, "total buffer size: %zu\n", size); - /* smb_uri size and length */ SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p); - DEBUG(SSSDBG_TRACE_FUNC, "smb_uri size: %d\n", len); + DEBUG(SSSDBG_TRACE_ALL, "smb_uri size: %d\n", len); if (len == 0) { return EINVAL; @@ -65,7 +63,22 @@ unpack_buffer(uint8_t *buf, if ((p + len ) > size) return EINVAL; ibuf->smb_uri = talloc_strndup(ibuf, (char *)(buf + p), len); if (ibuf->smb_uri == NULL) return ENOMEM; - DEBUG(SSSDBG_TRACE_FUNC, "got smb_uri: %s\n", ibuf->smb_uri); + DEBUG(SSSDBG_TRACE_ALL, "got smb_uri: %s\n", ibuf->smb_uri); + p += len; + } + + /* unix_path size and length */ + SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p); + + DEBUG(SSSDBG_TRACE_ALL, "unix_path size: %d\n", len); + + if (len == 0) { + return EINVAL; + } else { + if ((p + len ) > size) return EINVAL; + ibuf->unix_path = talloc_strndup(ibuf, (char *)(buf + p), len); + if (ibuf->unix_path == NULL) return ENOMEM; + DEBUG(SSSDBG_TRACE_ALL, "got unix_path: %s\n", ibuf->unix_path); p += len; } @@ -75,91 +88,36 @@ unpack_buffer(uint8_t *buf, static errno_t pack_buffer(struct response *r, - int result, - int allowed_size, - char **allowed_sids, - int denied_size, - char **denied_sids) + int result) { - int len = 0; size_t p = 0; - int i; - int sid_len = 0; /* A buffer with the following structure must be created: * uint32_t status of the request (required) - * uint32_t allowed_size (required) - * sid_message* (allowed_size instances) - * uint32_t denied_size (required) - * sid_message* (denied_size instances) - * - * A sid_message consists of: - * uint32_t sid_len - * uint8_t[sid_len] sid string */ - - DEBUG(SSSDBG_TRACE_FUNC, "entering pack_buffer\n"); - - for (i = 0; i < allowed_size; i++) { - len += strlen(allowed_sids[i]); - } - - for (i = 0; i < denied_size; i++) { - len += strlen(denied_sids[i]); - } - - r->size = (3 + allowed_size + denied_size) * sizeof(uint32_t) + len; - - DEBUG(SSSDBG_TRACE_FUNC, "response size: %zu\n",r->size); + r->size = sizeof(uint32_t); r->buf = talloc_array(r, uint8_t, r->size); if(r->buf == NULL) { return ENOMEM; } - DEBUG(SSSDBG_TRACE_FUNC, - "result [%d] allowed_size [%d] denied_size [%d]\n", - result, allowed_size, denied_size); + DEBUG(SSSDBG_TRACE_FUNC, "result [%d]\n", result); /* result */ SAFEALIGN_SET_UINT32(&r->buf[p], result, &p); - /* allowed_size */ - SAFEALIGN_SET_UINT32(&r->buf[p], allowed_size, &p); - - /* allowed_sids */ - for (i = 0; i < allowed_size; i++) { - sid_len = strlen(allowed_sids[i]); - SAFEALIGN_SET_UINT32(&r->buf[p], sid_len, &p); - safealign_memcpy(&r->buf[p], allowed_sids[i], sid_len, &p); - } - - /* denied_size */ - SAFEALIGN_SET_UINT32(&r->buf[p], denied_size, &p); - - /* denied_sids */ - for (i = 0; i < denied_size; i++) { - sid_len = strlen(denied_sids[i]); - SAFEALIGN_SET_UINT32(&r->buf[p], sid_len, &p); - safealign_memcpy(&r->buf[p], denied_sids[i], sid_len, &p); - } - return EOK; } static errno_t prepare_response(TALLOC_CTX *mem_ctx, int result, - int allowed_size, - char **allowed_sids, - int denied_size, - char **denied_sids, struct response **rsp) { int ret; struct response *r = NULL; - DEBUG(SSSDBG_TRACE_FUNC, "entering prepare_response.\n"); r = talloc_zero(mem_ctx, struct response); if (r == NULL) { return ENOMEM; @@ -168,7 +126,7 @@ prepare_response(TALLOC_CTX *mem_ctx, r->buf = NULL; r->size = 0; - ret = pack_buffer(r, result, allowed_size, allowed_sids, denied_size, denied_sids); + ret = pack_buffer(r, result); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "pack_buffer failed\n"); return ret; @@ -179,110 +137,92 @@ prepare_response(TALLOC_CTX *mem_ctx, return EOK; } +static void +sssd_krb_get_auth_data_fn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword) +{ + /* since we are using kerberos for authentication, we simply return */ + return; +} + /* - * 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. + * This function prepares the gpo_cache by: + * - parsing the input_unix_path into its component directories + * - creating each component directory (if it doesn't already exist) */ -static errno_t -parse_logon_right_with_libini(TALLOC_CTX *mem_ctx, - struct ini_cfgobj *ini_config, - const char *name, - int *_size, - char ***_sids) +static errno_t prepare_gpo_cache(TALLOC_CTX *mem_ctx, + const char *cache_dir, + const char *input_unix_path) { - int ret = 0; - struct value_obj *vobj = NULL; - char **ini_sids = NULL; - char *ini_sid = NULL; - int num_ini_sids = 0; - char **sids = NULL; + char *current_dir; + char *ptr; + const char delim = '/'; + int num_dirs = 0; int i; - TALLOC_CTX *tmp_ctx = NULL; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - ret = ENOMEM; - goto done; - } + char *first = NULL; + char *last = NULL; + char *unix_path = NULL; - 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; + unix_path = talloc_strdup(mem_ctx, input_unix_path); + if (unix_path == NULL) { + return ENOMEM; } - 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; + current_dir = talloc_strdup(mem_ctx, cache_dir); + if (current_dir == NULL) { + return ENOMEM; } - sids = talloc_array(tmp_ctx, char *, num_ini_sids + 1); - if (sids == NULL) { - ret = ENOMEM; - goto done; + ptr = unix_path + 1; + while ((ptr = strchr(ptr, delim))) { + ptr++; + num_dirs++; } - for (i = 0; i < num_ini_sids; i++) { - ini_sid = ini_sids[i]; + ptr = unix_path + 1; - /* remove the asterisk prefix found on sids in the .inf policy file */ - if (ini_sid[0] == '*') { - ini_sid++; + for (i = 0; i < num_dirs; i++) { + first = ptr; + last = strchr(first, delim); + if (last == NULL) { + return EINVAL; } - sids[i] = talloc_strdup(sids, ini_sid); - if (sids[i] == NULL) { - ret = ENOMEM; - goto done; - } - } - sids[i] = NULL; + *last = '\0'; + last++; - *_size = num_ini_sids; - *_sids = talloc_steal(mem_ctx, sids); + current_dir = talloc_asprintf(mem_ctx, "%s/%s", current_dir, first); + if ((mkdir(current_dir, 0644)) < 0 && errno != EEXIST) { + return EINVAL; + } - ret = EOK; + ptr = last; + } - done: + return EOK; - 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 + * This function stores the input buf to a local file, whose file path + * is constructed by concatenating GPO_CACHE_PATH to the input unix_path. + * Note that the backend will later read the policy file from the same file path. */ -static errno_t -ad_gpo_parse_security_cse_buffer(TALLOC_CTX *mem_ctx, - uint8_t *data_buf, - int data_len, - char ***allowed_sids, - int *allowed_size, - char ***denied_sids, - int *denied_size) +static errno_t store_bytes_in_gpo_cache(const char *unix_path, + uint8_t *buf, + int buflen) { - 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; + int fd = -1; + char *tmp_name = NULL; + ssize_t written; + mode_t old_umask; + char *filename = NULL; TALLOC_CTX *tmp_ctx = NULL; tmp_ctx = talloc_new(NULL); @@ -291,57 +231,67 @@ ad_gpo_parse_security_cse_buffer(TALLOC_CTX *mem_ctx, goto done; } - ret = ini_config_create(&ini_config); - if (ret != 0) { + /* create component directories of unix_path, if needed */ + ret = prepare_gpo_cache(tmp_ctx, GPO_CACHE_PATH, unix_path); + + filename = talloc_asprintf(tmp_ctx, GPO_CACHE_PATH"%s", unix_path); + tmp_name = talloc_asprintf(tmp_ctx, "%sXXXXXX", filename); + if (tmp_name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n"); + ret = ENOMEM; + goto done; + } + + old_umask = umask(077); + fd = mkstemp(tmp_name); + umask(old_umask); + if (fd == -1) { + ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, - "ini_config_create failed [%d][%s]\n", ret, strerror(ret)); + "mkstemp failed [%d][%s].\n", ret, strerror(ret)); goto done; } - ret = ini_config_file_from_mem(data_buf, data_len, &file_ctx); - if (ret != 0) { + errno = 0; + written = sss_atomic_write_s(fd, buf, buflen); + if (written == -1) { + ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, - "ini_config_file_from_mem failed [%d][%s]\n", ret, strerror(ret)); + "write 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) { + if (written != buflen) { DEBUG(SSSDBG_CRIT_FAILURE, - "ini_config_parse failed [%d][%s]\n", ret, strerror(ret)); + "Write error, wrote [%zd] bytes, expected [%d]\n", + written, buflen); + ret = EIO; goto done; } - key = ALLOW_LOGON_LOCALLY; - ret = parse_logon_right_with_libini(tmp_ctx, - ini_config, - key, - &allow_size, - &allow_sids); - if (ret != 0) { + ret = fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (ret == -1) { + ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, - "parse_logon_right_with_libini failed for %s [%d][%s]\n", - key, ret, strerror(ret)); + "fchmod failed [%d][%s].\n", 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) { + ret = close(fd); + if (ret == -1) { + ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, - "parse_logon_right_with_libini failed for %s [%d][%s]\n", - key, ret, strerror(ret)); + "close failed [%d][%s].\n", 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; + ret = rename(tmp_name, filename); + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "rename failed [%d][%s].\n", ret, strerror(ret)); + goto done; + } done: @@ -349,49 +299,25 @@ ad_gpo_parse_security_cse_buffer(TALLOC_CTX *mem_ctx, 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 void -sssd_krb_get_auth_data_fn(const char * pServer, - const char * pShare, - char * pWorkgroup, - int maxLenWorkgroup, - char * pUsername, - int maxLenUsername, - char * pPassword, - int maxLenPassword) -{ - /* since we are using kerberos for authentication, we simply return */ - return; -} - - /* * This cse-specific function (GP_EXT_GUID_SECURITY) opens an SMB connection, * retrieves the data referenced by the input smb_uri, and then closes the SMB - * connection. The data is then parsed and the results are used to populate the - * output parameters with the list of allowed_sids and denied_sids + * connection. The data is then written to a file in the GPO_CACHE directory, + * to be read by the backend. */ static errno_t process_security_settings_cse(TALLOC_CTX *mem_ctx, const char *smb_uri, - char ***_allowed_sids, - int *_allowed_size, - char ***_denied_sids, - int *_denied_size) + const char *unix_path) { SMBCCTX *context; int ret = 0; uint8_t *buf = NULL; - int bytesread = 0; - char **allowed_sids; - char **denied_sids; - int allowed_size = 0; - int denied_size = 0; + int buflen = 0; TALLOC_CTX *tmp_ctx = NULL; tmp_ctx = talloc_new(NULL); @@ -400,6 +326,7 @@ process_security_settings_cse(TALLOC_CTX *mem_ctx, } DEBUG(SSSDBG_TRACE_ALL, "%s\n", smb_uri); + DEBUG(SSSDBG_TRACE_ALL, "%s\n", unix_path); context = smbc_new_context(); if (context == NULL) { @@ -429,39 +356,25 @@ process_security_settings_cse(TALLOC_CTX *mem_ctx, } buf = talloc_array(tmp_ctx, uint8_t, SMB_BUFFER_SIZE); - bytesread = smbc_read(remotehandle, buf, SMB_BUFFER_SIZE); - if(bytesread < 0) { + buflen = smbc_read(remotehandle, buf, SMB_BUFFER_SIZE); + if(buflen < 0) { DEBUG(SSSDBG_CRIT_FAILURE, "smbc_read failed\n"); ret = EPIPE; goto done; } - DEBUG(SSSDBG_CRIT_FAILURE, "bytesread: %d\n", bytesread); + DEBUG(SSSDBG_CRIT_FAILURE, "buflen: %d\n", buflen); smbc_close(remotehandle); - ret = ad_gpo_parse_security_cse_buffer(tmp_ctx, - buf, - bytesread, - &allowed_sids, - &allowed_size, - &denied_sids, - &denied_size); - + ret = store_bytes_in_gpo_cache(unix_path, buf, buflen); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, - "ad_gpo_parse_security_cse_buffer failed [%d][%s]\n", + "store_bytes_in_gpo_cache failed [%d][%s]\n", ret, strerror(ret)); goto done; } - /* TBD: allowed/denied_sids/size should be stored in cache */ - - *_allowed_sids = talloc_steal(mem_ctx, allowed_sids); - *_allowed_size = allowed_size; - *_denied_sids = talloc_steal(mem_ctx, denied_sids); - *_denied_size = denied_size; - done: smbc_free_context(context, 0); talloc_free(tmp_ctx); @@ -482,11 +395,6 @@ main(int argc, const char *argv[]) struct input_buffer *ibuf = NULL; struct response *resp = NULL; size_t written; - char **allowed_sids; - int allowed_size; - char **denied_sids; - int denied_size; - int j; struct poptOption long_options[] = { POPT_AUTOHELP @@ -580,30 +488,14 @@ main(int argc, const char *argv[]) result = process_security_settings_cse(main_ctx, ibuf->smb_uri, - &allowed_sids, - &allowed_size, - &denied_sids, - &denied_size); + ibuf->unix_path); if (result != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "process_security_settings_cse failed.[%d][%s].\n", - ret, strerror(ret)); - goto fail; - } - - DEBUG(SSSDBG_CRIT_FAILURE, "allowed_size = %d\n", allowed_size); - for (j= 0; j < allowed_size; j++) { - DEBUG(SSSDBG_CRIT_FAILURE, "allowed_sids[%d] = %s\n", j, - allowed_sids[j]); - } - - DEBUG(SSSDBG_CRIT_FAILURE, "denied_size = %d\n", denied_size); - for (j= 0; j < denied_size; j++) { - DEBUG(SSSDBG_CRIT_FAILURE, " denied_sids[%d] = %s\n", j, - denied_sids[j]); + result, strerror(result)); } - ret = prepare_response(main_ctx, result, allowed_size, allowed_sids, denied_size, denied_sids, &resp); + ret = prepare_response(main_ctx, result, &resp); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "prepare_response failed. [%d][%s].\n", ret, strerror(ret)); @@ -611,7 +503,6 @@ main(int argc, const char *argv[]) } errno = 0; - DEBUG(SSSDBG_TRACE_FUNC, "resp->size: %zu\n", resp->size); written = sss_atomic_write_s(STDOUT_FILENO, resp->buf, resp->size); if (written == -1) { |