xref: /titanic_50/usr/src/lib/passwdutil/ldap_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 <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 <unistd.h>
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include "ns_sldap.h"
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
38*7c478bd9Sstevel@tonic-gate #include <nsswitch.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #include <pwd.h>
41*7c478bd9Sstevel@tonic-gate #include <shadow.h>
42*7c478bd9Sstevel@tonic-gate #include <syslog.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #include "passwdutil.h"
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #include "utils.h"
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate int ldap_getattr(char *name, attrlist *item, pwu_repository_t *rep);
49*7c478bd9Sstevel@tonic-gate int ldap_getpwnam(char *name, attrlist *items, pwu_repository_t *rep,
50*7c478bd9Sstevel@tonic-gate     void **buf);
51*7c478bd9Sstevel@tonic-gate int ldap_update(attrlist *items, pwu_repository_t *rep, void *buf);
52*7c478bd9Sstevel@tonic-gate int ldap_putpwnam(char *name, char *oldpw, char *dummy,
53*7c478bd9Sstevel@tonic-gate 	pwu_repository_t *rep, void *buf);
54*7c478bd9Sstevel@tonic-gate int ldap_user_to_authenticate(char *name, pwu_repository_t *rep,
55*7c478bd9Sstevel@tonic-gate 	char **auth_user, int *privileged);
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate /*
58*7c478bd9Sstevel@tonic-gate  * ldap function pointer table, used by passwdutil_init to initialize
59*7c478bd9Sstevel@tonic-gate  * the global Repository-OPerations table "rops"
60*7c478bd9Sstevel@tonic-gate  */
61*7c478bd9Sstevel@tonic-gate struct repops ldap_repops = {
62*7c478bd9Sstevel@tonic-gate 	NULL,	/* checkhistory */
63*7c478bd9Sstevel@tonic-gate 	ldap_getattr,
64*7c478bd9Sstevel@tonic-gate 	ldap_getpwnam,
65*7c478bd9Sstevel@tonic-gate 	ldap_update,
66*7c478bd9Sstevel@tonic-gate 	ldap_putpwnam,
67*7c478bd9Sstevel@tonic-gate 	ldap_user_to_authenticate,
68*7c478bd9Sstevel@tonic-gate 	NULL,	/* lock */
69*7c478bd9Sstevel@tonic-gate 	NULL	/* unlock */
70*7c478bd9Sstevel@tonic-gate };
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate /*
73*7c478bd9Sstevel@tonic-gate  * structure used to keep state between get/update/put calls
74*7c478bd9Sstevel@tonic-gate  */
75*7c478bd9Sstevel@tonic-gate typedef struct {
76*7c478bd9Sstevel@tonic-gate 	char *passwd;		/* encrypted password */
77*7c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
78*7c478bd9Sstevel@tonic-gate 	ns_ldap_attr_t **attrs;
79*7c478bd9Sstevel@tonic-gate } ldapbuf_t;
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  * The following define's are taken from
83*7c478bd9Sstevel@tonic-gate  *	usr/src/lib/nsswitch/ldap/common/getpwnam.c
84*7c478bd9Sstevel@tonic-gate  */
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate /* passwd attributes filters */
87*7c478bd9Sstevel@tonic-gate #define	_PWD_CN			"cn"
88*7c478bd9Sstevel@tonic-gate #define	_PWD_UID		"uid"
89*7c478bd9Sstevel@tonic-gate #define	_PWD_USERPASSWORD	"userpassword"
90*7c478bd9Sstevel@tonic-gate #define	_PWD_UIDNUMBER		"uidnumber"
91*7c478bd9Sstevel@tonic-gate #define	_PWD_GIDNUMBER		"gidnumber"
92*7c478bd9Sstevel@tonic-gate #define	_PWD_GECOS		"gecos"
93*7c478bd9Sstevel@tonic-gate #define	_PWD_DESCRIPTION	"description"
94*7c478bd9Sstevel@tonic-gate #define	_PWD_HOMEDIRECTORY	"homedirectory"
95*7c478bd9Sstevel@tonic-gate #define	_PWD_LOGINSHELL		"loginshell"
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate /*
98*7c478bd9Sstevel@tonic-gate  * int ldap_user_to_authenticate(user, rep, auth_user, privileged)
99*7c478bd9Sstevel@tonic-gate  *
100*7c478bd9Sstevel@tonic-gate  * We can't determine whether the user is "privileged" in the LDAP
101*7c478bd9Sstevel@tonic-gate  * sense. The operation should be attempted and will succeed if
102*7c478bd9Sstevel@tonic-gate  * the user had privileges.
103*7c478bd9Sstevel@tonic-gate  *
104*7c478bd9Sstevel@tonic-gate  * For our purposes, we say that the user is privileged if he/she
105*7c478bd9Sstevel@tonic-gate  * is attempting to change another user's password attributes.
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate int
108*7c478bd9Sstevel@tonic-gate ldap_user_to_authenticate(char *user, pwu_repository_t *rep,
109*7c478bd9Sstevel@tonic-gate 	char **auth_user, int *privileged)
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
112*7c478bd9Sstevel@tonic-gate 	uid_t uid;
113*7c478bd9Sstevel@tonic-gate 	uid_t priviledged_uid;
114*7c478bd9Sstevel@tonic-gate 	int res = PWU_SUCCESS;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	if (strcmp(user, "root") == 0)
117*7c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	if ((pw = getpwnam_from(user, rep, REP_LDAP)) == NULL)
120*7c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 	uid = getuid();
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	if (uid == pw->pw_uid) {
125*7c478bd9Sstevel@tonic-gate 		/* changing out own, not privileged */
126*7c478bd9Sstevel@tonic-gate 		*privileged = 0;
127*7c478bd9Sstevel@tonic-gate 		if ((*auth_user = strdup(user)) == NULL)
128*7c478bd9Sstevel@tonic-gate 			res = PWU_NOMEM;
129*7c478bd9Sstevel@tonic-gate 	} else {
130*7c478bd9Sstevel@tonic-gate 		char pwd_buf[1024];
131*7c478bd9Sstevel@tonic-gate 		struct passwd pwr;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 		*privileged = 1;
134*7c478bd9Sstevel@tonic-gate 		/*
135*7c478bd9Sstevel@tonic-gate 		 * specific case for root
136*7c478bd9Sstevel@tonic-gate 		 * we want 'user' to be authenticated.
137*7c478bd9Sstevel@tonic-gate 		 */
138*7c478bd9Sstevel@tonic-gate 		if (uid == 0)  {
139*7c478bd9Sstevel@tonic-gate 			priviledged_uid = pw->pw_uid;
140*7c478bd9Sstevel@tonic-gate 		} else {
141*7c478bd9Sstevel@tonic-gate 			priviledged_uid = uid;
142*7c478bd9Sstevel@tonic-gate 		}
143*7c478bd9Sstevel@tonic-gate 		if (getpwuid_r(priviledged_uid, &pwr, pwd_buf,
144*7c478bd9Sstevel@tonic-gate 				sizeof (pwd_buf)) != NULL) {
145*7c478bd9Sstevel@tonic-gate 			if ((*auth_user = strdup(pwr.pw_name)) ==  NULL)
146*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
147*7c478bd9Sstevel@tonic-gate 		} else {
148*7c478bd9Sstevel@tonic-gate 			/* hmm. can't find name of current user...??? */
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate #define	MAX_UID_LEN 11	/* UID's larger than 2^32 won't fit... */
151*7c478bd9Sstevel@tonic-gate 			if ((*auth_user = malloc(MAX_UID_LEN)) == NULL) {
152*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
153*7c478bd9Sstevel@tonic-gate 			} else {
154*7c478bd9Sstevel@tonic-gate 				(void) snprintf(*auth_user, MAX_UID_LEN, "%d",
155*7c478bd9Sstevel@tonic-gate 				    (int)uid);
156*7c478bd9Sstevel@tonic-gate 			}
157*7c478bd9Sstevel@tonic-gate 		}
158*7c478bd9Sstevel@tonic-gate 	}
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	return (res);
161*7c478bd9Sstevel@tonic-gate }
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate /*
164*7c478bd9Sstevel@tonic-gate  * int ldap_getattr(name, item, rep)
165*7c478bd9Sstevel@tonic-gate  *
166*7c478bd9Sstevel@tonic-gate  * retrieve attributes specified in "item" for user "name".
167*7c478bd9Sstevel@tonic-gate  */
168*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
169*7c478bd9Sstevel@tonic-gate int
170*7c478bd9Sstevel@tonic-gate ldap_getattr(char *name, attrlist *items, pwu_repository_t *rep)
171*7c478bd9Sstevel@tonic-gate {
172*7c478bd9Sstevel@tonic-gate 	int res;
173*7c478bd9Sstevel@tonic-gate 	struct passwd *pw = NULL;
174*7c478bd9Sstevel@tonic-gate 	struct spwd *spw = NULL;
175*7c478bd9Sstevel@tonic-gate 	attrlist *w;
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	int need_shadow = 0;	/* Need shadow info from LDAP server */
178*7c478bd9Sstevel@tonic-gate 	int need_normal = 0;	/* Need non-shadow info from LDAP server */
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	/* We need the "shadow" map for the password only */
181*7c478bd9Sstevel@tonic-gate 	for (w = items; w != NULL; w = w->next) {
182*7c478bd9Sstevel@tonic-gate 		if (w->type == ATTR_PASSWD ||
183*7c478bd9Sstevel@tonic-gate 			w->type == ATTR_PASSWD_SERVER_POLICY)
184*7c478bd9Sstevel@tonic-gate 			need_shadow = 1;
185*7c478bd9Sstevel@tonic-gate 		else
186*7c478bd9Sstevel@tonic-gate 			need_normal = 1;
187*7c478bd9Sstevel@tonic-gate 	}
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	if (need_normal) {
190*7c478bd9Sstevel@tonic-gate 		res = dup_pw(&pw, getpwnam_from(name, rep, REP_LDAP));
191*7c478bd9Sstevel@tonic-gate 		if (res != PWU_SUCCESS)
192*7c478bd9Sstevel@tonic-gate 			goto out;
193*7c478bd9Sstevel@tonic-gate 	}
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	if (need_shadow) {
196*7c478bd9Sstevel@tonic-gate 		res = dup_spw(&spw, getspnam_from(name, rep, REP_LDAP));
197*7c478bd9Sstevel@tonic-gate 		if (res != PWU_SUCCESS) {
198*7c478bd9Sstevel@tonic-gate 			goto out;
199*7c478bd9Sstevel@tonic-gate 		}
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	for (w = items; res == PWU_SUCCESS && w != NULL; w = w->next) {
203*7c478bd9Sstevel@tonic-gate 		switch (w->type) {
204*7c478bd9Sstevel@tonic-gate 		case ATTR_NAME:
205*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_name)) == NULL)
206*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
207*7c478bd9Sstevel@tonic-gate 			break;
208*7c478bd9Sstevel@tonic-gate 		case ATTR_COMMENT:
209*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_comment)) == NULL)
210*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
211*7c478bd9Sstevel@tonic-gate 			break;
212*7c478bd9Sstevel@tonic-gate 		case ATTR_GECOS:
213*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_gecos)) == NULL)
214*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
215*7c478bd9Sstevel@tonic-gate 			break;
216*7c478bd9Sstevel@tonic-gate 		case ATTR_HOMEDIR:
217*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_dir)) == NULL)
218*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
219*7c478bd9Sstevel@tonic-gate 			break;
220*7c478bd9Sstevel@tonic-gate 		case ATTR_SHELL:
221*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_shell)) == NULL)
222*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
223*7c478bd9Sstevel@tonic-gate 			break;
224*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
225*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD_SERVER_POLICY:
226*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(spw->sp_pwdp)) == NULL)
227*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
228*7c478bd9Sstevel@tonic-gate 			break;
229*7c478bd9Sstevel@tonic-gate 		case ATTR_AGE:
230*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_age)) == NULL)
231*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
232*7c478bd9Sstevel@tonic-gate 			break;
233*7c478bd9Sstevel@tonic-gate 		case ATTR_REP_NAME:
234*7c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup("ldap")) == NULL)
235*7c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
236*7c478bd9Sstevel@tonic-gate 			break;
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 		/* integer values */
239*7c478bd9Sstevel@tonic-gate 		case ATTR_UID:
240*7c478bd9Sstevel@tonic-gate 			w->data.val_i = pw->pw_uid;
241*7c478bd9Sstevel@tonic-gate 			break;
242*7c478bd9Sstevel@tonic-gate 		case ATTR_GID:
243*7c478bd9Sstevel@tonic-gate 			w->data.val_i = pw->pw_gid;
244*7c478bd9Sstevel@tonic-gate 			break;
245*7c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
246*7c478bd9Sstevel@tonic-gate 			w->data.val_i = -1;
247*7c478bd9Sstevel@tonic-gate 			break;
248*7c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
249*7c478bd9Sstevel@tonic-gate 			w->data.val_i = -1;
250*7c478bd9Sstevel@tonic-gate 			break;
251*7c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
252*7c478bd9Sstevel@tonic-gate 			w->data.val_i = -1;
253*7c478bd9Sstevel@tonic-gate 			break;
254*7c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
255*7c478bd9Sstevel@tonic-gate 			w->data.val_i = -1;
256*7c478bd9Sstevel@tonic-gate 			break;
257*7c478bd9Sstevel@tonic-gate 		case ATTR_INACT:
258*7c478bd9Sstevel@tonic-gate 			w->data.val_i = -1;
259*7c478bd9Sstevel@tonic-gate 			break;
260*7c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE:
261*7c478bd9Sstevel@tonic-gate 			w->data.val_i = -1;
262*7c478bd9Sstevel@tonic-gate 			break;
263*7c478bd9Sstevel@tonic-gate 		case ATTR_FLAG:
264*7c478bd9Sstevel@tonic-gate 			break;
265*7c478bd9Sstevel@tonic-gate 		default:
266*7c478bd9Sstevel@tonic-gate 			break;
267*7c478bd9Sstevel@tonic-gate 		}
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate out:
271*7c478bd9Sstevel@tonic-gate 	if (pw)
272*7c478bd9Sstevel@tonic-gate 		free_pwd(pw);
273*7c478bd9Sstevel@tonic-gate 	if (spw)
274*7c478bd9Sstevel@tonic-gate 		free_spwd(spw);
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	return (res);
277*7c478bd9Sstevel@tonic-gate }
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate /*
280*7c478bd9Sstevel@tonic-gate  * int ldap_getpwnam(name, items, rep, buf)
281*7c478bd9Sstevel@tonic-gate  *
282*7c478bd9Sstevel@tonic-gate  * There is no need to get the old values from the ldap
283*7c478bd9Sstevel@tonic-gate  * server, as the update will update each item individually.
284*7c478bd9Sstevel@tonic-gate  * Therefore, we only allocate a buffer that will be used by
285*7c478bd9Sstevel@tonic-gate  * _update and _putpwnam to hold the attributes to update.
286*7c478bd9Sstevel@tonic-gate  *
287*7c478bd9Sstevel@tonic-gate  * Only when we're about to update a password, we need to retrieve
288*7c478bd9Sstevel@tonic-gate  * the old password since it contains salt-information.
289*7c478bd9Sstevel@tonic-gate  */
290*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
291*7c478bd9Sstevel@tonic-gate int
292*7c478bd9Sstevel@tonic-gate ldap_getpwnam(char *name, attrlist *items, pwu_repository_t *rep,
293*7c478bd9Sstevel@tonic-gate     void **buf)
294*7c478bd9Sstevel@tonic-gate {
295*7c478bd9Sstevel@tonic-gate 	attrlist *p;
296*7c478bd9Sstevel@tonic-gate 	int nr_items;
297*7c478bd9Sstevel@tonic-gate 	int need_pwd = 0;
298*7c478bd9Sstevel@tonic-gate 	ldapbuf_t *ldapbuf;
299*7c478bd9Sstevel@tonic-gate 	int res;
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 	for (nr_items = 0, p = items; p != NULL; p = p->next) {
302*7c478bd9Sstevel@tonic-gate 		nr_items++;
303*7c478bd9Sstevel@tonic-gate 		if (p->type == ATTR_PASSWD ||
304*7c478bd9Sstevel@tonic-gate 		    p->type == ATTR_PASSWD_SERVER_POLICY)
305*7c478bd9Sstevel@tonic-gate 			need_pwd = 1;
306*7c478bd9Sstevel@tonic-gate 	}
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	ldapbuf = calloc(1, sizeof (ldapbuf_t));
310*7c478bd9Sstevel@tonic-gate 	if (ldapbuf == NULL)
311*7c478bd9Sstevel@tonic-gate 		return (PWU_NOMEM);
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	ldapbuf->attrs = calloc(nr_items, sizeof (ns_ldap_attr_t *));
314*7c478bd9Sstevel@tonic-gate 	if (ldapbuf->attrs == NULL)
315*7c478bd9Sstevel@tonic-gate 		return (PWU_NOMEM);
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	if (need_pwd) {
318*7c478bd9Sstevel@tonic-gate 		struct spwd *spw;
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 		res = dup_pw(&ldapbuf->pwd, getpwnam_from(name, rep, REP_LDAP));
321*7c478bd9Sstevel@tonic-gate 		if (res != PWU_SUCCESS)
322*7c478bd9Sstevel@tonic-gate 			return (res);
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 		spw  = getspnam_from(name, rep, REP_LDAP);
325*7c478bd9Sstevel@tonic-gate 		if (spw) {
326*7c478bd9Sstevel@tonic-gate 			ldapbuf->passwd = strdup(spw->sp_pwdp);
327*7c478bd9Sstevel@tonic-gate 			if (ldapbuf->passwd == NULL)
328*7c478bd9Sstevel@tonic-gate 				return (PWU_NOMEM);
329*7c478bd9Sstevel@tonic-gate 		}
330*7c478bd9Sstevel@tonic-gate 	}
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 	*buf = ldapbuf;
333*7c478bd9Sstevel@tonic-gate 	return (0);
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate /*
337*7c478bd9Sstevel@tonic-gate  * new_attr(name, value)
338*7c478bd9Sstevel@tonic-gate  *
339*7c478bd9Sstevel@tonic-gate  * create a new LDAP attribute to be sent to the server
340*7c478bd9Sstevel@tonic-gate  */
341*7c478bd9Sstevel@tonic-gate ns_ldap_attr_t *
342*7c478bd9Sstevel@tonic-gate new_attr(char *name, char *value)
343*7c478bd9Sstevel@tonic-gate {
344*7c478bd9Sstevel@tonic-gate 	ns_ldap_attr_t *tmp;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	tmp = malloc(sizeof (*tmp));
347*7c478bd9Sstevel@tonic-gate 	if (tmp != NULL) {
348*7c478bd9Sstevel@tonic-gate 		tmp->attrname = name;
349*7c478bd9Sstevel@tonic-gate 		tmp->attrvalue = (char **)calloc(2, sizeof (char *));
350*7c478bd9Sstevel@tonic-gate 		if (tmp->attrvalue == NULL) {
351*7c478bd9Sstevel@tonic-gate 			free(tmp);
352*7c478bd9Sstevel@tonic-gate 			return (NULL);
353*7c478bd9Sstevel@tonic-gate 		}
354*7c478bd9Sstevel@tonic-gate 		tmp->attrvalue[0] = value;
355*7c478bd9Sstevel@tonic-gate 		tmp->value_count = 1;
356*7c478bd9Sstevel@tonic-gate 	}
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 	return (tmp);
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate /*
362*7c478bd9Sstevel@tonic-gate  * ldap_update(items, rep, buf)
363*7c478bd9Sstevel@tonic-gate  *
364*7c478bd9Sstevel@tonic-gate  * create LDAP attributes in 'buf' for each attribute in 'items'.
365*7c478bd9Sstevel@tonic-gate  */
366*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
367*7c478bd9Sstevel@tonic-gate int
368*7c478bd9Sstevel@tonic-gate ldap_update(attrlist *items, pwu_repository_t *rep, void *buf)
369*7c478bd9Sstevel@tonic-gate {
370*7c478bd9Sstevel@tonic-gate 	attrlist *p;
371*7c478bd9Sstevel@tonic-gate 	int idx = 0;
372*7c478bd9Sstevel@tonic-gate 	ldapbuf_t *ldapbuf = (ldapbuf_t *)buf;
373*7c478bd9Sstevel@tonic-gate 	ns_ldap_attr_t **attrs = ldapbuf->attrs;
374*7c478bd9Sstevel@tonic-gate 	char *pwd, *val;
375*7c478bd9Sstevel@tonic-gate 	char *salt;
376*7c478bd9Sstevel@tonic-gate 	size_t cryptlen;
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate 	for (p = items; p != NULL; p = p->next) {
379*7c478bd9Sstevel@tonic-gate 		switch (p->type) {
380*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
381*7c478bd9Sstevel@tonic-gate 			salt = crypt_gensalt(ldapbuf->passwd, ldapbuf->pwd);
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 			if (salt == NULL) {
384*7c478bd9Sstevel@tonic-gate 				if (errno == ENOMEM)
385*7c478bd9Sstevel@tonic-gate 					return (PWU_NOMEM);
386*7c478bd9Sstevel@tonic-gate 				else {
387*7c478bd9Sstevel@tonic-gate 					/* algorithm problem? */
388*7c478bd9Sstevel@tonic-gate 					syslog(LOG_AUTH | LOG_ALERT,
389*7c478bd9Sstevel@tonic-gate 					    "passwdutil: crypt_gensalt "
390*7c478bd9Sstevel@tonic-gate 					    "%m");
391*7c478bd9Sstevel@tonic-gate 					return (PWU_UPDATE_FAILED);
392*7c478bd9Sstevel@tonic-gate 				}
393*7c478bd9Sstevel@tonic-gate 			}
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate 			pwd = crypt(p->data.val_s, salt);
396*7c478bd9Sstevel@tonic-gate 			free(salt);
397*7c478bd9Sstevel@tonic-gate 			cryptlen = strlen(pwd) + sizeof ("{crypt}");
398*7c478bd9Sstevel@tonic-gate 			val = malloc(cryptlen);
399*7c478bd9Sstevel@tonic-gate 			if (val == NULL)
400*7c478bd9Sstevel@tonic-gate 				return (PWU_NOMEM);
401*7c478bd9Sstevel@tonic-gate 			(void) snprintf(val, cryptlen, "{crypt}%s", pwd);
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 			attrs[idx] = new_attr(_PWD_USERPASSWORD, val);
404*7c478bd9Sstevel@tonic-gate 			break;
405*7c478bd9Sstevel@tonic-gate 		/*
406*7c478bd9Sstevel@tonic-gate 		 * For server policy, don't crypt the password,
407*7c478bd9Sstevel@tonic-gate 		 * send the password as is to the server and
408*7c478bd9Sstevel@tonic-gate 		 * let the LDAP server do its own password
409*7c478bd9Sstevel@tonic-gate 		 * encryption
410*7c478bd9Sstevel@tonic-gate 		 */
411*7c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD_SERVER_POLICY:
412*7c478bd9Sstevel@tonic-gate 			val = strdup(p->data.val_s);
413*7c478bd9Sstevel@tonic-gate 			if (val == NULL)
414*7c478bd9Sstevel@tonic-gate 				return (PWU_NOMEM);
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 			attrs[idx] = new_attr(_PWD_USERPASSWORD, val);
417*7c478bd9Sstevel@tonic-gate 			break;
418*7c478bd9Sstevel@tonic-gate 		case ATTR_COMMENT:
419*7c478bd9Sstevel@tonic-gate 			/* XX correct? */
420*7c478bd9Sstevel@tonic-gate 			attrs[idx] = new_attr(_PWD_DESCRIPTION, p->data.val_s);
421*7c478bd9Sstevel@tonic-gate 			break;
422*7c478bd9Sstevel@tonic-gate 		case ATTR_GECOS:
423*7c478bd9Sstevel@tonic-gate 			attrs[idx] = new_attr(_PWD_GECOS, p->data.val_s);
424*7c478bd9Sstevel@tonic-gate 			break;
425*7c478bd9Sstevel@tonic-gate 		case ATTR_HOMEDIR:
426*7c478bd9Sstevel@tonic-gate 			attrs[idx] = new_attr(_PWD_HOMEDIRECTORY,
427*7c478bd9Sstevel@tonic-gate 						p->data.val_s);
428*7c478bd9Sstevel@tonic-gate 			break;
429*7c478bd9Sstevel@tonic-gate 		case ATTR_SHELL:
430*7c478bd9Sstevel@tonic-gate 			attrs[idx] = new_attr(_PWD_LOGINSHELL, p->data.val_s);
431*7c478bd9Sstevel@tonic-gate 			break;
432*7c478bd9Sstevel@tonic-gate 		/* Unsupported items are below this line */
433*7c478bd9Sstevel@tonic-gate 		case ATTR_NAME:
434*7c478bd9Sstevel@tonic-gate 		case ATTR_UID:
435*7c478bd9Sstevel@tonic-gate 		case ATTR_GID:
436*7c478bd9Sstevel@tonic-gate 		case ATTR_AGE:
437*7c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
438*7c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
439*7c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
440*7c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
441*7c478bd9Sstevel@tonic-gate 		case ATTR_INACT:
442*7c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE:
443*7c478bd9Sstevel@tonic-gate 		case ATTR_FLAG:
444*7c478bd9Sstevel@tonic-gate 			break;
445*7c478bd9Sstevel@tonic-gate 		default:
446*7c478bd9Sstevel@tonic-gate 			break;
447*7c478bd9Sstevel@tonic-gate 		}
448*7c478bd9Sstevel@tonic-gate 		if (attrs[idx] == NULL)
449*7c478bd9Sstevel@tonic-gate 			return (PWU_NOMEM);
450*7c478bd9Sstevel@tonic-gate 		idx++;
451*7c478bd9Sstevel@tonic-gate 	}
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	attrs[idx] = NULL;
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 	return (PWU_SUCCESS);
456*7c478bd9Sstevel@tonic-gate }
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate /*
459*7c478bd9Sstevel@tonic-gate  * ldap_to_pwu_code(error, pwd_status)
460*7c478bd9Sstevel@tonic-gate  *
461*7c478bd9Sstevel@tonic-gate  * translation from LDAP return values and PWU return values
462*7c478bd9Sstevel@tonic-gate  */
463*7c478bd9Sstevel@tonic-gate int
464*7c478bd9Sstevel@tonic-gate ldap_to_pwu_code(int error, int pwd_status)
465*7c478bd9Sstevel@tonic-gate {
466*7c478bd9Sstevel@tonic-gate 	switch (error) {
467*7c478bd9Sstevel@tonic-gate 	case NS_LDAP_SUCCESS:	return (PWU_SUCCESS);
468*7c478bd9Sstevel@tonic-gate 	case NS_LDAP_OP_FAILED:	return (PWU_DENIED);
469*7c478bd9Sstevel@tonic-gate 	case NS_LDAP_NOTFOUND:	return (PWU_NOT_FOUND);
470*7c478bd9Sstevel@tonic-gate 	case NS_LDAP_MEMORY:	return (PWU_NOMEM);
471*7c478bd9Sstevel@tonic-gate 	case NS_LDAP_CONFIG:	return (PWU_NOT_FOUND);
472*7c478bd9Sstevel@tonic-gate 	case NS_LDAP_INTERNAL:
473*7c478bd9Sstevel@tonic-gate 		switch (pwd_status) {
474*7c478bd9Sstevel@tonic-gate 		case NS_PASSWD_EXPIRED:
475*7c478bd9Sstevel@tonic-gate 			return (PWU_DENIED);
476*7c478bd9Sstevel@tonic-gate 		case NS_PASSWD_CHANGE_NOT_ALLOWED:
477*7c478bd9Sstevel@tonic-gate 			return (PWU_CHANGE_NOT_ALLOWED);
478*7c478bd9Sstevel@tonic-gate 		case NS_PASSWD_TOO_SHORT:
479*7c478bd9Sstevel@tonic-gate 			return (PWU_PWD_TOO_SHORT);
480*7c478bd9Sstevel@tonic-gate 		case NS_PASSWD_INVALID_SYNTAX:
481*7c478bd9Sstevel@tonic-gate 			return (PWU_PWD_INVALID);
482*7c478bd9Sstevel@tonic-gate 		case NS_PASSWD_IN_HISTORY:
483*7c478bd9Sstevel@tonic-gate 			return (PWU_PWD_IN_HISTORY);
484*7c478bd9Sstevel@tonic-gate 		case NS_PASSWD_WITHIN_MIN_AGE:
485*7c478bd9Sstevel@tonic-gate 			return (PWU_WITHIN_MIN_AGE);
486*7c478bd9Sstevel@tonic-gate 		default:
487*7c478bd9Sstevel@tonic-gate 			return (PWU_SYSTEM_ERROR);
488*7c478bd9Sstevel@tonic-gate 		}
489*7c478bd9Sstevel@tonic-gate 	default:		return (PWU_SYSTEM_ERROR);
490*7c478bd9Sstevel@tonic-gate 	}
491*7c478bd9Sstevel@tonic-gate }
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate int
494*7c478bd9Sstevel@tonic-gate ldap_replaceattr(const char *dn, ns_ldap_attr_t **attrs, const char *binddn,
495*7c478bd9Sstevel@tonic-gate 	const char *pwd, int *pwd_status)
496*7c478bd9Sstevel@tonic-gate {
497*7c478bd9Sstevel@tonic-gate 	int		result = NS_LDAP_OP_FAILED;
498*7c478bd9Sstevel@tonic-gate 	int		ldaprc;
499*7c478bd9Sstevel@tonic-gate 	int		authstried = 0;
500*7c478bd9Sstevel@tonic-gate 	char		**certpath = NULL;
501*7c478bd9Sstevel@tonic-gate 	ns_auth_t	**app;
502*7c478bd9Sstevel@tonic-gate 	ns_auth_t	**authpp = NULL;
503*7c478bd9Sstevel@tonic-gate 	ns_auth_t	*authp = NULL;
504*7c478bd9Sstevel@tonic-gate 	ns_cred_t	*credp;
505*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*errorp = NULL;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	debug("%s: replace_ldapattr()", __FILE__);
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 	if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL)
510*7c478bd9Sstevel@tonic-gate 		return (PWU_NOMEM);
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	/* Fill in the user name and password */
513*7c478bd9Sstevel@tonic-gate 	if (dn == NULL || pwd == NULL)
514*7c478bd9Sstevel@tonic-gate 		goto out;
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	credp->cred.unix_cred.userID = strdup(binddn);
517*7c478bd9Sstevel@tonic-gate 	credp->cred.unix_cred.passwd = strdup(pwd);
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	/* get host certificate path, if one is configured */
520*7c478bd9Sstevel@tonic-gate 	ldaprc = __ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P,
521*7c478bd9Sstevel@tonic-gate 		(void ***)&certpath, &errorp);
522*7c478bd9Sstevel@tonic-gate 	if (ldaprc != NS_LDAP_SUCCESS)
523*7c478bd9Sstevel@tonic-gate 		goto out;
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	if (certpath && *certpath)
526*7c478bd9Sstevel@tonic-gate 		credp->hostcertpath = *certpath;
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	/* Load the service specific authentication method */
529*7c478bd9Sstevel@tonic-gate 	ldaprc = __ns_ldap_getServiceAuthMethods("passwd-cmd", &authpp,
530*7c478bd9Sstevel@tonic-gate 		&errorp);
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	if (ldaprc != NS_LDAP_SUCCESS)
533*7c478bd9Sstevel@tonic-gate 		goto out;
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate 	/*
536*7c478bd9Sstevel@tonic-gate 	 * if authpp is null, there is no serviceAuthenticationMethod
537*7c478bd9Sstevel@tonic-gate 	 * try default authenticationMethod
538*7c478bd9Sstevel@tonic-gate 	 */
539*7c478bd9Sstevel@tonic-gate 	if (authpp == NULL) {
540*7c478bd9Sstevel@tonic-gate 		ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp,
541*7c478bd9Sstevel@tonic-gate 			&errorp);
542*7c478bd9Sstevel@tonic-gate 		if (ldaprc != NS_LDAP_SUCCESS)
543*7c478bd9Sstevel@tonic-gate 			goto out;
544*7c478bd9Sstevel@tonic-gate 	}
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 	/*
547*7c478bd9Sstevel@tonic-gate 	 * if authpp is still null, then can not authenticate, syslog
548*7c478bd9Sstevel@tonic-gate 	 * error message and return error
549*7c478bd9Sstevel@tonic-gate 	 */
550*7c478bd9Sstevel@tonic-gate 	if (authpp == NULL) {
551*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
552*7c478bd9Sstevel@tonic-gate 		"passwdutil: no legal LDAP authentication method configured");
553*7c478bd9Sstevel@tonic-gate 		result = NS_LDAP_OP_FAILED;
554*7c478bd9Sstevel@tonic-gate 		goto out;
555*7c478bd9Sstevel@tonic-gate 	}
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	/*
558*7c478bd9Sstevel@tonic-gate 	 * Walk the array and try all authentication methods in order except
559*7c478bd9Sstevel@tonic-gate 	 * for "none".
560*7c478bd9Sstevel@tonic-gate 	 */
561*7c478bd9Sstevel@tonic-gate 	for (app = authpp; *app; app++) {
562*7c478bd9Sstevel@tonic-gate 		authp = *app;
563*7c478bd9Sstevel@tonic-gate 		/* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */
564*7c478bd9Sstevel@tonic-gate 		if (authp->type == NS_LDAP_AUTH_NONE)
565*7c478bd9Sstevel@tonic-gate 			continue;
566*7c478bd9Sstevel@tonic-gate 		authstried++;
567*7c478bd9Sstevel@tonic-gate 		credp->auth.type = authp->type;
568*7c478bd9Sstevel@tonic-gate 		credp->auth.tlstype = authp->tlstype;
569*7c478bd9Sstevel@tonic-gate 		credp->auth.saslmech = authp->saslmech;
570*7c478bd9Sstevel@tonic-gate 		credp->auth.saslopt = authp->saslopt;
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 		ldaprc = __ns_ldap_repAttr("shadow", dn,
573*7c478bd9Sstevel@tonic-gate 			(const ns_ldap_attr_t * const *)attrs,
574*7c478bd9Sstevel@tonic-gate 			credp, 0, &errorp);
575*7c478bd9Sstevel@tonic-gate 		if (ldaprc == NS_LDAP_SUCCESS) {
576*7c478bd9Sstevel@tonic-gate 			result = NS_LDAP_SUCCESS;
577*7c478bd9Sstevel@tonic-gate 			goto out;
578*7c478bd9Sstevel@tonic-gate 		}
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 		/*
581*7c478bd9Sstevel@tonic-gate 		 * other errors might need to be added to this list, for
582*7c478bd9Sstevel@tonic-gate 		 * the current supported mechanisms this is sufficient
583*7c478bd9Sstevel@tonic-gate 		 */
584*7c478bd9Sstevel@tonic-gate 		if ((ldaprc == NS_LDAP_INTERNAL) &&
585*7c478bd9Sstevel@tonic-gate 			(errorp->pwd_mgmt.status == NS_PASSWD_GOOD) &&
586*7c478bd9Sstevel@tonic-gate 			((errorp->status == LDAP_INAPPROPRIATE_AUTH) ||
587*7c478bd9Sstevel@tonic-gate 			(errorp->status == LDAP_INVALID_CREDENTIALS))) {
588*7c478bd9Sstevel@tonic-gate 			result = ldaprc;
589*7c478bd9Sstevel@tonic-gate 			goto out;
590*7c478bd9Sstevel@tonic-gate 		}
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate 		/*
593*7c478bd9Sstevel@tonic-gate 		 * If there is error related to password policy,
594*7c478bd9Sstevel@tonic-gate 		 * return it to caller
595*7c478bd9Sstevel@tonic-gate 		 */
596*7c478bd9Sstevel@tonic-gate 		if ((ldaprc == NS_LDAP_INTERNAL) &&
597*7c478bd9Sstevel@tonic-gate 			errorp->pwd_mgmt.status != NS_PASSWD_GOOD) {
598*7c478bd9Sstevel@tonic-gate 			*pwd_status = errorp->pwd_mgmt.status;
599*7c478bd9Sstevel@tonic-gate 			result = ldaprc;
600*7c478bd9Sstevel@tonic-gate 			goto out;
601*7c478bd9Sstevel@tonic-gate 		} else
602*7c478bd9Sstevel@tonic-gate 			*pwd_status = NS_PASSWD_GOOD;
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 		/* we don't really care about the error, just clean it up */
605*7c478bd9Sstevel@tonic-gate 		if (errorp)
606*7c478bd9Sstevel@tonic-gate 			(void) __ns_ldap_freeError(&errorp);
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 	if (authstried == 0) {
609*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
610*7c478bd9Sstevel@tonic-gate 		"passwdutil: no legal LDAP authentication method configured");
611*7c478bd9Sstevel@tonic-gate 		result = NS_LDAP_CONFIG;
612*7c478bd9Sstevel@tonic-gate 		goto out;
613*7c478bd9Sstevel@tonic-gate 	}
614*7c478bd9Sstevel@tonic-gate 	result = PWU_DENIED;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate out:
617*7c478bd9Sstevel@tonic-gate 	if (credp)
618*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeCred(&credp);
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 	if (authpp)
621*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeParam((void ***)&authpp);
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 	if (errorp)
624*7c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	return (result);
627*7c478bd9Sstevel@tonic-gate }
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate /*
632*7c478bd9Sstevel@tonic-gate  * ldap_putpwnam(name, oldpw, dummy, rep, buf)
633*7c478bd9Sstevel@tonic-gate  *
634*7c478bd9Sstevel@tonic-gate  * update the LDAP server with the attributes contained in 'buf'.
635*7c478bd9Sstevel@tonic-gate  * The dummy parameter is a placeholder for NIS+ where the old
636*7c478bd9Sstevel@tonic-gate  * RPC password is passwd.
637*7c478bd9Sstevel@tonic-gate  */
638*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
639*7c478bd9Sstevel@tonic-gate int
640*7c478bd9Sstevel@tonic-gate ldap_putpwnam(char *name, char *oldpw, char *dummy,
641*7c478bd9Sstevel@tonic-gate 	pwu_repository_t *rep, void *buf)
642*7c478bd9Sstevel@tonic-gate {
643*7c478bd9Sstevel@tonic-gate 	int res;
644*7c478bd9Sstevel@tonic-gate 	char *dn;	/* dn of user whose attributes we are changing */
645*7c478bd9Sstevel@tonic-gate 	char *binddn;	/* dn of user who is performing the change */
646*7c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *errorp;
647*7c478bd9Sstevel@tonic-gate 	ldapbuf_t *ldapbuf = (ldapbuf_t *)buf;
648*7c478bd9Sstevel@tonic-gate 	ns_ldap_attr_t **attrs = ldapbuf->attrs;
649*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
650*7c478bd9Sstevel@tonic-gate 	int pwd_status;
651*7c478bd9Sstevel@tonic-gate 	uid_t uid;
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	if (strcmp(name, "root") == 0)
654*7c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	/*
657*7c478bd9Sstevel@tonic-gate 	 * The LDAP server checks whether we are permitted to perform
658*7c478bd9Sstevel@tonic-gate 	 * the requested change. We need to send the name of the user
659*7c478bd9Sstevel@tonic-gate 	 * who is executing this piece of code, together with his
660*7c478bd9Sstevel@tonic-gate 	 * current password to the server.
661*7c478bd9Sstevel@tonic-gate 	 * If this is executed by a normal user changing his/her own
662*7c478bd9Sstevel@tonic-gate 	 * password, this will simply be the OLD password that is to
663*7c478bd9Sstevel@tonic-gate 	 * be changed.
664*7c478bd9Sstevel@tonic-gate 	 * Specific case if the user who is executing this piece
665*7c478bd9Sstevel@tonic-gate 	 * of code is root. We will then issue the LDAP request
666*7c478bd9Sstevel@tonic-gate 	 * with the DN of the user we want to change the passwd of.
667*7c478bd9Sstevel@tonic-gate 	 */
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 	/*
670*7c478bd9Sstevel@tonic-gate 	 * convert name of user whose attributes we are changing
671*7c478bd9Sstevel@tonic-gate 	 * to a distinguished name
672*7c478bd9Sstevel@tonic-gate 	 */
673*7c478bd9Sstevel@tonic-gate 	res = __ns_ldap_uid2dn(name, &dn, NULL, &errorp);
674*7c478bd9Sstevel@tonic-gate 	if (res != NS_LDAP_SUCCESS)
675*7c478bd9Sstevel@tonic-gate 		goto out;
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 	/*
678*7c478bd9Sstevel@tonic-gate 	 * create a dn for the user who is executing this code
679*7c478bd9Sstevel@tonic-gate 	 */
680*7c478bd9Sstevel@tonic-gate 	uid = getuid();
681*7c478bd9Sstevel@tonic-gate 	if (uid == 0) {
682*7c478bd9Sstevel@tonic-gate 		if ((pw = getpwnam_from(name, rep, REP_LDAP)) == NULL) {
683*7c478bd9Sstevel@tonic-gate 			res = NS_LDAP_OP_FAILED;
684*7c478bd9Sstevel@tonic-gate 			goto out;
685*7c478bd9Sstevel@tonic-gate 		}
686*7c478bd9Sstevel@tonic-gate 	} else if ((pw = getpwuid_from(uid, rep, REP_LDAP)) == NULL) {
687*7c478bd9Sstevel@tonic-gate 		/*
688*7c478bd9Sstevel@tonic-gate 		 * User executing this code is not known to the LDAP
689*7c478bd9Sstevel@tonic-gate 		 * server. This operation is to be denied
690*7c478bd9Sstevel@tonic-gate 		 */
691*7c478bd9Sstevel@tonic-gate 		res = NS_LDAP_OP_FAILED;
692*7c478bd9Sstevel@tonic-gate 		goto out;
693*7c478bd9Sstevel@tonic-gate 	}
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate 	res = __ns_ldap_uid2dn(pw->pw_name, &binddn, NULL, &errorp);
696*7c478bd9Sstevel@tonic-gate 	if (res != NS_LDAP_SUCCESS)
697*7c478bd9Sstevel@tonic-gate 		goto out;
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 	res = ldap_replaceattr(dn, attrs, binddn, oldpw,
700*7c478bd9Sstevel@tonic-gate 			&pwd_status);
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate out:
703*7c478bd9Sstevel@tonic-gate 	while (*attrs) {
704*7c478bd9Sstevel@tonic-gate 		free((*attrs)->attrvalue[0]);
705*7c478bd9Sstevel@tonic-gate 		free(*attrs);
706*7c478bd9Sstevel@tonic-gate 		attrs++;
707*7c478bd9Sstevel@tonic-gate 	}
708*7c478bd9Sstevel@tonic-gate 	if (ldapbuf->passwd) {
709*7c478bd9Sstevel@tonic-gate 		(void) memset(ldapbuf->passwd, 0, strlen(ldapbuf->passwd));
710*7c478bd9Sstevel@tonic-gate 		free(ldapbuf->passwd);
711*7c478bd9Sstevel@tonic-gate 	}
712*7c478bd9Sstevel@tonic-gate 	if (ldapbuf->pwd)
713*7c478bd9Sstevel@tonic-gate 		free_pwd(ldapbuf->pwd);
714*7c478bd9Sstevel@tonic-gate 	free(dn);
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	return (ldap_to_pwu_code(res, pwd_status));
717*7c478bd9Sstevel@tonic-gate }
718