17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
597682a82Scasper  * Common Development and Distribution License (the "License").
697682a82Scasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2291b2cbb3Sgww  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
267c478bd9Sstevel@tonic-gate #include <pwd.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <syslog.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate #include <auth_attr.h>
327c478bd9Sstevel@tonic-gate #include <deflt.h>
337c478bd9Sstevel@tonic-gate #include <priv.h>
347c478bd9Sstevel@tonic-gate #include <secdb.h>
357c478bd9Sstevel@tonic-gate #include <user_attr.h>
367c478bd9Sstevel@tonic-gate #include <sys/task.h>
377c478bd9Sstevel@tonic-gate #include <libintl.h>
387c478bd9Sstevel@tonic-gate #include <project.h>
397c478bd9Sstevel@tonic-gate #include <errno.h>
4097682a82Scasper #include <alloca.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <bsm/adt.h>
437c478bd9Sstevel@tonic-gate #include <bsm/adt_event.h>	/* adt_get_auid() */
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
467c478bd9Sstevel@tonic-gate #include <security/pam_modules.h>
477c478bd9Sstevel@tonic-gate #include <security/pam_impl.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #define	PROJECT		"project="
507c478bd9Sstevel@tonic-gate #define	PROJSZ		(sizeof (PROJECT) - 1)
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  *	unix_cred - PAM auth modules must contain both pam_sm_authenticate
547c478bd9Sstevel@tonic-gate  *		and pam_sm_setcred.  Some other auth module is responsible
557c478bd9Sstevel@tonic-gate  *		for authentication (e.g., pam_unix_auth.so), this module
567c478bd9Sstevel@tonic-gate  *		only implements pam_sm_setcred so that the authentication
577c478bd9Sstevel@tonic-gate  *		can be separated without knowledge of the Solaris Unix style
587c478bd9Sstevel@tonic-gate  *		credential setting.
597c478bd9Sstevel@tonic-gate  *		Solaris Unix style credential setting includes initializing
607c478bd9Sstevel@tonic-gate  *		the audit characteristics if not already initialized and
617c478bd9Sstevel@tonic-gate  *		setting the user's default and limit privileges.
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  *	unix_cred - pam_sm_authenticate
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  *	Returns	PAM_IGNORE.
687c478bd9Sstevel@tonic-gate  */
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /*ARGSUSED*/
717c478bd9Sstevel@tonic-gate int
pam_sm_authenticate(pam_handle_t * pamh,int flags,int argc,const char ** argv)727c478bd9Sstevel@tonic-gate pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	return (PAM_IGNORE);
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /*
78134a1f4eSCasper H.S. Dik  * Set the privilege set.  The attributes are enumerated by _enum_attrs,
79134a1f4eSCasper H.S. Dik  * including the attribues user_attr, prof_attr and policy.conf
807c478bd9Sstevel@tonic-gate  */
817c478bd9Sstevel@tonic-gate static int
getset(char * str,priv_set_t ** res)82134a1f4eSCasper H.S. Dik getset(char *str, priv_set_t **res)
837c478bd9Sstevel@tonic-gate {
847c478bd9Sstevel@tonic-gate 	priv_set_t *tmp;
8597682a82Scasper 	char *badp;
8697682a82Scasper 	int len;
877c478bd9Sstevel@tonic-gate 
88134a1f4eSCasper H.S. Dik 	if (str == NULL)
897c478bd9Sstevel@tonic-gate 		return (0);
907c478bd9Sstevel@tonic-gate 
9197682a82Scasper 	len = strlen(str) + 1;
9297682a82Scasper 	badp = alloca(len);
9397682a82Scasper 	(void) memset(badp, '\0', len);
9497682a82Scasper 	do {
9597682a82Scasper 		const char *q, *endp;
9697682a82Scasper 		tmp = priv_str_to_set(str, ",", &endp);
9797682a82Scasper 		if (tmp == NULL) {
9897682a82Scasper 			if (endp == NULL)
9997682a82Scasper 				break;
10097682a82Scasper 
10197682a82Scasper 			/* Now remove the bad privilege endp points to */
10297682a82Scasper 			q = strchr(endp, ',');
10397682a82Scasper 			if (q == NULL)
10497682a82Scasper 				q = endp + strlen(endp);
10597682a82Scasper 
10697682a82Scasper 			if (*badp != '\0')
10797682a82Scasper 				(void) strlcat(badp, ",", len);
10897682a82Scasper 			/* Memset above guarantees NUL termination */
10997682a82Scasper 			/* LINTED */
11097682a82Scasper 			(void) strncat(badp, endp, q - endp);
11197682a82Scasper 			/* excise bad privilege; strtok ignores 2x sep */
11297682a82Scasper 			(void) memmove((void *)endp, q, strlen(q) + 1);
11397682a82Scasper 		}
11497682a82Scasper 	} while (tmp == NULL && *str != '\0');
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (tmp == NULL) {
1177c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH|LOG_ERR,
11897682a82Scasper 		    "pam_setcred: can't parse privilege specification: %m\n");
1197c478bd9Sstevel@tonic-gate 		return (-1);
12097682a82Scasper 	} else if (*badp != '\0') {
12197682a82Scasper 		syslog(LOG_AUTH|LOG_DEBUG,
12297682a82Scasper 		    "pam_setcred: unrecognized privilege(s): %s\n", badp);
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 	*res = tmp;
1257c478bd9Sstevel@tonic-gate 	return (0);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
128134a1f4eSCasper H.S. Dik typedef struct deflim {
129134a1f4eSCasper H.S. Dik 	char *def;
130134a1f4eSCasper H.S. Dik 	char *lim;
131134a1f4eSCasper H.S. Dik } deflim_t;
132134a1f4eSCasper H.S. Dik 
133134a1f4eSCasper H.S. Dik /*ARGSUSED*/
134134a1f4eSCasper H.S. Dik static int
finddeflim(const char * name,kva_t * kva,void * ctxt,void * pres)135134a1f4eSCasper H.S. Dik finddeflim(const char *name, kva_t *kva, void *ctxt, void *pres)
136134a1f4eSCasper H.S. Dik {
137134a1f4eSCasper H.S. Dik 	deflim_t *pdef = pres;
138134a1f4eSCasper H.S. Dik 	char *val;
139134a1f4eSCasper H.S. Dik 
140134a1f4eSCasper H.S. Dik 	if (pdef->def == NULL) {
141134a1f4eSCasper H.S. Dik 		val = kva_match(kva, USERATTR_DFLTPRIV_KW);
142134a1f4eSCasper H.S. Dik 		if (val != NULL)
143134a1f4eSCasper H.S. Dik 			pdef->def = strdup(val);
144134a1f4eSCasper H.S. Dik 	}
145134a1f4eSCasper H.S. Dik 	if (pdef->lim == NULL) {
146134a1f4eSCasper H.S. Dik 		val = kva_match(kva, USERATTR_LIMPRIV_KW);
147134a1f4eSCasper H.S. Dik 		if (val != NULL)
148134a1f4eSCasper H.S. Dik 			pdef->lim = strdup(val);
149134a1f4eSCasper H.S. Dik 	}
150134a1f4eSCasper H.S. Dik 	return (pdef->lim != NULL && pdef->def != NULL);
151134a1f4eSCasper H.S. Dik }
152134a1f4eSCasper H.S. Dik 
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate  *	unix_cred - pam_sm_setcred
1557c478bd9Sstevel@tonic-gate  *
1567c478bd9Sstevel@tonic-gate  *	Entry flags = 	PAM_ESTABLISH_CRED, set up Solaris Unix cred.
1577c478bd9Sstevel@tonic-gate  *			PAM_DELETE_CRED, NOP, return PAM_SUCCESS.
1587c478bd9Sstevel@tonic-gate  *			PAM_REINITIALIZE_CRED, set up Solaris Unix cred,
1597c478bd9Sstevel@tonic-gate  *				or merge the current context with the new
1607c478bd9Sstevel@tonic-gate  *				user.
1617c478bd9Sstevel@tonic-gate  *			PAM_REFRESH_CRED, set up Solaris Unix cred.
1627c478bd9Sstevel@tonic-gate  *			PAM_SILENT, print no messages to user.
1637c478bd9Sstevel@tonic-gate  *
1647c478bd9Sstevel@tonic-gate  *	Returns	PAM_SUCCESS, if all successful.
1657c478bd9Sstevel@tonic-gate  *		PAM_CRED_ERR, if unable to set credentials.
1667c478bd9Sstevel@tonic-gate  *		PAM_USER_UNKNOWN, if PAM_USER not set, or unable to find
1677c478bd9Sstevel@tonic-gate  *			user in databases.
1687c478bd9Sstevel@tonic-gate  *		PAM_SYSTEM_ERR, if no valid flag, or unable to get/set
1697c478bd9Sstevel@tonic-gate  *			user's audit state.
1707c478bd9Sstevel@tonic-gate  */
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate int
pam_sm_setcred(pam_handle_t * pamh,int flags,int argc,const char ** argv)1737c478bd9Sstevel@tonic-gate pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	int	i;
1767c478bd9Sstevel@tonic-gate 	int	debug = 0;
1777c478bd9Sstevel@tonic-gate 	uint_t	nowarn = flags & PAM_SILENT;
1787c478bd9Sstevel@tonic-gate 	int	ret = PAM_SUCCESS;
1797c478bd9Sstevel@tonic-gate 	char	*user;
180bf430c99Sgww 	char	*auser;
1817c478bd9Sstevel@tonic-gate 	char	*rhost;
1827c478bd9Sstevel@tonic-gate 	char	*tty;
1837c478bd9Sstevel@tonic-gate 	au_id_t	auid;
1847c478bd9Sstevel@tonic-gate 	adt_session_data_t *ah;
1857c478bd9Sstevel@tonic-gate 	adt_termid_t	*termid = NULL;
18697682a82Scasper 	priv_set_t	*lim, *def, *tset;
1877c478bd9Sstevel@tonic-gate 	char		messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
1887c478bd9Sstevel@tonic-gate 	char		buf[PROJECT_BUFSZ];
1897c478bd9Sstevel@tonic-gate 	struct project	proj, *pproj;
1907c478bd9Sstevel@tonic-gate 	int		error;
1917c478bd9Sstevel@tonic-gate 	char		*projname;
1927c478bd9Sstevel@tonic-gate 	char		*kvs;
1937c478bd9Sstevel@tonic-gate 	struct passwd	pwd;
1947c478bd9Sstevel@tonic-gate 	char		pwbuf[NSS_BUFLEN_PASSWD];
195134a1f4eSCasper H.S. Dik 	deflim_t	deflim;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++) {
1987c478bd9Sstevel@tonic-gate 		if (strcmp(argv[i], "debug") == 0)
1997c478bd9Sstevel@tonic-gate 			debug = 1;
2007c478bd9Sstevel@tonic-gate 		else if (strcmp(argv[i], "nowarn") == 0)
2017c478bd9Sstevel@tonic-gate 			nowarn |= 1;
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	if (debug)
2057c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_DEBUG,
2067c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: pam_sm_setcred(flags = %x, argc= %d)",
2077c478bd9Sstevel@tonic-gate 		    flags, argc);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	(void) pam_get_item(pamh, PAM_USER, (void **)&user);
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	if (user == NULL || *user == '\0') {
2127c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_ERR,
2137c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: USER NULL or empty!\n");
2147c478bd9Sstevel@tonic-gate 		return (PAM_USER_UNKNOWN);
2157c478bd9Sstevel@tonic-gate 	}
216bf430c99Sgww 	(void) pam_get_item(pamh, PAM_AUSER, (void **)&auser);
2177c478bd9Sstevel@tonic-gate 	(void) pam_get_item(pamh, PAM_RHOST, (void **)&rhost);
2187c478bd9Sstevel@tonic-gate 	(void) pam_get_item(pamh, PAM_TTY, (void **)&tty);
2197c478bd9Sstevel@tonic-gate 	if (debug)
2207c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_DEBUG,
221bf430c99Sgww 		    "pam_unix_cred: user = %s, auser = %s, rhost = %s, "
2227c478bd9Sstevel@tonic-gate 		    "tty = %s", user,
223bf430c99Sgww 		    (auser == NULL) ? "NULL" : (*auser == '\0') ? "ZERO" :
224bf430c99Sgww 		    auser,
2257c478bd9Sstevel@tonic-gate 		    (rhost == NULL) ? "NULL" : (*rhost == '\0') ? "ZERO" :
2267c478bd9Sstevel@tonic-gate 		    rhost,
2277c478bd9Sstevel@tonic-gate 		    (tty == NULL) ? "NULL" : (*tty == '\0') ? "ZERO" :
2287c478bd9Sstevel@tonic-gate 		    tty);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	/* validate flags */
2317c478bd9Sstevel@tonic-gate 	switch (flags & (PAM_ESTABLISH_CRED | PAM_DELETE_CRED |
2327c478bd9Sstevel@tonic-gate 	    PAM_REINITIALIZE_CRED | PAM_REFRESH_CRED)) {
2337c478bd9Sstevel@tonic-gate 	case 0:
2347c478bd9Sstevel@tonic-gate 		/* set default flag */
2357c478bd9Sstevel@tonic-gate 		flags |= PAM_ESTABLISH_CRED;
2367c478bd9Sstevel@tonic-gate 		break;
2377c478bd9Sstevel@tonic-gate 	case PAM_ESTABLISH_CRED:
2387c478bd9Sstevel@tonic-gate 	case PAM_REINITIALIZE_CRED:
2397c478bd9Sstevel@tonic-gate 	case PAM_REFRESH_CRED:
2407c478bd9Sstevel@tonic-gate 		break;
2417c478bd9Sstevel@tonic-gate 	case PAM_DELETE_CRED:
2427c478bd9Sstevel@tonic-gate 		return (PAM_SUCCESS);
2437c478bd9Sstevel@tonic-gate 	default:
2447c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_ERR,
2457c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: invalid flags %x", flags);
2467c478bd9Sstevel@tonic-gate 		return (PAM_SYSTEM_ERR);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	/*
2507c478bd9Sstevel@tonic-gate 	 * if auditing on and process audit state not set,
2517c478bd9Sstevel@tonic-gate 	 * setup audit context for process.
2527c478bd9Sstevel@tonic-gate 	 */
2537c478bd9Sstevel@tonic-gate 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
2547c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_ERR,
2557c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: cannot create start audit session %m");
2567c478bd9Sstevel@tonic-gate 		return (PAM_SYSTEM_ERR);
2577c478bd9Sstevel@tonic-gate 	}
2587c478bd9Sstevel@tonic-gate 	adt_get_auid(ah, &auid);
2597c478bd9Sstevel@tonic-gate 	if (debug) {
2607c478bd9Sstevel@tonic-gate 		int	auditstate;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 		if (auditon(A_GETCOND, (caddr_t)&auditstate,
2637c478bd9Sstevel@tonic-gate 		    sizeof (auditstate)) != 0) {
2647c478bd9Sstevel@tonic-gate 			auditstate = AUC_DISABLED;
2657c478bd9Sstevel@tonic-gate 		}
2667c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_DEBUG,
2677c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: state = %d, auid = %d", auditstate,
2687c478bd9Sstevel@tonic-gate 		    auid);
2697c478bd9Sstevel@tonic-gate 	}
270f3e0b6b1Sgww 	if (getpwnam_r(user, &pwd, pwbuf, sizeof (pwbuf)) == NULL) {
2717c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_ERR,
2727c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: cannot get passwd entry for user = %s",
2737c478bd9Sstevel@tonic-gate 		    user);
2747c478bd9Sstevel@tonic-gate 		ret = PAM_USER_UNKNOWN;
2757c478bd9Sstevel@tonic-gate 		goto adt_done;
2767c478bd9Sstevel@tonic-gate 	}
2777c478bd9Sstevel@tonic-gate 
278550493b6Sgww 	if ((auid == AU_NOAUDITID) &&
279550493b6Sgww 	    (flags & PAM_ESTABLISH_CRED)) {
280bf430c99Sgww 		struct passwd	apwd;
281bf430c99Sgww 		char	apwbuf[NSS_BUFLEN_PASSWD];
2827c478bd9Sstevel@tonic-gate 
283ad84d946SJoep Vesseur 		errno = 0;
2847c478bd9Sstevel@tonic-gate 		if ((rhost == NULL || *rhost == '\0')) {
2857c478bd9Sstevel@tonic-gate 			if (adt_load_ttyname(tty, &termid) != 0) {
28691b2cbb3Sgww 				if (errno == ENETDOWN) {
28791b2cbb3Sgww 					/*
28891b2cbb3Sgww 					 * tolerate not being able to
28991b2cbb3Sgww 					 * translate local hostname
29091b2cbb3Sgww 					 * to a termid -- it will be
29191b2cbb3Sgww 					 * "loopback".
29291b2cbb3Sgww 					 */
29391b2cbb3Sgww 					syslog(LOG_AUTH | LOG_ERR,
29491b2cbb3Sgww 					    "pam_unix_cred: cannot load "
29591b2cbb3Sgww 					    "ttyname: %m, continuing.");
29691b2cbb3Sgww 					goto adt_setuser;
29791b2cbb3Sgww 				} else if (errno != 0) {
298ad84d946SJoep Vesseur 					syslog(LOG_AUTH | LOG_ERR,
299ad84d946SJoep Vesseur 					    "pam_unix_cred: cannot load "
300ad84d946SJoep Vesseur 					    "ttyname: %m.");
30191b2cbb3Sgww 				} else {
302ad84d946SJoep Vesseur 					syslog(LOG_AUTH | LOG_ERR,
303ad84d946SJoep Vesseur 					    "pam_unix_cred: cannot load "
304ad84d946SJoep Vesseur 					    "ttyname.");
30591b2cbb3Sgww 				}
3067c478bd9Sstevel@tonic-gate 				ret = PAM_SYSTEM_ERR;
3077c478bd9Sstevel@tonic-gate 				goto adt_done;
3087c478bd9Sstevel@tonic-gate 			}
3097c478bd9Sstevel@tonic-gate 		} else {
3107c478bd9Sstevel@tonic-gate 			if (adt_load_hostname(rhost, &termid) != 0) {
31191b2cbb3Sgww 				if (errno != 0) {
312ad84d946SJoep Vesseur 					syslog(LOG_AUTH | LOG_ERR,
313ad84d946SJoep Vesseur 					    "pam_unix_cred: cannot load "
314ad84d946SJoep Vesseur 					    "hostname: %m.");
31591b2cbb3Sgww 				} else {
316ad84d946SJoep Vesseur 					syslog(LOG_AUTH | LOG_ERR,
317ad84d946SJoep Vesseur 					    "pam_unix_cred: cannot load "
318ad84d946SJoep Vesseur 					    "hostname.");
31991b2cbb3Sgww 				}
3207c478bd9Sstevel@tonic-gate 				ret = PAM_SYSTEM_ERR;
3217c478bd9Sstevel@tonic-gate 				goto adt_done;
3227c478bd9Sstevel@tonic-gate 			}
3237c478bd9Sstevel@tonic-gate 		}
32491b2cbb3Sgww adt_setuser:
325bf430c99Sgww 		if ((auser != NULL) && (*auser != '\0') &&
326bf430c99Sgww 		    (getpwnam_r(auser, &apwd, apwbuf,
327bf430c99Sgww 		    sizeof (apwbuf)) != NULL)) {
3287c478bd9Sstevel@tonic-gate 			/*
3297c478bd9Sstevel@tonic-gate 			 * set up the initial audit for user coming
3307c478bd9Sstevel@tonic-gate 			 * from another user
3317c478bd9Sstevel@tonic-gate 			 */
332bf430c99Sgww 			if (adt_set_user(ah, apwd.pw_uid, apwd.pw_gid,
333bf430c99Sgww 			    apwd.pw_uid, apwd.pw_gid, termid, ADT_NEW) != 0) {
3347c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
335bf430c99Sgww 				    "pam_unix_cred: cannot set auser audit "
3367c478bd9Sstevel@tonic-gate 				    "%m");
3377c478bd9Sstevel@tonic-gate 				ret = PAM_SYSTEM_ERR;
3387c478bd9Sstevel@tonic-gate 				goto adt_done;
3397c478bd9Sstevel@tonic-gate 			}
3407c478bd9Sstevel@tonic-gate 			if (adt_set_user(ah, pwd.pw_uid, pwd.pw_gid,
3417c478bd9Sstevel@tonic-gate 			    pwd.pw_uid, pwd.pw_gid, NULL,
3427c478bd9Sstevel@tonic-gate 			    ADT_UPDATE) != 0) {
3437c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
3447c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: cannot merge user audit "
3457c478bd9Sstevel@tonic-gate 				    "%m");
3467c478bd9Sstevel@tonic-gate 				ret = PAM_SYSTEM_ERR;
3477c478bd9Sstevel@tonic-gate 				goto adt_done;
3487c478bd9Sstevel@tonic-gate 			}
3497c478bd9Sstevel@tonic-gate 			if (debug) {
3507c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_DEBUG,
3517c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: new audit set for %d:%d",
352bf430c99Sgww 				    apwd.pw_uid, pwd.pw_uid);
3537c478bd9Sstevel@tonic-gate 			}
3547c478bd9Sstevel@tonic-gate 		} else {
3557c478bd9Sstevel@tonic-gate 			/*
356bf430c99Sgww 			 * No authenticated user or authenticated user is
357bf430c99Sgww 			 * not a local user, no remote attribution, set
358bf430c99Sgww 			 * up the initial audit as for direct user login
3597c478bd9Sstevel@tonic-gate 			 */
3607c478bd9Sstevel@tonic-gate 			if (adt_set_user(ah, pwd.pw_uid, pwd.pw_gid,
3617c478bd9Sstevel@tonic-gate 			    pwd.pw_uid, pwd.pw_gid, termid, ADT_NEW) != 0) {
3627c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
3637c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: cannot set user audit %m");
3647c478bd9Sstevel@tonic-gate 				ret = PAM_SYSTEM_ERR;
3657c478bd9Sstevel@tonic-gate 				goto adt_done;
3667c478bd9Sstevel@tonic-gate 			}
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 		if (adt_set_proc(ah) != 0) {
3697c478bd9Sstevel@tonic-gate 			syslog(LOG_AUTH | LOG_ERR,
3707c478bd9Sstevel@tonic-gate 			    "pam_unix_cred: cannot set process audit %m");
3717c478bd9Sstevel@tonic-gate 			ret = PAM_CRED_ERR;
3727c478bd9Sstevel@tonic-gate 			goto adt_done;
3737c478bd9Sstevel@tonic-gate 		}
3747c478bd9Sstevel@tonic-gate 		if (debug) {
3757c478bd9Sstevel@tonic-gate 			syslog(LOG_AUTH | LOG_DEBUG,
3767c478bd9Sstevel@tonic-gate 			    "pam_unix_cred: new audit set for %d",
3777c478bd9Sstevel@tonic-gate 			    pwd.pw_uid);
3787c478bd9Sstevel@tonic-gate 		}
379550493b6Sgww 	} else if ((auid != AU_NOAUDITID) &&
380550493b6Sgww 	    (flags & PAM_REINITIALIZE_CRED)) {
3817c478bd9Sstevel@tonic-gate 		if (adt_set_user(ah, pwd.pw_uid, pwd.pw_gid, pwd.pw_uid,
3827c478bd9Sstevel@tonic-gate 		    pwd.pw_gid, NULL, ADT_UPDATE) != 0) {
3837c478bd9Sstevel@tonic-gate 			syslog(LOG_AUTH | LOG_ERR,
3847c478bd9Sstevel@tonic-gate 			    "pam_unix_cred: cannot set user audit %m");
3857c478bd9Sstevel@tonic-gate 			ret = PAM_SYSTEM_ERR;
3867c478bd9Sstevel@tonic-gate 			goto adt_done;
3877c478bd9Sstevel@tonic-gate 		}
3887c478bd9Sstevel@tonic-gate 		if (adt_set_proc(ah) != 0) {
3897c478bd9Sstevel@tonic-gate 			syslog(LOG_AUTH | LOG_ERR,
3907c478bd9Sstevel@tonic-gate 			    "pam_unix_cred: cannot set process audit %m");
3917c478bd9Sstevel@tonic-gate 			ret = PAM_CRED_ERR;
3927c478bd9Sstevel@tonic-gate 			goto adt_done;
3937c478bd9Sstevel@tonic-gate 		}
3947c478bd9Sstevel@tonic-gate 		if (debug) {
3957c478bd9Sstevel@tonic-gate 			syslog(LOG_AUTH | LOG_DEBUG,
3967c478bd9Sstevel@tonic-gate 			    "pam_unix_cred: audit merged for %d:%d",
3977c478bd9Sstevel@tonic-gate 			    auid, pwd.pw_uid);
3987c478bd9Sstevel@tonic-gate 		}
3997c478bd9Sstevel@tonic-gate 	} else if (debug) {
4007c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_DEBUG,
4017c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: audit already set for %d", auid);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate adt_done:
4047c478bd9Sstevel@tonic-gate 	if (termid != NULL)
4057c478bd9Sstevel@tonic-gate 		free(termid);
4067c478bd9Sstevel@tonic-gate 	if (adt_end_session(ah) != 0) {
4077c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_ERR,
4087c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: unable to end audit session");
4097c478bd9Sstevel@tonic-gate 	}
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	if (ret != PAM_SUCCESS)
4127c478bd9Sstevel@tonic-gate 		return (ret);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	/* Initialize the user's project */
4157c478bd9Sstevel@tonic-gate 	(void) pam_get_item(pamh, PAM_RESOURCE, (void **)&kvs);
4167c478bd9Sstevel@tonic-gate 	if (kvs != NULL) {
4177c478bd9Sstevel@tonic-gate 		char *tmp, *lasts, *tok;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 		kvs = tmp = strdup(kvs);
4207c478bd9Sstevel@tonic-gate 		if (kvs == NULL)
4217c478bd9Sstevel@tonic-gate 			return (PAM_BUF_ERR);
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 		while ((tok = strtok_r(tmp, ";", &lasts)) != NULL) {
4247c478bd9Sstevel@tonic-gate 			if (strncmp(tok, PROJECT, PROJSZ) == 0) {
4257c478bd9Sstevel@tonic-gate 				projname = tok + PROJSZ;
4267c478bd9Sstevel@tonic-gate 				break;
4277c478bd9Sstevel@tonic-gate 			}
4287c478bd9Sstevel@tonic-gate 			tmp = NULL;
4297c478bd9Sstevel@tonic-gate 		}
4307c478bd9Sstevel@tonic-gate 	} else {
4317c478bd9Sstevel@tonic-gate 		projname = NULL;
4327c478bd9Sstevel@tonic-gate 	}
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	if (projname == NULL || *projname == '\0') {
4357c478bd9Sstevel@tonic-gate 		pproj = getdefaultproj(user, &proj, (void *)&buf,
4367c478bd9Sstevel@tonic-gate 		    PROJECT_BUFSZ);
4377c478bd9Sstevel@tonic-gate 	} else {
4387c478bd9Sstevel@tonic-gate 		pproj = getprojbyname(projname, &proj, (void *)&buf,
4397c478bd9Sstevel@tonic-gate 		    PROJECT_BUFSZ);
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate 	/* projname points into kvs, so this is the first opportunity to free */
4427c478bd9Sstevel@tonic-gate 	if (kvs != NULL)
4437c478bd9Sstevel@tonic-gate 		free(kvs);
4447c478bd9Sstevel@tonic-gate 	if (pproj == NULL) {
4457c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_ERR,
4467c478bd9Sstevel@tonic-gate 		    "pam_unix_cred: no default project for user %s", user);
4477c478bd9Sstevel@tonic-gate 		if (!nowarn) {
4487c478bd9Sstevel@tonic-gate 			(void) snprintf(messages[0], sizeof (messages[0]),
4497c478bd9Sstevel@tonic-gate 			    dgettext(TEXT_DOMAIN, "No default project!"));
4507c478bd9Sstevel@tonic-gate 			(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
4517c478bd9Sstevel@tonic-gate 			    1, messages, NULL);
4527c478bd9Sstevel@tonic-gate 		}
4537c478bd9Sstevel@tonic-gate 		return (PAM_SYSTEM_ERR);
4547c478bd9Sstevel@tonic-gate 	}
4557c478bd9Sstevel@tonic-gate 	if ((error = setproject(proj.pj_name, user, TASK_NORMAL)) != 0) {
4567c478bd9Sstevel@tonic-gate 		kva_t *kv_array;
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 		switch (error) {
4597c478bd9Sstevel@tonic-gate 		case SETPROJ_ERR_TASK:
4607c478bd9Sstevel@tonic-gate 			if (errno == EAGAIN) {
4617c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
4627c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: project \"%s\" resource "
4637c478bd9Sstevel@tonic-gate 				    "control limit has been reached",
4647c478bd9Sstevel@tonic-gate 				    proj.pj_name);
4657c478bd9Sstevel@tonic-gate 				(void) snprintf(messages[0],
4667c478bd9Sstevel@tonic-gate 				    sizeof (messages[0]), dgettext(
4677c478bd9Sstevel@tonic-gate 				    TEXT_DOMAIN,
4687c478bd9Sstevel@tonic-gate 				    "Resource control limit has been "
4697c478bd9Sstevel@tonic-gate 				    "reached"));
4707c478bd9Sstevel@tonic-gate 			} else {
4717c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
4727c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: user %s could not join "
4737c478bd9Sstevel@tonic-gate 				    "project \"%s\": %m", user, proj.pj_name);
4747c478bd9Sstevel@tonic-gate 				(void) snprintf(messages[0],
4757c478bd9Sstevel@tonic-gate 				    sizeof (messages[0]), dgettext(
4767c478bd9Sstevel@tonic-gate 				    TEXT_DOMAIN,
4777c478bd9Sstevel@tonic-gate 				    "Could not join default project"));
4787c478bd9Sstevel@tonic-gate 			}
4797c478bd9Sstevel@tonic-gate 			if (!nowarn)
4807c478bd9Sstevel@tonic-gate 				(void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1,
4817c478bd9Sstevel@tonic-gate 				    messages, NULL);
4827c478bd9Sstevel@tonic-gate 			break;
4837c478bd9Sstevel@tonic-gate 		case SETPROJ_ERR_POOL:
4847c478bd9Sstevel@tonic-gate 			(void) snprintf(messages[0], sizeof (messages[0]),
4857c478bd9Sstevel@tonic-gate 			    dgettext(TEXT_DOMAIN,
4867c478bd9Sstevel@tonic-gate 			    "Could not bind to resource pool"));
4877c478bd9Sstevel@tonic-gate 			switch (errno) {
4887c478bd9Sstevel@tonic-gate 			case EACCES:
4897c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
4907c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: project \"%s\" could not "
4917c478bd9Sstevel@tonic-gate 				    "bind to resource pool: No resource pool "
4927c478bd9Sstevel@tonic-gate 				    "accepting default bindings exists",
4937c478bd9Sstevel@tonic-gate 				    proj.pj_name);
4947c478bd9Sstevel@tonic-gate 				(void) snprintf(messages[1],
4957c478bd9Sstevel@tonic-gate 				    sizeof (messages[1]),
4967c478bd9Sstevel@tonic-gate 				    dgettext(TEXT_DOMAIN,
4977c478bd9Sstevel@tonic-gate 				    "No resource pool accepting "
4987c478bd9Sstevel@tonic-gate 				    "default bindings exists"));
4997c478bd9Sstevel@tonic-gate 				break;
5007c478bd9Sstevel@tonic-gate 			case ESRCH:
5017c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
5027c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: project \"%s\" could not "
5037c478bd9Sstevel@tonic-gate 				    "bind to resource pool: The resource pool "
5047c478bd9Sstevel@tonic-gate 				    "is unknown", proj.pj_name);
5057c478bd9Sstevel@tonic-gate 				(void) snprintf(messages[1],
5067c478bd9Sstevel@tonic-gate 				    sizeof (messages[1]),
5077c478bd9Sstevel@tonic-gate 				    dgettext(TEXT_DOMAIN,
5087c478bd9Sstevel@tonic-gate 				    "The specified resource pool "
5097c478bd9Sstevel@tonic-gate 				    "is unknown"));
5107c478bd9Sstevel@tonic-gate 				break;
5117c478bd9Sstevel@tonic-gate 			default:
5127c478bd9Sstevel@tonic-gate 				(void) snprintf(messages[1],
5137c478bd9Sstevel@tonic-gate 				    sizeof (messages[1]),
5147c478bd9Sstevel@tonic-gate 				    dgettext(TEXT_DOMAIN,
5157c478bd9Sstevel@tonic-gate 				    "Failure during pool binding"));
5167c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
5177c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: project \"%s\" could not "
5187c478bd9Sstevel@tonic-gate 				    "bind to resource pool: %m", proj.pj_name);
5197c478bd9Sstevel@tonic-gate 			}
5207c478bd9Sstevel@tonic-gate 			if (!nowarn)
5217c478bd9Sstevel@tonic-gate 				(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
5227c478bd9Sstevel@tonic-gate 				    2, messages, NULL);
5237c478bd9Sstevel@tonic-gate 			break;
5247c478bd9Sstevel@tonic-gate 		default:
5257c478bd9Sstevel@tonic-gate 			/*
5267c478bd9Sstevel@tonic-gate 			 * Resource control assignment failed.  Unlike
527*bbf21555SRichard Lowe 			 * newtask(1), we treat this as an error.
5287c478bd9Sstevel@tonic-gate 			 */
5297c478bd9Sstevel@tonic-gate 			if (error < 0) {
5307c478bd9Sstevel@tonic-gate 				/*
5317c478bd9Sstevel@tonic-gate 				 * This isn't supposed to happen, but in
5327c478bd9Sstevel@tonic-gate 				 * case it does, this error message
5337c478bd9Sstevel@tonic-gate 				 * doesn't use error as an index, like
5347c478bd9Sstevel@tonic-gate 				 * the others might.
5357c478bd9Sstevel@tonic-gate 				 */
5367c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
5377c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: unkwown error joining "
5387c478bd9Sstevel@tonic-gate 				    "project \"%s\" (%d)", proj.pj_name, error);
5397c478bd9Sstevel@tonic-gate 				(void) snprintf(messages[0],
5407c478bd9Sstevel@tonic-gate 				    sizeof (messages[0]),
5417c478bd9Sstevel@tonic-gate 				    dgettext(TEXT_DOMAIN,
5427c478bd9Sstevel@tonic-gate 				    "unkwown error joining project \"%s\""
5437c478bd9Sstevel@tonic-gate 				    " (%d)"), proj.pj_name, error);
5447c478bd9Sstevel@tonic-gate 			} else if ((kv_array = _str2kva(proj.pj_attr, KV_ASSIGN,
5457c478bd9Sstevel@tonic-gate 			    KV_DELIMITER)) != NULL) {
5467c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
5477c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: %s resource control "
5487c478bd9Sstevel@tonic-gate 				    "assignment failed for project \"%s\"",
5497c478bd9Sstevel@tonic-gate 				    kv_array->data[error - 1].key,
5507c478bd9Sstevel@tonic-gate 				    proj.pj_name);
5517c478bd9Sstevel@tonic-gate 				(void) snprintf(messages[0],
5527c478bd9Sstevel@tonic-gate 				    sizeof (messages[0]),
5537c478bd9Sstevel@tonic-gate 				    dgettext(TEXT_DOMAIN,
5547c478bd9Sstevel@tonic-gate 				    "%s resource control assignment failed for "
5557c478bd9Sstevel@tonic-gate 				    "project \"%s\""),
5567c478bd9Sstevel@tonic-gate 				    kv_array->data[error - 1].key,
5577c478bd9Sstevel@tonic-gate 				    proj.pj_name);
5587c478bd9Sstevel@tonic-gate 				_kva_free(kv_array);
5597c478bd9Sstevel@tonic-gate 			} else {
5607c478bd9Sstevel@tonic-gate 				syslog(LOG_AUTH | LOG_ERR,
5617c478bd9Sstevel@tonic-gate 				    "pam_unix_cred: resource control "
5627c478bd9Sstevel@tonic-gate 				    "assignment failed for project \"%s\""
5637c478bd9Sstevel@tonic-gate 				    "attribute %d", proj.pj_name, error);
5647c478bd9Sstevel@tonic-gate 				(void) snprintf(messages[0],
5657c478bd9Sstevel@tonic-gate 				    sizeof (messages[0]),
5667c478bd9Sstevel@tonic-gate 				    dgettext(TEXT_DOMAIN,
5677c478bd9Sstevel@tonic-gate 				    "resource control assignment failed for "
5687c478bd9Sstevel@tonic-gate 				    "project \"%s\" attribute %d"),
5697c478bd9Sstevel@tonic-gate 				    proj.pj_name, error);
5707c478bd9Sstevel@tonic-gate 			}
5717c478bd9Sstevel@tonic-gate 			if (!nowarn)
5727c478bd9Sstevel@tonic-gate 				(void) __pam_display_msg(pamh, PAM_ERROR_MSG,
5737c478bd9Sstevel@tonic-gate 				    1, messages, NULL);
5747c478bd9Sstevel@tonic-gate 		}
5757c478bd9Sstevel@tonic-gate 		return (PAM_SYSTEM_ERR);
5767c478bd9Sstevel@tonic-gate 	}
5777c478bd9Sstevel@tonic-gate 
57897682a82Scasper 	tset = def = lim = NULL;
579134a1f4eSCasper H.S. Dik 	deflim.def = deflim.lim = NULL;
5807c478bd9Sstevel@tonic-gate 
581134a1f4eSCasper H.S. Dik 	(void) _enum_attrs(user, finddeflim, NULL, &deflim);
582134a1f4eSCasper H.S. Dik 
583134a1f4eSCasper H.S. Dik 	if (getset(deflim.lim, &lim) != 0 || getset(deflim.def, &def) != 0) {
5847c478bd9Sstevel@tonic-gate 		ret = PAM_SYSTEM_ERR;
5857c478bd9Sstevel@tonic-gate 		goto out;
5867c478bd9Sstevel@tonic-gate 	}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	if (def == NULL) {
589134a1f4eSCasper H.S. Dik 		def = priv_allocset();
590134a1f4eSCasper H.S. Dik 		if (def == NULL) {
591134a1f4eSCasper H.S. Dik 			ret = PAM_SYSTEM_ERR;
592134a1f4eSCasper H.S. Dik 			goto out;
593134a1f4eSCasper H.S. Dik 		}
594134a1f4eSCasper H.S. Dik 		priv_basicset(def);
59595dd9389SNils Goroll 		errno = 0;
59695dd9389SNils Goroll 		if ((pathconf("/", _PC_CHOWN_RESTRICTED) == -1) && (errno == 0))
5977c478bd9Sstevel@tonic-gate 			(void) priv_addset(def, PRIV_FILE_CHOWN_SELF);
5987c478bd9Sstevel@tonic-gate 	}
59997682a82Scasper 	/*
60097682a82Scasper 	 * Silently limit the privileges to those actually available
60197682a82Scasper 	 * in the current zone.
60297682a82Scasper 	 */
60397682a82Scasper 	tset = priv_allocset();
60497682a82Scasper 	if (tset == NULL) {
60597682a82Scasper 		ret = PAM_SYSTEM_ERR;
60697682a82Scasper 		goto out;
60797682a82Scasper 	}
60897682a82Scasper 	if (getppriv(PRIV_PERMITTED, tset) != 0) {
60997682a82Scasper 		ret = PAM_SYSTEM_ERR;
61097682a82Scasper 		goto out;
61197682a82Scasper 	}
61297682a82Scasper 	if (!priv_issubset(def, tset))
61397682a82Scasper 		priv_intersect(tset, def);
6147c478bd9Sstevel@tonic-gate 	/*
6157c478bd9Sstevel@tonic-gate 	 * We set privilege awareness here so that I gets copied to
6167c478bd9Sstevel@tonic-gate 	 * P & E when the final setuid(uid) happens.
6177c478bd9Sstevel@tonic-gate 	 */
6187c478bd9Sstevel@tonic-gate 	(void) setpflags(PRIV_AWARE, 1);
6197c478bd9Sstevel@tonic-gate 	if (setppriv(PRIV_SET, PRIV_INHERITABLE, def) != 0) {
6207c478bd9Sstevel@tonic-gate 		syslog(LOG_AUTH | LOG_ERR,
62195dd9389SNils Goroll 		    "pam_setcred: setppriv(defaultpriv) failed: %m");
6227c478bd9Sstevel@tonic-gate 		ret = PAM_CRED_ERR;
6237c478bd9Sstevel@tonic-gate 	}
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 	if (lim != NULL) {
62697682a82Scasper 		/*
62797682a82Scasper 		 * Silently limit the privileges to the limit set available.
62897682a82Scasper 		 */
62997682a82Scasper 		if (getppriv(PRIV_LIMIT, tset) != 0) {
63097682a82Scasper 			ret = PAM_SYSTEM_ERR;
63197682a82Scasper 			goto out;
63297682a82Scasper 		}
63397682a82Scasper 		if (!priv_issubset(lim, tset))
63497682a82Scasper 			priv_intersect(tset, lim);
635982b4ad2SCasper H.S. Dik 		if (setppriv(PRIV_SET, PRIV_LIMIT, lim) != 0) {
6367c478bd9Sstevel@tonic-gate 			syslog(LOG_AUTH | LOG_ERR,
63795dd9389SNils Goroll 			    "pam_setcred: setppriv(limitpriv) failed: %m");
6387c478bd9Sstevel@tonic-gate 			ret = PAM_CRED_ERR;
639982b4ad2SCasper H.S. Dik 			goto out;
6407c478bd9Sstevel@tonic-gate 		}
641982b4ad2SCasper H.S. Dik 		/*
642982b4ad2SCasper H.S. Dik 		 * In order not to surprise certain applications, we
643982b4ad2SCasper H.S. Dik 		 * need to get rid of privilege awareness and thus we must
644982b4ad2SCasper H.S. Dik 		 * set this flag which will cause a reset on set*uid().
645982b4ad2SCasper H.S. Dik 		 */
646982b4ad2SCasper H.S. Dik 		(void) setpflags(PRIV_AWARE_RESET, 1);
6477c478bd9Sstevel@tonic-gate 	}
648982b4ad2SCasper H.S. Dik 	/*
649982b4ad2SCasper H.S. Dik 	 * This may fail but we do not care as this will be reset later
650982b4ad2SCasper H.S. Dik 	 * when the uids are set to their final values.
651982b4ad2SCasper H.S. Dik 	 */
6527c478bd9Sstevel@tonic-gate 	(void) setpflags(PRIV_AWARE, 0);
653134a1f4eSCasper H.S. Dik 	/*
654134a1f4eSCasper H.S. Dik 	 * Remove PRIV_PFEXEC; stop running as if we are under a profile
655134a1f4eSCasper H.S. Dik 	 * shell.  A user with a profile shell will set PRIV_PFEXEC.
656134a1f4eSCasper H.S. Dik 	 */
657134a1f4eSCasper H.S. Dik 	(void) setpflags(PRIV_PFEXEC, 0);
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate out:
660134a1f4eSCasper H.S. Dik 	free(deflim.lim);
661134a1f4eSCasper H.S. Dik 	free(deflim.def);
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	if (lim != NULL)
6647c478bd9Sstevel@tonic-gate 		priv_freeset(lim);
6657c478bd9Sstevel@tonic-gate 	if (def != NULL)
6667c478bd9Sstevel@tonic-gate 		priv_freeset(def);
66797682a82Scasper 	if (tset != NULL)
66897682a82Scasper 		priv_freeset(tset);
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	return (ret);
6717c478bd9Sstevel@tonic-gate }
672