Print this page
uts: add a concept of a 'default' set of privileges, separate from 'basic'
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/pam_modules/unix_cred/unix_cred.c
+++ new/usr/src/lib/pam_modules/unix_cred/unix_cred.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 #include <nss_dbdefs.h>
26 26 #include <pwd.h>
27 27 #include <stdlib.h>
28 28 #include <string.h>
29 29 #include <syslog.h>
30 30 #include <unistd.h>
31 31 #include <auth_attr.h>
32 32 #include <deflt.h>
33 33 #include <priv.h>
34 34 #include <secdb.h>
35 35 #include <user_attr.h>
36 36 #include <sys/task.h>
37 37 #include <libintl.h>
38 38 #include <project.h>
39 39 #include <errno.h>
40 40 #include <alloca.h>
41 41
42 42 #include <bsm/adt.h>
43 43 #include <bsm/adt_event.h> /* adt_get_auid() */
44 44
45 45 #include <security/pam_appl.h>
46 46 #include <security/pam_modules.h>
47 47 #include <security/pam_impl.h>
48 48
49 49 #define PROJECT "project="
50 50 #define PROJSZ (sizeof (PROJECT) - 1)
51 51
52 52 /*
53 53 * unix_cred - PAM auth modules must contain both pam_sm_authenticate
54 54 * and pam_sm_setcred. Some other auth module is responsible
55 55 * for authentication (e.g., pam_unix_auth.so), this module
56 56 * only implements pam_sm_setcred so that the authentication
57 57 * can be separated without knowledge of the Solaris Unix style
58 58 * credential setting.
59 59 * Solaris Unix style credential setting includes initializing
60 60 * the audit characteristics if not already initialized and
61 61 * setting the user's default and limit privileges.
62 62 */
63 63
64 64 /*
65 65 * unix_cred - pam_sm_authenticate
66 66 *
67 67 * Returns PAM_IGNORE.
68 68 */
69 69
70 70 /*ARGSUSED*/
71 71 int
72 72 pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
73 73 {
74 74 return (PAM_IGNORE);
75 75 }
76 76
77 77 /*
78 78 * Set the privilege set. The attributes are enumerated by _enum_attrs,
79 79 * including the attribues user_attr, prof_attr and policy.conf
80 80 */
81 81 static int
82 82 getset(char *str, priv_set_t **res)
83 83 {
84 84 priv_set_t *tmp;
85 85 char *badp;
86 86 int len;
87 87
88 88 if (str == NULL)
89 89 return (0);
90 90
91 91 len = strlen(str) + 1;
92 92 badp = alloca(len);
93 93 (void) memset(badp, '\0', len);
94 94 do {
95 95 const char *q, *endp;
96 96 tmp = priv_str_to_set(str, ",", &endp);
97 97 if (tmp == NULL) {
98 98 if (endp == NULL)
99 99 break;
100 100
101 101 /* Now remove the bad privilege endp points to */
102 102 q = strchr(endp, ',');
103 103 if (q == NULL)
104 104 q = endp + strlen(endp);
105 105
106 106 if (*badp != '\0')
107 107 (void) strlcat(badp, ",", len);
108 108 /* Memset above guarantees NUL termination */
109 109 /* LINTED */
110 110 (void) strncat(badp, endp, q - endp);
111 111 /* excise bad privilege; strtok ignores 2x sep */
112 112 (void) memmove((void *)endp, q, strlen(q) + 1);
113 113 }
114 114 } while (tmp == NULL && *str != '\0');
115 115
116 116 if (tmp == NULL) {
117 117 syslog(LOG_AUTH|LOG_ERR,
118 118 "pam_setcred: can't parse privilege specification: %m\n");
119 119 return (-1);
120 120 } else if (*badp != '\0') {
121 121 syslog(LOG_AUTH|LOG_DEBUG,
122 122 "pam_setcred: unrecognized privilege(s): %s\n", badp);
123 123 }
124 124 *res = tmp;
125 125 return (0);
126 126 }
127 127
128 128 typedef struct deflim {
129 129 char *def;
130 130 char *lim;
131 131 } deflim_t;
132 132
133 133 /*ARGSUSED*/
134 134 static int
135 135 finddeflim(const char *name, kva_t *kva, void *ctxt, void *pres)
136 136 {
137 137 deflim_t *pdef = pres;
138 138 char *val;
139 139
140 140 if (pdef->def == NULL) {
141 141 val = kva_match(kva, USERATTR_DFLTPRIV_KW);
142 142 if (val != NULL)
143 143 pdef->def = strdup(val);
144 144 }
145 145 if (pdef->lim == NULL) {
146 146 val = kva_match(kva, USERATTR_LIMPRIV_KW);
147 147 if (val != NULL)
148 148 pdef->lim = strdup(val);
149 149 }
150 150 return (pdef->lim != NULL && pdef->def != NULL);
151 151 }
152 152
153 153 /*
154 154 * unix_cred - pam_sm_setcred
155 155 *
156 156 * Entry flags = PAM_ESTABLISH_CRED, set up Solaris Unix cred.
157 157 * PAM_DELETE_CRED, NOP, return PAM_SUCCESS.
158 158 * PAM_REINITIALIZE_CRED, set up Solaris Unix cred,
159 159 * or merge the current context with the new
160 160 * user.
161 161 * PAM_REFRESH_CRED, set up Solaris Unix cred.
162 162 * PAM_SILENT, print no messages to user.
163 163 *
164 164 * Returns PAM_SUCCESS, if all successful.
165 165 * PAM_CRED_ERR, if unable to set credentials.
166 166 * PAM_USER_UNKNOWN, if PAM_USER not set, or unable to find
167 167 * user in databases.
168 168 * PAM_SYSTEM_ERR, if no valid flag, or unable to get/set
169 169 * user's audit state.
170 170 */
171 171
172 172 int
173 173 pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
174 174 {
175 175 int i;
176 176 int debug = 0;
177 177 uint_t nowarn = flags & PAM_SILENT;
178 178 int ret = PAM_SUCCESS;
179 179 char *user;
180 180 char *auser;
181 181 char *rhost;
182 182 char *tty;
183 183 au_id_t auid;
184 184 adt_session_data_t *ah;
185 185 adt_termid_t *termid = NULL;
186 186 priv_set_t *lim, *def, *tset;
187 187 char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
188 188 char buf[PROJECT_BUFSZ];
189 189 struct project proj, *pproj;
190 190 int error;
191 191 char *projname;
192 192 char *kvs;
193 193 struct passwd pwd;
194 194 char pwbuf[NSS_BUFLEN_PASSWD];
195 195 deflim_t deflim;
196 196
197 197 for (i = 0; i < argc; i++) {
198 198 if (strcmp(argv[i], "debug") == 0)
199 199 debug = 1;
200 200 else if (strcmp(argv[i], "nowarn") == 0)
201 201 nowarn |= 1;
202 202 }
203 203
204 204 if (debug)
205 205 syslog(LOG_AUTH | LOG_DEBUG,
206 206 "pam_unix_cred: pam_sm_setcred(flags = %x, argc= %d)",
207 207 flags, argc);
208 208
209 209 (void) pam_get_item(pamh, PAM_USER, (void **)&user);
210 210
211 211 if (user == NULL || *user == '\0') {
212 212 syslog(LOG_AUTH | LOG_ERR,
213 213 "pam_unix_cred: USER NULL or empty!\n");
214 214 return (PAM_USER_UNKNOWN);
215 215 }
216 216 (void) pam_get_item(pamh, PAM_AUSER, (void **)&auser);
217 217 (void) pam_get_item(pamh, PAM_RHOST, (void **)&rhost);
218 218 (void) pam_get_item(pamh, PAM_TTY, (void **)&tty);
219 219 if (debug)
220 220 syslog(LOG_AUTH | LOG_DEBUG,
221 221 "pam_unix_cred: user = %s, auser = %s, rhost = %s, "
222 222 "tty = %s", user,
223 223 (auser == NULL) ? "NULL" : (*auser == '\0') ? "ZERO" :
224 224 auser,
225 225 (rhost == NULL) ? "NULL" : (*rhost == '\0') ? "ZERO" :
226 226 rhost,
227 227 (tty == NULL) ? "NULL" : (*tty == '\0') ? "ZERO" :
228 228 tty);
229 229
230 230 /* validate flags */
231 231 switch (flags & (PAM_ESTABLISH_CRED | PAM_DELETE_CRED |
232 232 PAM_REINITIALIZE_CRED | PAM_REFRESH_CRED)) {
233 233 case 0:
234 234 /* set default flag */
235 235 flags |= PAM_ESTABLISH_CRED;
236 236 break;
237 237 case PAM_ESTABLISH_CRED:
238 238 case PAM_REINITIALIZE_CRED:
239 239 case PAM_REFRESH_CRED:
240 240 break;
241 241 case PAM_DELETE_CRED:
242 242 return (PAM_SUCCESS);
243 243 default:
244 244 syslog(LOG_AUTH | LOG_ERR,
245 245 "pam_unix_cred: invalid flags %x", flags);
246 246 return (PAM_SYSTEM_ERR);
247 247 }
248 248
249 249 /*
250 250 * if auditing on and process audit state not set,
251 251 * setup audit context for process.
252 252 */
253 253 if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
254 254 syslog(LOG_AUTH | LOG_ERR,
255 255 "pam_unix_cred: cannot create start audit session %m");
256 256 return (PAM_SYSTEM_ERR);
257 257 }
258 258 adt_get_auid(ah, &auid);
259 259 if (debug) {
260 260 int auditstate;
261 261
262 262 if (auditon(A_GETCOND, (caddr_t)&auditstate,
263 263 sizeof (auditstate)) != 0) {
264 264 auditstate = AUC_DISABLED;
265 265 }
266 266 syslog(LOG_AUTH | LOG_DEBUG,
267 267 "pam_unix_cred: state = %d, auid = %d", auditstate,
268 268 auid);
269 269 }
270 270 if (getpwnam_r(user, &pwd, pwbuf, sizeof (pwbuf)) == NULL) {
271 271 syslog(LOG_AUTH | LOG_ERR,
272 272 "pam_unix_cred: cannot get passwd entry for user = %s",
273 273 user);
274 274 ret = PAM_USER_UNKNOWN;
275 275 goto adt_done;
276 276 }
277 277
278 278 if ((auid == AU_NOAUDITID) &&
279 279 (flags & PAM_ESTABLISH_CRED)) {
280 280 struct passwd apwd;
281 281 char apwbuf[NSS_BUFLEN_PASSWD];
282 282
283 283 errno = 0;
284 284 if ((rhost == NULL || *rhost == '\0')) {
285 285 if (adt_load_ttyname(tty, &termid) != 0) {
286 286 if (errno == ENETDOWN) {
287 287 /*
288 288 * tolerate not being able to
289 289 * translate local hostname
290 290 * to a termid -- it will be
291 291 * "loopback".
292 292 */
293 293 syslog(LOG_AUTH | LOG_ERR,
294 294 "pam_unix_cred: cannot load "
295 295 "ttyname: %m, continuing.");
296 296 goto adt_setuser;
297 297 } else if (errno != 0) {
298 298 syslog(LOG_AUTH | LOG_ERR,
299 299 "pam_unix_cred: cannot load "
300 300 "ttyname: %m.");
301 301 } else {
302 302 syslog(LOG_AUTH | LOG_ERR,
303 303 "pam_unix_cred: cannot load "
304 304 "ttyname.");
305 305 }
306 306 ret = PAM_SYSTEM_ERR;
307 307 goto adt_done;
308 308 }
309 309 } else {
310 310 if (adt_load_hostname(rhost, &termid) != 0) {
311 311 if (errno != 0) {
312 312 syslog(LOG_AUTH | LOG_ERR,
313 313 "pam_unix_cred: cannot load "
314 314 "hostname: %m.");
315 315 } else {
316 316 syslog(LOG_AUTH | LOG_ERR,
317 317 "pam_unix_cred: cannot load "
318 318 "hostname.");
319 319 }
320 320 ret = PAM_SYSTEM_ERR;
321 321 goto adt_done;
322 322 }
323 323 }
324 324 adt_setuser:
325 325 if ((auser != NULL) && (*auser != '\0') &&
326 326 (getpwnam_r(auser, &apwd, apwbuf,
327 327 sizeof (apwbuf)) != NULL)) {
328 328 /*
329 329 * set up the initial audit for user coming
330 330 * from another user
331 331 */
332 332 if (adt_set_user(ah, apwd.pw_uid, apwd.pw_gid,
333 333 apwd.pw_uid, apwd.pw_gid, termid, ADT_NEW) != 0) {
334 334 syslog(LOG_AUTH | LOG_ERR,
335 335 "pam_unix_cred: cannot set auser audit "
336 336 "%m");
337 337 ret = PAM_SYSTEM_ERR;
338 338 goto adt_done;
339 339 }
340 340 if (adt_set_user(ah, pwd.pw_uid, pwd.pw_gid,
341 341 pwd.pw_uid, pwd.pw_gid, NULL,
342 342 ADT_UPDATE) != 0) {
343 343 syslog(LOG_AUTH | LOG_ERR,
344 344 "pam_unix_cred: cannot merge user audit "
345 345 "%m");
346 346 ret = PAM_SYSTEM_ERR;
347 347 goto adt_done;
348 348 }
349 349 if (debug) {
350 350 syslog(LOG_AUTH | LOG_DEBUG,
351 351 "pam_unix_cred: new audit set for %d:%d",
352 352 apwd.pw_uid, pwd.pw_uid);
353 353 }
354 354 } else {
355 355 /*
356 356 * No authenticated user or authenticated user is
357 357 * not a local user, no remote attribution, set
358 358 * up the initial audit as for direct user login
359 359 */
360 360 if (adt_set_user(ah, pwd.pw_uid, pwd.pw_gid,
361 361 pwd.pw_uid, pwd.pw_gid, termid, ADT_NEW) != 0) {
362 362 syslog(LOG_AUTH | LOG_ERR,
363 363 "pam_unix_cred: cannot set user audit %m");
364 364 ret = PAM_SYSTEM_ERR;
365 365 goto adt_done;
366 366 }
367 367 }
368 368 if (adt_set_proc(ah) != 0) {
369 369 syslog(LOG_AUTH | LOG_ERR,
370 370 "pam_unix_cred: cannot set process audit %m");
371 371 ret = PAM_CRED_ERR;
372 372 goto adt_done;
373 373 }
374 374 if (debug) {
375 375 syslog(LOG_AUTH | LOG_DEBUG,
376 376 "pam_unix_cred: new audit set for %d",
377 377 pwd.pw_uid);
378 378 }
379 379 } else if ((auid != AU_NOAUDITID) &&
380 380 (flags & PAM_REINITIALIZE_CRED)) {
381 381 if (adt_set_user(ah, pwd.pw_uid, pwd.pw_gid, pwd.pw_uid,
382 382 pwd.pw_gid, NULL, ADT_UPDATE) != 0) {
383 383 syslog(LOG_AUTH | LOG_ERR,
384 384 "pam_unix_cred: cannot set user audit %m");
385 385 ret = PAM_SYSTEM_ERR;
386 386 goto adt_done;
387 387 }
388 388 if (adt_set_proc(ah) != 0) {
389 389 syslog(LOG_AUTH | LOG_ERR,
390 390 "pam_unix_cred: cannot set process audit %m");
391 391 ret = PAM_CRED_ERR;
392 392 goto adt_done;
393 393 }
394 394 if (debug) {
395 395 syslog(LOG_AUTH | LOG_DEBUG,
396 396 "pam_unix_cred: audit merged for %d:%d",
397 397 auid, pwd.pw_uid);
398 398 }
399 399 } else if (debug) {
400 400 syslog(LOG_AUTH | LOG_DEBUG,
401 401 "pam_unix_cred: audit already set for %d", auid);
402 402 }
403 403 adt_done:
404 404 if (termid != NULL)
405 405 free(termid);
406 406 if (adt_end_session(ah) != 0) {
407 407 syslog(LOG_AUTH | LOG_ERR,
408 408 "pam_unix_cred: unable to end audit session");
409 409 }
410 410
411 411 if (ret != PAM_SUCCESS)
412 412 return (ret);
413 413
414 414 /* Initialize the user's project */
415 415 (void) pam_get_item(pamh, PAM_RESOURCE, (void **)&kvs);
416 416 if (kvs != NULL) {
417 417 char *tmp, *lasts, *tok;
418 418
419 419 kvs = tmp = strdup(kvs);
420 420 if (kvs == NULL)
421 421 return (PAM_BUF_ERR);
422 422
423 423 while ((tok = strtok_r(tmp, ";", &lasts)) != NULL) {
424 424 if (strncmp(tok, PROJECT, PROJSZ) == 0) {
425 425 projname = tok + PROJSZ;
426 426 break;
427 427 }
428 428 tmp = NULL;
429 429 }
430 430 } else {
431 431 projname = NULL;
432 432 }
433 433
434 434 if (projname == NULL || *projname == '\0') {
435 435 pproj = getdefaultproj(user, &proj, (void *)&buf,
436 436 PROJECT_BUFSZ);
437 437 } else {
438 438 pproj = getprojbyname(projname, &proj, (void *)&buf,
439 439 PROJECT_BUFSZ);
440 440 }
441 441 /* projname points into kvs, so this is the first opportunity to free */
442 442 if (kvs != NULL)
443 443 free(kvs);
444 444 if (pproj == NULL) {
445 445 syslog(LOG_AUTH | LOG_ERR,
446 446 "pam_unix_cred: no default project for user %s", user);
447 447 if (!nowarn) {
448 448 (void) snprintf(messages[0], sizeof (messages[0]),
449 449 dgettext(TEXT_DOMAIN, "No default project!"));
450 450 (void) __pam_display_msg(pamh, PAM_ERROR_MSG,
451 451 1, messages, NULL);
452 452 }
453 453 return (PAM_SYSTEM_ERR);
454 454 }
455 455 if ((error = setproject(proj.pj_name, user, TASK_NORMAL)) != 0) {
456 456 kva_t *kv_array;
457 457
458 458 switch (error) {
459 459 case SETPROJ_ERR_TASK:
460 460 if (errno == EAGAIN) {
461 461 syslog(LOG_AUTH | LOG_ERR,
462 462 "pam_unix_cred: project \"%s\" resource "
463 463 "control limit has been reached",
464 464 proj.pj_name);
465 465 (void) snprintf(messages[0],
466 466 sizeof (messages[0]), dgettext(
467 467 TEXT_DOMAIN,
468 468 "Resource control limit has been "
469 469 "reached"));
470 470 } else {
471 471 syslog(LOG_AUTH | LOG_ERR,
472 472 "pam_unix_cred: user %s could not join "
473 473 "project \"%s\": %m", user, proj.pj_name);
474 474 (void) snprintf(messages[0],
475 475 sizeof (messages[0]), dgettext(
476 476 TEXT_DOMAIN,
477 477 "Could not join default project"));
478 478 }
479 479 if (!nowarn)
480 480 (void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
481 481 messages, NULL);
482 482 break;
483 483 case SETPROJ_ERR_POOL:
484 484 (void) snprintf(messages[0], sizeof (messages[0]),
485 485 dgettext(TEXT_DOMAIN,
486 486 "Could not bind to resource pool"));
487 487 switch (errno) {
488 488 case EACCES:
489 489 syslog(LOG_AUTH | LOG_ERR,
490 490 "pam_unix_cred: project \"%s\" could not "
491 491 "bind to resource pool: No resource pool "
492 492 "accepting default bindings exists",
493 493 proj.pj_name);
494 494 (void) snprintf(messages[1],
495 495 sizeof (messages[1]),
496 496 dgettext(TEXT_DOMAIN,
497 497 "No resource pool accepting "
498 498 "default bindings exists"));
499 499 break;
500 500 case ESRCH:
501 501 syslog(LOG_AUTH | LOG_ERR,
502 502 "pam_unix_cred: project \"%s\" could not "
503 503 "bind to resource pool: The resource pool "
504 504 "is unknown", proj.pj_name);
505 505 (void) snprintf(messages[1],
506 506 sizeof (messages[1]),
507 507 dgettext(TEXT_DOMAIN,
508 508 "The specified resource pool "
509 509 "is unknown"));
510 510 break;
511 511 default:
512 512 (void) snprintf(messages[1],
513 513 sizeof (messages[1]),
514 514 dgettext(TEXT_DOMAIN,
515 515 "Failure during pool binding"));
516 516 syslog(LOG_AUTH | LOG_ERR,
517 517 "pam_unix_cred: project \"%s\" could not "
518 518 "bind to resource pool: %m", proj.pj_name);
519 519 }
520 520 if (!nowarn)
521 521 (void) __pam_display_msg(pamh, PAM_ERROR_MSG,
522 522 2, messages, NULL);
523 523 break;
524 524 default:
525 525 /*
526 526 * Resource control assignment failed. Unlike
527 527 * newtask(1m), we treat this as an error.
528 528 */
529 529 if (error < 0) {
530 530 /*
531 531 * This isn't supposed to happen, but in
532 532 * case it does, this error message
533 533 * doesn't use error as an index, like
534 534 * the others might.
535 535 */
536 536 syslog(LOG_AUTH | LOG_ERR,
537 537 "pam_unix_cred: unkwown error joining "
538 538 "project \"%s\" (%d)", proj.pj_name, error);
539 539 (void) snprintf(messages[0],
540 540 sizeof (messages[0]),
541 541 dgettext(TEXT_DOMAIN,
542 542 "unkwown error joining project \"%s\""
543 543 " (%d)"), proj.pj_name, error);
544 544 } else if ((kv_array = _str2kva(proj.pj_attr, KV_ASSIGN,
545 545 KV_DELIMITER)) != NULL) {
546 546 syslog(LOG_AUTH | LOG_ERR,
547 547 "pam_unix_cred: %s resource control "
548 548 "assignment failed for project \"%s\"",
549 549 kv_array->data[error - 1].key,
550 550 proj.pj_name);
551 551 (void) snprintf(messages[0],
552 552 sizeof (messages[0]),
553 553 dgettext(TEXT_DOMAIN,
554 554 "%s resource control assignment failed for "
555 555 "project \"%s\""),
556 556 kv_array->data[error - 1].key,
557 557 proj.pj_name);
558 558 _kva_free(kv_array);
559 559 } else {
560 560 syslog(LOG_AUTH | LOG_ERR,
561 561 "pam_unix_cred: resource control "
562 562 "assignment failed for project \"%s\""
563 563 "attribute %d", proj.pj_name, error);
564 564 (void) snprintf(messages[0],
565 565 sizeof (messages[0]),
566 566 dgettext(TEXT_DOMAIN,
567 567 "resource control assignment failed for "
568 568 "project \"%s\" attribute %d"),
569 569 proj.pj_name, error);
570 570 }
571 571 if (!nowarn)
572 572 (void) __pam_display_msg(pamh, PAM_ERROR_MSG,
573 573 1, messages, NULL);
574 574 }
575 575 return (PAM_SYSTEM_ERR);
576 576 }
577 577
578 578 tset = def = lim = NULL;
579 579 deflim.def = deflim.lim = NULL;
580 580
581 581 (void) _enum_attrs(user, finddeflim, NULL, &deflim);
582 582
583 583 if (getset(deflim.lim, &lim) != 0 || getset(deflim.def, &def) != 0) {
↓ open down ↓ |
583 lines elided |
↑ open up ↑ |
584 584 ret = PAM_SYSTEM_ERR;
585 585 goto out;
586 586 }
587 587
588 588 if (def == NULL) {
589 589 def = priv_allocset();
590 590 if (def == NULL) {
591 591 ret = PAM_SYSTEM_ERR;
592 592 goto out;
593 593 }
594 - priv_basicset(def);
594 + priv_defaultset(def);
595 595 errno = 0;
596 596 if ((pathconf("/", _PC_CHOWN_RESTRICTED) == -1) && (errno == 0))
597 597 (void) priv_addset(def, PRIV_FILE_CHOWN_SELF);
598 598 }
599 599 /*
600 600 * Silently limit the privileges to those actually available
601 601 * in the current zone.
602 + *
603 + * XXX: i think this applies to non-zone cases too, fix the comment.
602 604 */
603 605 tset = priv_allocset();
604 606 if (tset == NULL) {
605 607 ret = PAM_SYSTEM_ERR;
606 608 goto out;
607 609 }
608 610 if (getppriv(PRIV_PERMITTED, tset) != 0) {
609 611 ret = PAM_SYSTEM_ERR;
610 612 goto out;
611 613 }
612 614 if (!priv_issubset(def, tset))
613 615 priv_intersect(tset, def);
614 616 /*
615 617 * We set privilege awareness here so that I gets copied to
616 618 * P & E when the final setuid(uid) happens.
617 619 */
618 620 (void) setpflags(PRIV_AWARE, 1);
619 621 if (setppriv(PRIV_SET, PRIV_INHERITABLE, def) != 0) {
620 622 syslog(LOG_AUTH | LOG_ERR,
621 623 "pam_setcred: setppriv(defaultpriv) failed: %m");
622 624 ret = PAM_CRED_ERR;
623 625 }
624 626
625 627 if (lim != NULL) {
626 628 /*
627 629 * Silently limit the privileges to the limit set available.
628 630 */
629 631 if (getppriv(PRIV_LIMIT, tset) != 0) {
630 632 ret = PAM_SYSTEM_ERR;
631 633 goto out;
632 634 }
633 635 if (!priv_issubset(lim, tset))
634 636 priv_intersect(tset, lim);
635 637 if (setppriv(PRIV_SET, PRIV_LIMIT, lim) != 0) {
636 638 syslog(LOG_AUTH | LOG_ERR,
637 639 "pam_setcred: setppriv(limitpriv) failed: %m");
638 640 ret = PAM_CRED_ERR;
639 641 goto out;
640 642 }
641 643 /*
642 644 * In order not to surprise certain applications, we
643 645 * need to get rid of privilege awareness and thus we must
644 646 * set this flag which will cause a reset on set*uid().
645 647 */
646 648 (void) setpflags(PRIV_AWARE_RESET, 1);
647 649 }
648 650 /*
649 651 * This may fail but we do not care as this will be reset later
650 652 * when the uids are set to their final values.
651 653 */
652 654 (void) setpflags(PRIV_AWARE, 0);
653 655 /*
654 656 * Remove PRIV_PFEXEC; stop running as if we are under a profile
655 657 * shell. A user with a profile shell will set PRIV_PFEXEC.
656 658 */
657 659 (void) setpflags(PRIV_PFEXEC, 0);
658 660
659 661 out:
660 662 free(deflim.lim);
661 663 free(deflim.def);
662 664
663 665 if (lim != NULL)
664 666 priv_freeset(lim);
665 667 if (def != NULL)
666 668 priv_freeset(def);
667 669 if (tset != NULL)
668 670 priv_freeset(tset);
669 671
670 672 return (ret);
671 673 }
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX