Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37906388
en ru br
ALT Linux repos
S:2.8.1-alt3.1

Group :: System/Servers
RPM: sssd

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: sssd-2.8.1-alt.patch
Download


 Makefile.am                                    |   1 +
 configure.ac                                   |   2 +-
 src/db/sysdb_init.c                            |   3 +-
 src/db/sysdb_private.h                         |   4 +-
 src/db/sysdb_upgrade.c                         |  16 ++-
 src/examples/logrotate                         |  12 --
 src/examples/logrotate.in                      |  13 ++
 src/external/pac_responder.m4                  |   3 +-
 src/providers/ad/ad_gpo.c                      |  17 ++-
 src/providers/ad/ad_gpo_child.c                |  10 +-
 src/providers/data_provider/dp_targets.c       |   3 +
 src/providers/ipa/ipa_deskprofile_rules_util.c | 165 ++-----------------------
 src/providers/ipa/ipa_deskprofile_rules_util.h |  12 +-
 src/providers/ipa/ipa_session.c                |  10 +-
 src/sss_client/common.c                        |  24 +++-
 src/tests/cwrap/Makefile.am                    |   1 +
 src/tests/cwrap/test_become_user.c             |  48 +++++++
 src/util/become_user.c                         |  48 ++++++-
 src/util/domain_info_utils.c                   |  18 +++
 src/util/server.c                              |   2 +-
 src/util/util.h                                |   4 +
 21 files changed, 214 insertions(+), 202 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 62b3e573c..2e038d026 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1013,6 +1013,7 @@ libsss_cert_la_LIBADD = \
     libsss_crypt.la \
     libsss_child.la \
     libsss_debug.la \
+    libsss_child.la \
     $(NULL)
 libsss_cert_la_LDFLAGS = \
     -avoid-version \
diff --git a/configure.ac b/configure.ac
index 85a1a97d2..e9ba5131b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -537,7 +537,7 @@ AC_SUBST([abs_builddir], $abs_build_dir)
 my_srcdir=`readlink -f $srcdir`
 AC_DEFINE_UNQUOTED([ABS_SRC_DIR], ["$my_srcdir"], [Absolute path to the source directory])
 
