diff --git a/debian/changelog b/debian/changelog index a69513d..e098040 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +libpam-privtmp (0.1-2) unstable; urgency=low + + * Autocreate user's tmp directory if doesn't exist. + + -- Eugeny Sokolov Sun, 2 May 2017 19:44:24 +0600 + libpam-privtmp (0.1-1) unstable; urgency=low * Initial release. diff --git a/pam_privtmp.c b/pam_privtmp.c index c963d3f..efd0d1a 100644 --- a/pam_privtmp.c +++ b/pam_privtmp.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -30,7 +32,6 @@ void to_log(int prio, const char *format, ...) closelog(); } - int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *PAM_user = NULL; @@ -56,27 +57,38 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **ar snprintf(usertmp, 200, "%s/tmp", pw->pw_dir); ret = stat(usertmp, &statbuf); - if (ret == 0 && S_ISDIR(statbuf.st_mode)) { - // Try to unshare - ret = unshare(CLONE_NEWNS); - if (ret) { - to_log(LOG_ERR, "failed to unshare mounts namespace for user %s\n", pw->pw_name); - return PAM_SESSION_ERR; - } - // Mark / as slave - ret = mount("", "/", "none", MS_REC|MS_SLAVE, NULL); + if (ret != 0 || ! S_ISDIR(statbuf.st_mode)) { + to_log(LOG_INFO, "user's temp dir not found: '%s'. Trying to create it.\n", usertmp); + ret = mkdir(usertmp, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (ret) { - to_log(LOG_ERR, "failed to mark root tree as rslave for user %s\n", pw->pw_name); + to_log(LOG_ERR, "Can't create user's temp dir '%s'. %s\n", usertmp, strerror(errno)); return PAM_SESSION_ERR; } - // Mount user's tmp - ret = mount(usertmp, "/tmp", "none", MS_BIND, NULL); + ret = chown(usertmp, pw->pw_uid, pw->pw_gid); if (ret) { - to_log(LOG_ERR, "failed to bind mount temp dir for user %s\n", pw->pw_name); + to_log(LOG_ERR, "can't chown user's temp directory '%s' for user '%s'\n", usertmp, pw->pw_name); return PAM_SESSION_ERR; } - } else - to_log(LOG_INFO, "user's temp dir not found: %s\n", usertmp); + } + + // Try to unshare + ret = unshare(CLONE_NEWNS); + if (ret) { + to_log(LOG_ERR, "failed to unshare mounts namespace for user %s\n", pw->pw_name); + return PAM_SESSION_ERR; + } + // Mark / as slave + ret = mount("", "/", "none", MS_REC|MS_SLAVE, NULL); + if (ret) { + to_log(LOG_ERR, "failed to mark root tree as rslave for user %s\n", pw->pw_name); + return PAM_SESSION_ERR; + } + // Mount user's tmp + ret = mount(usertmp, "/tmp", "none", MS_BIND, NULL); + if (ret) { + to_log(LOG_ERR, "failed to bind mount temp dir for user %s\n", pw->pw_name); + return PAM_SESSION_ERR; + } return PAM_SUCCESS; }