summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2013-03-15 15:27:31 -0400
committerJakub Hrozek <jhrozek@redhat.com>2013-04-15 15:15:54 +0200
commit2d654a45796b1c50a3c2368ba2aa78412073171d (patch)
treee00d60eca667adca30c4b6b7efdb430d3eeda968
parent5925e134b87e79e60177b5861ec2a67b659aaa27 (diff)
downloadsssd-2d654a45796b1c50a3c2368ba2aa78412073171d.tar.gz
sssd-2d654a45796b1c50a3c2368ba2aa78412073171d.tar.xz
sssd-2d654a45796b1c50a3c2368ba2aa78412073171d.zip
ldap: Fallback option for rfc2307 schema
Add option to fallback to fetch local users if rfc2307is being used. This is useful for cases where people added local users as LDAP members and rely on these group memberships to be maintained on the local host. Disabled by default as it violates identity domain separation. Ticket: https://fedorahosted.org/sssd/ticket/1020
-rw-r--r--Makefile.am1
-rw-r--r--src/config/etc/sssd.api.d/sssd-ad.conf1
-rw-r--r--src/config/etc/sssd.api.d/sssd-ipa.conf1
-rw-r--r--src/config/etc/sssd.api.d/sssd-ldap.conf1
-rw-r--r--src/man/sssd-ldap.5.xml31
-rw-r--r--src/providers/ad/ad_opts.h1
-rw-r--r--src/providers/ipa/ipa_opts.h1
-rw-r--r--src/providers/ldap/ldap_id.c39
-rw-r--r--src/providers/ldap/ldap_opts.h1
-rw-r--r--src/providers/ldap/sdap.h1
-rw-r--r--src/providers/ldap/sdap_async_initgroups.c17
-rw-r--r--src/providers/ldap/sdap_async_private.h10
-rw-r--r--src/providers/ldap/sdap_async_users.c91
-rw-r--r--src/providers/ldap/sdap_users.h43
14 files changed, 228 insertions, 11 deletions
diff --git a/Makefile.am b/Makefile.am
index 223431da4..f4934c054 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -426,6 +426,7 @@ dist_noinst_HEADERS = \
src/providers/ldap/sdap_id_op.h \
src/providers/ldap/ldap_opts.h \
src/providers/ldap/sdap_range.h \
+ src/providers/ldap/sdap_users.h \
src/providers/ipa/ipa_common.h \
src/providers/ipa/ipa_config.h \
src/providers/ipa/ipa_access.h \
diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
index 0154e6aa9..85e34cb18 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -104,6 +104,7 @@ ldap_idmap_default_domain = str, None, false
ldap_idmap_default_domain_sid = str, None, false
ldap_groups_use_matching_rule_in_chain = bool, None, false
ldap_initgroups_use_matching_rule_in_chain = bool, None, false
+ldap_rfc2307_fallback_to_local_users = bool, None, false
[provider/ad/auth]
krb5_ccachedir = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index efc1e8b3d..9092df905 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -124,6 +124,7 @@ ldap_idmap_default_domain = str, None, false
ldap_idmap_default_domain_sid = str, None, false
ldap_groups_use_matching_rule_in_chain = bool, None, false
ldap_initgroups_use_matching_rule_in_chain = bool, None, false
+ldap_rfc2307_fallback_to_local_users = bool, None, false
[provider/ipa/auth]
krb5_ccachedir = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
index 3b6b4e8fb..40e2aa09d 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -114,6 +114,7 @@ ldap_idmap_default_domain = str, None, false
ldap_idmap_default_domain_sid = str, None, false
ldap_groups_use_matching_rule_in_chain = bool, None, false
ldap_initgroups_use_matching_rule_in_chain = bool, None, false
+ldap_rfc2307_fallback_to_local_users = bool, None, false
[provider/ldap/auth]
ldap_pwd_policy = str, None, false
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 4879db75d..562cbd8f2 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1810,6 +1810,37 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>ldap_rfc2307_fallback_to_local_users (boolean)</term>
+ <listitem>
+ <para>
+ Allows to retain local users as members of an LDAP
+ group for servers that use the RFC2307 schema.
+ </para>
+ <para>
+ In some environments where the RFC2307 schema is
+ used, local users are made members of LDAP groups
+ by adding their names to the memberUid attribute.
+ The self-consistency of the domain is compromised
+ when this is done, so SSSD would normally remove
+ the "missing" users from the cached group
+ memberships as soon as nsswitch tries to fetch
+ information about the user via getpw*() or
+ initgroups() calls.
+ </para>
+ <para>
+ This option falls back to checking if local users
+ are referenced, and caches them so that later
+ initgroups() calls will augment the local users
+ with the additional LDAP groups.
+ </para>
+ <para>
+ Default: false
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</para>
</refsect1>
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
index bcf848c07..c283f714a 100644
--- a/src/providers/ad/ad_opts.h
+++ b/src/providers/ad/ad_opts.h
@@ -120,6 +120,7 @@ struct dp_option ad_def_ldap_opts[] = {
{ "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_rfc2307_fallback_to_local_users", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
DP_OPTION_TERMINATOR
};
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index fe9f48930..ff461db19 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -134,6 +134,7 @@ struct dp_option ipa_def_ldap_opts[] = {
{ "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_rfc2307_fallback_to_local_users", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
DP_OPTION_TERMINATOR
};
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index b8520df83..d8dc3b299 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -32,6 +32,7 @@
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_async.h"
#include "providers/ldap/sdap_idmap.h"
+#include "providers/ldap/sdap_users.h"
/* =Users-Related-Functions-(by-name,by-uid)============================== */
@@ -244,6 +245,44 @@ static void users_get_done(struct tevent_req *subreq)
return;
}
+ if ((ret == ENOENT) &&
+ (state->ctx->opts->schema_type == SDAP_SCHEMA_RFC2307) &&
+ (dp_opt_get_bool(state->ctx->opts->basic,
+ SDAP_RFC2307_FALLBACK_TO_LOCAL_USERS) == true)) {
+ struct sysdb_attrs **usr_attrs;
+ const char *name = NULL;
+ bool fallback;
+
+ switch (state->filter_type) {
+ case BE_FILTER_NAME:
+ name = state->name;
+ uid = -1;
+ fallback = true;
+ break;
+ case BE_FILTER_IDNUM:
+ uid = (uid_t) strtouint32(state->name, &endptr, 10);
+ if (errno || *endptr || (state->name == endptr)) {
+ tevent_req_error(req, errno ? errno : EINVAL);
+ return;
+ }
+ fallback = true;
+ break;
+ default:
+ fallback = false;
+ break;
+ }
+
+ if (fallback) {
+ ret = sdap_fallback_local_user(state, state->ctx->opts,
+ name, uid, &usr_attrs);
+ if (ret == EOK) {
+ ret = sdap_save_user(state, state->sysdb,
+ state->ctx->opts, state->domain,
+ usr_attrs[0], false, NULL, 0);
+ }
+ }
+ }
+
if (ret && ret != ENOENT) {
state->dp_error = dp_error;
tevent_req_error(req, ret);
diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
index 5a941a4c6..2ed89f977 100644
--- a/src/providers/ldap/ldap_opts.h
+++ b/src/providers/ldap/ldap_opts.h
@@ -112,6 +112,7 @@ struct dp_option default_basic_opts[] = {
{ "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "ldap_rfc2307_fallback_to_local_users", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
DP_OPTION_TERMINATOR
};
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index d14365799..5bbf27594 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -228,6 +228,7 @@ enum sdap_basic_opt {
SDAP_IDMAP_DEFAULT_DOMAIN_SID,
SDAP_AD_MATCHING_RULE_GROUPS,
SDAP_AD_MATCHING_RULE_INITGROUPS,
+ SDAP_RFC2307_FALLBACK_TO_LOCAL_USERS,
SDAP_OPTS_BASIC /* opts counter */
};
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index e9d1f3cc9..57ad0e578 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -26,6 +26,7 @@
#include "providers/ldap/sdap_async_private.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_idmap.h"
+#include "providers/ldap/sdap_users.h"
/* ==Save-fake-group-list=====================================*/
static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
@@ -2656,8 +2657,20 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
return;
}
- tevent_req_error(req, ENOENT);
- return;
+ /* fallback to fetch a local user if required */
+ if ((state->opts->schema_type == SDAP_SCHEMA_RFC2307) &&
+ (dp_opt_get_bool(state->opts->basic,
+ SDAP_RFC2307_FALLBACK_TO_LOCAL_USERS) == true)) {
+ ret = sdap_fallback_local_user(state, state->opts,
+ state->name, -1, &usr_attrs);
+ } else {
+ ret = ENOENT;
+ }
+
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
} else if (count != 1) {
DEBUG(2, ("Expected one user entry and got %d\n", count));
tevent_req_error(req, EINVAL);
diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h
index c0faab50e..1fea5bd7b 100644
--- a/src/providers/ldap/sdap_async_private.h
+++ b/src/providers/ldap/sdap_async_private.h
@@ -89,15 +89,6 @@ int sdap_get_tgt_recv(struct tevent_req *req,
char **ccname,
time_t *expire_time_out);
-int sdap_save_user(TALLOC_CTX *memctx,
- struct sysdb_ctx *ctx,
- struct sdap_options *opts,
- struct sss_domain_info *dom,
- struct sysdb_attrs *attrs,
- bool is_initgr,
- char **_usn_value,
- time_t now);
-
int sdap_save_users(TALLOC_CTX *memctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *dom,
@@ -118,4 +109,5 @@ errno_t get_sysdb_grouplist(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
const char *name,
char ***grouplist);
+
#endif /* _SDAP_ASYNC_PRIVATE_H_ */
diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
index ade1d37b5..5a2e375cb 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -26,6 +26,8 @@
#include "providers/ldap/sdap_async_private.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_idmap.h"
+#include "providers/ldap/sdap_users.h"
+
/* ==Save-User-Entry====================================================== */
@@ -700,3 +702,92 @@ int sdap_get_users_recv(struct tevent_req *req,
return EOK;
}
+
+/* ==Fetch-Fallback-local-user============================================ */
+
+errno_t sdap_fallback_local_user(TALLOC_CTX *memctx,
+ struct sdap_options *opts,
+ const char *name, uid_t uid,
+ struct sysdb_attrs ***reply)
+{
+ struct sysdb_attrs **ua;
+ struct sysdb_attrs *user;
+ struct passwd *pwd;
+ int ret;
+
+ if (name) {
+ pwd = getpwnam(name);
+ } else {
+ pwd = getpwuid(uid);
+ }
+
+ if (!pwd) {
+ return errno ? errno : ENOENT;
+ }
+
+ ua = talloc_array(memctx, struct sysdb_attrs *, 2);
+ if (!ua) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ua[1] = NULL;
+
+ user = sysdb_new_attrs(ua);
+ if (!user) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ua[0] = user;
+
+ ret = sysdb_attrs_add_string(user, SYSDB_NAME, pwd->pw_name);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ if (pwd->pw_passwd) {
+ ret = sysdb_attrs_add_string(user, SYSDB_PWD, pwd->pw_passwd);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+ ret = sysdb_attrs_add_long(user, SYSDB_UIDNUM, (long)pwd->pw_uid);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_long(user, SYSDB_GIDNUM, (long)pwd->pw_gid);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ if (pwd->pw_gecos) {
+ ret = sysdb_attrs_add_string(user, SYSDB_GECOS, pwd->pw_gecos);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+ if (pwd->pw_dir) {
+ ret = sysdb_attrs_add_string(user, SYSDB_HOMEDIR, pwd->pw_dir);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+ if (pwd->pw_shell) {
+ ret = sysdb_attrs_add_string(user, SYSDB_SHELL, pwd->pw_shell);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+done:
+ if (ret != EOK) {
+ talloc_free(ua);
+ } else {
+ *reply = ua;
+ }
+
+ return ret;
+}
diff --git a/src/providers/ldap/sdap_users.h b/src/providers/ldap/sdap_users.h
new file mode 100644
index 000000000..16620a9ed
--- /dev/null
+++ b/src/providers/ldap/sdap_users.h
@@ -0,0 +1,43 @@
+/*
+ SSSD
+
+ Async LDAP Helper routines
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _SDAP_USERS_H_
+#define _SDAP_USERS_H_
+
+#include "config.h"
+
+/* shared non-async user functions */
+
+errno_t sdap_fallback_local_user(TALLOC_CTX *memctx,
+ struct sdap_options *opts,
+ const char *name, uid_t uid,
+ struct sysdb_attrs ***reply);
+
+int sdap_save_user(TALLOC_CTX *memctx,
+ struct sysdb_ctx *ctx,
+ struct sdap_options *opts,
+ struct sss_domain_info *dom,
+ struct sysdb_attrs *attrs,
+ bool is_initgr,
+ char **_usn_value,
+ time_t now);
+
+#endif /* _SDAP_USERS_H_ */