-AC_CONFIG_FILES([Makefile contrib/sssd.spec src/examples/rwtab src/doxy.config
+AC_CONFIG_FILES([Makefile contrib/sssd.spec src/examples/rwtab src/examples/logrotate src/doxy.config
                  contrib/sssd-pcsc.rules
                  src/sysv/sssd src/sysv/gentoo/sssd src/sysv/gentoo/sssd-kcm
                  po/Makefile.in src/man/Makefile src/tests/cwrap/Makefile
diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c
index c2ea6c369..008ac6233 100644
--- a/src/db/sysdb_init.c
+++ b/src/db/sysdb_init.c
@@ -1036,7 +1036,8 @@ int sysdb_init_ext(TALLOC_CTX *mem_ctx,
 
     if (upgrade_ctx != NULL) {
         /* check if we have an old sssd.ldb to upgrade */
-        ret = sysdb_check_upgrade_02(domains, DB_PATH);
+        ret = sysdb_check_upgrade_02(domains, DB_PATH,
+			             chown_dbfile, uid, gid);
         if (ret != EOK) {
             return ret;
         }
diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h
index 1f55007bc..c79746419 100644
--- a/src/db/sysdb_private.h
+++ b/src/db/sysdb_private.h
@@ -166,7 +166,9 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
 /* Upgrade routines */
 int sysdb_upgrade_01(struct ldb_context *ldb, const char **ver);
 int sysdb_check_upgrade_02(struct sss_domain_info *domains,
-                           const char *db_path);
+                           const char *db_path,
+                           bool chown_local_dbfile,
+                           uid_t uid, gid_t gid);
 int sysdb_upgrade_03(struct sysdb_ctx *sysdb, const char **ver);
 int sysdb_upgrade_04(struct sysdb_ctx *sysdb, const char **ver);
 int sysdb_upgrade_05(struct sysdb_ctx *sysdb, const char **ver);
diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c
index 346a1cb0b..4e4cf6ae6 100644
--- a/src/db/sysdb_upgrade.c
+++ b/src/db/sysdb_upgrade.c
@@ -264,7 +264,10 @@ done:
 }
 
 int sysdb_check_upgrade_02(struct sss_domain_info *domains,
-                           const char *db_path)
+                           const char *db_path,
+                           bool chown_local_dbfile,
+                           uid_t uid,
+                           gid_t gid)
 {
     TALLOC_CTX *tmp_ctx = NULL;
     struct ldb_context *ldb;
@@ -298,6 +301,17 @@ int sysdb_check_upgrade_02(struct sss_domain_info *domains,
         return ret;
     }
 
+    if (chown_local_dbfile) {
+        ret = chown(ldb_file, uid, gid);
+        if (ret != 0) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Cannot set ownership of %s to %"SPRIuid":%"SPRIgid"\n",
+                  ldb_file, uid, gid);
+            ret = errno;
+            goto exit;
+	}
+    }
+
     verdn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE);
     if (!verdn) {
         ret = EIO;
diff --git a/src/examples/logrotate b/src/examples/logrotate
deleted file mode 100644
index ecf0c6102..000000000
--- a/src/examples/logrotate
+++ /dev/null
@@ -1,12 +0,0 @@
-/var/log/sssd/*.log {
-    weekly
-    missingok
-    notifempty
-    sharedscripts
-    rotate 2
-    compress
-    delaycompress
-    postrotate
-        /bin/kill -HUP `cat /var/run/sssd.pid  2>/dev/null`  2> /dev/null || true
-    endscript
-}
diff --git a/src/examples/logrotate.in b/src/examples/logrotate.in
new file mode 100644
index 000000000..2c34e7d87
--- /dev/null
+++ b/src/examples/logrotate.in
@@ -0,0 +1,13 @@
+/var/log/sssd/*.log {
+    su root @SSSD_USER@
+    weekly
+    missingok
+    notifempty
+    sharedscripts
+    rotate 2
+    compress
+    delaycompress
+    postrotate
+        /bin/kill -HUP `cat /var/run/sssd.pid  2>/dev/null`  2> /dev/null || true
+    endscript
+}
diff --git a/src/external/pac_responder.m4 b/src/external/pac_responder.m4
index 3cbe3c9cf..90727185b 100644
--- a/src/external/pac_responder.m4
+++ b/src/external/pac_responder.m4
@@ -22,7 +22,8 @@ then
         Kerberos\ 5\ release\ 1.17* | \
         Kerberos\ 5\ release\ 1.18* | \
         Kerberos\ 5\ release\ 1.19* | \
-        Kerberos\ 5\ release\ 1.20*)
+        Kerberos\ 5\ release\ 1.20* | \
+        Kerberos\ 5\ release\ 1.21*)
             krb5_version_ok=yes
             AC_MSG_RESULT([yes])
             ;;
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index 4b7bbf182..905adc226 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -1352,7 +1352,7 @@ ad_gpo_store_policy_settings(struct sss_domain_info *domain,
     ret = ini_config_file_open(filename, 0, &file_ctx);
     if (ret != 0) {
         DEBUG(SSSDBG_CRIT_FAILURE,
-              "ini_config_file_open failed [%d][%s]\n", ret, strerror(ret));
+              "ini_config_file_open failed [%d][%s][%s]\n", ret, strerror(ret), filename);
         goto done;
     }
 
@@ -1395,8 +1395,8 @@ ad_gpo_store_policy_settings(struct sss_domain_info *domain,
         ret = ini_config_file_open(filename, 0, &file_ctx);
         if (ret != 0) {
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "ini_config_file_open failed [%d][%s]\n",
-                  ret, strerror(ret));
+                  "ini_config_file_open failed again [%d][%s][%s]\n",
+                  ret, strerror(ret), filename);
             goto done;
         }
 
@@ -4934,8 +4934,15 @@ ad_gpo_get_sd_referral_send(TALLOC_CTX *mem_ctx,
      * in these referrals, so we can use that to look up the
      * necessary connection.
      */
-    state->ref_domain = find_domain_by_name(state->host_domain,
-                                            lud->lud_host, true);
+    state->ref_domain = find_domain_by_hostname(state->host_domain,
+                                                lud->lud_host, true);
+
+    /* Try to find domain name as is for backward compatibility
+     */
+    if (!state->ref_domain) {
+        state->ref_domain = find_domain_by_name(state->host_domain,
+                                                lud->lud_host, true);
+    }
     if (!state->ref_domain) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               "Could not find domain matching [%s]\n",
diff --git a/src/providers/ad/ad_gpo_child.c b/src/providers/ad/ad_gpo_child.c
index 319156b8c..3bae0e771 100644
--- a/src/providers/ad/ad_gpo_child.c
+++ b/src/providers/ad/ad_gpo_child.c
@@ -578,7 +578,7 @@ perform_smb_operations(int cached_gpt_version,
 {
     SMBCCTX *smbc_ctx;
     int ret;
-    int sysvol_gpt_version;
+    int sysvol_gpt_version = cached_gpt_version;
     char *ini_filename = NULL;
     TALLOC_CTX *tmp_ctx = NULL;
 
@@ -644,9 +644,13 @@ perform_smb_operations(int cached_gpt_version,
         ret = EOK;
     }
 
-    *_sysvol_gpt_version = sysvol_gpt_version;
-
  done:
+    if (sysvol_gpt_version >= 0)
+        ret = EOK;
+
+    if (ret == EOK)
+        *_sysvol_gpt_version = sysvol_gpt_version;
+
     talloc_free(tmp_ctx);
     smbc_free_context(smbc_ctx, 0);
     return ret;
diff --git a/src/providers/data_provider/dp_targets.c b/src/providers/data_provider/dp_targets.c
index d2cb50f0c..57d4ffb66 100644
--- a/src/providers/data_provider/dp_targets.c
+++ b/src/providers/data_provider/dp_targets.c
@@ -20,6 +20,7 @@
 
 #include <talloc.h>
 #include <dlfcn.h>
+#include <selinux/selinux.h>
 
 #include "config.h"
 #include "providers/data_provider/dp.h"
@@ -154,6 +155,8 @@ static const char *dp_target_default_module(struct dp_target **targets,
         return "permit";
     case DPT_CHPASS:
         return dp_target_module_name(targets, DPT_AUTH);
+    case DPT_SELINUX:
+        return is_selinux_enabled() ? dp_target_module_name(targets, DPT_ID) : "none";
     case DP_TARGET_SENTINEL:
         return NULL;
     default:
diff --git a/src/providers/ipa/ipa_deskprofile_rules_util.c b/src/providers/ipa/ipa_deskprofile_rules_util.c
index d6fa3cc37..ab80b4c11 100644
--- a/src/providers/ipa/ipa_deskprofile_rules_util.c
+++ b/src/providers/ipa/ipa_deskprofile_rules_util.c
@@ -220,9 +220,7 @@ done:
 
 errno_t
 ipa_deskprofile_rules_create_user_dir(
-                                    const char *username, /* fully-qualified */
-                                    uid_t uid,
-                                    gid_t gid)
+                                    const char *username /* fully-qualified */)
 {
     TALLOC_CTX *tmp_ctx;
     char *shortname;
@@ -230,12 +228,17 @@ ipa_deskprofile_rules_create_user_dir(
     char *domain_dir;
     errno_t ret;
     mode_t old_umask;
+    uid_t uid;
+    gid_t gid;
 
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
         return ENOMEM;
     }
 
+    uid = geteuid();
+    gid = getegid();
+
     ret = sss_parse_internal_fqname(tmp_ctx, username, &shortname, &domain);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -244,9 +247,9 @@ ipa_deskprofile_rules_create_user_dir(
         goto done;
     }
 
-    old_umask = umask(0026);
-    ret = sss_create_dir(IPA_DESKPROFILE_RULES_USER_DIR, domain, 0751,
-                         getuid(), getgid());
+    old_umask = umask(0077);
+    ret = sss_create_dir(IPA_DESKPROFILE_RULES_USER_DIR, domain, 0700,
+                         uid, gid);
     umask(old_umask);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -684,9 +687,7 @@ ipa_deskprofile_rules_save_rule_to_disk(
                                     struct sysdb_attrs *rule,
                                     struct sss_domain_info *domain,
                                     const char *hostname,
-                                    const char *username, /* fully-qualified */
-                                    uid_t uid,
-                                    gid_t gid)
+                                    const char *username /* fully-qualified */ )
 {
     TALLOC_CTX *tmp_ctx;
     const char *rule_name;
@@ -706,8 +707,6 @@ ipa_deskprofile_rules_save_rule_to_disk(
     const char *extension = "json";
     uint32_t prio;
     int fd = -1;
-    gid_t orig_gid;
-    uid_t orig_uid;
     errno_t ret;
 
     tmp_ctx = talloc_new(mem_ctx);
@@ -715,9 +714,6 @@ ipa_deskprofile_rules_save_rule_to_disk(
         return ENOMEM;
     }
 
-    orig_gid = getegid();
-    orig_uid = geteuid();
-
     ret = sysdb_attrs_get_string(rule, IPA_CN, &rule_name);
     if (ret != EOK) {
         DEBUG(SSSDBG_TRACE_FUNC,
@@ -880,26 +876,6 @@ ipa_deskprofile_rules_save_rule_to_disk(
         goto done;
     }
 
-    ret = setegid(gid);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Unable to set effective group id (%"PRIu32") of the domain's "
-              "process [%d]: %s\n",
-              gid, ret, sss_strerror(ret));
-        goto done;
-    }
-
-    ret = seteuid(uid);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Unable to set effective user id (%"PRIu32") of the domain's "
-              "process [%d]: %s\n",
-              uid, ret, sss_strerror(ret));
-        goto done;
-    }
-
     fd = open(filename_path, O_WRONLY | O_CREAT | O_TRUNC, 0400);
     if (fd == -1) {
         ret = errno;
@@ -920,94 +896,21 @@ ipa_deskprofile_rules_save_rule_to_disk(
         goto done;
     }
 
-    ret = seteuid(orig_uid);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Failed to set the effect user id (%"PRIu32") of the domain's "
-              "process [%d]: %s\n",
-              orig_uid, ret, sss_strerror(ret));
-        goto done;
-    }
-
-    ret = setegid(orig_gid);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Failed to set the effect group id (%"PRIu32") of the domain's "
-              "process [%d]: %s\n",
-              orig_gid, ret, sss_strerror(ret));
-        goto done;
-    }
-
     ret = EOK;
 
 done:
     if (fd != -1) {
         close(fd);
     }
-    if (geteuid() != orig_uid) {
-        ret = seteuid(orig_uid);
-        if (ret == -1) {
-            ret = errno;
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Unable to set effective user id (%"PRIu32") of the "
-                  "domain's process [%d]: %s\n",
-                  orig_uid, ret, sss_strerror(ret));
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Sending SIGUSR2 to the process: %d\n", getpid());
-            kill(getpid(), SIGUSR2);
-        }
-    }
-    if (getegid() != orig_gid) {
-        ret = setegid(orig_gid);
-        if (ret == -1) {
-            ret = errno;
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Unable to set effective group id (%"PRIu32") of the "
-                  "domain's process. Let's have the process restarted!\n",
-                  orig_gid);
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Sending SIGUSR2 to the process: %d\n", getpid());
-            kill(getpid(), SIGUSR2);
-        }
-    }
     talloc_free(tmp_ctx);
     return ret;
 }
 
 errno_t
-ipa_deskprofile_rules_remove_user_dir(const char *user_dir,
-                                      uid_t uid,
-                                      gid_t gid)
+ipa_deskprofile_rules_remove_user_dir(const char *user_dir)
 {
-    gid_t orig_gid;
-    uid_t orig_uid;
     errno_t ret;
 
-    orig_gid = getegid();
-    orig_uid = geteuid();
-
-    ret = setegid(gid);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Unable to set effective group id (%"PRIu32") of the domain's "
-              "process [%d]: %s\n",
-              gid, ret, sss_strerror(ret));
-        goto done;
-    }
-
-    ret = seteuid(uid);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Unable to set effective user id (%"PRIu32") of the domain's "
-              "process [%d]: %s\n",
-              uid, ret, sss_strerror(ret));
-        goto done;
-    }
-
     ret = sss_remove_subtree(user_dir);
     if (ret != EOK && ret != ENOENT) {
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -1016,26 +919,6 @@ ipa_deskprofile_rules_remove_user_dir(const char *user_dir,
         goto done;
     }
 
-    ret = seteuid(orig_uid);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Failed to set the effect user id (%"PRIu32") of the domain's "
-              "process [%d]: %s\n",
-              orig_uid, ret, sss_strerror(ret));
-        goto done;
-    }
-
-    ret = setegid(orig_gid);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Failed to set the effect group id (%"PRIu32") of the domain's "
-              "process [%d]: %s\n",
-              orig_gid, ret, sss_strerror(ret));
-        goto done;
-    }
-
     ret = sss_remove_tree(user_dir);
     if ((ret != EOK) && (ret != ENOENT)) {
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -1047,32 +930,6 @@ ipa_deskprofile_rules_remove_user_dir(const char *user_dir,
     ret = EOK;
 
 done:
-    if (geteuid() != orig_uid) {
-        ret = seteuid(orig_uid);
-        if (ret == -1) {
-            ret = errno;
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "unable to set effective user id (%"PRIu32") of the "
-                  "domain's process [%d]: %s\n",
-                  orig_uid, ret, sss_strerror(ret));
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Sending SIGUSR2 to the process: %d\n", getpid());
-            kill(getpid(), SIGUSR2);
-        }
-    }
-    if (getegid() != orig_gid) {
-        ret = setegid(orig_gid);
-        if (ret == -1) {
-            ret = errno;
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Unable to set effective user id (%"PRIu32") of the "
-                  "domain's process [%d]: %s\n",
-                  orig_uid, ret, sss_strerror(ret));
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Sending SIGUSR2 to the process: %d\n", getpid());
-            kill(getpid(), SIGUSR2);
-        }
-    }
     return ret;
 }
 
