summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac1
-rw-r--r--contrib/sssd.spec.in3
-rw-r--r--src/conf_macros.m417
-rw-r--r--src/providers/ad/ad_gpo.c366
-rw-r--r--src/providers/ad/ad_gpo_child.c387
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) {