]>
Commit | Line | Data |
---|---|---|
5b8f84e4 JR |
1 | diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/Makefile.am Linux-PAM-0.99.7.1/modules/pam_mkhomedir/Makefile.am |
2 | --- Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/Makefile.am 2006-06-01 20:53:15.000000000 +0200 | |
3 | +++ Linux-PAM-0.99.7.1/modules/pam_mkhomedir/Makefile.am 2007-02-03 22:09:37.950620500 +0100 | |
4 | @@ -25,6 +25,10 @@ | |
5 | securelib_LTLIBRARIES = pam_mkhomedir.la | |
6 | pam_mkhomedir_la_SOURCES = pam_mkhomedir.c | |
7 | ||
8 | +install-exec-local: | |
9 | + $(LN_S) pam_mkhomedir.so $(DESTDIR)$(SECUREDIR)/pam_homedir.so | |
10 | + echo ".so pam_mkhomedir.8" > $(DESTDIR)$(man8dir)/pam_homedir.8 | |
11 | + | |
12 | if ENABLE_REGENERATE_MAN | |
13 | noinst_DATA = README | |
14 | README: pam_mkhomedir.8.xml | |
15 | diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8 Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.8 | |
16 | --- Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8 2006-06-02 17:37:39.000000000 +0200 | |
17 | +++ Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.8 2007-02-03 22:09:37.958621000 +0100 | |
18 | @@ -14,7 +14,7 @@ | |
19 | pam_mkhomedir \- PAM module to create users home directory | |
20 | .SH "SYNOPSIS" | |
21 | .HP 17 | |
22 | -\fBpam_mkhomedir.so\fR [silent] [umask=\fImode\fR] [skel=\fIskeldir\fR] | |
23 | +\fBpam_mkhomedir.so\fR [silent] [umask=\fImode\fR] [defmode=\fImode\fR] [minmode=\fImode\fR] [chmod] [notfound=[\fIcreate\fR|\fIdeny\fR|\fIignore\fR]] [skel=\fIskeldir\fR] | |
24 | .SH "DESCRIPTION" | |
25 | .PP | |
26 | The pam_mkhomedir PAM module will create a users home directory if it does not exist when the session begins. This allows users to be present in central database (such as NIS, kerberos or LDAP) without using a distributed file system or pre\-creating a large number of directories. The skeleton directory (usually | |
27 | @@ -22,6 +22,28 @@ | |
28 | The user file\-creation mask is set to | |
29 | \fImask\fR. The default value of mask is 0022. | |
30 | .TP 3n | |
31 | +\fBdefmode=\fR\fB\fImode\fR\fR | |
32 | +Default permissions for the home directory. The default value of | |
33 | +\fImode\fR | |
34 | +is 0755. | |
35 | +.TP 3n | |
36 | +\fBminmode=\fR\fB\fImode\fR\fR | |
37 | +Minimal permissions for the home directory. The default value of | |
38 | +\fImode\fR | |
39 | +is 0755. | |
40 | +.TP 3n | |
41 | +\fBchmod\fR | |
42 | +If this option is specified and home directory access permissions has more bits set than in minmode then do `chmod defmode $HOME`. | |
43 | +.TP 3n | |
44 | +\fBnotfound=[\fR\fB\fIcreate\fR\fR\fB|\fR\fB\fIdeny\fR\fR\fB|\fR\fB\fIignore\fR\fR\fB]\fR | |
45 | +What to do if home directory is not found or it is not a directory. | |
46 | +\fIcreate\fR | |
47 | +\- default, make home directory; | |
48 | +\fIdeny\fR | |
49 | +\- deny access; | |
50 | +\fIignore\fR | |
51 | +\- do nothing | |
52 | +.TP 3n | |
53 | \fBskel=\fR\fB\fI/path/to/skel/directory\fR\fR | |
54 | Indicate an alternative | |
55 | \fIskel\fR | |
56 | 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 | |
57 | --- Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml 2006-05-30 15:03:09.000000000 +0200 | |
58 | +++ Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.8.xml 2007-02-03 22:09:37.942620000 +0100 | |
59 | @@ -29,6 +29,18 @@ | |
60 | umask=<replaceable>mode</replaceable> | |
61 | </arg> | |
62 | <arg choice="opt"> | |
63 | + defmode=<replaceable>mode</replaceable> | |
64 | + </arg> | |
65 | + <arg choice="opt"> | |
66 | + minmode=<replaceable>mode</replaceable> | |
67 | + </arg> | |
68 | + <arg choice="opt"> | |
69 | + chmod | |
70 | + </arg> | |
71 | + <arg choice="opt"> | |
72 | + notfound=[<replaceable>create</replaceable>|<replaceable>deny</replaceable>|<replaceable>ignore</replaceable>] | |
73 | + </arg> | |
74 | + <arg choice="opt"> | |
75 | skel=<replaceable>skeldir</replaceable> | |
76 | </arg> | |
77 | </cmdsynopsis> | |
78 | @@ -82,6 +94,59 @@ | |
79 | ||
80 | <varlistentry> | |
81 | <term> | |
82 | + <option>defmode=<replaceable>mode</replaceable></option> | |
83 | + </term> | |
84 | + <listitem> | |
85 | + <para> | |
86 | + Default permissions for the home directory. | |
87 | + The default value of <replaceable>mode</replaceable> is | |
88 | + 0755. | |
89 | + </para> | |
90 | + </listitem> | |
91 | + </varlistentry> | |
92 | + | |
93 | + <varlistentry> | |
94 | + <term> | |
95 | + <option>minmode=<replaceable>mode</replaceable></option> | |
96 | + </term> | |
97 | + <listitem> | |
98 | + <para> | |
99 | + Minimal permissions for the home directory. | |
100 | + The default value of <replaceable>mode</replaceable> is | |
101 | + 0755. | |
102 | + </para> | |
103 | + </listitem> | |
104 | + </varlistentry> | |
105 | + | |
106 | + <varlistentry> | |
107 | + <term> | |
108 | + <option>chmod</option> | |
109 | + </term> | |
110 | + <listitem> | |
111 | + <para> | |
112 | + If this option is specified and home directory access | |
113 | + permissions has more bits set than in minmode then | |
114 | + do `chmod defmode $HOME`. | |
115 | + </para> | |
116 | + </listitem> | |
117 | + </varlistentry> | |
118 | + | |
119 | + <varlistentry> | |
120 | + <term> | |
121 | + <option>notfound=[<replaceable>create</replaceable>|<replaceable>deny</replaceable>|<replaceable>ignore</replaceable>]</option> | |
122 | + </term> | |
123 | + <listitem> | |
124 | + <para> | |
125 | + What to do if home directory is not found or it is not a directory. | |
126 | + <replaceable>create</replaceable> - default, make home directory; | |
127 | + <replaceable>deny</replaceable> - deny access; | |
128 | + <replaceable>ignore</replaceable> - do nothing | |
129 | + </para> | |
130 | + </listitem> | |
131 | + </varlistentry> | |
132 | + | |
133 | + <varlistentry> | |
134 | + <term> | |
135 | <option>skel=<replaceable>/path/to/skel/directory</replaceable></option> | |
136 | </term> | |
137 | <listitem> | |
138 | 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 | |
139 | --- Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.c 2006-12-07 13:34:26.000000000 +0100 | |
140 | +++ Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.c 2007-02-03 22:09:37.890616750 +0100 | |
141 | @@ -58,17 +58,43 @@ | |
142 | ||
143 | ||
144 | /* argument parsing */ | |
ab9532e0 | 145 | -#define MKHOMEDIR_DEBUG 020 /* be verbose about things */ |
5b8f84e4 JR |
146 | -#define MKHOMEDIR_QUIET 040 /* keep quiet about things */ |
147 | - | |
148 | -static unsigned int UMask = 0022; | |
149 | -static char SkelDir[BUFSIZ] = "/etc/skel"; /* THIS MODULE IS NOT THREAD SAFE */ | |
150 | +#define MKHOMEDIR_DEBUG 0x10 /* keep quiet about things */ | |
151 | +#define MKHOMEDIR_QUIET 0x20 /* keep quiet about things */ | |
152 | +/* what to do, if home directory does not exist? */ | |
153 | +#define HOMEDIR_CREATE 0x40 /* create it */ | |
154 | +#define HOMEDIR_BARF 0x80 /* deny access */ | |
155 | + | |
156 | +struct homedir_options { | |
157 | + unsigned int home_access; /* create ~/ by default */ | |
158 | + unsigned int default_mode; /* 0755 access rights for home dir */ | |
159 | + unsigned int minimal_mode; /* 0755 but this is enough... */ | |
160 | + unsigned int umask; /* 0022 umask for ~/ files */ | |
161 | + unsigned int do_chmod; /* chmod user ~ if it has insecure permissions */ | |
162 | +#ifdef PATH_MAX | |
163 | + char skel_dir[PATH_MAX]; | |
164 | +#else | |
165 | + char skel_dir[BUFSIZ]; | |
166 | +#endif | |
167 | +}; | |
168 | ||
169 | static int | |
170 | -_pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv) | |
171 | +_pam_parse (const pam_handle_t *pamh, struct homedir_options *opt, | |
172 | + int flags, int argc, const char **argv) | |
173 | { | |
174 | int ctrl = 0; | |
175 | ||
176 | + opt->home_access = HOMEDIR_CREATE; | |
177 | + opt->default_mode = 0755; | |
178 | + opt->minimal_mode = 0755; | |
179 | + opt->do_chmod = 0; | |
180 | +#ifdef PATH_MAX | |
181 | + strncpy(opt->skel_dir, "/etc/skel", PATH_MAX-1); | |
182 | + opt->skel_dir[PATH_MAX-1] = '\0'; | |
183 | +#else | |
184 | + strncpy(opt->skel_dir, "/etc/skel", BUFSIZ-1); | |
185 | + opt->skel_dir[BUFSIZ-1] = '\0'; | |
186 | +#endif | |
187 | + | |
188 | /* does the appliction require quiet? */ | |
189 | if ((flags & PAM_SILENT) == PAM_SILENT) | |
190 | ctrl |= MKHOMEDIR_QUIET; | |
191 | @@ -79,10 +105,35 @@ | |
192 | if (!strcmp(*argv, "silent")) { | |
193 | ctrl |= MKHOMEDIR_QUIET; | |
194 | } else if (!strncmp(*argv,"umask=",6)) { | |
195 | - UMask = strtol(*argv+6,0,0); | |
196 | + opt->umask = strtol(*argv+6,0,0); | |
197 | + opt->default_mode = opt->minimal_mode = 0777 & ~(opt->umask); | |
198 | + } else if (!strncmp(*argv,"defmode=",8)) | |
199 | + opt->default_mode = strtol(*argv+8,0,0); | |
200 | + else if (!strncmp(*argv,"minmode=",8)) | |
201 | + opt->minimal_mode = strtol(*argv+8,0,0); | |
202 | + else if (!strncmp(*argv,"chmod",5)) | |
203 | + opt->do_chmod = 1; | |
204 | + else if (!strncmp(*argv,"notfound=",9)) | |
205 | + { | |
206 | + if (!strcmp(*argv + 9, "create")) | |
207 | + opt->home_access = HOMEDIR_CREATE; | |
208 | + else if (!strcmp(*argv + 9, "deny")) | |
209 | + opt->home_access = HOMEDIR_BARF; | |
210 | + else if (!strcmp(*argv + 9, "ignore")) | |
211 | + opt->home_access &= ~(HOMEDIR_CREATE | HOMEDIR_BARF); | |
212 | + else | |
213 | + { | |
214 | + pam_syslog(pamh, LOG_ERR, "unknown parameter for \"create\" option: %s", *argv + 9); | |
215 | + opt->home_access = HOMEDIR_CREATE; | |
216 | + } | |
217 | } else if (!strncmp(*argv,"skel=",5)) { | |
218 | - strncpy(SkelDir,*argv+5,sizeof(SkelDir)); | |
219 | - SkelDir[sizeof(SkelDir)-1] = '\0'; | |
220 | +#ifdef PATH_MAX | |
221 | + strncpy(opt->skel_dir, *argv+5, PATH_MAX-1); | |
222 | + opt->skel_dir[PATH_MAX-1] = '\0'; | |
223 | +#else | |
224 | + strncpy(opt->skel_dir, *argv+5, BUFSIZ-1); | |
225 | + opt->skel_dir[BUFSIZ-1] = '\0'; | |
226 | +#endif | |
227 | } else { | |
228 | pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); | |
229 | } | |
230 | @@ -127,7 +178,7 @@ | |
231 | /* Do the actual work of creating a home dir */ | |
232 | static int | |
233 | create_homedir (pam_handle_t * pamh, int ctrl, | |
234 | - const struct passwd *pwd, | |
235 | + const struct passwd *pwd, struct homedir_options *opt, | |
236 | const char *source, const char *dest) | |
237 | { | |
238 | char remark[BUFSIZ]; | |
239 | @@ -292,7 +292,7 @@ | |
240 | /* If it's a directory, recurse. */ | |
241 | if (S_ISDIR(St.st_mode)) | |
242 | { | |
243 | - retval = create_homedir (pamh, ctrl, pwd, newsource, newdest); | |
244 | + retval = create_homedir (pamh, ctrl, pwd, opt, newsource, newdest); | |
245 | ||
246 | #ifndef PATH_MAX | |
247 | free(newsource); newsource = NULL; | |
248 | @@ -372,10 +423,10 @@ | |
249 | return PAM_PERM_DENIED; | |
250 | } | |
251 | ||
252 | - /* Set the proper ownership and permissions for the module. We make | |
253 | + /* Set the proper ownership and permissions for the file. We make | |
254 | the file a+w and then mask it with the set mask. This preseves | |
255 | execute bits */ | |
256 | - if (fchmod(DestFd,(St.st_mode | 0222) & (~UMask)) != 0 || | |
257 | + if (fchmod(DestFd,(St.st_mode | 0222) & (~opt->umask)) != 0 || | |
258 | fchown(DestFd,pwd->pw_uid,pwd->pw_gid) != 0) | |
259 | { | |
260 | pam_syslog(pamh, LOG_DEBUG, | |
261 | @@ -435,7 +486,7 @@ | |
262 | ||
263 | go_out: | |
264 | ||
265 | - if (chmod(dest,0777 & (~UMask)) != 0 || | |
266 | + if (chmod(dest, opt->default_mode) != 0 || | |
267 | chown(dest,pwd->pw_uid,pwd->pw_gid) != 0) | |
268 | { | |
269 | pam_syslog(pamh, LOG_DEBUG, | |
161071ac | 270 | @@ -446,6 +497,63 @@ |
5b8f84e4 JR |
271 | return retval; |
272 | } | |
273 | ||
274 | +/* Do the actual work of creating a home dir */ | |
275 | +static int check_homedir(pam_handle_t * pamh, int ctrl, | |
276 | + const struct passwd *pwd, | |
277 | + struct homedir_options *opt) | |
278 | +{ | |
5b8f84e4 JR |
279 | + struct stat stbuf; |
280 | + | |
281 | + /* Stat the home directory, if something exists then we assume it is | |
282 | + correct and return a success */ | |
283 | + if (stat(pwd->pw_dir, &stbuf) == 0) { | |
284 | + if (stbuf.st_mode & ~(opt->minimal_mode | S_IFDIR)) { | |
285 | + /* Aieee, user did something bad to his/hers home */ | |
286 | + if (!S_ISDIR(stbuf.st_mode)) { | |
287 | + /* This user home is really broken... */ | |
6d558595 | 288 | + pam_info(pamh, "Home directory '%s' is not a directory!", pwd->pw_dir); |
5b8f84e4 JR |
289 | + |
290 | + pam_syslog(pamh, LOG_DEBUG, "directory %s is not a directory (mode 0%o)", pwd->pw_dir, stbuf.st_mode); | |
291 | + if (opt->home_access == HOMEDIR_BARF) | |
292 | + return PAM_PERM_DENIED; | |
293 | + else if (opt->home_access == HOMEDIR_CREATE) { | |
294 | + pam_syslog(pamh, LOG_DEBUG, "trying to unlink directory %s", pwd->pw_dir); | |
295 | + if (unlink(pwd->pw_dir) == -1) { | |
296 | + pam_syslog(pamh, LOG_DEBUG, "failed to unlink directory %s", pwd->pw_dir); | |
297 | + return PAM_PERM_DENIED; | |
298 | + } | |
299 | + } else | |
300 | + return PAM_SUCCESS; | |
301 | + } else { | |
6d558595 JR |
302 | + pam_info(pamh, "Home directory '%s' has insecure permissions 0%o.", |
303 | + pwd->pw_dir, stbuf.st_mode); | |
5b8f84e4 JR |
304 | + |
305 | + pam_syslog(pamh, LOG_DEBUG, "directory %s has insecure permissions 0%o", pwd->pw_dir, stbuf.st_mode); | |
306 | + | |
307 | + if (opt->do_chmod) | |
308 | + if (chmod(pwd->pw_dir, opt->default_mode) < 0) { | |
309 | + pam_syslog(pamh, LOG_DEBUG, "unable to chmod home directory %s", pwd->pw_dir); | |
310 | + return PAM_PERM_DENIED; | |
311 | + } | |
312 | + return PAM_SUCCESS; | |
313 | + } | |
314 | + } else | |
315 | + return PAM_SUCCESS; | |
316 | + } | |
317 | + | |
318 | + switch (opt->home_access) { | |
319 | + case HOMEDIR_CREATE: | |
320 | + return create_homedir(pamh, ctrl, pwd, opt, opt->skel_dir, pwd->pw_dir); | |
321 | + case HOMEDIR_BARF: | |
322 | + return PAM_PERM_DENIED; | |
323 | + default: | |
324 | + return PAM_SUCCESS; | |
325 | + } | |
326 | + | |
327 | + /* If we ever get here sue authors of the compiler */ | |
328 | + return PAM_SERVICE_ERR; | |
329 | +} | |
330 | + | |
331 | /* --- authentication management functions (only) --- */ | |
332 | ||
333 | PAM_EXTERN int | |
161071ac JR |
334 | @@ -456,10 +572,10 @@ |
335 | int retval, ctrl; | |
5b8f84e4 JR |
336 | const void *user; |
337 | const struct passwd *pwd; | |
161071ac | 338 | - struct stat St; |
5b8f84e4 JR |
339 | + struct homedir_options opt; |
340 | ||
341 | /* Parse the flag values */ | |
342 | - ctrl = _pam_parse(pamh, flags, argc, argv); | |
343 | + ctrl = _pam_parse(pamh, &opt, flags, argc, argv); | |
344 | ||
345 | /* Determine the user name so we can get the home directory */ | |
346 | retval = pam_get_item(pamh, PAM_USER, &user); | |
347 | @@ -476,12 +593,7 @@ | |
348 | return PAM_CRED_INSUFFICIENT; | |
349 | } | |
350 | ||
351 | - /* Stat the home directory, if something exists then we assume it is | |
352 | - correct and return a success*/ | |
353 | - if (stat(pwd->pw_dir,&St) == 0) | |
354 | - return PAM_SUCCESS; | |
355 | - | |
356 | - return create_homedir(pamh,ctrl,pwd,SkelDir,pwd->pw_dir); | |
357 | + return check_homedir(pamh, ctrl, pwd, &opt); | |
358 | } | |
359 | ||
360 | /* Ignore */ |