diff options
| author | casper <none@none> | 2006-03-10 13:15:03 -0800 |
|---|---|---|
| committer | casper <none@none> | 2006-03-10 13:15:03 -0800 |
| commit | 97682a823d4ed139a3af5f6e1385b1de019d55d3 (patch) | |
| tree | d3141654eeb8b3732d63ac78c47d2f8700c87aa6 | |
| parent | bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77db (diff) | |
| download | illumos-joyent-97682a823d4ed139a3af5f6e1385b1de019d55d3.tar.gz | |
6346529 Login should not fail when unknown privileges are requested
6395043 having extra privileges prevents logins in zones
| -rw-r--r-- | usr/src/lib/pam_modules/unix_cred/unix_cred.c | 71 |
1 files changed, 62 insertions, 9 deletions
diff --git a/usr/src/lib/pam_modules/unix_cred/unix_cred.c b/usr/src/lib/pam_modules/unix_cred/unix_cred.c index f3226a7aac..f12b0260c5 100644 --- a/usr/src/lib/pam_modules/unix_cred/unix_cred.c +++ b/usr/src/lib/pam_modules/unix_cred/unix_cred.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,6 +40,7 @@ #include <libintl.h> #include <project.h> #include <errno.h> +#include <alloca.h> #include <bsm/adt.h> #include <bsm/adt_event.h> /* adt_get_auid() */ @@ -86,19 +86,46 @@ getset(char *keyname, char *defname, userattr_t *ua, priv_set_t **res) { char *str; priv_set_t *tmp; + char *badp; + int len; if ((ua == NULL || ua->attr == NULL || (str = kva_match(ua->attr, keyname)) == NULL) && (str = defread(defname)) == NULL) return (0); - tmp = priv_str_to_set(str, ",", NULL); + len = strlen(str) + 1; + badp = alloca(len); + (void) memset(badp, '\0', len); + do { + const char *q, *endp; + tmp = priv_str_to_set(str, ",", &endp); + if (tmp == NULL) { + if (endp == NULL) + break; + + /* Now remove the bad privilege endp points to */ + q = strchr(endp, ','); + if (q == NULL) + q = endp + strlen(endp); + + if (*badp != '\0') + (void) strlcat(badp, ",", len); + /* Memset above guarantees NUL termination */ + /* LINTED */ + (void) strncat(badp, endp, q - endp); + /* excise bad privilege; strtok ignores 2x sep */ + (void) memmove((void *)endp, q, strlen(q) + 1); + } + } while (tmp == NULL && *str != '\0'); if (tmp == NULL) { syslog(LOG_AUTH|LOG_ERR, - "pam_setcred: bad privilege specification: %s\n", str); - priv_freeset(tmp); + "pam_setcred: can't parse privilege specification: %m\n"); return (-1); + } else if (*badp != '\0') { + syslog(LOG_AUTH|LOG_DEBUG, + "pam_setcred: unrecognized privilege(s): %s\n", badp); } *res = tmp; return (0); @@ -138,7 +165,7 @@ pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) adt_session_data_t *ah; adt_termid_t *termid = NULL; userattr_t *ua; - priv_set_t *lim, *def; + priv_set_t *lim, *def, *tset; char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE]; char buf[PROJECT_BUFSZ]; struct project proj, *pproj; @@ -506,7 +533,7 @@ adt_done: (void) defopen(AUTH_POLICY); - def = lim = NULL; + tset = def = lim = NULL; if (getset(USERATTR_LIMPRIV_KW, DEF_LIMITPRIV, ua, &lim) != 0 || getset(USERATTR_DFLTPRIV_KW, DEF_DFLTPRIV, ua, &def) != 0) { @@ -520,6 +547,21 @@ adt_done: (void) priv_addset(def, PRIV_FILE_CHOWN_SELF); } /* + * Silently limit the privileges to those actually available + * in the current zone. + */ + tset = priv_allocset(); + if (tset == NULL) { + ret = PAM_SYSTEM_ERR; + goto out; + } + if (getppriv(PRIV_PERMITTED, tset) != 0) { + ret = PAM_SYSTEM_ERR; + goto out; + } + if (!priv_issubset(def, tset)) + priv_intersect(tset, def); + /* * We set privilege awareness here so that I gets copied to * P & E when the final setuid(uid) happens. */ @@ -532,6 +574,15 @@ adt_done: if (lim != NULL) { /* + * Silently limit the privileges to the limit set available. + */ + if (getppriv(PRIV_LIMIT, tset) != 0) { + ret = PAM_SYSTEM_ERR; + goto out; + } + if (!priv_issubset(lim, tset)) + priv_intersect(tset, lim); + /* * In order not to suprise certain applications, we * need to retain privilege awareness and thus we must * also set P and E. @@ -554,6 +605,8 @@ out: priv_freeset(lim); if (def != NULL) priv_freeset(def); + if (tset != NULL) + priv_freeset(tset); return (ret); } |