diff --git a/src/providers/ipa/ipa_deskprofile_rules_util.h b/src/providers/ipa/ipa_deskprofile_rules_util.h
index 063bbd20b..87060d338 100644
--- a/src/providers/ipa/ipa_deskprofile_rules_util.h
+++ b/src/providers/ipa/ipa_deskprofile_rules_util.h
@@ -46,9 +46,7 @@ ipa_deskprofile_get_filename_path(TALLOC_CTX *mem_ctx,
 
 errno_t
 ipa_deskprofile_rules_create_user_dir(
-                                    const char *username, /* fully-qualified */
-                                    uid_t uid,
-                                    gid_t gid);
+                                    const char *username /* fully-qualified */);
 errno_t
 ipa_deskprofile_rules_save_rule_to_disk(
                                     TALLOC_CTX *mem_ctx,
@@ -56,13 +54,9 @@ ipa_deskprofile_rules_save_rule_to_disk(
                                     struct sysdb_attrs *rule,
                                     struct sss_domain_info *domain,
                                     const char *hostname,
-                                    const char *username, /* fully-qualified */
-                                    uid_t uid,
-                                    gid_t gid);
+                                    const char *username /* fully-qualified */);
 errno_t
-ipa_deskprofile_rules_remove_user_dir(const char *user_dir,
-                                      uid_t uid,
-                                      gid_t gid);
+ipa_deskprofile_rules_remove_user_dir(const char *user_dir);
 
 errno_t
 deskprofile_get_cached_priority(struct sss_domain_info *domain,
diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c
index cd43031ce..3d21d9a7c 100644
--- a/src/providers/ipa/ipa_session.c
+++ b/src/providers/ipa/ipa_session.c
@@ -528,9 +528,7 @@ ipa_pam_session_handler_send(TALLOC_CTX *mem_ctx,
     /* As no proper merging mechanism has been implemented yet ...
      * let's just remove the user directory stored in the disk as it's
      * going to be created again in case there's any rule fetched. */
-    ret = ipa_deskprofile_rules_remove_user_dir(state->user_dir,
-                                                state->uid,
-                                                state->gid);
+    ret = ipa_deskprofile_rules_remove_user_dir(state->user_dir);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               "ipa_deskprofile_rules_remove_user_dir() failed.\n");
@@ -764,7 +762,7 @@ ipa_pam_session_handler_save_deskprofile_rules(
     }
 
     /* Create the user directory where the rules are going to be stored */
-    ret = ipa_deskprofile_rules_create_user_dir(username, uid, gid);
+    ret = ipa_deskprofile_rules_create_user_dir(username);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               "Cannot create the user directory [%d]: %s\n",
@@ -779,9 +777,7 @@ ipa_pam_session_handler_save_deskprofile_rules(
                                                       rules[i],
                                                       domain,
                                                       hostname,
-                                                      username,
-                                                      uid,
-                                                      gid);
+                                                      username);
         if (ret != EOK) {
             DEBUG(SSSDBG_OP_FAILURE,
                   "Failed to save a Desktop Profile Rule to disk [%d]: %s\n",
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index d762dff49..2c888faa9 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -27,6 +27,7 @@
 #include <nss.h>
 #include <security/pam_modules.h>
 #include <errno.h>
+#include <stdatomic.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -63,7 +64,8 @@
 
 #ifdef HAVE_PTHREAD_EXT
 static pthread_key_t sss_sd_key;
-static pthread_once_t sss_sd_key_initialized = PTHREAD_ONCE_INIT;
+static pthread_once_t sss_sd_key_init = PTHREAD_ONCE_INIT;
+static atomic_bool sss_sd_key_initialized = false;
 static __thread int sss_cli_sd = -1; /* the sss client socket descriptor */
 static __thread struct stat sss_cli_sb; /* the sss client stat buffer */
 #else
@@ -71,9 +73,6 @@ static int sss_cli_sd = -1; /* the sss client socket descriptor */
 static struct stat sss_cli_sb; /* the sss client stat buffer */
 #endif
 
-#if HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR
-__attribute__((destructor))
-#endif
 void sss_cli_close_socket(void)
 {
     if (sss_cli_sd != -1) {
@@ -91,9 +90,24 @@ static void sss_at_thread_exit(void *v)
 static void init_sd_key(void)
 {
     pthread_key_create(&sss_sd_key, sss_at_thread_exit);
+    sss_sd_key_initialized = true;
+}
+#endif
+
+#if HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR
+__attribute__((destructor)) void sss_at_lib_unload(void)
+{
+#ifdef HAVE_PTHREAD_EXT
+    if (sss_sd_key_initialized) {
+        sss_sd_key_initialized = false;
+        pthread_key_delete(sss_sd_key);
+    }
+#endif
+    sss_cli_close_socket();
 }
 #endif
 
+
 /* Requests:
  *
  * byte 0-3: 32bit unsigned with length (the complete packet length: 0 to X)
@@ -572,7 +586,7 @@ static int sss_cli_open_socket(int *errnop, const char *socket_name, int timeout
     }
 
 #ifdef HAVE_PTHREAD_EXT
-    pthread_once(&sss_sd_key_initialized, init_sd_key); /* once for all threads */
+    pthread_once(&sss_sd_key_init, init_sd_key); /* once for all threads */
 
     /* It actually doesn't matter what value to set for a key.
      * The only important thing: key must be non-NULL to ensure
diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
index f25d2e3c6..9a0096b8c 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -11,6 +11,7 @@ AM_CPPFLAGS = \
     -DSYSCONFDIR=\"$(sysconfdir)\" \
     $(DBUS_CFLAGS) \
     $(GLIB2_CFLAGS) \
+    $(PCRE_CFLAGS) \
     $(NULL)
 
 TESTS_ENVIRONMENT = \
diff --git a/src/tests/cwrap/test_become_user.c b/src/tests/cwrap/test_become_user.c
index e63cde9d7..c808d7293 100644
--- a/src/tests/cwrap/test_become_user.c
+++ b/src/tests/cwrap/test_become_user.c
@@ -70,6 +70,53 @@ void test_become_user(void **state)
     assert_int_equal(WEXITSTATUS(status), 0);
 }
 
+void test_become_server_user(void **state)
+{
+    struct passwd *sssd;
+    gid_t gid;
+    errno_t ret;
+    pid_t pid, wpid;
+    int status;
+    int group_count;
+
+    /* Must root as root, real or fake */
+    assert_int_equal(geteuid(), 0);
+
+    sssd = getpwnam("sssd");
+    assert_non_null(sssd);
+
+    pid = fork();
+    if (pid == 0) {
+        /* Change the UID in a child */
+        ret = become_server_user(sssd->pw_uid, sssd->pw_gid);
+        assert_int_equal(ret, EOK);
+
+        /* Make sure we have the requested UID and GID now and there
+         * are no supplementary groups
+         */
+        assert_int_equal(geteuid(), sssd->pw_uid);
+        assert_int_equal(getegid(), sssd->pw_gid);
+        assert_int_equal(getuid(), sssd->pw_uid);
+        assert_int_equal(getgid(), sssd->pw_gid);
+
+        /* Another become_user is a no-op */
+        ret = become_user(sssd->pw_uid, sssd->pw_gid);
+        assert_int_equal(ret, EOK);
+
+        group_count = getgroups(1, &gid);
+        assert_int_equal(1, group_count);
+        assert_int_equal(gid, sssd->pw_gid);
+        exit(0);
+    }
+
+    assert_int_not_equal(pid, -1);
+
+    wpid = waitpid(pid, &status, 0);
+    assert_int_equal(wpid, pid);
+    assert_true(WIFEXITED(status));
+    assert_int_equal(WEXITSTATUS(status), 0);
+}
+
 void test_switch_user(void **state)
 {
     errno_t ret;
@@ -137,6 +184,7 @@ int main(int argc, const char *argv[])
 
     const struct CMUnitTest tests[] = {
         cmocka_unit_test(test_become_user),
+        cmocka_unit_test(test_become_server_user),
         cmocka_unit_test(test_switch_user),
     };
 
diff --git a/src/util/become_user.c b/src/util/become_user.c
index c3f726d18..d94350872 100644
--- a/src/util/become_user.c
+++ b/src/util/become_user.c
@@ -24,8 +24,34 @@
 
 #include "util/util.h"
 #include <grp.h>
+#include <pwd.h>
 
-errno_t become_user(uid_t uid, gid_t gid)
+static errno_t init_user_groups(uid_t uid, gid_t gid)
+{
+    int ret;
+    struct passwd *pwd;
+
+    errno = 0;
+    pwd = getpwuid(uid);
+    if (pwd == NULL || pwd->pw_name == NULL) {
+        ret = errno ?: ENOENT;
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "getpwuid failed [%d][%s].\n", ret, strerror(ret));
+        return ret;
+    }
+
+    ret = initgroups(pwd->pw_name, gid);
+    if (ret == -1) {
+        ret = errno;
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "initgroups failed [%d][%s].\n", ret, strerror(ret));
+        return ret;
+    }
+
+    return EOK;
+}
+
+static errno_t become_user_ex(uid_t uid, gid_t gid, bool init_groups_flag)
 {
     uid_t cuid;
     int ret;
@@ -49,6 +75,16 @@ errno_t become_user(uid_t uid, gid_t gid)
         return ret;
     }
 
+    /* init supplmentary groups */
+    if (init_groups_flag) {
+        ret = init_user_groups(uid, gid);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "init_user_groups failed [%d][%s].\n", ret, strerror(ret));
+            return ret;
+        }
+    }
+
     /* change GID so that root cannot be regained (changes saved GID too) */
     ret = setresgid(gid, gid, gid);
     if (ret == -1) {
@@ -71,6 +107,16 @@ errno_t become_user(uid_t uid, gid_t gid)
     return EOK;
 }
 
