xref: /titanic_54/usr/src/lib/passwdutil/nss_attr.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <errno.h>
31*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
32*7c478bd9Sstevel@tonic-gate #include <pwd.h>
33*7c478bd9Sstevel@tonic-gate #include <shadow.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <unistd.h>
37*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include "passwdutil.h"
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate /* from files_attr.c */
42*7c478bd9Sstevel@tonic-gate struct passwd *private_getpwnam_r(const char *name, struct passwd *result,
43*7c478bd9Sstevel@tonic-gate     char *buffer, int buflen);
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate int nss_getattr(char *name, attrlist *item, pwu_repository_t *rep);
46*7c478bd9Sstevel@tonic-gate int nss_getpwnam(char *name, attrlist *items, pwu_repository_t *rep,
47*7c478bd9Sstevel@tonic-gate     void **buf);
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate /*
50*7c478bd9Sstevel@tonic-gate  * nss function pointer table, used by passwdutil_init to initialize
51*7c478bd9Sstevel@tonic-gate  * the global Repository-OPerations table "rops"
52*7c478bd9Sstevel@tonic-gate  */
53*7c478bd9Sstevel@tonic-gate struct repops nss_repops = {
54*7c478bd9Sstevel@tonic-gate 	NULL,		/* checkhistory */
55*7c478bd9Sstevel@tonic-gate 	nss_getattr,
56*7c478bd9Sstevel@tonic-gate 	nss_getpwnam,
57*7c478bd9Sstevel@tonic-gate 	NULL,		/* update */
58*7c478bd9Sstevel@tonic-gate 	NULL,		/* putpwnam */
59*7c478bd9Sstevel@tonic-gate 	NULL,		/* user_to_authenticate */
60*7c478bd9Sstevel@tonic-gate 	NULL,		/* lock */
61*7c478bd9Sstevel@tonic-gate 	NULL		/* unlock */
62*7c478bd9Sstevel@tonic-gate };
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /*
65*7c478bd9Sstevel@tonic-gate  * this structure defines the buffer used to keep state between
66*7c478bd9Sstevel@tonic-gate  * get/update/put calls
67*7c478bd9Sstevel@tonic-gate  */
68*7c478bd9Sstevel@tonic-gate struct pwbuf {
69*7c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
70*7c478bd9Sstevel@tonic-gate 	char   *pwd_scratch;
71*7c478bd9Sstevel@tonic-gate 	struct spwd *spwd;
72*7c478bd9Sstevel@tonic-gate 	char   *spwd_scratch;
73*7c478bd9Sstevel@tonic-gate 	char   *rep_name;
74*7c478bd9Sstevel@tonic-gate };
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /*
77*7c478bd9Sstevel@tonic-gate  * We should use sysconf, but there is no sysconf name for SHADOW
78*7c478bd9Sstevel@tonic-gate  * so we use these from nss_dbdefs
79*7c478bd9Sstevel@tonic-gate  */
80*7c478bd9Sstevel@tonic-gate #define	PWD_SCRATCH_SIZE NSS_LINELEN_PASSWD
81*7c478bd9Sstevel@tonic-gate #define	SPW_SCRATCH_SIZE NSS_LINELEN_SHADOW
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate /*
85*7c478bd9Sstevel@tonic-gate  * nss_getpwnam(name, items, rep, buf)
86*7c478bd9Sstevel@tonic-gate  *
87*7c478bd9Sstevel@tonic-gate  */
88*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
89*7c478bd9Sstevel@tonic-gate int
90*7c478bd9Sstevel@tonic-gate nss_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, void **buf)
91*7c478bd9Sstevel@tonic-gate {
92*7c478bd9Sstevel@tonic-gate 	attrlist *p;
93*7c478bd9Sstevel@tonic-gate 	struct pwbuf *pwbuf;
94*7c478bd9Sstevel@tonic-gate 	int repositories = REP_ERANGE;	/* changed if ATTR_REP_NAME is set */
95*7c478bd9Sstevel@tonic-gate 	int err = PWU_SUCCESS;
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	*buf = calloc(1, sizeof (struct pwbuf));
98*7c478bd9Sstevel@tonic-gate 	pwbuf = (struct pwbuf *)*buf;
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	/*
101*7c478bd9Sstevel@tonic-gate 	 * determine which password structure (/etc/passwd or /etc/shadow)
102*7c478bd9Sstevel@tonic-gate 	 * we need for the items we need to update
103*7c478bd9Sstevel@tonic-gate 	 */
104*7c478bd9Sstevel@tonic-gate 	for (p = items; p != NULL; p = p->next) {
105*7c478bd9Sstevel@tonic-gate 		switch (p->type) {
106*7c478bd9Sstevel@tonic-gate 		case ATTR_NAME:
107*7c478bd9Sstevel@tonic-gate 		case ATTR_UID:
108*7c478bd9Sstevel@tonic-gate 		case ATTR_GID:
109*7c478bd9Sstevel@tonic-gate 		case ATTR_AGE:
110*7c478bd9Sstevel@tonic-gate 		case ATTR_COMMENT:
111*7c478bd9Sstevel@tonic-gate 		case ATTR_GECOS:
112*7c478bd9Sstevel@tonic-gate 		case ATTR_HOMEDIR:
113*7c478bd9Sstevel@tonic-gate 		case ATTR_SHELL:
114*7c478bd9Sstevel@tonic-gate 			if (pwbuf->pwd == NULL)
115*7c478bd9Sstevel@tonic-gate 				pwbuf->pwd = (struct passwd *)
116*7c478bd9Sstevel@tonic-gate 				    malloc(sizeof (struct passwd));
117*7c478bd9Sstevel@tonic-gate 			if (pwbuf->pwd == NULL) {
118*7c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
119*7c478bd9Sstevel@tonic-gate 				if (pwbuf->spwd)
120*7c478bd9Sstevel@tonic-gate 					free(pwbuf->spwd);
121*7c478bd9Sstevel@tonic-gate 				return (PWU_NOMEM);
122*7c478bd9Sstevel@tonic-gate 			}
123*7c478bd9Sstevel@tonic-gate 			break;
124*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
125*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD_SERVER_POLICY:
126*7c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
127*7c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
128*7c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
129*7c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
130*7c478bd9Sstevel@tonic-gate 		case ATTR_INACT:
131*7c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE:
132*7c478bd9Sstevel@tonic-gate 		case ATTR_FLAG:
133*7c478bd9Sstevel@tonic-gate 		case ATTR_LOCK_ACCOUNT:
134*7c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE_PASSWORD:
135*7c478bd9Sstevel@tonic-gate 		case ATTR_FAILED_LOGINS:
136*7c478bd9Sstevel@tonic-gate 			if (pwbuf->spwd == NULL)
137*7c478bd9Sstevel@tonic-gate 				pwbuf->spwd = (struct spwd *)
138*7c478bd9Sstevel@tonic-gate 				    malloc(sizeof (struct spwd));
139*7c478bd9Sstevel@tonic-gate 			if (pwbuf->spwd == NULL) {
140*7c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
141*7c478bd9Sstevel@tonic-gate 				if (pwbuf->pwd)
142*7c478bd9Sstevel@tonic-gate 					free(pwbuf->pwd);
143*7c478bd9Sstevel@tonic-gate 				return (PWU_NOMEM);
144*7c478bd9Sstevel@tonic-gate 			}
145*7c478bd9Sstevel@tonic-gate 			break;
146*7c478bd9Sstevel@tonic-gate 		case ATTR_REP_NAME:
147*7c478bd9Sstevel@tonic-gate 			/* get the compat names (REP_COMPAT_*) */
148*7c478bd9Sstevel@tonic-gate 			repositories = get_ns(rep, PWU_READ);
149*7c478bd9Sstevel@tonic-gate 			break;
150*7c478bd9Sstevel@tonic-gate 		default:
151*7c478bd9Sstevel@tonic-gate 			/*
152*7c478bd9Sstevel@tonic-gate 			 * Some other repository might have different values
153*7c478bd9Sstevel@tonic-gate 			 * so we ignore those.
154*7c478bd9Sstevel@tonic-gate 			 */
155*7c478bd9Sstevel@tonic-gate 			break;
156*7c478bd9Sstevel@tonic-gate 		}
157*7c478bd9Sstevel@tonic-gate 	}
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	if (pwbuf->pwd) {
160*7c478bd9Sstevel@tonic-gate 		if ((pwbuf->pwd_scratch = malloc(PWD_SCRATCH_SIZE)) == NULL) {
161*7c478bd9Sstevel@tonic-gate 			err = PWU_NOMEM;
162*7c478bd9Sstevel@tonic-gate 			goto error;
163*7c478bd9Sstevel@tonic-gate 		}
164*7c478bd9Sstevel@tonic-gate 		if (getpwnam_r(name, pwbuf->pwd, pwbuf->pwd_scratch,
165*7c478bd9Sstevel@tonic-gate 		    PWD_SCRATCH_SIZE) == NULL) {
166*7c478bd9Sstevel@tonic-gate 			err = PWU_NOT_FOUND;
167*7c478bd9Sstevel@tonic-gate 			goto error;
168*7c478bd9Sstevel@tonic-gate 		}
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	if (pwbuf->spwd) {
172*7c478bd9Sstevel@tonic-gate 		if ((pwbuf->spwd_scratch = malloc(SPW_SCRATCH_SIZE)) == NULL) {
173*7c478bd9Sstevel@tonic-gate 			err = PWU_NOMEM;
174*7c478bd9Sstevel@tonic-gate 			goto error;
175*7c478bd9Sstevel@tonic-gate 		}
176*7c478bd9Sstevel@tonic-gate 		if (getspnam_r(name, pwbuf->spwd, pwbuf->spwd_scratch,
177*7c478bd9Sstevel@tonic-gate 		    SPW_SCRATCH_SIZE) == NULL) {
178*7c478bd9Sstevel@tonic-gate 			err = PWU_NOT_FOUND;
179*7c478bd9Sstevel@tonic-gate 			goto error;
180*7c478bd9Sstevel@tonic-gate 		}
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	/* pwbuf->rep_name tells us where the user in fact comes from */
184*7c478bd9Sstevel@tonic-gate 	if (repositories != REP_ERANGE) {
185*7c478bd9Sstevel@tonic-gate 		struct passwd pwd;
186*7c478bd9Sstevel@tonic-gate 		char pwd_scratch[PWD_SCRATCH_SIZE];
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 		/* can we find the user locally? */
189*7c478bd9Sstevel@tonic-gate 		if (private_getpwnam_r(name, &pwd, pwd_scratch,
190*7c478bd9Sstevel@tonic-gate 		    PWD_SCRATCH_SIZE) != NULL)
191*7c478bd9Sstevel@tonic-gate 			pwbuf->rep_name = "files";
192*7c478bd9Sstevel@tonic-gate 		else if (repositories & REP_COMPAT_NISPLUS)
193*7c478bd9Sstevel@tonic-gate 			pwbuf->rep_name = "nisplus";
194*7c478bd9Sstevel@tonic-gate 		else if (repositories & REP_COMPAT_LDAP)
195*7c478bd9Sstevel@tonic-gate 			pwbuf->rep_name = "ldap";
196*7c478bd9Sstevel@tonic-gate 		else if (repositories & REP_COMPAT_NIS)
197*7c478bd9Sstevel@tonic-gate 			pwbuf->rep_name = "nis";
198*7c478bd9Sstevel@tonic-gate 		else
199*7c478bd9Sstevel@tonic-gate 			pwbuf->rep_name = "nss";
200*7c478bd9Sstevel@tonic-gate 	} else
201*7c478bd9Sstevel@tonic-gate 		pwbuf->rep_name = "nss";
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	return (PWU_SUCCESS);
204*7c478bd9Sstevel@tonic-gate error:
205*7c478bd9Sstevel@tonic-gate 	if (pwbuf->pwd) free(pwbuf->pwd);
206*7c478bd9Sstevel@tonic-gate 	if (pwbuf->pwd_scratch) free(pwbuf->pwd_scratch);
207*7c478bd9Sstevel@tonic-gate 	if (pwbuf->spwd) free(pwbuf->spwd);
208*7c478bd9Sstevel@tonic-gate 	if (pwbuf->spwd_scratch) free(pwbuf->spwd_scratch);
209*7c478bd9Sstevel@tonic-gate 	free(pwbuf);
210*7c478bd9Sstevel@tonic-gate 	*buf = NULL;
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 	return (err);
213*7c478bd9Sstevel@tonic-gate }
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate /*
217*7c478bd9Sstevel@tonic-gate  * nss_getattr(name, items, rep)
218*7c478bd9Sstevel@tonic-gate  *
219*7c478bd9Sstevel@tonic-gate  * Get attributes specified in list 'items'
220*7c478bd9Sstevel@tonic-gate  */
221*7c478bd9Sstevel@tonic-gate int
222*7c478bd9Sstevel@tonic-gate nss_getattr(char *name, attrlist *items, pwu_repository_t *rep)
223*7c478bd9Sstevel@tonic-gate {
224*7c478bd9Sstevel@tonic-gate 	struct pwbuf *pwbuf;
225*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
226*7c478bd9Sstevel@tonic-gate 	struct spwd *spw;
227*7c478bd9Sstevel@tonic-gate 	attrlist *w;
228*7c478bd9Sstevel@tonic-gate 	int res = 0;
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	res = nss_getpwnam(name, items, rep, (void **)&pwbuf);
231*7c478bd9Sstevel@tonic-gate 	if (res != PWU_SUCCESS)
232*7c478bd9Sstevel@tonic-gate 		return (res);
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	pw = pwbuf->pwd;
235*7c478bd9Sstevel@tonic-gate 	spw = pwbuf->spwd;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	for (w = items; res == PWU_SUCCESS && w != NULL; w = w->next) {
238*7c478bd9Sstevel@tonic-gate 		switch (w->type) {
239*7c478bd9Sstevel@tonic-gate 		case ATTR_NAME:
240*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_name)) == NULL)
241*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
242*7c478bd9Sstevel@tonic-gate 			break;
243*7c478bd9Sstevel@tonic-gate 		case ATTR_COMMENT:
244*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_comment)) == NULL)
245*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
246*7c478bd9Sstevel@tonic-gate 			break;
247*7c478bd9Sstevel@tonic-gate 		case ATTR_GECOS:
248*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_gecos)) == NULL)
249*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
250*7c478bd9Sstevel@tonic-gate 			break;
251*7c478bd9Sstevel@tonic-gate 		case ATTR_HOMEDIR:
252*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_dir)) == NULL)
253*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
254*7c478bd9Sstevel@tonic-gate 			break;
255*7c478bd9Sstevel@tonic-gate 		case ATTR_SHELL:
256*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_shell)) == NULL)
257*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
258*7c478bd9Sstevel@tonic-gate 			break;
259*7c478bd9Sstevel@tonic-gate 		/*
260*7c478bd9Sstevel@tonic-gate 		 * Nothing special needs to be done for
261*7c478bd9Sstevel@tonic-gate 		 * server policy
262*7c478bd9Sstevel@tonic-gate 		 */
263*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
264*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD_SERVER_POLICY:
265*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(spw->sp_pwdp)) == NULL)
266*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
267*7c478bd9Sstevel@tonic-gate 			break;
268*7c478bd9Sstevel@tonic-gate 		case ATTR_AGE:
269*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_age)) == NULL)
270*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
271*7c478bd9Sstevel@tonic-gate 			break;
272*7c478bd9Sstevel@tonic-gate 		case ATTR_REP_NAME:
273*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pwbuf->rep_name)) == NULL)
274*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
275*7c478bd9Sstevel@tonic-gate 			break;
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 		/* integer values */
278*7c478bd9Sstevel@tonic-gate 		case ATTR_UID:
279*7c478bd9Sstevel@tonic-gate 			w->data.val_i = pw->pw_uid;
280*7c478bd9Sstevel@tonic-gate 			break;
281*7c478bd9Sstevel@tonic-gate 		case ATTR_GID:
282*7c478bd9Sstevel@tonic-gate 			w->data.val_i = pw->pw_gid;
283*7c478bd9Sstevel@tonic-gate 			break;
284*7c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
285*7c478bd9Sstevel@tonic-gate 			w->data.val_i = spw->sp_lstchg;
286*7c478bd9Sstevel@tonic-gate 			break;
287*7c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
288*7c478bd9Sstevel@tonic-gate 			w->data.val_i = spw->sp_min;
289*7c478bd9Sstevel@tonic-gate 			break;
290*7c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
291*7c478bd9Sstevel@tonic-gate 			w->data.val_i = spw->sp_max;
292*7c478bd9Sstevel@tonic-gate 			break;
293*7c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
294*7c478bd9Sstevel@tonic-gate 			w->data.val_i = spw->sp_warn;
295*7c478bd9Sstevel@tonic-gate 			break;
296*7c478bd9Sstevel@tonic-gate 		case ATTR_INACT:
297*7c478bd9Sstevel@tonic-gate 			w->data.val_i = spw->sp_inact;
298*7c478bd9Sstevel@tonic-gate 			break;
299*7c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE:
300*7c478bd9Sstevel@tonic-gate 			w->data.val_i = spw->sp_expire;
301*7c478bd9Sstevel@tonic-gate 			break;
302*7c478bd9Sstevel@tonic-gate 		case ATTR_FLAG:
303*7c478bd9Sstevel@tonic-gate 			w->data.val_i = spw->sp_flag;
304*7c478bd9Sstevel@tonic-gate 			break;
305*7c478bd9Sstevel@tonic-gate 		case ATTR_FAILED_LOGINS:
306*7c478bd9Sstevel@tonic-gate 			w->data.val_i = spw->sp_flag & FAILCOUNT_MASK;
307*7c478bd9Sstevel@tonic-gate 			break;
308*7c478bd9Sstevel@tonic-gate 		default:
309*7c478bd9Sstevel@tonic-gate 			break;
310*7c478bd9Sstevel@tonic-gate 		}
311*7c478bd9Sstevel@tonic-gate 	}
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	if (pwbuf->pwd) free(pwbuf->pwd);
314*7c478bd9Sstevel@tonic-gate 	if (pwbuf->pwd_scratch) free(pwbuf->pwd_scratch);
315*7c478bd9Sstevel@tonic-gate 	if (pwbuf->spwd) free(pwbuf->spwd);
316*7c478bd9Sstevel@tonic-gate 	if (pwbuf->spwd_scratch) free(pwbuf->spwd_scratch);
317*7c478bd9Sstevel@tonic-gate 	free(pwbuf);
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	return (res);
320*7c478bd9Sstevel@tonic-gate }
321