From b85f4eaa1f0e48f6040e34103fbbfe9ea55ee993 Mon Sep 17 00:00:00 2001 From: Pavel Reichl Date: Wed, 22 Jan 2014 16:47:22 +0000 Subject: AD: support for subdomain_homedir Homedir is defaultly set accordingly to subdomain_homedir for users from AD. Resolves: https://fedorahosted.org/sssd/ticket/2169 Reviewed-by: Jakub Hrozek --- src/providers/ipa/ipa_subdomains_id.c | 190 ++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index c29a2a304..fb1ad8968 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -25,6 +25,7 @@ #include #include "util/util.h" +#include "util/sss_nss.h" #include "util/strtonum.h" #include "db/sysdb.h" #include "providers/ldap/ldap_common.h" @@ -350,6 +351,185 @@ ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx, return (iter) ? iter->ad_id_ctx : NULL; } +static errno_t +get_subdomain_homedir_of_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, + const char *fqname, uint32_t uid, + const char **_homedir) +{ + errno_t ret; + char *name; + const char *homedir; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sss_parse_name(tmp_ctx, dom->names, fqname, NULL, &name); + if (ret != EOK) { + goto done; + } + + homedir = expand_homedir_template(tmp_ctx, dom->subdomain_homedir, name, + uid, NULL, dom->name, dom->flat_name); + + if (homedir == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("expand_homedir_template failed\n")); + ret = ENOMEM; + goto done; + } + + if (_homedir == NULL) { + ret = EINVAL; + goto done; + } + *_homedir = talloc_steal(mem_ctx, homedir); + +done: + talloc_free(tmp_ctx); + return ret; +} + +static errno_t +store_homedir_of_user(struct sss_domain_info *domain, + const char *fqname, const char *homedir) +{ + errno_t ret; + errno_t sret; + TALLOC_CTX *tmp_ctx; + bool in_transaction = false; + struct sysdb_attrs *attrs; + struct sysdb_ctx *sysdb = domain->sysdb; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + attrs = sysdb_new_attrs(tmp_ctx); + if (attrs == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, homedir); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Error setting homedir: [%s]\n", + strerror(ret))); + goto done; + } + + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); + goto done; + } + + in_transaction = true; + + ret = sysdb_set_user_attr(sysdb, domain, fqname, attrs, SYSDB_MOD_REP); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to update homedir information!\n")); + goto done; + } + + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot commit sysdb transaction [%d]: %s.\n", + ret, strerror(ret))); + goto done; + } + + in_transaction = false; + +done: + if (in_transaction) { + sret = sysdb_transaction_cancel(sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction.\n")); + } + } + talloc_free(tmp_ctx); + return ret; +} + +static errno_t +apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, + int filter_type, const char *filter_value) +{ + errno_t ret; + uint32_t uid; + const char *fqname; + const char *homedir = NULL; + struct ldb_result *res; + + if (filter_type == BE_FILTER_NAME) { + ret = sysdb_getpwnam(mem_ctx, dom->sysdb, dom, filter_value, &res); + } else if (filter_type == BE_FILTER_IDNUM) { + errno = 0; + uid = strtouint32(filter_value, NULL, 10); + if (errno != 0) { + ret = errno; + goto done; + } + ret = sysdb_getpwuid(mem_ctx, dom->sysdb, dom, uid, &res); + } else { + DEBUG(SSSDBG_OP_FAILURE, + ("Unsupported filter type: [%d].\n", filter_type)); + ret = EINVAL; + goto done; + } + + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Failed to make request to our cache: [%d]: [%s]\n", + ret, sss_strerror(ret))); + goto done; + } + + if (res->count == 0) { + ret = ENOENT; + goto done; + } + + /* + * Homedir is always overriden by subdomain_homedir even if it was + * explicitly set by user. + */ + fqname = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL); + uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0); + if (uid == 0) { + DEBUG(SSSDBG_OP_FAILURE, ("UID for user [%s] is not known.\n", + filter_value)); + ret = ENOENT; + goto done; + } + + ret = get_subdomain_homedir_of_user(mem_ctx, dom, fqname, uid, &homedir); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("get_subdomain_homedir_of_user failed: [%d]: [%s]\n", + ret, sss_strerror(ret))); + goto done; + } + + ret = store_homedir_of_user(dom, fqname, homedir); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("store_homedir_of_user failed: [%d]: [%s]\n", + ret, sss_strerror(ret))); + goto done; + } + +done: + return ret; +} + static void ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) { @@ -367,6 +547,16 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) return; } + ret = apply_subdomain_homedir(state, state->user_dom, + state->ar->filter_type, + state->ar->filter_value); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("apply_subdomain_homedir failed: [%d]: [%s].\n", + ret, sss_strerror(ret))); + goto fail; + } + if ((state->ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS) { tevent_req_done(req); return; -- cgit