+errno_t become_user(uid_t uid, gid_t gid)
+{
+    return become_user_ex(uid, gid, false);
+}
+
+errno_t become_server_user(uid_t uid, gid_t gid)
+{
+    return become_user_ex(uid, gid, true);
+}
+
 struct sss_creds {
     uid_t uid;
     gid_t gid;
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 33aaa6eec..22a8141e2 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -133,6 +133,24 @@ struct sss_domain_info *find_domain_by_name(struct sss_domain_info *domain,
     return find_domain_by_name_ex(domain, name, match_any, SSS_GND_DESCEND);
 }
 
+struct sss_domain_info *find_domain_by_hostname(struct sss_domain_info *domain,
+                                                const char *hostname,
+                                                bool match_any)
+{
+    char *hostdomain;
+
+    if (hostname == NULL) {
+        return NULL;
+    }
+
+    hostdomain = strrchr(hostname, '.');
+    if (hostdomain == NULL || *(hostdomain + 1) == '\0' || hostdomain == hostname) {
+        return NULL;
+    }
+
+    return find_domain_by_name_ex(domain, hostdomain, match_any, SSS_GND_DESCEND);
+}
+
 struct sss_domain_info *find_domain_by_sid(struct sss_domain_info *domain,
                                               const char *sid)
 {
diff --git a/src/util/server.c b/src/util/server.c
index 76a558fb5..6c3f1b15d 100644
--- a/src/util/server.c
+++ b/src/util/server.c
@@ -531,7 +531,7 @@ int server_setup(const char *name, bool is_responder,
                   "Cannot chown the debug files, debugging might not work!\n");
         }
 
-        ret = become_user(uid, gid);
+        ret = become_server_user(uid, gid);
         if (ret != EOK) {
             DEBUG(SSSDBG_FUNC_DATA,
                   "Cannot become user [%"SPRIuid"][%"SPRIgid"].\n", uid, gid);
diff --git a/src/util/util.h b/src/util/util.h
index bacafc8ed..4e92a3b5e 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -577,6 +577,9 @@ struct sss_domain_info *get_next_domain(struct sss_domain_info *domain,
 struct sss_domain_info *find_domain_by_name(struct sss_domain_info *domain,
                                             const char *name,
                                             bool match_any);
+struct sss_domain_info *find_domain_by_hostname(struct sss_domain_info *domain,
+                                                const char *hostname,
+                                                bool match_any);
 struct sss_domain_info *find_domain_by_name_ex(struct sss_domain_info *domain,
                                                const char *name,
                                                bool match_any,
@@ -707,6 +710,7 @@ errno_t mod_defaults_list(TALLOC_CTX *mem_ctx, const char **defaults_list,
 
 /* from become_user.c */
 errno_t become_user(uid_t uid, gid_t gid);
+errno_t become_server_user(uid_t uid, gid_t gid);
 struct sss_creds;
 errno_t switch_creds(TALLOC_CTX *mem_ctx,
                      uid_t uid, gid_t gid,
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin