xref: /titanic_51/usr/src/lib/nsswitch/ldap/common/getspent.c (revision dd1104fbe0f0f41434502f335b9f0b34999f771c)
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
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * 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 /*
22*dd1104fbSMichen Chang  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <shadow.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include "ldap_common.h"
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /* shadow attributes filters */
317c478bd9Sstevel@tonic-gate #define	_S_UID			"uid"
327c478bd9Sstevel@tonic-gate #define	_S_USERPASSWORD		"userpassword"
33*dd1104fbSMichen Chang #define	_S_LASTCHANGE		"shadowlastchange"
34*dd1104fbSMichen Chang #define	_S_MIN			"shadowmin"
35*dd1104fbSMichen Chang #define	_S_MAX			"shadowmax"
36*dd1104fbSMichen Chang #define	_S_WARNING		"shadowwarning"
37*dd1104fbSMichen Chang #define	_S_INACTIVE		"shadowinactive"
38*dd1104fbSMichen Chang #define	_S_EXPIRE		"shadowexpire"
397c478bd9Sstevel@tonic-gate #define	_S_FLAG			"shadowflag"
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #define	_F_GETSPNAM		"(&(objectClass=shadowAccount)(uid=%s))"
427c478bd9Sstevel@tonic-gate #define	_F_GETSPNAM_SSD		"(&(%%s)(uid=%s))"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate static const char *sp_attrs[] = {
457c478bd9Sstevel@tonic-gate 	_S_UID,
467c478bd9Sstevel@tonic-gate 	_S_USERPASSWORD,
47*dd1104fbSMichen Chang 	_S_LASTCHANGE,
48*dd1104fbSMichen Chang 	_S_MIN,
49*dd1104fbSMichen Chang 	_S_MAX,
50*dd1104fbSMichen Chang 	_S_WARNING,
51*dd1104fbSMichen Chang 	_S_INACTIVE,
52*dd1104fbSMichen Chang 	_S_EXPIRE,
537c478bd9Sstevel@tonic-gate 	_S_FLAG,
547c478bd9Sstevel@tonic-gate 	(char *)NULL
557c478bd9Sstevel@tonic-gate };
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*
58cb5caa98Sdjl  * _nss_ldap_shadow2str is the data marshaling method for the shadow getXbyY
597c478bd9Sstevel@tonic-gate  * (e.g., getspnam(), getspent()) backend processes. This method is called after
607c478bd9Sstevel@tonic-gate  * a successful ldap search has been performed. This method will parse the
61cb5caa98Sdjl  * ldap search values into the file format.
62cb5caa98Sdjl  * e.g.
63cb5caa98Sdjl  *
64cb5caa98Sdjl  * myname:gaBXNJuz4JDmA:6445::::::
65cb5caa98Sdjl  *
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate static int
69cb5caa98Sdjl _nss_ldap_shadow2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate 	int		nss_result;
72cb5caa98Sdjl 	int		buflen = 0;
73*dd1104fbSMichen Chang 	int		shadow_update_enabled;
747c478bd9Sstevel@tonic-gate 	unsigned long	len = 0L;
75cb5caa98Sdjl 	char		*tmp, *buffer = NULL;
76cb5caa98Sdjl 	char		*pw_passwd = NULL;
777c478bd9Sstevel@tonic-gate 	ns_ldap_result_t	*result = be->result;
78*dd1104fbSMichen Chang 	char		**uid, **passwd, **last, **smin, **smax;
79*dd1104fbSMichen Chang 	char		**warning, **inactive, **expire, **flag;
80*dd1104fbSMichen Chang 	char		*last_str, *min_str, *max_str, *warning_str;
81*dd1104fbSMichen Chang 	char		*inactive_str, *expire_str, *flag_str;
827c478bd9Sstevel@tonic-gate 
83cb5caa98Sdjl 	if (result == NULL)
84cb5caa98Sdjl 		return (NSS_STR_PARSE_PARSE);
85cb5caa98Sdjl 	buflen = argp->buf.buflen;
867c478bd9Sstevel@tonic-gate 
87cb5caa98Sdjl 	nss_result = NSS_STR_PARSE_SUCCESS;
88cb5caa98Sdjl 	(void) memset(argp->buf.buffer, 0, buflen);
89cb5caa98Sdjl 
90cb5caa98Sdjl 	uid = __ns_ldap_getAttr(result->entry, _S_UID);
91cb5caa98Sdjl 	if (uid == NULL || uid[0] == NULL || (strlen(uid[0]) < 1)) {
92cb5caa98Sdjl 		nss_result = NSS_STR_PARSE_PARSE;
93cb5caa98Sdjl 		goto result_spd2str;
947c478bd9Sstevel@tonic-gate 	}
95cb5caa98Sdjl 	len += strlen(uid[0]);
967c478bd9Sstevel@tonic-gate 
97cb5caa98Sdjl 	passwd = __ns_ldap_getAttr(result->entry, _S_USERPASSWORD);
98a1e48794Schinlong 	if (passwd == NULL || passwd[0] == NULL) {
99a1e48794Schinlong 		/*
100a1e48794Schinlong 		 * ACL does not allow userpassword to return or
101a1e48794Schinlong 		 * userpassword is not defined
102a1e48794Schinlong 		 */
10366e150d7SJohn Sonnenschein 		pw_passwd = NOPWDRTR;
104a1e48794Schinlong 	} else if (strcmp(passwd[0], "") == 0) {
105a1e48794Schinlong 		/*
106a1e48794Schinlong 		 * An empty password is not supported
107a1e48794Schinlong 		 */
108a1e48794Schinlong 		nss_result = NSS_STR_PARSE_PARSE;
109a1e48794Schinlong 		goto result_spd2str;
110cb5caa98Sdjl 	} else {
111cb5caa98Sdjl 		if ((tmp = strstr(passwd[0], "{crypt}")) != NULL ||
112cb5caa98Sdjl 		    (tmp = strstr(passwd[0], "{CRYPT}")) != NULL) {
113cb5caa98Sdjl 			if (tmp != passwd[0])
11466e150d7SJohn Sonnenschein 				pw_passwd = NOPWDRTR;
115*dd1104fbSMichen Chang 			else {
116cb5caa98Sdjl 				pw_passwd = tmp + strlen("{crypt}");
117*dd1104fbSMichen Chang 				if (strcmp(pw_passwd,
118*dd1104fbSMichen Chang 				    NS_LDAP_NO_UNIX_PASSWORD) == 0)
119*dd1104fbSMichen Chang 					*pw_passwd = '\0';
120*dd1104fbSMichen Chang 			}
1217c478bd9Sstevel@tonic-gate 		} else {
12266e150d7SJohn Sonnenschein 		/* mark password as not retrievable */
12366e150d7SJohn Sonnenschein 			pw_passwd = NOPWDRTR;
1247c478bd9Sstevel@tonic-gate 		}
1257c478bd9Sstevel@tonic-gate 	}
126cb5caa98Sdjl 	len += strlen(pw_passwd);
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	/*
129*dd1104fbSMichen Chang 	 * If shadow update is not enabled, ignore the following
130*dd1104fbSMichen Chang 	 * password aging related attributes:
1317c478bd9Sstevel@tonic-gate 	 * -- shadowlastchange
1327c478bd9Sstevel@tonic-gate 	 * -- shadowmin
1337c478bd9Sstevel@tonic-gate 	 * -- shadowmax
1347c478bd9Sstevel@tonic-gate 	 * -- shadowwarning
1357c478bd9Sstevel@tonic-gate 	 * -- shadowinactive
1367c478bd9Sstevel@tonic-gate 	 * -- shadowexpire
137*dd1104fbSMichen Chang 	 * When shadow update is not enabled, the LDAP naming
138*dd1104fbSMichen Chang 	 * service does not support the password aging fields
139*dd1104fbSMichen Chang 	 * defined in the shadow structure. These fields, sp_lstchg,
1407c478bd9Sstevel@tonic-gate 	 * sp_min, sp_max, sp_warn, sp_inact, and sp_expire,
141cb5caa98Sdjl 	 * will be set to -1 by the front end marshaller.
1427c478bd9Sstevel@tonic-gate 	 */
143*dd1104fbSMichen Chang 
144*dd1104fbSMichen Chang 	shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
145*dd1104fbSMichen Chang 	if (shadow_update_enabled) {
146*dd1104fbSMichen Chang 		last = __ns_ldap_getAttr(result->entry, _S_LASTCHANGE);
147*dd1104fbSMichen Chang 		if (last == NULL || last[0] == NULL)
148*dd1104fbSMichen Chang 			last_str = _NO_VALUE;
149*dd1104fbSMichen Chang 		else
150*dd1104fbSMichen Chang 			last_str = last[0];
151*dd1104fbSMichen Chang 		len += strlen(last_str);
152*dd1104fbSMichen Chang 
153*dd1104fbSMichen Chang 		smin = __ns_ldap_getAttr(result->entry, _S_MIN);
154*dd1104fbSMichen Chang 		if (smin == NULL || smin[0] == NULL)
155*dd1104fbSMichen Chang 			min_str = _NO_VALUE;
156*dd1104fbSMichen Chang 		else
157*dd1104fbSMichen Chang 			min_str = smin[0];
158*dd1104fbSMichen Chang 		len += strlen(min_str);
159*dd1104fbSMichen Chang 
160*dd1104fbSMichen Chang 		smax = __ns_ldap_getAttr(result->entry, _S_MAX);
161*dd1104fbSMichen Chang 		if (smax == NULL || smax[0] == NULL)
162*dd1104fbSMichen Chang 			max_str = _NO_VALUE;
163*dd1104fbSMichen Chang 		else
164*dd1104fbSMichen Chang 			max_str = smax[0];
165*dd1104fbSMichen Chang 		len += strlen(max_str);
166*dd1104fbSMichen Chang 
167*dd1104fbSMichen Chang 		warning = __ns_ldap_getAttr(result->entry, _S_WARNING);
168*dd1104fbSMichen Chang 		if (warning == NULL || warning[0] == NULL)
169*dd1104fbSMichen Chang 			warning_str = _NO_VALUE;
170*dd1104fbSMichen Chang 		else
171*dd1104fbSMichen Chang 			warning_str = warning[0];
172*dd1104fbSMichen Chang 		len += strlen(warning_str);
173*dd1104fbSMichen Chang 
174*dd1104fbSMichen Chang 		inactive = __ns_ldap_getAttr(result->entry, _S_INACTIVE);
175*dd1104fbSMichen Chang 		if (inactive == NULL || inactive[0] == NULL)
176*dd1104fbSMichen Chang 			inactive_str = _NO_VALUE;
177*dd1104fbSMichen Chang 		else
178*dd1104fbSMichen Chang 			inactive_str = inactive[0];
179*dd1104fbSMichen Chang 		len += strlen(inactive_str);
180*dd1104fbSMichen Chang 
181*dd1104fbSMichen Chang 		expire = __ns_ldap_getAttr(result->entry, _S_EXPIRE);
182*dd1104fbSMichen Chang 		if (expire == NULL || expire[0] == NULL)
183*dd1104fbSMichen Chang 			expire_str = _NO_VALUE;
184*dd1104fbSMichen Chang 		else
185*dd1104fbSMichen Chang 			expire_str = expire[0];
186*dd1104fbSMichen Chang 		len += strlen(expire_str);
187*dd1104fbSMichen Chang 	}
188*dd1104fbSMichen Chang 
189cb5caa98Sdjl 	flag = __ns_ldap_getAttr(result->entry, _S_FLAG);
190cb5caa98Sdjl 	if (flag == NULL || flag[0] == NULL)
191cb5caa98Sdjl 		flag_str = _NO_VALUE;
192cb5caa98Sdjl 	else
193cb5caa98Sdjl 		flag_str = flag[0];
1947c478bd9Sstevel@tonic-gate 
195cb5caa98Sdjl 	/* 9 = 8 ':' + 1 '\0' */
196cb5caa98Sdjl 	len += strlen(flag_str) + 9;
197cb5caa98Sdjl 
198cb5caa98Sdjl 	if (len > buflen) {
199cb5caa98Sdjl 		nss_result = NSS_STR_PARSE_ERANGE;
200cb5caa98Sdjl 		goto result_spd2str;
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
203cb5caa98Sdjl 	if (argp->buf.result != NULL) {
204cb5caa98Sdjl 		be->buffer = calloc(1, len);
205cb5caa98Sdjl 		if (be->buffer == NULL) {
206cb5caa98Sdjl 			nss_result = NSS_STR_PARSE_PARSE;
207cb5caa98Sdjl 			goto result_spd2str;
2087c478bd9Sstevel@tonic-gate 		}
209cb5caa98Sdjl 		buffer = be->buffer;
210cb5caa98Sdjl 	} else
211cb5caa98Sdjl 		buffer = argp->buf.buffer;
2127c478bd9Sstevel@tonic-gate 
213*dd1104fbSMichen Chang 	if (shadow_update_enabled) {
214*dd1104fbSMichen Chang 		(void) snprintf(buffer, len, "%s:%s:%s:%s:%s:%s:%s:%s:%s",
215*dd1104fbSMichen Chang 		    uid[0], pw_passwd, last_str, min_str, max_str, warning_str,
216*dd1104fbSMichen Chang 		    inactive_str, expire_str, flag_str);
217*dd1104fbSMichen Chang 	} else {
218cb5caa98Sdjl 		(void) snprintf(buffer, len, "%s:%s:::::::%s",
219cb5caa98Sdjl 		    uid[0], pw_passwd, flag_str);
220*dd1104fbSMichen Chang 	}
2217c478bd9Sstevel@tonic-gate 
222cb5caa98Sdjl 	/* The front end marhsaller doesn't need the trailing null */
223cb5caa98Sdjl 	if (argp->buf.result != NULL)
224cb5caa98Sdjl 		be->buflen = strlen(be->buffer);
225cb5caa98Sdjl result_spd2str:
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
2287c478bd9Sstevel@tonic-gate 	return ((int)nss_result);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate /*
2327c478bd9Sstevel@tonic-gate  * getbynam gets a passwd entry by uid name. This function constructs an ldap
2337c478bd9Sstevel@tonic-gate  * search filter using the name invocation parameter and the getspnam search
2347c478bd9Sstevel@tonic-gate  * filter defined. Once the filter is constructed we search for a matching
2357c478bd9Sstevel@tonic-gate  * entry and marshal the data results into struct shadow for the frontend
2367c478bd9Sstevel@tonic-gate  * process. The function _nss_ldap_shadow2ent performs the data marshaling.
2377c478bd9Sstevel@tonic-gate  */
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate static nss_status_t
2407c478bd9Sstevel@tonic-gate getbynam(ldap_backend_ptr be, void *a)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2437c478bd9Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
2447c478bd9Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
2457c478bd9Sstevel@tonic-gate 	char		name[SEARCHFILTERLEN + 1];
2467c478bd9Sstevel@tonic-gate 	int		ret;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
2497c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETSPNAM, name);
2527c478bd9Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
2537c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata), _F_GETSPNAM_SSD, name);
2567c478bd9Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
2577c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	return (_nss_ldap_lookup(be, argp, _SHADOW, searchfilter, NULL,
2607c478bd9Sstevel@tonic-gate 	    _merge_SSD_filter, userdata));
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate static ldap_backend_op_t sp_ops[] = {
2647c478bd9Sstevel@tonic-gate     _nss_ldap_destr,
2657c478bd9Sstevel@tonic-gate     _nss_ldap_endent,
2667c478bd9Sstevel@tonic-gate     _nss_ldap_setent,
2677c478bd9Sstevel@tonic-gate     _nss_ldap_getent,
2687c478bd9Sstevel@tonic-gate     getbynam
2697c478bd9Sstevel@tonic-gate };
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate  * _nss_ldap_passwd_constr is where life begins. This function calls the
2747c478bd9Sstevel@tonic-gate  * generic ldap constructor function to define and build the abstract
2757c478bd9Sstevel@tonic-gate  * data types required to support ldap operations.
2767c478bd9Sstevel@tonic-gate  */
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate /*ARGSUSED0*/
2797c478bd9Sstevel@tonic-gate nss_backend_t *
2807c478bd9Sstevel@tonic-gate _nss_ldap_shadow_constr(const char *dummy1, const char *dummy2,
2817c478bd9Sstevel@tonic-gate 			const char *dummy3)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(sp_ops,
2857c478bd9Sstevel@tonic-gate 	    sizeof (sp_ops)/sizeof (sp_ops[0]),
286cb5caa98Sdjl 	    _SHADOW, sp_attrs, _nss_ldap_shadow2str));
2877c478bd9Sstevel@tonic-gate }
288