diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/config/etc/sssd.api.d/sssd-ad.conf | 1 | ||||
-rw-r--r-- | src/config/etc/sssd.api.d/sssd-ipa.conf | 1 | ||||
-rw-r--r-- | src/config/etc/sssd.api.d/sssd-ldap.conf | 1 | ||||
-rw-r--r-- | src/man/sssd-ldap.5.xml | 31 | ||||
-rw-r--r-- | src/providers/ad/ad_opts.h | 1 | ||||
-rw-r--r-- | src/providers/ipa/ipa_opts.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/ldap_id.c | 39 | ||||
-rw-r--r-- | src/providers/ldap/ldap_opts.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_initgroups.c | 17 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_private.h | 10 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_users.c | 91 | ||||
-rw-r--r-- | src/providers/ldap/sdap_users.h | 43 |
14 files changed, 228 insertions, 11 deletions
diff --git a/Makefile.am b/Makefile.am index 211472195..9dbde0391 100644 --- a/Makefile.am +++ b/Makefile.am @@ -440,6 +440,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 87f69a23f..e9c7b2326 100644 --- a/src/config/etc/sssd.api.d/sssd-ipa.conf +++ b/src/config/etc/sssd.api.d/sssd-ipa.conf @@ -125,6 +125,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 c1553c736..799213300 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 efd966e93..285672226 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 7923b1ec8..cb6f40e8b 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -136,6 +136,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 d24b8aa69..073f6869e 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 27f18ae17..1235d1df3 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -215,6 +215,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 a4310b463..23be22fd1 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, @@ -2658,8 +2659,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 156255b97..71cb2e53f 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, @@ -120,4 +111,5 @@ errno_t get_sysdb_grouplist(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, 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 cd577a7f7..ccd2f24e0 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====================================================== */ @@ -701,3 +703,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_ */ |