diff options
author | dshein-alt <76520100+dshein-alt@users.noreply.github.com> | 2021-03-05 17:09:02 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-05 15:09:02 +0100 |
commit | 75818d51e631e325987ffe024905480827997b7d (patch) | |
tree | 9a15e6863efc4d8af693fbe940f099e537bd82db | |
parent | 70b34aa509095407fa37b72dc7c69f546713126e (diff) | |
download | pam-75818d51e631e325987ffe024905480827997b7d.tar.gz pam-75818d51e631e325987ffe024905480827997b7d.tar.bz2 pam-75818d51e631e325987ffe024905480827997b7d.zip |
pam_mkhomedir: use HOME_MODE or UMASK from /etc/login.defs
Follow the example of useradd(8) and set the user home directory mode
to the value of HOME_MODE or UMASK configuration item from
/etc/login.defs when umask option is not specified.
-rw-r--r-- | modules/pam_mkhomedir/mkhomedir_helper.8.xml | 7 | ||||
-rw-r--r-- | modules/pam_mkhomedir/mkhomedir_helper.c | 37 | ||||
-rw-r--r-- | modules/pam_mkhomedir/pam_mkhomedir.8.xml | 11 | ||||
-rw-r--r-- | modules/pam_mkhomedir/pam_mkhomedir.c | 41 |
4 files changed, 87 insertions, 9 deletions
diff --git a/modules/pam_mkhomedir/mkhomedir_helper.8.xml b/modules/pam_mkhomedir/mkhomedir_helper.8.xml index c834eddd..8a76f2d6 100644 --- a/modules/pam_mkhomedir/mkhomedir_helper.8.xml +++ b/modules/pam_mkhomedir/mkhomedir_helper.8.xml @@ -25,6 +25,9 @@ <replaceable>umask</replaceable> <arg choice="opt"> <replaceable>path-to-skel</replaceable> + <arg choice="opt"> + <replaceable>home_mode</replaceable> + </arg> </arg> </arg> </cmdsynopsis> @@ -43,7 +46,9 @@ <para> The default value of <replaceable>umask</replaceable> is 0022 and the default value of <replaceable>path-to-skel</replaceable> is - <emphasis>/etc/skel</emphasis>. + <emphasis>/etc/skel</emphasis>. The default value of + <replaceable>home_mode</replaceable> is computed from the value of + <replaceable>umask</replaceable>. </para> <para> diff --git a/modules/pam_mkhomedir/mkhomedir_helper.c b/modules/pam_mkhomedir/mkhomedir_helper.c index 2278ff64..582fecce 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 */ @@ -334,6 +335,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; @@ -366,9 +385,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; } @@ -379,7 +399,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') { @@ -396,6 +415,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) @@ -404,5 +435,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); } diff --git a/modules/pam_mkhomedir/pam_mkhomedir.8.xml b/modules/pam_mkhomedir/pam_mkhomedir.8.xml index 9b8ef14b..10109067 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.8.xml +++ b/modules/pam_mkhomedir/pam_mkhomedir.8.xml @@ -91,8 +91,15 @@ <listitem> <para> The file mode creation mask is set to - <replaceable>mask</replaceable>. The default value of mask is - 0022. + <replaceable>mask</replaceable>. The default value of mask + is 0022. If this option is not specified, then the permissions + of created user home directory is set to the value of + <option>HOME_MODE</option> configuration item from + <filename>/etc/login.defs</filename>. If there is no such + configuration item then the value is computed from the + value of <option>UMASK</option> in the same file. If + there is no such configuration option either the default + value of 0755 is used for the mode. </para> </listitem> </varlistentry> diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index cb773e8f..48e578fa 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -56,6 +56,9 @@ #define MKHOMEDIR_DEBUG 020 /* be verbose about things */ #define MKHOMEDIR_QUIET 040 /* keep quiet about things */ +#define LOGIN_DEFS "/etc/login.defs" +#define UMASK_DEFAULT "0022" + struct options_t { int ctrl; const char *umask; @@ -68,7 +71,7 @@ _pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv, options_t *opt) { opt->ctrl = 0; - opt->umask = "0022"; + opt->umask = NULL; opt->skeldir = "/etc/skel"; /* does the application require quiet? */ @@ -94,6 +97,17 @@ _pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv, } } +static char* +_pam_conv_str_umask_to_homemode(const char *umask) +{ + unsigned int m = 0; + char tmp[5]; + + m = 0777 & ~strtoul(umask, NULL, 8); + (void) snprintf(tmp, sizeof(tmp), "0%o", m); + return strdup(tmp); +} + /* Do the actual work of creating a home dir */ static int create_homedir (pam_handle_t *pamh, options_t *opt, @@ -101,6 +115,8 @@ create_homedir (pam_handle_t *pamh, options_t *opt, { int retval, child; struct sigaction newsa, oldsa; + char *login_umask = NULL; + char *login_homemode = NULL; /* Mention what is happening, if the notification fails that is OK */ if (!(opt->ctrl & MKHOMEDIR_QUIET)) @@ -122,11 +138,26 @@ create_homedir (pam_handle_t *pamh, options_t *opt, pam_syslog(pamh, LOG_DEBUG, "Executing mkhomedir_helper."); } + /* fetch UMASK from /etc/login.defs if not in argv */ + if (opt->umask == NULL) { + login_umask = pam_modutil_search_key(pamh, LOGIN_DEFS, "UMASK"); + login_homemode = pam_modutil_search_key(pamh, LOGIN_DEFS, "HOME_MODE"); + if (login_homemode == NULL) { + if (login_umask != NULL) { + login_homemode = _pam_conv_str_umask_to_homemode(login_umask); + } else { + login_homemode = _pam_conv_str_umask_to_homemode(UMASK_DEFAULT); + } + } + } else { + login_homemode = _pam_conv_str_umask_to_homemode(opt->umask); + } + /* fork */ child = fork(); if (child == 0) { static char *envp[] = { NULL }; - const char *args[] = { NULL, NULL, NULL, NULL, NULL }; + const char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL }; if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_PIPE_FD, PAM_MODUTIL_PIPE_FD, @@ -136,8 +167,9 @@ create_homedir (pam_handle_t *pamh, options_t *opt, /* exec the mkhomedir helper */ args[0] = MKHOMEDIR_HELPER; args[1] = user; - args[2] = opt->umask; + args[2] = opt->umask ? opt->umask : UMASK_DEFAULT; args[3] = opt->skeldir; + args[4] = login_homemode; DIAG_PUSH_IGNORE_CAST_QUAL; execve(MKHOMEDIR_HELPER, (char **)args, envp); @@ -175,6 +207,9 @@ create_homedir (pam_handle_t *pamh, options_t *opt, dir); } + free(login_umask); + free(login_homemode); + D(("returning %d", retval)); return retval; } |