From 34ade2c34f97e70c52873fff9c4ddb5b2536c9ef Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov Date: Wed, 30 Aug 2023 22:38:45 +0200 Subject: [PATCH] RESPONDER: make all responders members of sssd group Previously it was only for sssd_nss TODO: - explanation - move to monitor/systemd service file --- src/responder/common/responder.h | 6 ++ src/responder/common/responder_common.c | 79 ++++++++++++++++ src/responder/nss/nss_private.h | 2 - src/responder/nss/nsssrv.c | 120 ++++++------------------ src/responder/nss/nsssrv_mmap_cache.c | 2 + 5 files changed, 114 insertions(+), 95 deletions(-) diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h index 90078dda782..c206b949f28 100644 --- a/src/responder/common/responder.h +++ b/src/responder/common/responder.h @@ -143,6 +143,12 @@ struct resp_ctx { bool socket_activated; bool cache_first; bool enumeration_warn_logged; + +#ifdef SSSD_NON_ROOT_USER + /* uid / gid of SSSD_USER */ + uid_t uid; + gid_t gid; +#endif /* SSSD_NON_ROOT_USER */ }; struct cli_creds; diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c index ea9b62bf14c..bf634b44581 100644 --- a/src/responder/common/responder_common.c +++ b/src/responder/common/responder_common.c @@ -1282,6 +1282,67 @@ static errno_t sss_get_etc_shells(TALLOC_CTX *mem_ctx, char ***_shells) return ret; } +#ifdef SSSD_NON_ROOT_USER +static int set_supplementary_group(gid_t gid) +{ + errno_t ret; + int size; + gid_t *supp_gids = NULL; + + if (getgid() == gid) { + DEBUG(SSSDBG_TRACE_FUNC, "Already running as the sssd group\n"); + return EOK; + } + + size = getgroups(0, NULL); + if (size == -1) { + ret = errno; + DEBUG(SSSDBG_TRACE_FUNC, "Getgroups failed! (%d, %s)\n", + ret, sss_strerror(ret)); + return ret; + } + + if (size > 0) { + supp_gids = talloc_zero_array(NULL, gid_t, size); + if (supp_gids == NULL) { + DEBUG(SSSDBG_TRACE_FUNC, "Allocation failed!\n"); + ret = ENOMEM; + goto done; + } + + size = getgroups(size, supp_gids); + if (size == -1) { + ret = errno; + DEBUG(SSSDBG_TRACE_FUNC, "Getgroups failed! (%d, %s)\n", + ret, sss_strerror(ret)); + goto done; + } + + for (int i = 0; i < size; i++) { + if (supp_gids[i] == gid) { + DEBUG(SSSDBG_TRACE_FUNC, + "Already assigned to the SSSD supplementary group\n"); + ret = EOK; + goto done; + } + } + } + + ret = setgroups(1, &gid); + if (ret != EOK) { + ret = errno; + DEBUG(SSSDBG_TRACE_FUNC, + "Cannot setgroups [%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } + + ret = EOK; +done: + talloc_free(supp_gids); + return ret; +} +#endif /* SSSD_NON_ROOT_USER */ + int sss_process_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct confdb_ctx *cdb, @@ -1317,6 +1378,24 @@ int sss_process_init(TALLOC_CTX *mem_ctx, rctx->shutting_down = false; rctx->socket_activated = is_socket_activated(); +#ifdef SSSD_NON_ROOT_USER + /* In case SSSD is built with non-root user support, + * a number of files are sssd:sssd owned. + * If responder runs under root, add process to sssd + * supplementary group to avoid the need for + * CAP_DAC_OVERRIDE or CAP_CHOWN. + */ + sss_sssd_user_uid_and_gid(&rctx->uid, &rctx->gid); + if ((getuid() == 0) || (geteuid() == 0)) { + ret = set_supplementary_group(rctx->gid); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to add process to the sssd supplementary group\n"); + goto fail; + } + } +#endif /* SSSD_NON_ROOT_USER */ + talloc_set_destructor((TALLOC_CTX*)rctx, sss_responder_ctx_destructor); ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path, diff --git a/src/responder/nss/nss_private.h b/src/responder/nss/nss_private.h index e2f5a3e5a58..71e33ff1b80 100644 --- a/src/responder/nss/nss_private.h +++ b/src/responder/nss/nss_private.h @@ -93,8 +93,6 @@ struct sss_nss_ctx { struct sss_mc_ctx *grp_mc_ctx; struct sss_mc_ctx *initgr_mc_ctx; struct sss_mc_ctx *sid_mc_ctx; - uid_t mc_uid; - gid_t mc_gid; }; struct sss_cmd_table *get_sss_nss_cmds(void); diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c index 4673a64ca47..b99b58c6f5a 100644 --- a/src/responder/nss/nsssrv.c +++ b/src/responder/nss/nsssrv.c @@ -57,6 +57,16 @@ sss_nss_clear_memcache(TALLOC_CTX *mem_ctx, { int memcache_timeout; errno_t ret; + uid_t uid; + gid_t gid; + +#ifdef SSSD_NON_ROOT_USER + uid = nctx->rctx->uid; + gid = nctx->rctx->gid; +#else + uid = 0; + gid = 0; +#endif /* SSSD_NON_ROOT_USER */ if (access(SSS_NSS_MCACHE_DIR"/"CLEAR_MC_FLAG, F_OK) < 0) { ret = errno; @@ -92,7 +102,7 @@ sss_nss_clear_memcache(TALLOC_CTX *mem_ctx, } DEBUG(SSSDBG_TRACE_FUNC, "Clearing memory caches.\n"); - ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid, + ret = sss_mmap_cache_reinit(nctx, uid, gid, -1, /* keep current size */ (time_t) memcache_timeout, &nctx->pwd_mc_ctx); @@ -102,7 +112,7 @@ sss_nss_clear_memcache(TALLOC_CTX *mem_ctx, goto done; } - ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid, + ret = sss_mmap_cache_reinit(nctx, uid, gid, -1, /* keep current size */ (time_t) memcache_timeout, &nctx->grp_mc_ctx); @@ -112,7 +122,7 @@ sss_nss_clear_memcache(TALLOC_CTX *mem_ctx, goto done; } - ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid, + ret = sss_mmap_cache_reinit(nctx, uid, gid, -1, /* keep current size */ (time_t)memcache_timeout, &nctx->initgr_mc_ctx); @@ -287,6 +297,16 @@ static int setup_memcaches(struct sss_nss_ctx *nctx) int mc_size_group; int mc_size_initgroups; int mc_size_sid; + uid_t uid; + gid_t gid; + +#ifdef SSSD_NON_ROOT_USER + uid = nctx->rctx->uid; + gid = nctx->rctx->gid; +#else + uid = 0; + gid = 0; +#endif /* SSSD_NON_ROOT_USER */ /* Remove the CLEAR_MC_FLAG file if exists. */ ret = unlink(SSS_NSS_MCACHE_DIR"/"CLEAR_MC_FLAG); @@ -361,7 +381,7 @@ static int setup_memcaches(struct sss_nss_ctx *nctx) /* Initialize the fast in-memory caches if they were not disabled */ ret = sss_mmap_cache_init(nctx, "passwd", - nctx->mc_uid, nctx->mc_gid, + uid, gid, SSS_MC_PASSWD, mc_size_passwd * SSS_MC_CACHE_SLOTS_PER_MB, (time_t)memcache_timeout, @@ -373,7 +393,7 @@ static int setup_memcaches(struct sss_nss_ctx *nctx) } ret = sss_mmap_cache_init(nctx, "group", - nctx->mc_uid, nctx->mc_gid, + uid, gid, SSS_MC_GROUP, mc_size_group * SSS_MC_CACHE_SLOTS_PER_MB, (time_t)memcache_timeout, @@ -385,7 +405,7 @@ static int setup_memcaches(struct sss_nss_ctx *nctx) } ret = sss_mmap_cache_init(nctx, "initgroups", - nctx->mc_uid, nctx->mc_gid, + uid, gid, SSS_MC_INITGROUPS, mc_size_initgroups * SSS_MC_CACHE_SLOTS_PER_MB, (time_t)memcache_timeout, @@ -397,7 +417,7 @@ static int setup_memcaches(struct sss_nss_ctx *nctx) } ret = sss_mmap_cache_init(nctx, "sid", - nctx->mc_uid, nctx->mc_gid, + uid, gid, SSS_MC_SID, mc_size_sid * SSS_MC_CACHE_SLOTS_PER_MB, (time_t)memcache_timeout, @@ -441,79 +461,6 @@ sss_nss_register_service_iface(struct sss_nss_ctx *nss_ctx, return ret; } -static int sssd_supplementary_group(struct sss_nss_ctx *nss_ctx) -{ - errno_t ret; - int size; - gid_t *supp_gids = NULL; - - /* - * We explicitly read the IDs of the SSSD user even though the server - * receives --uid and --gid by parameters to account for the case where - * the SSSD is compiled --with-sssd-user=sssd but the default of the - * user option is root (this is what RHEL does) - */ - ret = sss_user_by_name_or_uid(SSSD_USER, - &nss_ctx->mc_uid, - &nss_ctx->mc_gid); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, "Cannot get info on "SSSD_USER); - return ret; - } - - if (getgid() == nss_ctx->mc_gid) { - DEBUG(SSSDBG_TRACE_FUNC, "Already running as the sssd group\n"); - return EOK; - } - - size = getgroups(0, NULL); - if (size == -1) { - ret = errno; - DEBUG(SSSDBG_CRIT_FAILURE, "Getgroups failed! (%d, %s)\n", - ret, sss_strerror(ret)); - return ret; - } - - if (size > 0) { - supp_gids = talloc_zero_array(NULL, gid_t, size); - if (supp_gids == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Allocation failed!\n"); - ret = ENOMEM; - goto done; - } - - size = getgroups(size, supp_gids); - if (size == -1) { - ret = errno; - DEBUG(SSSDBG_CRIT_FAILURE, "Getgroups failed! (%d, %s)\n", - ret, sss_strerror(ret)); - goto done; - } - - for (int i = 0; i < size; i++) { - if (supp_gids[i] == nss_ctx->mc_gid) { - DEBUG(SSSDBG_TRACE_FUNC, - "Already assigned to the SSSD supplementary group\n"); - ret = EOK; - goto done; - } - } - } - - ret = setgroups(1, &nss_ctx->mc_gid); - if (ret != EOK) { - ret = errno; - DEBUG(SSSDBG_OP_FAILURE, - "Cannot setgroups [%d]: %s\n", ret, sss_strerror(ret)); - goto done; - } - - ret = EOK; -done: - talloc_free(supp_gids); - return ret; -} - int sss_nss_process_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct confdb_ctx *cdb) @@ -613,19 +560,6 @@ int sss_nss_process_init(TALLOC_CTX *mem_ctx, goto fail; } - /* - * Adding the NSS process to the SSSD supplementary group avoids - * dac_override AVC messages from SELinux in case sssd_nss runs - * as root and tries to write to memcache owned by sssd:sssd - */ - ret = sssd_supplementary_group(nctx); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Cannot add process to the sssd supplementary group [%d]: %s\n", - ret, sss_strerror(ret)); - goto fail; - } - ret = setup_memcaches(nctx); if (ret != EOK) { goto fail; diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c index 90d12299a40..5563a709ff0 100644 --- a/src/responder/nss/nsssrv_mmap_cache.c +++ b/src/responder/nss/nsssrv_mmap_cache.c @@ -1271,6 +1271,7 @@ static errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx) return ret; } +#ifdef SSSD_NON_ROOT_USER /* Make sure that the memory cache files are chowned to sssd.sssd even * if the nss responder runs as root. This is because the specfile * has the ownership recorded as sssd.sssd @@ -1284,6 +1285,7 @@ static errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx) return ret; } } +#endif /* SSSD_NON_ROOT_USER */ ret = sss_br_lock_file(mc_ctx->fd, 0, 1, retries, t); if (ret != EOK) {