WINBIND_MKHOMEDIR_AS_USER
authorStefan Metzmacher <metze@samba.org>
Tue, 11 Apr 2023 10:20:03 +0000 (12:20 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 28 Apr 2023 11:18:26 +0000 (13:18 +0200)
nsswitch/pam_winbind.c
nsswitch/pam_winbind.h

index 5e5cf0af8b89158d8bfe391f514667929861d885..50fb14da3c08327208fb5aeeff4c02f4c86a216f 100644 (file)
@@ -11,6 +11,7 @@
 */
 
 #include "pam_winbind.h"
+#include "lib/util/setid.h"
 
 enum pam_winbind_request_type
 {
@@ -477,6 +478,9 @@ static int _pam_parse(const pam_handle_t *pamh,
 
        if (tiniparser_getboolean(d, "global:mkhomedir", false)) {
                ctrl |= WINBIND_MKHOMEDIR;
+               if (tiniparser_getboolean(d, "global:mkhomedir_as_user", false)) {
+                       ctrl |= WINBIND_MKHOMEDIR_AS_USER;
+               }
        }
 
        if (tiniparser_getboolean(d, "global:pwd_change_prompt", false)) {
@@ -523,6 +527,8 @@ config_from_pam:
                        ctrl |= WINBIND_CACHED_LOGIN;
                else if (!strcasecmp(*v, "mkhomedir"))
                        ctrl |= WINBIND_MKHOMEDIR;
+               else if (!strcasecmp(*v, "mkhomedir_as_user"))
+                       ctrl |= WINBIND_MKHOMEDIR_AS_USER;
                else if (!strncasecmp(*v, "warn_pwd_expire",
                        strlen("warn_pwd_expire")))
                        ctrl |= WINBIND_WARN_PWD_EXPIRE;
@@ -1658,6 +1664,30 @@ static int _pam_mkhomedir(struct pwb_context *ctx)
        }
        _pam_log_debug(ctx, LOG_DEBUG, "homedir is: %s", pwd->pw_dir);
 
+       if (ctx->ctrl & WINBIND_MKHOMEDIR_AS_USER) {
+               uid_t saved_uid = geteuid();
+               gid_t saved_gid = getegid();
+
+               ret = setegid(pwd->pw_gid);
+               if (ret != 0) {
+                       _pam_log(ctx, LOG_ERR, "setegid(%u) failed - %s",
+                                (unsigned)pwd->pw_gid, strerror(errno));
+                       return PAM_SERVICE_ERR;
+               }
+
+               ret = seteuid(pwd->pw_uid);
+               if (ret != 0) {
+                       setegid(saved_gid);
+                       _pam_log(ctx, LOG_ERR, "seteuid(%u) failed - %s",
+                                (unsigned)pwd->pw_uid, strerror(errno));
+                       return PAM_SERVICE_ERR;
+               }
+               ret = _pam_create_homedir(ctx, pwd->pw_dir, 0700);
+               seteuid(saved_uid);
+               setegid(saved_gid);
+               return ret;
+       }
+
        ret = _pam_create_homedir(ctx, pwd->pw_dir, 0700);
        if (ret == PAM_SUCCESS) {
                ret = _pam_chown_homedir(ctx, pwd->pw_dir,
index 2f4a25729bddc789749d6348d0f86ee5ca078d76..9675cfcaa1209751452bdb0c96be4bfd5bc836ac 100644 (file)
@@ -158,6 +158,7 @@ do {                             \
 #define WINBIND_MKHOMEDIR              0x00004000
 #define WINBIND_TRY_AUTHTOK_ARG                0x00008000
 #define WINBIND_PWD_CHANGE_PROMPT      0x00010000
+#define WINBIND_MKHOMEDIR_AS_USER      0x00020000
 
 #if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
 #define _(string) dgettext(MODULE_NAME, string)