]> git.pld-linux.org Git - packages/pam.git/blame - pam-namespace-temp-logon.patch
- rel 3
[packages/pam.git] / pam-namespace-temp-logon.patch
CommitLineData
bd9a1e0d
JR
1 support for temporary logons
2
3diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml
4--- Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml.temp-logon 2007-06-18 12:46:47.000000000 +0200
5+++ Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml 2007-08-06 13:16:56.000000000 +0200
6@@ -72,10 +72,13 @@
7
8 <para>
9 The third field, <replaceable>method</replaceable>, is the method
10- used for polyinstantiation. It can take 3 different values; "user"
11+ used for polyinstantiation. It can take these values; "user"
12 for polyinstantiation based on user name, "level" for
13- polyinstantiation based on process MLS level and user name, and "context" for
14- polyinstantiation based on process security context and user name
15+ polyinstantiation based on process MLS level and user name, "context" for
16+ polyinstantiation based on process security context and user name,
17+ "tmpfs" for mounting tmpfs filesystem as an instance dir, and
18+ "tmpdir" for creating temporary directory as an instance dir which is
19+ removed when the user's session is closed.
20 Methods "context" and "level" are only available with SELinux. This
21 field cannot be blank.
22 </para>
23@@ -84,7 +87,8 @@
24 The fourth field, <replaceable>list_of_uids</replaceable>, is
25 a comma separated list of user names for whom the polyinstantiation
26 is not performed. If left blank, polyinstantiation will be performed
27- for all users.
28+ for all users. If the list is preceded with a single "~" character,
29+ polyinstantiation is performed only for users in the list.
30 </para>
31
32 <para>
33diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h
34--- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h.temp-logon 2007-06-18 12:46:47.000000000 +0200
35+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h 2007-08-06 11:41:46.000000000 +0200
36@@ -90,6 +90,7 @@
37 #define PAMNS_NO_UNMOUNT_ON_CLOSE 0x00010000 /* no unmount at session close */
38
39 #define NAMESPACE_MAX_DIR_LEN 80
40+#define NAMESPACE_POLYDIR_DATA "pam_namespace:polydir_data"
41
42 /*
43 * Polyinstantiation method options, based on user, security context
44@@ -100,6 +101,8 @@ enum polymethod {
45 USER,
46 CONTEXT,
47 LEVEL,
48+ TMPDIR,
49+ TMPFS
50 };
51
52 /*
53@@ -128,6 +131,7 @@ struct polydir_s {
54 enum polymethod method; /* method used to polyinstantiate */
55 unsigned int num_uids; /* number of override uids */
56 uid_t *uid; /* list of override uids */
57+ int exclusive; /* polyinstatiate exclusively for override uids */
58 struct polydir_s *next; /* pointer to the next polydir entry */
59 };
60
61diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c
62--- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.temp-logon 2007-06-18 12:46:47.000000000 +0200
63+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c 2007-08-06 11:41:46.000000000 +0200
64@@ -43,6 +43,7 @@ static int copy_ent(const struct polydir
65 strcpy(pent->instance_prefix, ent->instance_prefix);
66 pent->method = ent->method;
67 pent->num_uids = ent->num_uids;
68+ pent->exclusive = ent->exclusive;
69 if (ent->num_uids) {
70 uid_t *pptr, *eptr;
71
72@@ -120,6 +121,10 @@ static void del_polydir_list(struct poly
73 }
74 }
75
76+static void cleanup_data(pam_handle_t *pamh, void *data, int err)
77+{
78+ del_polydir_list(data);
79+}
80
81 /*
82 * Called from parse_config_file, this function processes a single line
83@@ -140,6 +145,7 @@ static int process_line(char *line, cons
84
85 poly.uid = NULL;
86 poly.num_uids = 0;
87+ poly.exclusive = 0;
88
89 /*
90 * skip the leading white space
91@@ -223,24 +229,13 @@ static int process_line(char *line, cons
92 }
93
94 /*
95- * Ensure that all pathnames are absolute path names.
96- */
97- if ((dir[0] != '/') || (instance_prefix[0] != '/')) {
98- pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must start with '/'");
99- goto skipping;
100- }
101- if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
102- pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must not contain '..'");
103- goto skipping;
104- }
105-
106- /*
107 * Populate polyinstantiated directory structure with appropriate
108 * pathnames and the method with which to polyinstantiate.
109 */
110 if (strlen(dir) >= sizeof(poly.dir)
111 || strlen(instance_prefix) >= sizeof(poly.instance_prefix)) {
112 pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
113+ goto skipping;
114 }
115 strcpy(poly.dir, dir);
116 strcpy(poly.instance_prefix, instance_prefix);
117@@ -248,6 +243,18 @@ static int process_line(char *line, cons
118 poly.method = NONE;
119 if (strcmp(method, "user") == 0)
120 poly.method = USER;
121+
122+ if (strcmp(method, "tmpdir") == 0) {
123+ poly.method = TMPDIR;
124+ if (sizeof(poly.instance_prefix) - strlen(poly.instance_prefix) < 7) {
125+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
126+ goto skipping;
127+ }
128+ strcat(poly.instance_prefix, "XXXXXX");
129+ }
130+
131+ if (strcmp(method, "tmpfs") == 0)
132+ poly.method = TMPFS;
133
134 #ifdef WITH_SELINUX
135 if (strcmp(method, "level") == 0) {
136@@ -266,12 +273,24 @@ static int process_line(char *line, cons
137
138 #endif
139
140- if ( poly.method == NONE) {
141+ if (poly.method == NONE) {
142 pam_syslog(idata->pamh, LOG_NOTICE, "Illegal method");
143 goto skipping;
144 }
145
146 /*
147+ * Ensure that all pathnames are absolute path names.
148+ */
149+ if ((dir[0] != '/') || (poly.method != TMPFS && instance_prefix[0] != '/')) {
150+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must start with '/'");
151+ goto skipping;
152+ }
153+ if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
154+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must not contain '..'");
155+ goto skipping;
156+ }
157+
158+ /*
159 * If the line in namespace.conf for a directory to polyinstantiate
160 * contains a list of override users (users for whom polyinstantiation
161 * is not performed), read the user ids, convert names into uids, and
162@@ -281,7 +300,11 @@ static int process_line(char *line, cons
163 uid_t *uidptr;
164 const char *ustr, *sstr;
165 int count, i;
166-
167+
168+ if (*uids == '~') {
169+ poly.exclusive = 1;
170+ uids++;
171+ }
172 for (count = 0, ustr = sstr = uids; sstr; ustr = sstr + 1, count++)
173 sstr = strchr(ustr, ',');
174
175@@ -419,6 +442,7 @@ static int parse_config_file(struct inst
176 * directory's list of override uids. If the uid is one of the override
177 * uids for the polyinstantiated directory, polyinstantiation is not
178 * performed for that user for that directory.
179+ * If exclusive is set the returned values are opposite.
180 */
181 static int ns_override(struct polydir_s *polyptr, struct instance_data *idata,
182 uid_t uid)
183@@ -432,11 +456,11 @@ static int ns_override(struct polydir_s
184
185 for (i = 0; i < polyptr->num_uids; i++) {
186 if (uid == polyptr->uid[i]) {
187- return 1;
188+ return !polyptr->exclusive;
189 }
190 }
191
192- return 0;
193+ return polyptr->exclusive;
194 }
195
196 /*
197@@ -622,6 +646,12 @@ static int poly_name(const struct polydi
198
199 #endif /* WITH_SELINUX */
200
201+ case TMPDIR:
202+ case TMPFS:
203+ if ((*i_name=strdup("")) == NULL)
204+ goto fail;
205+ return PAM_SUCCESS;
206+
207 default:
208 if (idata->flags & PAMNS_DEBUG)
209 pam_syslog(idata->pamh, LOG_ERR, "Unknown method");
210@@ -725,7 +755,7 @@ static int check_inst_parent(char *ipath
211 * execute it and pass directory to polyinstantiate and instance
212 * directory as arguments.
213 */
214-static int inst_init(const struct polydir_s *polyptr, char *ipath,
215+static int inst_init(const struct polydir_s *polyptr, const char *ipath,
216 struct instance_data *idata)
217 {
218 pid_t rc, pid;
219@@ -791,11 +821,11 @@ out:
220 * Create polyinstantiated instance directory (ipath).
221 */
222 #ifdef WITH_SELINUX
223-static int create_dirs(const struct polydir_s *polyptr, char *ipath,
224+static int create_dirs(struct polydir_s *polyptr, char *ipath,
225 security_context_t icontext, security_context_t ocontext,
226 struct instance_data *idata)
227 #else
228-static int create_dirs(const struct polydir_s *polyptr, char *ipath,
229+static int create_dirs(struct polydir_s *polyptr, char *ipath,
230 struct instance_data *idata)
231 #endif
232 {
233@@ -834,7 +864,17 @@ static int create_dirs(const struct poly
234 * attributes to match that of the original directory that is being
235 * polyinstantiated.
236 */
237- if (mkdir(ipath, S_IRUSR) < 0) {
238+
239+ if (polyptr->method == TMPDIR) {
240+ if (mkdtemp(polyptr->instance_prefix) == NULL) {
241+ pam_syslog(idata->pamh, LOG_ERR, "Error creating temporary instance %s, %m",
242+ polyptr->instance_prefix);
243+ polyptr->method = NONE; /* do not clean up! */
244+ return PAM_SESSION_ERR;
245+ }
246+ /* copy the actual directory name to ipath */
247+ strcpy(ipath, polyptr->instance_prefix);
248+ } else if (mkdir(ipath, S_IRUSR) < 0) {
249 if (errno == EEXIST)
250 goto inst_init;
251 else {
252@@ -920,13 +960,12 @@ inst_init:
253 * security attributes, and performs bind mount to setup the process
254 * namespace.
255 */
256-static int ns_setup(const struct polydir_s *polyptr,
257+static int ns_setup(struct polydir_s *polyptr,
258 struct instance_data *idata)
259 {
260 int retval = 0;
261 char *inst_dir = NULL;
262 char *instname = NULL;
263- char *dir;
264 #ifdef WITH_SELINUX
265 security_context_t instcontext = NULL, origcontext = NULL;
266 #endif
267@@ -935,9 +974,15 @@ static int ns_setup(const struct polydir
268 pam_syslog(idata->pamh, LOG_DEBUG,
269 "Set namespace for directory %s", polyptr->dir);
270
271- dir = strrchr(polyptr->dir, '/');
272- if (dir && strlen(dir) > 1)
273- dir++;
274+ if (polyptr->method == TMPFS) {
275+ if (mount("tmpfs", polyptr->dir, "tmpfs", 0, NULL) < 0) {
276+ pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m",
277+ polyptr->dir);
278+ return PAM_SESSION_ERR;
279+ }
280+ /* we must call inst_init after the mount in this case */
281+ return inst_init(polyptr, "tmpfs", idata);
282+ }
283
284 /*
285 * Obtain the name of instance pathname based on the
286@@ -1043,6 +1088,58 @@ static int cwd_in(char *dir, struct inst
287 return retval;
288 }
289
290+static int cleanup_tmpdirs(struct instance_data *idata)
291+{
292+ struct polydir_s *pptr;
293+ pid_t rc, pid;
294+ sighandler_t osighand = NULL;
295+ int status;
296+
297+ osighand = signal(SIGCHLD, SIG_DFL);
298+ if (osighand == SIG_ERR) {
299+ pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
300+ rc = PAM_SESSION_ERR;
301+ goto out;
302+ }
303+
304+ for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) {
305+ if (pptr->method == TMPDIR && access(pptr->instance_prefix, F_OK) == 0) {
306+ pid = fork();
307+ if (pid == 0) {
308+#ifdef WITH_SELINUX
309+ if (idata->flags & PAMNS_SELINUX_ENABLED) {
310+ if (setexeccon(NULL) < 0)
311+ exit(1);
312+ }
313+#endif
314+ if (execl("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, (char *)NULL) < 0)
315+ exit(1);
316+ } else if (pid > 0) {
317+ while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
318+ (errno == EINTR));
319+ if (rc == (pid_t)-1) {
320+ pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m");
321+ rc = PAM_SESSION_ERR;
322+ goto out;
323+ }
324+ if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) {
325+ pam_syslog(idata->pamh, LOG_ERR,
326+ "Error removing %s", pptr->instance_prefix);
327+ }
328+ } else if (pid < 0) {
329+ pam_syslog(idata->pamh, LOG_ERR,
330+ "Cannot fork to run namespace init script, %m");
331+ rc = PAM_SESSION_ERR;
332+ goto out;
333+ }
334+ }
335+ }
336+
337+ rc = PAM_SUCCESS;
338+out:
339+ signal(SIGCHLD, osighand);
340+ return rc;
341+}
342
343 /*
344 * This function checks to see if polyinstantiation is needed for any
345@@ -1111,13 +1208,22 @@ static int setup_namespace(struct instan
346 * disassociate from the parent namespace.
347 */
348 if (need_poly) {
349+ if (pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, idata->polydirs_ptr,
350+ cleanup_data) != PAM_SUCCESS) {
351+ pam_syslog(idata->pamh, LOG_ERR,
352+ "Unable to set namespace data");
353+ return PAM_SYSTEM_ERR;
354+ }
355 if (unshare(CLONE_NEWNS) < 0) {
356- pam_syslog(idata->pamh, LOG_ERR,
357+ pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
358+ pam_syslog(idata->pamh, LOG_ERR,
359 "Unable to unshare from parent namespace, %m");
360 return PAM_SESSION_ERR;
361 }
362- } else
363+ } else {
364+ del_polydir_list(idata->polydirs_ptr);
365 return PAM_SUCCESS;
366+ }
367
368 /*
369 * Again cycle through all polyinstantiated directories, this time,
370@@ -1144,7 +1250,8 @@ static int setup_namespace(struct instan
371 * umount
372 */
373 if ((changing_dir = cwd_in(pptr->dir, idata)) < 0) {
374- return PAM_SESSION_ERR;
375+ retval = PAM_SESSION_ERR;
376+ goto out;
377 } else if (changing_dir) {
378 if (idata->flags & PAMNS_DEBUG)
379 pam_syslog(idata->pamh, LOG_DEBUG, "changing cwd");
380@@ -1172,8 +1279,10 @@ static int setup_namespace(struct instan
381 int saved_errno = errno;
382 pam_syslog(idata->pamh, LOG_ERR, "Unmount of %s failed, %m",
383 pptr->dir);
384- if (saved_errno != EINVAL)
385- return PAM_SESSION_ERR;
386+ if (saved_errno != EINVAL) {
387+ retval = PAM_SESSION_ERR;
388+ goto out;
389+ }
390 } else if (idata->flags & PAMNS_DEBUG)
391 pam_syslog(idata->pamh, LOG_DEBUG, "Umount succeeded %s",
392 pptr->dir);
393@@ -1185,7 +1294,9 @@ static int setup_namespace(struct instan
394 break;
395 }
396 }
397-
398+out:
399+ if (retval != PAM_SUCCESS)
400+ cleanup_tmpdirs(idata);
401 return retval;
402 }
403
404@@ -1224,8 +1335,10 @@ static int orig_namespace(struct instanc
405 } else if (idata->flags & PAMNS_DEBUG)
406 pam_syslog(idata->pamh, LOG_DEBUG, "Unmount of %s succeeded",
407 pptr->dir);
408- }
409+ }
410 }
411+
412+ cleanup_tmpdirs(idata);
413 return 0;
414 }
415
416@@ -1350,7 +1463,8 @@ PAM_EXTERN int pam_sm_open_session(pam_h
417 } else if (idata.flags & PAMNS_DEBUG)
418 pam_syslog(idata.pamh, LOG_DEBUG, "Nothing to polyinstantiate");
419
420- del_polydir_list(idata.polydirs_ptr);
421+ if (retval != PAM_SUCCESS)
422+ del_polydir_list(idata.polydirs_ptr);
423 return retval;
424 }
425
426@@ -1365,6 +1479,7 @@ PAM_EXTERN int pam_sm_close_session(pam_
427 struct instance_data idata;
428 char *user_name;
429 struct passwd *pwd;
430+ const void *polyptr;
431
432 /* init instance data */
433 idata.flags = 0;
434@@ -1428,16 +1543,12 @@ PAM_EXTERN int pam_sm_close_session(pam_
435 strncat(idata.user, user_name, sizeof(idata.user) - 1);
436 idata.uid = pwd->pw_uid;
437
438- /*
439- * Parse namespace configuration file which lists directories that
440- * are polyinstantiated, directories where instance directories are
441- * created and the method used for polyinstantiation.
442- */
443- retval = parse_config_file(&idata);
444- if ((retval != PAM_SUCCESS) || !idata.polydirs_ptr) {
445- del_polydir_list(idata.polydirs_ptr);
446- return PAM_SESSION_ERR;
447- }
448+ retval = pam_get_data(idata.pamh, NAMESPACE_POLYDIR_DATA, &polyptr);
449+ if (retval != PAM_SUCCESS || polyptr == NULL)
450+ /* nothing to reset */
451+ return PAM_SUCCESS;
452+
453+ idata.polydirs_ptr = polyptr;
454
455 if (idata.flags & PAMNS_DEBUG)
456 pam_syslog(idata.pamh, LOG_DEBUG, "Resetting namespace for pid %d",
457@@ -1452,7 +1563,9 @@ PAM_EXTERN int pam_sm_close_session(pam_
458 pam_syslog(idata.pamh, LOG_DEBUG,
459 "resetting namespace ok for pid %d", getpid());
460 }
461- del_polydir_list(idata.polydirs_ptr);
462+
463+ pam_set_data(idata.pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
464+
465 return PAM_SUCCESS;
466 }
467
This page took 0.407126 seconds and 4 git commands to generate.