Skip to content

Commit

Permalink
RESPONDER: make all responders members of sssd group
Browse files Browse the repository at this point in the history
Previously it was only for sssd_nss

TODO:
 - explanation
 - move to monitor/systemd service file
  • Loading branch information
alexey-tikhonov committed Aug 30, 2023
1 parent 0255699 commit 7979f10
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 95 deletions.
6 changes: 6 additions & 0 deletions src/responder/common/responder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
77 changes: 77 additions & 0 deletions src/responder/common/responder_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1282,6 +1282,65 @@ static errno_t sss_get_etc_shells(TALLOC_CTX *mem_ctx, char ***_shells)
return ret;
}

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;
}

int sss_process_init(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct confdb_ctx *cdb,
Expand Down Expand Up @@ -1317,6 +1376,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,
Expand Down
2 changes: 0 additions & 2 deletions src/responder/nss/nss_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
120 changes: 27 additions & 93 deletions src/responder/nss/nsssrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/responder/nss/nsssrv_mmap_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand Down

0 comments on commit 7979f10

Please sign in to comment.