1 diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.8.xml
2 --- Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml 2006-05-30 15:03:09.000000000 +0200
3 +++ Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.8.xml 2007-02-03 22:09:37.942620000 +0100
5 umask=<replaceable>mode</replaceable>
8 + defmode=<replaceable>mode</replaceable>
11 + minmode=<replaceable>mode</replaceable>
17 + notfound=[<replaceable>create</replaceable>|<replaceable>deny</replaceable>|<replaceable>ignore</replaceable>]
20 skel=<replaceable>skeldir</replaceable>
27 + <option>defmode=<replaceable>mode</replaceable></option>
31 + Default permissions for the home directory.
32 + The default value of <replaceable>mode</replaceable> is
40 + <option>minmode=<replaceable>mode</replaceable></option>
44 + Minimal permissions for the home directory.
45 + The default value of <replaceable>mode</replaceable> is
53 + <option>chmod</option>
57 + If this option is specified and home directory access
58 + permissions has more bits set than in minmode then
59 + do `chmod defmode $HOME`.
66 + <option>notfound=[<replaceable>create</replaceable>|<replaceable>deny</replaceable>|<replaceable>ignore</replaceable>]</option>
70 + What to do if home directory is not found or it is not a directory.
71 + <replaceable>create</replaceable> - default, make home directory;
72 + <replaceable>deny</replaceable> - deny access;
73 + <replaceable>ignore</replaceable> - do nothing
80 <option>skel=<replaceable>/path/to/skel/directory</replaceable></option>
83 diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.c Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.c
84 --- Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.c 2006-12-07 13:34:26.000000000 +0100
85 +++ Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.c 2007-02-03 22:09:37.890616750 +0100
89 /* argument parsing */
90 -#define MKHOMEDIR_DEBUG 020 /* be verbose about things */
91 -#define MKHOMEDIR_QUIET 040 /* keep quiet about things */
93 -static unsigned int UMask = 0022;
94 -static char SkelDir[BUFSIZ] = "/etc/skel"; /* THIS MODULE IS NOT THREAD SAFE */
95 +#define MKHOMEDIR_DEBUG 0x10 /* keep quiet about things */
96 +#define MKHOMEDIR_QUIET 0x20 /* keep quiet about things */
97 +/* what to do, if home directory does not exist? */
98 +#define HOMEDIR_CREATE 0x40 /* create it */
99 +#define HOMEDIR_BARF 0x80 /* deny access */
101 +struct homedir_options {
102 + unsigned int home_access; /* create ~/ by default */
103 + unsigned int default_mode; /* 0755 access rights for home dir */
104 + unsigned int minimal_mode; /* 0755 but this is enough... */
105 + unsigned int umask; /* 0022 umask for ~/ files */
106 + unsigned int do_chmod; /* chmod user ~ if it has insecure permissions */
108 + char skel_dir[PATH_MAX];
110 + char skel_dir[BUFSIZ];
115 -_pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv)
116 +_pam_parse (const pam_handle_t *pamh, struct homedir_options *opt,
117 + int flags, int argc, const char **argv)
121 + opt->home_access = HOMEDIR_CREATE;
122 + opt->default_mode = 0755;
123 + opt->minimal_mode = 0755;
126 + strncpy(opt->skel_dir, "/etc/skel", PATH_MAX-1);
127 + opt->skel_dir[PATH_MAX-1] = '\0';
129 + strncpy(opt->skel_dir, "/etc/skel", BUFSIZ-1);
130 + opt->skel_dir[BUFSIZ-1] = '\0';
133 /* does the appliction require quiet? */
134 if ((flags & PAM_SILENT) == PAM_SILENT)
135 ctrl |= MKHOMEDIR_QUIET;
137 } else if (!strcmp(*argv, "debug")) {
138 ctrl |= MKHOMEDIR_DEBUG;
139 } else if (!strncmp(*argv,"umask=",6)) {
140 - UMask = strtol(*argv+6,0,0);
141 + opt->umask = strtol(*argv+6,0,0);
142 + opt->default_mode = opt->minimal_mode = 0777 & ~(opt->umask);
143 + } else if (!strncmp(*argv,"defmode=",8))
144 + opt->default_mode = strtol(*argv+8,0,0);
145 + else if (!strncmp(*argv,"minmode=",8))
146 + opt->minimal_mode = strtol(*argv+8,0,0);
147 + else if (!strncmp(*argv,"chmod",5))
149 + else if (!strncmp(*argv,"notfound=",9))
151 + if (!strcmp(*argv + 9, "create"))
152 + opt->home_access = HOMEDIR_CREATE;
153 + else if (!strcmp(*argv + 9, "deny"))
154 + opt->home_access = HOMEDIR_BARF;
155 + else if (!strcmp(*argv + 9, "ignore"))
156 + opt->home_access &= ~(HOMEDIR_CREATE | HOMEDIR_BARF);
159 + pam_syslog(pamh, LOG_ERR, "unknown parameter for \"create\" option: %s", *argv + 9);
160 + opt->home_access = HOMEDIR_CREATE;
162 } else if (!strncmp(*argv,"skel=",5)) {
163 - strncpy(SkelDir,*argv+5,sizeof(SkelDir));
164 - SkelDir[sizeof(SkelDir)-1] = '\0';
166 + strncpy(opt->skel_dir, *argv+5, PATH_MAX-1);
167 + opt->skel_dir[PATH_MAX-1] = '\0';
169 + strncpy(opt->skel_dir, *argv+5, BUFSIZ-1);
170 + opt->skel_dir[BUFSIZ-1] = '\0';
173 pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
176 /* Do the actual work of creating a home dir */
178 create_homedir (pam_handle_t * pamh, int ctrl,
179 - const struct passwd *pwd,
180 + const struct passwd *pwd, struct homedir_options *opt,
181 const char *source, const char *dest)
185 /* If it's a directory, recurse. */
186 if (S_ISDIR(St.st_mode))
188 - retval = create_homedir (pamh, ctrl, pwd, newsource, newdest);
189 + retval = create_homedir (pamh, ctrl, pwd, opt, newsource, newdest);
192 free(newsource); newsource = NULL;
193 @@ -372,10 +423,10 @@
194 return PAM_PERM_DENIED;
197 - /* Set the proper ownership and permissions for the module. We make
198 + /* Set the proper ownership and permissions for the file. We make
199 the file a+w and then mask it with the set mask. This preseves
201 - if (fchmod(DestFd,(St.st_mode | 0222) & (~UMask)) != 0 ||
202 + if (fchmod(DestFd,(St.st_mode | 0222) & (~opt->umask)) != 0 ||
203 fchown(DestFd,pwd->pw_uid,pwd->pw_gid) != 0)
205 pam_syslog(pamh, LOG_DEBUG,
210 - if (chmod(dest,0777 & (~UMask)) != 0 ||
211 + if (chmod(dest, opt->default_mode) != 0 ||
212 chown(dest,pwd->pw_uid,pwd->pw_gid) != 0)
214 pam_syslog(pamh, LOG_DEBUG,
219 +/* Do the actual work of creating a home dir */
220 +static int check_homedir(pam_handle_t * pamh, int ctrl,
221 + const struct passwd *pwd,
222 + struct homedir_options *opt)
226 + /* Stat the home directory, if something exists then we assume it is
227 + correct and return a success */
228 + if (stat(pwd->pw_dir, &stbuf) == 0) {
229 + if (stbuf.st_mode & ~(opt->minimal_mode | S_IFDIR)) {
230 + /* Aieee, user did something bad to his/hers home */
231 + if (!S_ISDIR(stbuf.st_mode)) {
232 + /* This user home is really broken... */
233 + pam_info(pamh, "Home directory '%s' is not a directory!", pwd->pw_dir);
235 + pam_syslog(pamh, LOG_DEBUG, "directory %s is not a directory (mode 0%o)", pwd->pw_dir, stbuf.st_mode);
236 + if (opt->home_access == HOMEDIR_BARF)
237 + return PAM_PERM_DENIED;
238 + else if (opt->home_access == HOMEDIR_CREATE) {
239 + pam_syslog(pamh, LOG_DEBUG, "trying to unlink directory %s", pwd->pw_dir);
240 + if (unlink(pwd->pw_dir) == -1) {
241 + pam_syslog(pamh, LOG_DEBUG, "failed to unlink directory %s", pwd->pw_dir);
242 + return PAM_PERM_DENIED;
245 + return PAM_SUCCESS;
247 + pam_info(pamh, "Home directory '%s' has insecure permissions 0%o.",
248 + pwd->pw_dir, stbuf.st_mode);
250 + pam_syslog(pamh, LOG_DEBUG, "directory %s has insecure permissions 0%o", pwd->pw_dir, stbuf.st_mode);
253 + if (chmod(pwd->pw_dir, opt->default_mode) < 0) {
254 + pam_syslog(pamh, LOG_DEBUG, "unable to chmod home directory %s", pwd->pw_dir);
255 + return PAM_PERM_DENIED;
257 + return PAM_SUCCESS;
260 + return PAM_SUCCESS;
263 + switch (opt->home_access) {
264 + case HOMEDIR_CREATE:
265 + return create_homedir(pamh, ctrl, pwd, opt, opt->skel_dir, pwd->pw_dir);
267 + return PAM_PERM_DENIED;
269 + return PAM_SUCCESS;
272 + /* If we ever get here sue authors of the compiler */
273 + return PAM_SERVICE_ERR;
276 /* --- authentication management functions (only) --- */
279 @@ -456,10 +572,10 @@
282 const struct passwd *pwd;
284 + struct homedir_options opt;
286 /* Parse the flag values */
287 - ctrl = _pam_parse(pamh, flags, argc, argv);
288 + ctrl = _pam_parse(pamh, &opt, flags, argc, argv);
290 /* Determine the user name so we can get the home directory */
291 retval = pam_get_item(pamh, PAM_USER, &user);
293 return PAM_CRED_INSUFFICIENT;
296 - /* Stat the home directory, if something exists then we assume it is
297 - correct and return a success*/
298 - if (stat(pwd->pw_dir,&St) == 0)
299 - return PAM_SUCCESS;
301 - return create_homedir(pamh,ctrl,pwd,SkelDir,pwd->pw_dir);
302 + return check_homedir(pamh, ctrl, pwd, &opt);