When login is almost done it chdir()'s into the user's home directory.
It currently uses pwd->pw_dir, i.e the home dir actually assigned to the
user.
OTOH it explicitly allows overriding HOME (see comment in
init_environ()), and explicitly imports PAM's env vars (which quite
possibly contain $HOME) into its env block.
This patch makes sure that HOME is *properly* overridable via the env
var and via PAM: it actually honours it for the chdir().
(Background: I am working on a PAM module that under some conditions
would like to redirect the home dir to some other dir, and while I can
nicely set $HOME from the PAM module, it has not as much as effect as I
wish, because whie the rest of userspace respects it login so far didn't
and leaves the user in the wrong dir).
extern void free_getlogindefs_data(void);
extern int logindefs_setenv(const char *name, const char *conf, const char *dflt);
extern int effective_access(const char *path, int mode);
-extern int get_hushlogin_status(struct passwd *pwd, int force_check);
+extern int get_hushlogin_status(struct passwd *pwd, const char *override_home, int force_check);
#endif /* UTIL_LINUX_LOGINDEFS_H */
* BSD setreuid().
*/
-int get_hushlogin_status(struct passwd *pwd, int force_check)
+int get_hushlogin_status(struct passwd *pwd, const char *override_home, int force_check)
{
const char *files[] = { _PATH_HUSHLOGINS, _PATH_HUSHLOGIN, NULL };
const char *file;
if (strlen(pwd->pw_dir) + strlen(file) + 2 > sizeof(buf))
continue;
- if (snprintf(buf, sizeof(buf), "%s/%s", pwd->pw_dir, file) < 0)
+ if (snprintf(buf, sizeof(buf), "%s/%s", override_home ?: pwd->pw_dir, file) < 0)
continue;
if (force_check) {
}
}
- cxt.quiet = get_hushlogin_status(pwd, 1) == 1 ? 1 : 0;
+ cxt.quiet = get_hushlogin_status(pwd, pam_getenv(cxt.pamh, "HOME"), 1) == 1 ? 1 : 0;
/*
* Open PAM session (after successful authentication and account check).
}
/* wait until here to change directory! */
- if (chdir(pwd->pw_dir) < 0) {
- warn(_("%s: change directory failed"), pwd->pw_dir);
+ const char *home = getenv("HOME") ?: pwd->pw_dir;
+ if (chdir(home) < 0) {
+ warn(_("%s: change directory failed"), home);
if (!getlogindefs_bool("DEFAULT_HOME", 1))
exit(0);
}
break;
case COL_HUSH_STATUS:
- user->hushed = get_hushlogin_status(pwd, 0);
+ user->hushed = get_hushlogin_status(pwd, /* override_home= */ NULL, 0);
if (user->hushed == -1)
user->hushed = STATUS_UNKNOWN;
break;