diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
commit | 74aa0bc6779af38018a03fd2cf4419fe85917904 (patch) | |
tree | 9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/responder/nss/nss_iface.c | |
parent | Initial commit. (diff) | |
download | sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.tar.xz sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.zip |
Adding upstream version 2.9.4.upstream/2.9.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/responder/nss/nss_iface.c')
-rw-r--r-- | src/responder/nss/nss_iface.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/src/responder/nss/nss_iface.c b/src/responder/nss/nss_iface.c new file mode 100644 index 0000000..db743f8 --- /dev/null +++ b/src/responder/nss/nss_iface.c @@ -0,0 +1,242 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + 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/>. +*/ + +#include "responder/nss/nss_private.h" +#include "responder/nss/nss_iface.h" +#include "sss_iface/sss_iface_async.h" + +static void +sss_nss_update_initgr_memcache(struct sss_nss_ctx *nctx, + const char *fq_name, const char *domain, + int gnum, uint32_t *groups) +{ + TALLOC_CTX *tmp_ctx = NULL; + struct sss_domain_info *dom; + struct ldb_result *res; + struct sized_string *delete_name; + bool changed = false; + uint32_t id; + uint32_t gids[gnum]; + int ret; + int i, j; + + for (dom = nctx->rctx->domains; + dom; + dom = get_next_domain(dom, SSS_GND_DESCEND)) { + if (strcasecmp(dom->name, domain) == 0) { + break; + } + } + + if (dom == NULL) { + DEBUG(SSSDBG_OP_FAILURE, + "Unknown domain (%s) requested by provider\n", domain); + return; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return; + } + + ret = sized_output_name(tmp_ctx, nctx->rctx, fq_name, dom, &delete_name); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sized_output_name failed for '%s': %d [%s]\n", + fq_name, ret, sss_strerror(ret)); + goto done; + } + + ret = sysdb_initgroups(tmp_ctx, dom, fq_name, &res); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "sysdb_initgroups() failed [%d][%s]\n", + ret, strerror(ret)); + goto done; + } + + /* copy, we need the original intact in case we need to invalidate + * all the original groups */ + memcpy(gids, groups, gnum * sizeof(uint32_t)); + + if (ret == ENOENT || res->count == 0) { + /* The user is gone. Invalidate the mc record */ + ret = sss_mmap_cache_pw_invalidate(&nctx->pwd_mc_ctx, delete_name); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Internal failure in memory cache code: %d [%s]\n", + ret, strerror(ret)); + } + + /* Also invalidate his groups */ + changed = true; + } else { + /* we skip the first entry, it's the user itself */ + for (i = 0; i < res->count; i++) { + id = ldb_msg_find_attr_as_uint(res->msgs[i], SYSDB_GIDNUM, 0); + if (id == 0) { + /* probably non-POSIX group, skip */ + continue; + } + for (j = 0; j < gnum; j++) { + if (gids[j] == id) { + gids[j] = 0; + break; + } + } + if (j >= gnum) { + /* we couldn't find a match, this means the groups have + * changed after the refresh */ + changed = true; + break; + } + } + + if (!changed) { + for (j = 0; j < gnum; j++) { + if (gids[j] != 0) { + /* we found an un-cleared groups, this means the groups + * have changed after the refresh (some got deleted) */ + changed = true; + break; + } + } + } + } + + if (changed) { + for (i = 0; i < gnum; i++) { + id = groups[i]; + + ret = sss_mmap_cache_gr_invalidate_gid(&nctx->grp_mc_ctx, id); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Internal failure in memory cache code: %d [%s]\n", + ret, strerror(ret)); + } + } + + to_sized_string(delete_name, fq_name); + ret = sss_mmap_cache_initgr_invalidate(&nctx->initgr_mc_ctx, + delete_name); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Internal failure in memory cache code: %d [%s]\n", + ret, strerror(ret)); + } + } + +done: + talloc_free(tmp_ctx); +} + +static errno_t +sss_nss_memorycache_invalidate_users(TALLOC_CTX *mem_ctx, + struct sbus_request *sbus_req, + struct sss_nss_ctx *nctx) +{ + DEBUG(SSSDBG_TRACE_LIBS, "Invalidating all users in memory cache\n"); + sss_mmap_cache_reset(nctx->pwd_mc_ctx); + + return EOK; +} + +static errno_t +sss_nss_memorycache_invalidate_groups(TALLOC_CTX *mem_ctx, + struct sbus_request *sbus_req, + struct sss_nss_ctx *nctx) +{ + DEBUG(SSSDBG_TRACE_LIBS, "Invalidating all groups in memory cache\n"); + sss_mmap_cache_reset(nctx->grp_mc_ctx); + + return EOK; +} + +static errno_t +sss_nss_memorycache_invalidate_initgroups(TALLOC_CTX *mem_ctx, + struct sbus_request *sbus_req, + struct sss_nss_ctx *nctx) +{ + DEBUG(SSSDBG_TRACE_LIBS, + "Invalidating all initgroup records in memory cache\n"); + sss_mmap_cache_reset(nctx->initgr_mc_ctx); + + return EOK; +} + +static errno_t +sss_nss_memorycache_update_initgroups(TALLOC_CTX *mem_ctx, + struct sbus_request *sbus_req, + struct sss_nss_ctx *nctx, + const char *user, + const char *domain, + uint32_t *groups) +{ + DEBUG(SSSDBG_TRACE_LIBS, "Updating initgroups memory cache of [%s@%s]\n", + user, domain); + + sss_nss_update_initgr_memcache(nctx, user, domain, + talloc_array_length(groups), groups); + + return EOK; +} + +static errno_t +sss_nss_memorycache_invalidate_group_by_id(TALLOC_CTX *mem_ctx, + struct sbus_request *sbus_req, + struct sss_nss_ctx *nctx, + uint32_t gid) +{ + + DEBUG(SSSDBG_TRACE_LIBS, + "Invalidating group %u from memory cache\n", gid); + + sss_mmap_cache_gr_invalidate_gid(&nctx->grp_mc_ctx, gid); + + return EOK; +} + +errno_t +sss_nss_register_backend_iface(struct sbus_connection *conn, + struct sss_nss_ctx *nss_ctx) +{ + errno_t ret; + + SBUS_INTERFACE(iface, + sssd_nss_MemoryCache, + SBUS_METHODS( + SBUS_SYNC(METHOD, sssd_nss_MemoryCache, UpdateInitgroups, sss_nss_memorycache_update_initgroups, nss_ctx), + SBUS_SYNC(METHOD, sssd_nss_MemoryCache, InvalidateAllUsers, sss_nss_memorycache_invalidate_users, nss_ctx), + SBUS_SYNC(METHOD, sssd_nss_MemoryCache, InvalidateAllGroups, sss_nss_memorycache_invalidate_groups, nss_ctx), + SBUS_SYNC(METHOD, sssd_nss_MemoryCache, InvalidateAllInitgroups, sss_nss_memorycache_invalidate_initgroups, nss_ctx), + SBUS_SYNC(METHOD, sssd_nss_MemoryCache, InvalidateGroupById, sss_nss_memorycache_invalidate_group_by_id, nss_ctx) + ), + SBUS_SIGNALS(SBUS_NO_SIGNALS), + SBUS_PROPERTIES(SBUS_NO_PROPERTIES) + ); + + ret = sbus_connection_add_path(conn, SSS_BUS_PATH, &iface); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register service interface" + "[%d]: %s\n", ret, sss_strerror(ret)); + } + + return ret; +} |