diff --git a/Makefile.am b/Makefile.am
index 2ed5a866b74..46ef95a8865 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -105,12 +105,15 @@ if SSSD_NON_ROOT_USER
additional_caps = CAP_DAC_OVERRIDE
nss_service_user_group = User=$(SSSD_USER)\nGroup=$(SSSD_USER)
nss_socket_user_group = SocketUser=$(SSSD_USER)\nSocketGroup=$(SSSD_USER)
-endif
+supplementary_groups = \# If service configured to be run under "root", uncomment "SupplementaryGroups"\n\#SupplementaryGroups=$(SSSD_USER)
+else
+supplementary_groups = \# Note: SSSD package was built without support of running as non-privileged user
+endif # SSSD_NON_ROOT_USER
else
ifp_dbus_exec_comment = \# "sss_signal" is used to force SSSD monitor to trigger "sssd_ifp" reconnection to dbus
ifp_dbus_exec_cmd = $(sssdlibexecdir)/sss_signal
ifp_systemdservice =
-endif
+endif # HAVE_SYSTEMD_UNIT
secdbpath = @secdbpath@
@@ -1511,6 +1514,7 @@ endif
####################
sssd_SOURCES = \
src/monitor/monitor.c \
+ src/monitor/monitor_bootstrap.c \
src/monitor/monitor_netlink.c \
src/confdb/confdb_setup.c \
src/util/nscd.c \
@@ -5279,7 +5283,8 @@ edit_cmd = $(SED) \
-e 's|@condconfigexists[@]|$(condconfigexists)|g' \
-e 's|@additional_caps[@]|$(additional_caps)|g' \
-e 's|@nss_service_user_group[@]|$(nss_service_user_group)|g' \
- -e 's|@nss_socket_user_group[@]|$(nss_socket_user_group)|g'
+ -e 's|@nss_socket_user_group[@]|$(nss_socket_user_group)|g' \
+ -e 's|@supplementary_groups[@]|$(supplementary_groups)|g'
replace_script = \
@rm -f $@ $@.tmp; \
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index 7f071970200..74c665cffbd 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -19,6 +19,7 @@
along with this program. If not, see .
*/
+#include "config.h"
#include "util/util.h"
#include "util/child_common.h"
#include
@@ -1973,6 +1974,8 @@ static void monitor_restart_service(struct mt_svc *svc)
}
}
+int bootstrap_monitor_process(void);
+
int main(int argc, const char *argv[])
{
int opt;
@@ -2085,6 +2088,7 @@ int main(int argc, const char *argv[])
poptFreeContext(pc);
+ /* TODO: revisit */
uid = getuid();
if (uid != 0) {
ERROR("Running under %"PRIu64", must be root\n", (uint64_t) uid);
@@ -2092,6 +2096,13 @@ int main(int argc, const char *argv[])
return 1;
}
+ ret = bootstrap_monitor_process();
+ if (ret != 0) {
+ ERROR("Failed to boostrap SSSD 'monitor' process: %s", sss_strerror(ret));
+ sss_log(SSS_LOG_ALERT, "Failed to boostrap SSSD 'monitor' process.");
+ return 5;
+ }
+
/* default value of 'debug_prg_name' will be used */
DEBUG_INIT(debug_level, opt_logger);
diff --git a/src/monitor/monitor_bootstrap.c b/src/monitor/monitor_bootstrap.c
new file mode 100644
index 00000000000..2ee33f079c8
--- /dev/null
+++ b/src/monitor/monitor_bootstrap.c
@@ -0,0 +1,122 @@
+/*
+ SSSD
+
+ Service monitor bootstrap
+
+ 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 .
+*/
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+
+#include "util/util.h"
+
+
+/* Attention!
+ * When those routines are being executed, internal logger isn't yet initialized.
+ */
+
+
+#ifdef SSSD_NON_ROOT_USER
+/* returns: -1 on error, 0 - group not set, 1 - group set */
+static int check_supplementary_group(gid_t gid)
+{
+ int size;
+ gid_t *supp_gids = NULL;
+
+ if (getegid() == gid) {
+ return 1;
+ }
+
+ size = getgroups(0, NULL);
+ if (size == -1) {
+ return -1;
+ }
+
+ if (size > 0) {
+ supp_gids = talloc_zero_array(NULL, gid_t, size);
+ if (supp_gids == NULL) {
+ return -1;
+ }
+
+ size = getgroups(size, supp_gids);
+ if (size == -1) {
+ talloc_free(supp_gids);
+ return -1;
+ }
+
+ for (int i = 0; i < size; i++) {
+ if (supp_gids[i] == gid) {
+ talloc_free(supp_gids);
+ return 1;
+ }
+ }
+
+ talloc_free(supp_gids);
+ }
+
+ return 0;
+}
+#endif /* SSSD_NON_ROOT_USER */
+
+int bootstrap_monitor_process(void)
+{
+
+#ifdef SSSD_NON_ROOT_USER
+ /* In case SSSD is built with non-root user support,
+ * a number of files are sssd:sssd owned.
+ * Make sure all processes are added to sssd supplementary
+ * group to avoid the need for CAP_DAC_OVERRIDE.
+ *
+ * TODO: read 'sssd.conf::user' first and in case it is set
+ * to 'sssd' become_user(sssd) instead.
+ */
+ int ret;
+ gid_t sssd_gid = 0;
+ if ((getuid() == 0) || (geteuid() == 0)) {
+ sss_sssd_user_uid_and_gid(NULL, &sssd_gid);
+ ret = check_supplementary_group(sssd_gid);
+ if (ret == -1) {
+ sss_log(SSS_LOG_ALERT, "Can't check own supplementary groups.");
+ return 1;
+ }
+ /* Expected outcome is 'ret == 1' since supplementary group should be set
+ by systemd service description. */
+ if (ret == 0) {
+ /* Probably non-systemd based system or service file was edited,
+ let's try to set group manually. */
+ sss_log(SSS_LOG_WARNING,
+ "SSSD is built with support of 'run under non-root user' "
+ "feature but started under 'root'. Trying to add process "
+ "to SSSD supplementary group.");
+ ret = setgroups(1, &sssd_gid);
+ if (ret != 0) {
+ sss_log(SSS_LOG_CRIT,
+ "Failed to add process to the "SSSD_USER" supplementary group. "
+ "Either run under '"SSSD_USER"' or make sure that run-under-root "
+ "main SSSD process has CAP_SETGID.");
+ return 1;
+ }
+ }
+
+ /* TODO: drop CAP_SET_GID capability */
+ }
+#endif /* SSSD_NON_ROOT_USER */
+
+ return 0;
+}
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 45ce78fcaad..0bc53191233 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -92,7 +92,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, -1, -1,
-1, /* keep current size */
(time_t) memcache_timeout,
&nctx->pwd_mc_ctx);
@@ -102,7 +102,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, -1, -1,
-1, /* keep current size */
(time_t) memcache_timeout,
&nctx->grp_mc_ctx);
@@ -112,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, -1, -1,
-1, /* keep current size */
(time_t)memcache_timeout,
&nctx->initgr_mc_ctx);
@@ -287,6 +287,10 @@ 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;
+
+ sss_sssd_user_uid_and_gid(&uid, &gid);
/* Remove the CLEAR_MC_FLAG file if exists. */
ret = unlink(SSS_NSS_MCACHE_DIR"/"CLEAR_MC_FLAG);
@@ -361,7 +365,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 +377,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 +389,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 +401,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 +445,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)
@@ -605,19 +536,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 06f3d7a694a..7d4f23c05e4 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -1291,6 +1291,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
@@ -1304,6 +1305,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) {
diff --git a/src/sysv/systemd/sssd-autofs.service.in b/src/sysv/systemd/sssd-autofs.service.in
index e917ed78e27..ce597602b24 100644
--- a/src/sysv/systemd/sssd-autofs.service.in
+++ b/src/sysv/systemd/sssd-autofs.service.in
@@ -16,3 +16,4 @@ ExecStart=@libexecdir@/sssd/sssd_autofs ${DEBUG_LOGGER} --socket-activated
Restart=on-failure
User=@SSSD_USER@
Group=@SSSD_USER@
+@supplementary_groups@
diff --git a/src/sysv/systemd/sssd-ifp.service.in b/src/sysv/systemd/sssd-ifp.service.in
index 4aed90bb96b..2e307f3b001 100644
--- a/src/sysv/systemd/sssd-ifp.service.in
+++ b/src/sysv/systemd/sssd-ifp.service.in
@@ -18,3 +18,4 @@ CapabilityBoundingSet= @additional_caps@
Restart=on-failure
User=@SSSD_USER@
Group=@SSSD_USER@
+@supplementary_groups@
diff --git a/src/sysv/systemd/sssd-kcm.service.in b/src/sysv/systemd/sssd-kcm.service.in
index cb1e7a3a154..1c6b914ab82 100644
--- a/src/sysv/systemd/sssd-kcm.service.in
+++ b/src/sysv/systemd/sssd-kcm.service.in
@@ -14,3 +14,4 @@ ExecStart=@libexecdir@/sssd/sssd_kcm ${DEBUG_LOGGER}
# ('User=' and 'Group=' defaults to 'root' for system services)
# 'CapabilityBoundingSet' is used to limit privileges set:
CapabilityBoundingSet= @additional_caps@ CAP_SETGID CAP_SETUID
+@supplementary_groups@
diff --git a/src/sysv/systemd/sssd-nss.service.in b/src/sysv/systemd/sssd-nss.service.in
index 0bf2bb2de13..c0e5fa4ec31 100644
--- a/src/sysv/systemd/sssd-nss.service.in
+++ b/src/sysv/systemd/sssd-nss.service.in
@@ -20,3 +20,4 @@ Restart=on-failure
# In case SSSD was built with support of running under non-root user, there is a special
# handling in 'libnss_sss' and it is allowed to use build time configured user in 'User='/'Group='
@nss_service_user_group@
+@supplementary_groups@
diff --git a/src/sysv/systemd/sssd-pac.service.in b/src/sysv/systemd/sssd-pac.service.in
index db435897abb..b1bc2907303 100644
--- a/src/sysv/systemd/sssd-pac.service.in
+++ b/src/sysv/systemd/sssd-pac.service.in
@@ -16,3 +16,4 @@ ExecStart=@libexecdir@/sssd/sssd_pac ${DEBUG_LOGGER} --socket-activated
Restart=on-failure
User=@SSSD_USER@
Group=@SSSD_USER@
+@supplementary_groups@
diff --git a/src/sysv/systemd/sssd-pam.service.in b/src/sysv/systemd/sssd-pam.service.in
index ffb9665d2d8..19d4bd3c733 100644
--- a/src/sysv/systemd/sssd-pam.service.in
+++ b/src/sysv/systemd/sssd-pam.service.in
@@ -16,3 +16,4 @@ ExecStart=@libexecdir@/sssd/sssd_pam ${DEBUG_LOGGER} --socket-activated
Restart=on-failure
User=@SSSD_USER@
Group=@SSSD_USER@
+@supplementary_groups@
diff --git a/src/sysv/systemd/sssd-ssh.service.in b/src/sysv/systemd/sssd-ssh.service.in
index 5b992e08376..42324b922c2 100644
--- a/src/sysv/systemd/sssd-ssh.service.in
+++ b/src/sysv/systemd/sssd-ssh.service.in
@@ -16,3 +16,4 @@ ExecStart=@libexecdir@/sssd/sssd_ssh ${DEBUG_LOGGER} --socket-activated
Restart=on-failure
User=@SSSD_USER@
Group=@SSSD_USER@
+@supplementary_groups@
diff --git a/src/sysv/systemd/sssd-sudo.service.in b/src/sysv/systemd/sssd-sudo.service.in
index 0092442fbc3..0adb9c0a9d3 100644
--- a/src/sysv/systemd/sssd-sudo.service.in
+++ b/src/sysv/systemd/sssd-sudo.service.in
@@ -16,3 +16,4 @@ ExecStart=@libexecdir@/sssd/sssd_sudo ${DEBUG_LOGGER} --socket-activated
Restart=on-failure
User=@SSSD_USER@
Group=@SSSD_USER@
+@supplementary_groups@
diff --git a/src/sysv/systemd/sssd.service.in b/src/sysv/systemd/sssd.service.in
index 4d9596a8374..b988d43b6d9 100644
--- a/src/sysv/systemd/sssd.service.in
+++ b/src/sysv/systemd/sssd.service.in
@@ -19,6 +19,7 @@ PIDFile=@pidpath@/sssd.pid
# 'CapabilityBoundingSet' is used to limit privileges set:
CapabilityBoundingSet= @additional_caps@ CAP_CHOWN CAP_KILL CAP_SETGID CAP_SETUID
Restart=on-abnormal
+@supplementary_groups@
[Install]
WantedBy=multi-user.target