diff options
Diffstat (limited to 'modules/pam_mkhomedir/mkhomedir_helper.c')
-rw-r--r-- | modules/pam_mkhomedir/mkhomedir_helper.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/modules/pam_mkhomedir/mkhomedir_helper.c b/modules/pam_mkhomedir/mkhomedir_helper.c index 8969da52..643d5d01 100644 --- a/modules/pam_mkhomedir/mkhomedir_helper.c +++ b/modules/pam_mkhomedir/mkhomedir_helper.c @@ -27,6 +27,7 @@ #include <security/pam_modutil.h> static unsigned long u_mask = 0022; +static unsigned long home_mode = 0; static char skeldir[BUFSIZ] = "/etc/skel"; /* Do the actual work of creating a home dir */ @@ -38,6 +39,7 @@ create_homedir(const struct passwd *pwd, DIR *d; struct dirent *dent; int retval = PAM_SESSION_ERR; + struct stat stat_buf; /* Create the new directory */ if (mkdir(dest, 0700) && errno != EEXIST) @@ -53,6 +55,12 @@ create_homedir(const struct passwd *pwd, goto go_out; } + /* Various things such as an autofs mount with browsing disabled + * can cause the directory to appear only on stat. The intent is + * to minimize network traversal when a file explorer tries to + * traverse large chunks of a directory tree. So stat first.*/ + stat(source, &stat_buf); + /* Scan the directory */ d = opendir(source); if (d == NULL) @@ -183,8 +191,7 @@ create_homedir(const struct passwd *pwd, else pointed[pointedlen] = 0; #else - char pointed[PATH_MAX]; - memset(pointed, 0, sizeof(pointed)); + char pointed[PATH_MAX] = {}; pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1); #endif @@ -232,6 +239,8 @@ create_homedir(const struct passwd *pwd, { pam_syslog(NULL, LOG_DEBUG, "unable to open or stat src file %s: %m", newsource); + if (srcfd >= 0) + close(srcfd); closedir(d); #ifndef PATH_MAX @@ -258,7 +267,7 @@ create_homedir(const struct passwd *pwd, } /* Set the proper ownership and permissions for the module. We make - the file a+w and then mask it with the set mask. This preseves + the file a+w and then mask it with the set mask. This preserves execute bits */ if (fchmod(destfd, (st.st_mode | 0222) & (~u_mask)) != 0 || fchown(destfd, pwd->pw_uid, pwd->pw_gid) != 0) @@ -332,6 +341,24 @@ create_homedir(const struct passwd *pwd, } static int +create_homedir_helper(const struct passwd *_pwd, + const char *_skeldir, const char *_homedir) +{ + int retval = PAM_SESSION_ERR; + + retval = create_homedir(_pwd, _skeldir, _homedir); + + if (chmod(_homedir, home_mode) != 0) + { + pam_syslog(NULL, LOG_DEBUG, + "unable to change perms on home directory %s: %m", _homedir); + return PAM_PERM_DENIED; + } + + return retval; +} + +static int make_parent_dirs(char *dir, int make) { int rc = PAM_SUCCESS; @@ -364,9 +391,10 @@ main(int argc, char *argv[]) { struct passwd *pwd; struct stat st; + char *eptr; if (argc < 2) { - fprintf(stderr, "Usage: %s <username> [<umask> [<skeldir>]]\n", argv[0]); + fprintf(stderr, "Usage: %s <username> [<umask> [<skeldir> [<home_mode>]]]\n", argv[0]); return PAM_SESSION_ERR; } @@ -377,7 +405,6 @@ main(int argc, char *argv[]) } if (argc >= 3) { - char *eptr; errno = 0; u_mask = strtoul(argv[2], &eptr, 0); if (errno != 0 || *eptr != '\0') { @@ -394,6 +421,18 @@ main(int argc, char *argv[]) strcpy(skeldir, argv[3]); } + if (argc >= 5) { + errno = 0; + home_mode = strtoul(argv[4], &eptr, 0); + if (errno != 0 || *eptr != '\0') { + pam_syslog(NULL, LOG_ERR, "Bogus home_mode value %s", argv[4]); + return PAM_SESSION_ERR; + } + } + + if (home_mode == 0) + home_mode = 0777 & ~u_mask; + /* Stat the home directory, if something exists then we assume it is correct and return a success */ if (stat(pwd->pw_dir, &st) == 0) @@ -402,5 +441,5 @@ main(int argc, char *argv[]) if (make_parent_dirs(pwd->pw_dir, 0) != PAM_SUCCESS) return PAM_PERM_DENIED; - return create_homedir(pwd, skeldir, pwd->pw_dir); + return create_homedir_helper(pwd, skeldir, pwd->pw_dir); } |