219 lines
9.1 KiB
Diff
219 lines
9.1 KiB
Diff
|
From 2f27dd9f05c2d3ed1c190ba387bc97738988efb0 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
|
||
|
Date: Wed, 17 Oct 2018 16:57:20 +0200
|
||
|
Subject: [PATCH] GPO: Add option ad_gpo_ignore_unreadable
|
||
|
|
||
|
Add option to ignore group policy containers in AD
|
||
|
with unreadable or missing attributes. This is
|
||
|
for the case when server contains GPOs that
|
||
|
have very strict permissions on their attributes
|
||
|
in AD but are unrelated to access control.
|
||
|
|
||
|
Rather then using this option it is better to
|
||
|
change the permissions on the AD objects but
|
||
|
that may not be always possible (company policy,
|
||
|
not access to server etc.).
|
||
|
|
||
|
Resolves:
|
||
|
https://pagure.io/SSSD/sssd/issue/3867
|
||
|
CVE-2018-16838
|
||
|
|
||
|
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
|
||
|
---
|
||
|
src/config/cfg_rules.ini | 1 +
|
||
|
src/man/sssd-ad.5.xml | 19 +++++++++++++
|
||
|
src/providers/ad/ad_common.h | 1 +
|
||
|
src/providers/ad/ad_gpo.c | 67 +++++++++++++++++++++++++++++++++++++++++---
|
||
|
src/providers/ad/ad_opts.c | 1 +
|
||
|
5 files changed, 85 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
|
||
|
index b3764bd..292aa4d 100644
|
||
|
--- a/src/config/cfg_rules.ini
|
||
|
+++ b/src/config/cfg_rules.ini
|
||
|
@@ -441,6 +441,7 @@ option = ad_enabled_domains
|
||
|
option = ad_enable_gc
|
||
|
option = ad_gpo_access_control
|
||
|
option = ad_gpo_implicit_deny
|
||
|
+option = ad_gpo_ignore_unreadable
|
||
|
option = ad_gpo_cache_timeout
|
||
|
option = ad_gpo_default_right
|
||
|
option = ad_gpo_map_batch
|
||
|
diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
|
||
|
index ae3279d..5c51e80 100644
|
||
|
--- a/src/man/sssd-ad.5.xml
|
||
|
+++ b/src/man/sssd-ad.5.xml
|
||
|
@@ -437,6 +437,25 @@ DOM:dom1:(memberOf:1.2.840.113556.1.4.1941:=cn=nestedgroup,ou=groups,dc=example,
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
|
||
|
+ <varlistentry>
|
||
|
+ <term>ad_gpo_ignore_unreadable (boolean)</term>
|
||
|
+ <listitem>
|
||
|
+ <para>
|
||
|
+ Normally when some group policy containers (AD
|
||
|
+ object) of applicable group policy objects are
|
||
|
+ not readable by SSSD then users are denied access.
|
||
|
+ This option allows to ignore group policy
|
||
|
+ containers and with them associated policies
|
||
|
+ if their attributes in group policy containers
|
||
|
+ are not readable for SSSD.
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+ Default: False
|
||
|
+ </para>
|
||
|
+ </listitem>
|
||
|
+ </varlistentry>
|
||
|
+
|
||
|
+
|
||
|
|
||
|
<varlistentry>
|
||
|
<term>ad_gpo_cache_timeout (integer)</term>
|
||
|
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
|
||
|
index 662276c..4eb4101 100644
|
||
|
--- a/src/providers/ad/ad_common.h
|
||
|
+++ b/src/providers/ad/ad_common.h
|
||
|
@@ -53,6 +53,7 @@ enum ad_basic_opt {
|
||
|
AD_ENABLE_GC,
|
||
|
AD_GPO_ACCESS_CONTROL,
|
||
|
AD_GPO_IMPLICIT_DENY,
|
||
|
+ AD_GPO_IGNORE_UNREADABLE,
|
||
|
AD_GPO_CACHE_TIMEOUT,
|
||
|
AD_GPO_MAP_INTERACTIVE,
|
||
|
AD_GPO_MAP_REMOTE_INTERACTIVE,
|
||
|
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
|
||
|
index 3b472e0..5f85910 100644
|
||
|
--- a/src/providers/ad/ad_gpo.c
|
||
|
+++ b/src/providers/ad/ad_gpo.c
|
||
|
@@ -3603,6 +3603,7 @@ struct ad_gpo_process_gpo_state {
|
||
|
struct ad_access_ctx *access_ctx;
|
||
|
struct tevent_context *ev;
|
||
|
struct sdap_id_op *sdap_op;
|
||
|
+ struct dp_option *ad_options;
|
||
|
struct sdap_options *opts;
|
||
|
char *server_hostname;
|
||
|
struct sss_domain_info *host_domain;
|
||
|
@@ -3647,6 +3648,7 @@ ad_gpo_process_gpo_send(TALLOC_CTX *mem_ctx,
|
||
|
|
||
|
state->ev = ev;
|
||
|
state->sdap_op = sdap_op;
|
||
|
+ state->ad_options = access_ctx->ad_options;
|
||
|
state->opts = opts;
|
||
|
state->server_hostname = server_hostname;
|
||
|
state->host_domain = host_domain;
|
||
|
@@ -3872,6 +3874,54 @@ static bool machine_ext_names_is_blank(char *attr_value)
|
||
|
}
|
||
|
|
||
|
static errno_t
|
||
|
+ad_gpo_missing_or_unreadable_attr(struct ad_gpo_process_gpo_state *state,
|
||
|
+ struct tevent_req *req)
|
||
|
+{
|
||
|
+ bool ignore_unreadable = dp_opt_get_bool(state->ad_options,
|
||
|
+ AD_GPO_IGNORE_UNREADABLE);
|
||
|
+
|
||
|
+ if (ignore_unreadable) {
|
||
|
+ /* If admins decided to skip GPOs with unreadable
|
||
|
+ * attributes just log the SID of skipped GPO */
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Group Policy Container with DN [%s] has unreadable or missing "
|
||
|
+ "attributes -> skipping this GPO "
|
||
|
+ "(ad_gpo_ignore_unreadable = True)\n",
|
||
|
+ state->candidate_gpos[state->gpo_index]->gpo_dn);
|
||
|
+ state->gpo_index++;
|
||
|
+ return ad_gpo_get_gpo_attrs_step(req);
|
||
|
+ } else {
|
||
|
+ /* Inform in logs and syslog that this GPO can
|
||
|
+ * not be processed due to unreadable or missing
|
||
|
+ * attributes and point to possible server side
|
||
|
+ * and client side solutions. */
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Group Policy Container with DN [%s] is unreadable or has "
|
||
|
+ "unreadable or missing attributes. In order to fix this "
|
||
|
+ "make sure that this AD object has following attributes "
|
||
|
+ "readable: nTSecurityDescriptor, cn, gPCFileSysPath, "
|
||
|
+ "gPCMachineExtensionNames, gPCFunctionalityVersion, flags. "
|
||
|
+ "Alternatively if you do not have access to the server or can "
|
||
|
+ "not change permissions on this object, you can use option "
|
||
|
+ "ad_gpo_ignore_unreadable = True which will skip this GPO."
|
||
|
+ "See 'man ad_gpo_ignore_unreadable for details.'\n",
|
||
|
+ state->candidate_gpos[state->gpo_index]->gpo_dn);
|
||
|
+ sss_log(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Group Policy Container with DN [%s] is unreadable or has "
|
||
|
+ "unreadable or missing attributes. In order to fix this "
|
||
|
+ "make sure that this AD object has following attributes "
|
||
|
+ "readable: nTSecurityDescriptor, cn, gPCFileSysPath, "
|
||
|
+ "gPCMachineExtensionNames, gPCFunctionalityVersion, flags. "
|
||
|
+ "Alternatively if you do not have access to the server or can "
|
||
|
+ "not change permissions on this object, you can use option "
|
||
|
+ "ad_gpo_ignore_unreadable = True which will skip this GPO."
|
||
|
+ "See 'man ad_gpo_ignore_unreadable for details.'\n",
|
||
|
+ state->candidate_gpos[state->gpo_index]->gpo_dn);
|
||
|
+ return EFAULT;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
ad_gpo_sd_process_attrs(struct tevent_req *req,
|
||
|
char *smb_host,
|
||
|
struct sysdb_attrs *result)
|
||
|
@@ -3890,7 +3940,10 @@ ad_gpo_sd_process_attrs(struct tevent_req *req,
|
||
|
|
||
|
/* retrieve AD_AT_CN */
|
||
|
ret = sysdb_attrs_get_string(result, AD_AT_CN, &gpo_guid);
|
||
|
- if (ret != EOK) {
|
||
|
+ if (ret == ENOENT) {
|
||
|
+ ret = ad_gpo_missing_or_unreadable_attr(state, req);
|
||
|
+ goto done;
|
||
|
+ } else if (ret != EOK) {
|
||
|
DEBUG(SSSDBG_OP_FAILURE,
|
||
|
"sysdb_attrs_get_string failed: [%d](%s)\n",
|
||
|
ret, sss_strerror(ret));
|
||
|
@@ -3911,7 +3964,10 @@ ad_gpo_sd_process_attrs(struct tevent_req *req,
|
||
|
AD_AT_FILE_SYS_PATH,
|
||
|
&raw_file_sys_path);
|
||
|
|
||
|
- if (ret != EOK) {
|
||
|
+ if (ret == ENOENT) {
|
||
|
+ ret = ad_gpo_missing_or_unreadable_attr(state, req);
|
||
|
+ goto done;
|
||
|
+ } else if (ret != EOK) {
|
||
|
DEBUG(SSSDBG_OP_FAILURE,
|
||
|
"sysdb_attrs_get_string failed: [%d](%s)\n",
|
||
|
ret, sss_strerror(ret));
|
||
|
@@ -3959,7 +4015,10 @@ ad_gpo_sd_process_attrs(struct tevent_req *req,
|
||
|
/* retrieve AD_AT_FLAGS */
|
||
|
ret = sysdb_attrs_get_int32_t(result, AD_AT_FLAGS,
|
||
|
&gp_gpo->gpo_flags);
|
||
|
- if (ret != EOK) {
|
||
|
+ if (ret == ENOENT) {
|
||
|
+ ret = ad_gpo_missing_or_unreadable_attr(state, req);
|
||
|
+ goto done;
|
||
|
+ } else if (ret != EOK) {
|
||
|
DEBUG(SSSDBG_OP_FAILURE,
|
||
|
"sysdb_attrs_get_int32_t failed: [%d](%s)\n",
|
||
|
ret, sss_strerror(ret));
|
||
|
@@ -3977,7 +4036,7 @@ ad_gpo_sd_process_attrs(struct tevent_req *req,
|
||
|
if ((ret == ENOENT) || (el->num_values == 0)) {
|
||
|
DEBUG(SSSDBG_OP_FAILURE,
|
||
|
"nt_sec_desc attribute not found or has no value\n");
|
||
|
- ret = ENOENT;
|
||
|
+ ret = ad_gpo_missing_or_unreadable_attr(state, req);
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
|
||
|
index 9ca18c4..f2ca215 100644
|
||
|
--- a/src/providers/ad/ad_opts.c
|
||
|
+++ b/src/providers/ad/ad_opts.c
|
||
|
@@ -39,6 +39,7 @@ struct dp_option ad_basic_opts[] = {
|
||
|
{ "ad_enable_gc", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
|
||
|
{ "ad_gpo_access_control", DP_OPT_STRING, { AD_GPO_ACCESS_MODE_DEFAULT }, NULL_STRING },
|
||
|
{ "ad_gpo_implicit_deny", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
|
||
|
+ { "ad_gpo_ignore_unreadable", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
|
||
|
{ "ad_gpo_cache_timeout", DP_OPT_NUMBER, { .number = 5 }, NULL_NUMBER },
|
||
|
{ "ad_gpo_map_interactive", DP_OPT_STRING, NULL_STRING, NULL_STRING },
|
||
|
{ "ad_gpo_map_remote_interactive", DP_OPT_STRING, NULL_STRING, NULL_STRING },
|
||
|
--
|
||
|
2.9.5
|
||
|
|