xref: /titanic_44/usr/src/lib/passwdutil/nis_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 2005 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 <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <errno.h>
31*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
32*7c478bd9Sstevel@tonic-gate #include <string.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
34*7c478bd9Sstevel@tonic-gate #include <pwd.h>
35*7c478bd9Sstevel@tonic-gate #include <unistd.h>
36*7c478bd9Sstevel@tonic-gate #include <syslog.h>
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #include <netdb.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
41*7c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h>
42*7c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
43*7c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #include "passwdutil.h"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate int nis_getattr(char *name, attrlist *item, pwu_repository_t *rep);
48*7c478bd9Sstevel@tonic-gate int nis_getpwnam(char *name, attrlist *items, pwu_repository_t *rep,
49*7c478bd9Sstevel@tonic-gate     void **buf);
50*7c478bd9Sstevel@tonic-gate int nis_update(attrlist *items, pwu_repository_t *rep, void *buf);
51*7c478bd9Sstevel@tonic-gate int nis_putpwnam(char *name, char *oldpw, char *dummy,
52*7c478bd9Sstevel@tonic-gate 	pwu_repository_t *rep, void *buf);
53*7c478bd9Sstevel@tonic-gate int nis_user_to_authenticate(char *user, pwu_repository_t *rep,
54*7c478bd9Sstevel@tonic-gate 	char **auth_user, int *privileged);
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  * nis function pointer table, used by passwdutil_init to initialize
58*7c478bd9Sstevel@tonic-gate  * the global Repository-OPerations table "rops"
59*7c478bd9Sstevel@tonic-gate  */
60*7c478bd9Sstevel@tonic-gate struct repops nis_repops = {
61*7c478bd9Sstevel@tonic-gate 	NULL,	/* checkhistory */
62*7c478bd9Sstevel@tonic-gate 	nis_getattr,
63*7c478bd9Sstevel@tonic-gate 	nis_getpwnam,
64*7c478bd9Sstevel@tonic-gate 	nis_update,
65*7c478bd9Sstevel@tonic-gate 	nis_putpwnam,
66*7c478bd9Sstevel@tonic-gate 	nis_user_to_authenticate,
67*7c478bd9Sstevel@tonic-gate 	NULL,	/* lock */
68*7c478bd9Sstevel@tonic-gate 	NULL	/* unlock */
69*7c478bd9Sstevel@tonic-gate };
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate /*
72*7c478bd9Sstevel@tonic-gate  * structure used to keep state between get/update/put calls
73*7c478bd9Sstevel@tonic-gate  */
74*7c478bd9Sstevel@tonic-gate typedef struct {
75*7c478bd9Sstevel@tonic-gate 	char *domain;
76*7c478bd9Sstevel@tonic-gate 	char *master;
77*7c478bd9Sstevel@tonic-gate 	char *scratch;
78*7c478bd9Sstevel@tonic-gate 	int scratchlen;
79*7c478bd9Sstevel@tonic-gate 	char *c2scratch;
80*7c478bd9Sstevel@tonic-gate 	int c2scratchlen;
81*7c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
82*7c478bd9Sstevel@tonic-gate } nisbuf_t;
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate /*
85*7c478bd9Sstevel@tonic-gate  * Are we a 'privileged' process? Yes if we are running on the
86*7c478bd9Sstevel@tonic-gate  * NIS server AND we are root...
87*7c478bd9Sstevel@tonic-gate  */
88*7c478bd9Sstevel@tonic-gate int
89*7c478bd9Sstevel@tonic-gate nis_privileged(nisbuf_t *nisbuf)
90*7c478bd9Sstevel@tonic-gate {
91*7c478bd9Sstevel@tonic-gate 	char thishost[MAXHOSTNAMELEN];
92*7c478bd9Sstevel@tonic-gate 	if (gethostname(thishost, sizeof (thishost)) == -1) {
93*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "passwdutil.so: Can't get hostname");
94*7c478bd9Sstevel@tonic-gate 		return (0);
95*7c478bd9Sstevel@tonic-gate 	}
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	if (strcmp(nisbuf->master, thishost) != 0)
98*7c478bd9Sstevel@tonic-gate 		return (0);
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	/* We're running on the NIS server. */
101*7c478bd9Sstevel@tonic-gate 	return (getuid() == 0);
102*7c478bd9Sstevel@tonic-gate }
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate /*
105*7c478bd9Sstevel@tonic-gate  * nis_to_pwd()
106*7c478bd9Sstevel@tonic-gate  *
107*7c478bd9Sstevel@tonic-gate  * convert password-entry-line to "struct passwd"
108*7c478bd9Sstevel@tonic-gate  */
109*7c478bd9Sstevel@tonic-gate void
110*7c478bd9Sstevel@tonic-gate nis_to_pwd(char *nis, struct passwd *pwd)
111*7c478bd9Sstevel@tonic-gate {
112*7c478bd9Sstevel@tonic-gate 	pwd->pw_name = strsep(&nis, ":");
113*7c478bd9Sstevel@tonic-gate 	pwd->pw_passwd = strsep(&nis, ":");
114*7c478bd9Sstevel@tonic-gate 	pwd->pw_uid = atoi(strsep(&nis, ":"));
115*7c478bd9Sstevel@tonic-gate 	pwd->pw_gid = atoi(strsep(&nis, ":"));
116*7c478bd9Sstevel@tonic-gate 	pwd->pw_gecos = strsep(&nis, ":");
117*7c478bd9Sstevel@tonic-gate 	pwd->pw_dir = strsep(&nis, ":");
118*7c478bd9Sstevel@tonic-gate 	pwd->pw_shell = nis;
119*7c478bd9Sstevel@tonic-gate 	if (pwd->pw_shell[0])
120*7c478bd9Sstevel@tonic-gate 		pwd->pw_shell[strlen(pwd->pw_shell)-1] = '\0';
121*7c478bd9Sstevel@tonic-gate }
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate /*
124*7c478bd9Sstevel@tonic-gate  * nis_user_to_authenticate(name, rep, auth_user, privileged)
125*7c478bd9Sstevel@tonic-gate  *
126*7c478bd9Sstevel@tonic-gate  */
127*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
128*7c478bd9Sstevel@tonic-gate int
129*7c478bd9Sstevel@tonic-gate nis_user_to_authenticate(char *user, pwu_repository_t *rep,
130*7c478bd9Sstevel@tonic-gate 	char **auth_user, int *privileged)
131*7c478bd9Sstevel@tonic-gate {
132*7c478bd9Sstevel@tonic-gate 	nisbuf_t *buf = NULL;
133*7c478bd9Sstevel@tonic-gate 	int res;
134*7c478bd9Sstevel@tonic-gate 	attrlist attr_tmp[1];
135*7c478bd9Sstevel@tonic-gate 	uid_t uid;
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	/*
138*7c478bd9Sstevel@tonic-gate 	 * special NIS case: don't bother to get "root" from NIS
139*7c478bd9Sstevel@tonic-gate 	 */
140*7c478bd9Sstevel@tonic-gate 	if (strcmp(user, "root") == 0)
141*7c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 	attr_tmp[0].type = ATTR_UID;
144*7c478bd9Sstevel@tonic-gate 	attr_tmp[0].next = NULL;
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate 	res = nis_getpwnam(user, &attr_tmp[0], rep, (void **)&buf);
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	if (res != PWU_SUCCESS)
149*7c478bd9Sstevel@tonic-gate 		return (res);
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	if (nis_privileged(buf)) {
152*7c478bd9Sstevel@tonic-gate 		*privileged = 1;
153*7c478bd9Sstevel@tonic-gate 		*auth_user = NULL;
154*7c478bd9Sstevel@tonic-gate 		res = PWU_SUCCESS;
155*7c478bd9Sstevel@tonic-gate 	} else {
156*7c478bd9Sstevel@tonic-gate 		uid = getuid();
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 		*privileged = (uid == (uid_t)0);
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 		/* root, or user herself can change attributes */
161*7c478bd9Sstevel@tonic-gate 		if (uid == 0 || uid == buf->pwd->pw_uid) {
162*7c478bd9Sstevel@tonic-gate 			*auth_user = strdup(user);
163*7c478bd9Sstevel@tonic-gate 			res = PWU_SUCCESS;
164*7c478bd9Sstevel@tonic-gate 		} else {
165*7c478bd9Sstevel@tonic-gate 			res = PWU_DENIED;
166*7c478bd9Sstevel@tonic-gate 		}
167*7c478bd9Sstevel@tonic-gate 	}
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	/*
170*7c478bd9Sstevel@tonic-gate 	 * Do not release buf->domain.
171*7c478bd9Sstevel@tonic-gate 	 * It's been set by yp_get_default_domain()
172*7c478bd9Sstevel@tonic-gate 	 * and must not be freed.
173*7c478bd9Sstevel@tonic-gate 	 * See man page yp_get_default_domain(3NSL)
174*7c478bd9Sstevel@tonic-gate 	 * for details.
175*7c478bd9Sstevel@tonic-gate 	 */
176*7c478bd9Sstevel@tonic-gate 	if (buf->master)
177*7c478bd9Sstevel@tonic-gate 		free(buf->master);
178*7c478bd9Sstevel@tonic-gate 	if (buf->scratch)
179*7c478bd9Sstevel@tonic-gate 		free(buf->scratch);
180*7c478bd9Sstevel@tonic-gate 	if (buf->c2scratch)
181*7c478bd9Sstevel@tonic-gate 		free(buf->c2scratch);
182*7c478bd9Sstevel@tonic-gate 	free(buf->pwd);
183*7c478bd9Sstevel@tonic-gate 	free(buf);
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	return (res);
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate /*
190*7c478bd9Sstevel@tonic-gate  * nis_getattr(name, items, rep)
191*7c478bd9Sstevel@tonic-gate  *
192*7c478bd9Sstevel@tonic-gate  * get account attributes specified in 'items'
193*7c478bd9Sstevel@tonic-gate  */
194*7c478bd9Sstevel@tonic-gate int
195*7c478bd9Sstevel@tonic-gate nis_getattr(char *name, attrlist *items, pwu_repository_t *rep)
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	nisbuf_t *nisbuf = NULL;
198*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
199*7c478bd9Sstevel@tonic-gate 	attrlist *w;
200*7c478bd9Sstevel@tonic-gate 	int res;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	res = nis_getpwnam(name, items, rep, (void **)&nisbuf);
203*7c478bd9Sstevel@tonic-gate 	if (res != PWU_SUCCESS)
204*7c478bd9Sstevel@tonic-gate 		return (res);
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	pw = nisbuf->pwd;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	for (w = items; w != NULL; w = w->next) {
209*7c478bd9Sstevel@tonic-gate 		switch (w->type) {
210*7c478bd9Sstevel@tonic-gate 		case ATTR_NAME:
211*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_name)) == NULL)
212*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
213*7c478bd9Sstevel@tonic-gate 			break;
214*7c478bd9Sstevel@tonic-gate 		case ATTR_COMMENT:
215*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_comment)) == NULL)
216*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
217*7c478bd9Sstevel@tonic-gate 			break;
218*7c478bd9Sstevel@tonic-gate 		case ATTR_GECOS:
219*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_gecos)) == NULL)
220*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
221*7c478bd9Sstevel@tonic-gate 			break;
222*7c478bd9Sstevel@tonic-gate 		case ATTR_HOMEDIR:
223*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_dir)) == NULL)
224*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
225*7c478bd9Sstevel@tonic-gate 			break;
226*7c478bd9Sstevel@tonic-gate 		case ATTR_SHELL:
227*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_shell)) == NULL)
228*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
229*7c478bd9Sstevel@tonic-gate 			break;
230*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
231*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD_SERVER_POLICY:
232*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_passwd)) == NULL)
233*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
234*7c478bd9Sstevel@tonic-gate 			break;
235*7c478bd9Sstevel@tonic-gate 		case ATTR_REP_NAME:
236*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup("nis")) == NULL)
237*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
238*7c478bd9Sstevel@tonic-gate 			break;
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 		/* integer values */
241*7c478bd9Sstevel@tonic-gate 		case ATTR_UID:
242*7c478bd9Sstevel@tonic-gate 			w->data.val_i = nisbuf->pwd->pw_uid;
243*7c478bd9Sstevel@tonic-gate 			break;
244*7c478bd9Sstevel@tonic-gate 		case ATTR_GID:
245*7c478bd9Sstevel@tonic-gate 			w->data.val_i = nisbuf->pwd->pw_gid;
246*7c478bd9Sstevel@tonic-gate 			break;
247*7c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
248*7c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
249*7c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
250*7c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
251*7c478bd9Sstevel@tonic-gate 		case ATTR_INACT:
252*7c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE:
253*7c478bd9Sstevel@tonic-gate 		case ATTR_FLAG:
254*7c478bd9Sstevel@tonic-gate 		case ATTR_AGE:
255*7c478bd9Sstevel@tonic-gate 			w->data.val_i = -1;	/* not used for NIS */
256*7c478bd9Sstevel@tonic-gate 			break;
257*7c478bd9Sstevel@tonic-gate 		default:
258*7c478bd9Sstevel@tonic-gate 			break;
259*7c478bd9Sstevel@tonic-gate 		}
260*7c478bd9Sstevel@tonic-gate 	}
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	/*
263*7c478bd9Sstevel@tonic-gate 	 * Do not release nisbuf->domain.
264*7c478bd9Sstevel@tonic-gate 	 * It's been set by yp_get_default_domain()
265*7c478bd9Sstevel@tonic-gate 	 * and must not be freed.
266*7c478bd9Sstevel@tonic-gate 	 * See man page yp_get_default_domain(3NSL)
267*7c478bd9Sstevel@tonic-gate 	 * for details.
268*7c478bd9Sstevel@tonic-gate 	 */
269*7c478bd9Sstevel@tonic-gate 	if (nisbuf->master)
270*7c478bd9Sstevel@tonic-gate 		free(nisbuf->master);
271*7c478bd9Sstevel@tonic-gate 	if (nisbuf->scratch)
272*7c478bd9Sstevel@tonic-gate 		free(nisbuf->scratch);
273*7c478bd9Sstevel@tonic-gate 	if (nisbuf->c2scratch)
274*7c478bd9Sstevel@tonic-gate 		free(nisbuf->c2scratch);
275*7c478bd9Sstevel@tonic-gate 	free(nisbuf->pwd);
276*7c478bd9Sstevel@tonic-gate 	free(nisbuf);
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	return (res);
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate /*
282*7c478bd9Sstevel@tonic-gate  * nis_getpwnam(name, items, rep)
283*7c478bd9Sstevel@tonic-gate  *
284*7c478bd9Sstevel@tonic-gate  * Get the account information of user 'name'
285*7c478bd9Sstevel@tonic-gate  */
286*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
287*7c478bd9Sstevel@tonic-gate int
288*7c478bd9Sstevel@tonic-gate nis_getpwnam(char *name, attrlist *items, pwu_repository_t *rep,
289*7c478bd9Sstevel@tonic-gate     void **buf)
290*7c478bd9Sstevel@tonic-gate {
291*7c478bd9Sstevel@tonic-gate 	nisbuf_t *nisbuf;
292*7c478bd9Sstevel@tonic-gate 	int nisresult;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	nisbuf = calloc(sizeof (*nisbuf), 1);
295*7c478bd9Sstevel@tonic-gate 	if (nisbuf == NULL)
296*7c478bd9Sstevel@tonic-gate 		return (PWU_NOMEM);
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	nisbuf->pwd = malloc(sizeof (struct passwd));
299*7c478bd9Sstevel@tonic-gate 	if (nisbuf->pwd == NULL) {
300*7c478bd9Sstevel@tonic-gate 		free(nisbuf);
301*7c478bd9Sstevel@tonic-gate 		return (PWU_NOMEM);
302*7c478bd9Sstevel@tonic-gate 	}
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	/*
305*7c478bd9Sstevel@tonic-gate 	 * Do not release nisbuf->domain.
306*7c478bd9Sstevel@tonic-gate 	 * It is going to be set by yp_get_default_domain()
307*7c478bd9Sstevel@tonic-gate 	 * and must not be freed.
308*7c478bd9Sstevel@tonic-gate 	 * See man page yp_get_default_domain(3NSL)
309*7c478bd9Sstevel@tonic-gate 	 * for details.
310*7c478bd9Sstevel@tonic-gate 	 */
311*7c478bd9Sstevel@tonic-gate 	if (yp_get_default_domain(&nisbuf->domain) != 0) {
312*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "passwdutil.so: can't get domain");
313*7c478bd9Sstevel@tonic-gate 		free(nisbuf->pwd);
314*7c478bd9Sstevel@tonic-gate 		free(nisbuf);
315*7c478bd9Sstevel@tonic-gate 		return (PWU_SERVER_ERROR);
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	if (yp_master(nisbuf->domain, "passwd.byname", &nisbuf->master) != 0) {
319*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
320*7c478bd9Sstevel@tonic-gate 			"passwdutil.so: can't get master for passwd map");
321*7c478bd9Sstevel@tonic-gate 		if (nisbuf->master)
322*7c478bd9Sstevel@tonic-gate 			free(nisbuf->master);
323*7c478bd9Sstevel@tonic-gate 		free(nisbuf->pwd);
324*7c478bd9Sstevel@tonic-gate 		free(nisbuf);
325*7c478bd9Sstevel@tonic-gate 		return (PWU_SERVER_ERROR);
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	nisresult = yp_match(nisbuf->domain, "passwd.byname", name,
329*7c478bd9Sstevel@tonic-gate 				strlen(name), &(nisbuf->scratch),
330*7c478bd9Sstevel@tonic-gate 				&(nisbuf->scratchlen));
331*7c478bd9Sstevel@tonic-gate 	if (nisresult != 0) {
332*7c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->pwd);
333*7c478bd9Sstevel@tonic-gate 		if (nisbuf->scratch)
334*7c478bd9Sstevel@tonic-gate 			(void) free(nisbuf->scratch);
335*7c478bd9Sstevel@tonic-gate 		if (nisbuf->master)
336*7c478bd9Sstevel@tonic-gate 			(void) free(nisbuf->master);
337*7c478bd9Sstevel@tonic-gate 		(void) free(nisbuf);
338*7c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
339*7c478bd9Sstevel@tonic-gate 	}
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	nis_to_pwd(nisbuf->scratch, nisbuf->pwd);
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	/*
344*7c478bd9Sstevel@tonic-gate 	 * check for the C2 security flag "##" in the passwd field.
345*7c478bd9Sstevel@tonic-gate 	 * If the first 2 chars in the passwd field is "##", get
346*7c478bd9Sstevel@tonic-gate 	 * the user's passwd from passwd.adjunct.byname map.
347*7c478bd9Sstevel@tonic-gate 	 * The lookup to this passwd.adjunct.byname map will only
348*7c478bd9Sstevel@tonic-gate 	 * succeed if the caller's uid is 0 because only root user
349*7c478bd9Sstevel@tonic-gate 	 * can use privilege port.
350*7c478bd9Sstevel@tonic-gate 	 */
351*7c478bd9Sstevel@tonic-gate 	if (nisbuf->pwd->pw_passwd[0] == '#' &&
352*7c478bd9Sstevel@tonic-gate 	    nisbuf->pwd->pw_passwd[1] == '#') {
353*7c478bd9Sstevel@tonic-gate 		char *key = &nisbuf->pwd->pw_passwd[2];
354*7c478bd9Sstevel@tonic-gate 		int keylen;
355*7c478bd9Sstevel@tonic-gate 		char *p;
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 		keylen = strlen(key);
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 		nisresult = yp_match(nisbuf->domain, "passwd.adjunct.byname",
360*7c478bd9Sstevel@tonic-gate 				key, keylen, &(nisbuf->c2scratch),
361*7c478bd9Sstevel@tonic-gate 				&(nisbuf->c2scratchlen));
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 		if (nisresult == 0 && nisbuf->c2scratch != NULL) {
364*7c478bd9Sstevel@tonic-gate 			/* Skip username (first field), and pick up password */
365*7c478bd9Sstevel@tonic-gate 			p = nisbuf->c2scratch;
366*7c478bd9Sstevel@tonic-gate 			(void) strsep(&p, ":");
367*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_passwd = strsep(&p, ":");
368*7c478bd9Sstevel@tonic-gate 		}
369*7c478bd9Sstevel@tonic-gate 	}
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 	*buf = (void *)nisbuf;
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	return (PWU_SUCCESS);
374*7c478bd9Sstevel@tonic-gate }
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate /*
377*7c478bd9Sstevel@tonic-gate  * nis_update(items, rep, buf)
378*7c478bd9Sstevel@tonic-gate  *
379*7c478bd9Sstevel@tonic-gate  * update the information in "buf" with the attribute/values
380*7c478bd9Sstevel@tonic-gate  * specified in "items".
381*7c478bd9Sstevel@tonic-gate  */
382*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
383*7c478bd9Sstevel@tonic-gate int
384*7c478bd9Sstevel@tonic-gate nis_update(attrlist *items, pwu_repository_t *rep, void *buf)
385*7c478bd9Sstevel@tonic-gate {
386*7c478bd9Sstevel@tonic-gate 	attrlist *p;
387*7c478bd9Sstevel@tonic-gate 	nisbuf_t *nisbuf = (nisbuf_t *)buf;
388*7c478bd9Sstevel@tonic-gate 	char *salt;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	for (p = items; p != NULL; p = p->next) {
391*7c478bd9Sstevel@tonic-gate 		switch (p->type) {
392*7c478bd9Sstevel@tonic-gate 		case ATTR_NAME:
393*7c478bd9Sstevel@tonic-gate 			break;
394*7c478bd9Sstevel@tonic-gate 		/*
395*7c478bd9Sstevel@tonic-gate 		 * Nothing special needs to be done for
396*7c478bd9Sstevel@tonic-gate 		 * server policy
397*7c478bd9Sstevel@tonic-gate 		 */
398*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
399*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD_SERVER_POLICY:
400*7c478bd9Sstevel@tonic-gate 			salt = crypt_gensalt(
401*7c478bd9Sstevel@tonic-gate 			    nisbuf->pwd->pw_passwd, nisbuf->pwd);
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 			if (salt == NULL) {
404*7c478bd9Sstevel@tonic-gate 				if (errno == ENOMEM)
405*7c478bd9Sstevel@tonic-gate 					return (PWU_NOMEM);
406*7c478bd9Sstevel@tonic-gate 				else {
407*7c478bd9Sstevel@tonic-gate 					/* algorithm problem? */
408*7c478bd9Sstevel@tonic-gate 					syslog(LOG_AUTH | LOG_ALERT,
409*7c478bd9Sstevel@tonic-gate 					    "passwdutil: crypt_gensalt "
410*7c478bd9Sstevel@tonic-gate 					    "%m");
411*7c478bd9Sstevel@tonic-gate 					return (PWU_UPDATE_FAILED);
412*7c478bd9Sstevel@tonic-gate 				}
413*7c478bd9Sstevel@tonic-gate 			}
414*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_passwd = crypt(p->data.val_s, salt);
415*7c478bd9Sstevel@tonic-gate 			free(salt);
416*7c478bd9Sstevel@tonic-gate 			break;
417*7c478bd9Sstevel@tonic-gate 		case ATTR_UID:
418*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_uid = (uid_t)p->data.val_i;
419*7c478bd9Sstevel@tonic-gate 			break;
420*7c478bd9Sstevel@tonic-gate 		case ATTR_GID:
421*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_gid = (gid_t)p->data.val_i;
422*7c478bd9Sstevel@tonic-gate 			break;
423*7c478bd9Sstevel@tonic-gate 		case ATTR_AGE:
424*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_age = p->data.val_s;
425*7c478bd9Sstevel@tonic-gate 			break;
426*7c478bd9Sstevel@tonic-gate 		case ATTR_COMMENT:
427*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_comment = p->data.val_s;
428*7c478bd9Sstevel@tonic-gate 			break;
429*7c478bd9Sstevel@tonic-gate 		case ATTR_GECOS:
430*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_gecos = p->data.val_s;
431*7c478bd9Sstevel@tonic-gate 			break;
432*7c478bd9Sstevel@tonic-gate 		case ATTR_HOMEDIR:
433*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_dir = p->data.val_s;
434*7c478bd9Sstevel@tonic-gate 			break;
435*7c478bd9Sstevel@tonic-gate 		case ATTR_SHELL:
436*7c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_shell = p->data.val_s;
437*7c478bd9Sstevel@tonic-gate 			break;
438*7c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
439*7c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
440*7c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
441*7c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
442*7c478bd9Sstevel@tonic-gate 		case ATTR_INACT:
443*7c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE:
444*7c478bd9Sstevel@tonic-gate 		case ATTR_FLAG:
445*7c478bd9Sstevel@tonic-gate 		default:
446*7c478bd9Sstevel@tonic-gate 			break;
447*7c478bd9Sstevel@tonic-gate 		}
448*7c478bd9Sstevel@tonic-gate 	}
449*7c478bd9Sstevel@tonic-gate 	return (PWU_SUCCESS);
450*7c478bd9Sstevel@tonic-gate }
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate /*
453*7c478bd9Sstevel@tonic-gate  * nis_putpwnam(name, oldpw, dummy, rep, buf)
454*7c478bd9Sstevel@tonic-gate  *
455*7c478bd9Sstevel@tonic-gate  * Update the NIS server. The passwd structure in buf will be sent to
456*7c478bd9Sstevel@tonic-gate  * the server for user "name" authenticating with password "oldpw".
457*7c478bd9Sstevel@tonic-gate  * The dummy parameter is a placeholder where for NIS+ where the
458*7c478bd9Sstevel@tonic-gate  * old RPC password is passwd.
459*7c478bd9Sstevel@tonic-gate  */
460*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
461*7c478bd9Sstevel@tonic-gate int
462*7c478bd9Sstevel@tonic-gate nis_putpwnam(char *name, char *oldpw, char *dummy, pwu_repository_t *rep,
463*7c478bd9Sstevel@tonic-gate 	void *buf)
464*7c478bd9Sstevel@tonic-gate {
465*7c478bd9Sstevel@tonic-gate 	nisbuf_t *nisbuf = (nisbuf_t *)buf;
466*7c478bd9Sstevel@tonic-gate 	struct yppasswd yppasswd;
467*7c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
468*7c478bd9Sstevel@tonic-gate 	int ok;
469*7c478bd9Sstevel@tonic-gate 	enum clnt_stat ans;
470*7c478bd9Sstevel@tonic-gate 	CLIENT *client;
471*7c478bd9Sstevel@tonic-gate 	struct timeval timeout;
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	if (strcmp(name, "root") == 0)
474*7c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	yppasswd.oldpass = oldpw ? oldpw : "";
477*7c478bd9Sstevel@tonic-gate 	yppasswd.newpw = *nisbuf->pwd;
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 	/*
480*7c478bd9Sstevel@tonic-gate 	 * If we are privileged, we create a ticlts connection to the
481*7c478bd9Sstevel@tonic-gate 	 * NIS server so that it can check our credentials
482*7c478bd9Sstevel@tonic-gate 	 */
483*7c478bd9Sstevel@tonic-gate 	if (nis_privileged(nisbuf)) {
484*7c478bd9Sstevel@tonic-gate 		nconf = getnetconfigent("ticlts");
485*7c478bd9Sstevel@tonic-gate 		if (!nconf) {
486*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
487*7c478bd9Sstevel@tonic-gate 				"passwdutil.so: Couldn't get netconfig entry");
488*7c478bd9Sstevel@tonic-gate 			return (PWU_SYSTEM_ERROR);
489*7c478bd9Sstevel@tonic-gate 		}
490*7c478bd9Sstevel@tonic-gate 		client = clnt_tp_create(nisbuf->master, YPPASSWDPROG,
491*7c478bd9Sstevel@tonic-gate 					YPPASSWDVERS, nconf);
492*7c478bd9Sstevel@tonic-gate 		freenetconfigent(nconf);
493*7c478bd9Sstevel@tonic-gate 	} else {
494*7c478bd9Sstevel@tonic-gate 		/* Try IPv6 first */
495*7c478bd9Sstevel@tonic-gate 		client = clnt_create(nisbuf->master, YPPASSWDPROG,
496*7c478bd9Sstevel@tonic-gate 					YPPASSWDVERS, "udp6");
497*7c478bd9Sstevel@tonic-gate 		if (client == NULL)
498*7c478bd9Sstevel@tonic-gate 			client = clnt_create(nisbuf->master, YPPASSWDPROG,
499*7c478bd9Sstevel@tonic-gate 						YPPASSWDVERS, "udp");
500*7c478bd9Sstevel@tonic-gate 	}
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	if (client == NULL) {
503*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
504*7c478bd9Sstevel@tonic-gate 			"passwdutil.so: couldn't create client to YP master");
505*7c478bd9Sstevel@tonic-gate 		return (PWU_SERVER_ERROR);
506*7c478bd9Sstevel@tonic-gate 	}
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 	timeout.tv_usec = 0;
509*7c478bd9Sstevel@tonic-gate 	timeout.tv_sec = 55;	/* ndp uses 55 seconds */
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	ans = CLNT_CALL(client, YPPASSWDPROC_UPDATE, xdr_yppasswd,
512*7c478bd9Sstevel@tonic-gate 		(char *)&yppasswd, xdr_int, (char *)&ok, timeout);
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	if (nisbuf->pwd)
515*7c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->pwd);
516*7c478bd9Sstevel@tonic-gate 	if (nisbuf->master)
517*7c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->master);
518*7c478bd9Sstevel@tonic-gate 	if (nisbuf->scratch)
519*7c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->scratch);
520*7c478bd9Sstevel@tonic-gate 	if (nisbuf->c2scratch)
521*7c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->c2scratch);
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	(void) clnt_destroy(client);
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	if (ans != RPC_SUCCESS) {
526*7c478bd9Sstevel@tonic-gate 		return (PWU_UPDATE_FAILED);
527*7c478bd9Sstevel@tonic-gate 	}
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 	/* These errors are obtained from the yppasswdd.c code */
530*7c478bd9Sstevel@tonic-gate 	switch (ok) {
531*7c478bd9Sstevel@tonic-gate 		case 2: return (PWU_DENIED);
532*7c478bd9Sstevel@tonic-gate 		case 8: return (PWU_BUSY);
533*7c478bd9Sstevel@tonic-gate 		case 9: return (PWU_SERVER_ERROR);
534*7c478bd9Sstevel@tonic-gate 		case 4: return (PWU_NOT_FOUND);
535*7c478bd9Sstevel@tonic-gate 		case 3: return (PWU_NO_CHANGE);
536*7c478bd9Sstevel@tonic-gate 		case 7: return (PWU_DENIED);
537*7c478bd9Sstevel@tonic-gate 		case 0: return (PWU_SUCCESS);
538*7c478bd9Sstevel@tonic-gate 		default: return (PWU_SYSTEM_ERROR);
539*7c478bd9Sstevel@tonic-gate 	}
540*7c478bd9Sstevel@tonic-gate }
541