xref: /titanic_52/usr/src/lib/nsswitch/ldap/common/getspent.c (revision ea8dc4b6d2251b437950c0056bc626b311c73c27)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <shadow.h>
30 #include <stdlib.h>
31 #include "ldap_common.h"
32 
33 /* shadow attributes filters */
34 #define	_S_CN			"cn"
35 #define	_S_UID			"uid"
36 #define	_S_USERPASSWORD		"userpassword"
37 #define	_S_FLAG			"shadowflag"
38 
39 #define	_F_GETSPNAM		"(&(objectClass=shadowAccount)(uid=%s))"
40 #define	_F_GETSPNAM_SSD		"(&(%%s)(uid=%s))"
41 
42 static const char *sp_attrs[] = {
43 	_S_UID,
44 	_S_USERPASSWORD,
45 	_S_FLAG,
46 	(char *)NULL
47 };
48 
49 
50 extern ns_ldap_attr_t *getattr(ns_ldap_result_t *result, int i);
51 
52 /*
53  * _nss_ldap_shadow2ent is the data marshaling method for the passwd getXbyY
54  * (e.g., getspnam(), getspent()) backend processes. This method is called after
55  * a successful ldap search has been performed. This method will parse the
56  * ldap search values into struct spwd = argp->buf.buffer which the frontend
57  * process expects. Three error conditions are expected and returned to
58  * nsswitch.
59  */
60 
61 static int
62 _nss_ldap_shadow2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
63 {
64 	int		i = 0;
65 	int		nss_result;
66 	int		buflen = (int)0;
67 	unsigned long	len = 0L;
68 	char		*buffer = (char *)NULL;
69 	char		*ceiling = (char *)NULL;
70 	char		*pw_passwd = (char *)NULL;
71 	char		*nullstring = (char *)NULL;
72 	char		np[] = "*NP*";
73 	ns_ldap_result_t	*result = be->result;
74 	ns_ldap_attr_t	*attrptr;
75 	long		ltmp = (long)0L;
76 	struct spwd	*spd = (struct spwd *)NULL;
77 
78 #ifdef DEBUG
79 	(void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow2ent]\n");
80 #endif /* DEBUG */
81 
82 	buffer = argp->buf.buffer;
83 	buflen = (size_t)argp->buf.buflen;
84 	if (!argp->buf.result) {
85 		nss_result = (int)NSS_STR_PARSE_ERANGE;
86 		goto result_spd2ent;
87 	}
88 	spd = (struct spwd *)argp->buf.result;
89 	ceiling = buffer + buflen;
90 	nullstring = (buffer + (buflen - 1));
91 
92 	/* Default values */
93 	spd->sp_lstchg = -1;	spd->sp_min    = -1;
94 	spd->sp_max    = -1;	spd->sp_warn   = -1;
95 	spd->sp_inact  = -1;	spd->sp_expire = -1;
96 	spd->sp_flag   = 0;	spd->sp_pwdp = NULL;
97 
98 	nss_result = (int)NSS_STR_PARSE_SUCCESS;
99 	(void) memset(buffer, 0, buflen);
100 
101 	attrptr = getattr(result, 0);
102 	if (attrptr == NULL) {
103 		nss_result = (int)NSS_STR_PARSE_PARSE;
104 		goto result_spd2ent;
105 	}
106 
107 	for (i = 0; i < result->entry->attr_count; i++) {
108 		attrptr = getattr(result, i);
109 		if (strcasecmp(attrptr->attrname, _S_UID) == 0) {
110 			if ((attrptr->attrvalue[0] == NULL) ||
111 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
112 				nss_result = (int)NSS_STR_PARSE_PARSE;
113 				goto result_spd2ent;
114 			}
115 			spd->sp_namp = buffer;
116 			buffer += len + 1;
117 			if (buffer >= ceiling) {
118 				nss_result = (int)NSS_STR_PARSE_ERANGE;
119 				goto result_spd2ent;
120 			}
121 			(void) strcpy(spd->sp_namp, attrptr->attrvalue[0]);
122 			continue;
123 		}
124 		if (strcasecmp(attrptr->attrname, _S_USERPASSWORD) == 0) {
125 			if (attrptr->attrvalue[0] == '\0') {
126 				spd->sp_pwdp = nullstring;
127 				nss_result = (int)NSS_STR_PARSE_PARSE;
128 				goto result_spd2ent;
129 			}
130 			pw_passwd = attrptr->attrvalue[0];
131 			if (pw_passwd) {
132 				char	*tmp;
133 
134 				if ((tmp = strstr(pw_passwd, "{crypt}"))
135 					!= NULL) {
136 					if (tmp != pw_passwd)
137 						pw_passwd = np;
138 					else
139 						pw_passwd += 7;
140 				} else if ((tmp = strstr(pw_passwd, "{CRYPT}"))
141 					!= NULL) {
142 					if (tmp != pw_passwd)
143 						pw_passwd = np;
144 					else
145 						pw_passwd += 7;
146 				} else {
147 					pw_passwd = np;
148 				}
149 			}
150 			len = (unsigned long)strlen(pw_passwd);
151 			if (len < 1) {
152 				spd->sp_pwdp = nullstring;
153 			} else {
154 				spd->sp_pwdp = buffer;
155 				buffer += len + 1;
156 				if (buffer >= ceiling) {
157 					nss_result = (int)NSS_STR_PARSE_ERANGE;
158 					goto result_spd2ent;
159 				}
160 			}
161 			(void) strcpy(spd->sp_pwdp, pw_passwd);
162 		}
163 
164 		/*
165 		 * Ignore the following password aging related attributes:
166 		 * -- shadowlastchange
167 		 * -- shadowmin
168 		 * -- shadowmax
169 		 * -- shadowwarning
170 		 * -- shadowinactive
171 		 * -- shadowexpire
172 		 * This is because the LDAP naming service does not
173 		 * really support the password aging fields defined
174 		 * in the shadow structure. These fields, sp_lstchg,
175 		 * sp_min, sp_max, sp_warn, sp_inact, and sp_expire,
176 		 * have been set to -1.
177 		 */
178 
179 		if (strcasecmp(attrptr->attrname, _S_FLAG) == 0) {
180 			if (attrptr->attrvalue[0] == '\0') {
181 				nss_result = (int)NSS_STR_PARSE_PARSE;
182 				goto result_spd2ent;
183 			}
184 			errno = 0;
185 			ltmp = strtol(attrptr->attrvalue[0], (char **)NULL, 10);
186 			if (errno != 0) {
187 				nss_result = (int)NSS_STR_PARSE_PARSE;
188 				goto result_spd2ent;
189 			}
190 			spd->sp_flag = (int)ltmp;
191 			continue;
192 		}
193 	}
194 
195 	/* we will not allow for an empty password to be */
196 	/* returned to the front end as this is not a supported */
197 	/* configuration.  Since we got to this point without */
198 	/* the password being set, we assume that no password was */
199 	/* set on the server which is consider a misconfiguration. */
200 	/* We will proceed and set the password to *NP* as no password */
201 	/* is not supported */
202 
203 	if (spd->sp_pwdp == NULL) {
204 		spd->sp_pwdp = buffer;
205 		buffer += strlen(np) + 1;
206 		if (buffer >= ceiling) {
207 			nss_result = (int)NSS_STR_PARSE_ERANGE;
208 			goto result_spd2ent;
209 		}
210 		strcpy(spd->sp_pwdp, np);
211 	}
212 
213 
214 #ifdef DEBUG
215 	(void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow2ent]\n");
216 	(void) fprintf(stdout, "       sp_namp: [%s]\n", spd->sp_namp);
217 	(void) fprintf(stdout, "       sp_pwdp: [%s]\n", spd->sp_pwdp);
218 	(void) fprintf(stdout, "     sp_latchg: [%d]\n", spd->sp_lstchg);
219 	(void) fprintf(stdout, "        sp_min: [%d]\n", spd->sp_min);
220 	(void) fprintf(stdout, "        sp_max: [%d]\n", spd->sp_max);
221 	(void) fprintf(stdout, "       sp_warn: [%d]\n", spd->sp_warn);
222 	(void) fprintf(stdout, "      sp_inact: [%d]\n", spd->sp_inact);
223 	(void) fprintf(stdout, "     sp_expire: [%d]\n", spd->sp_expire);
224 	(void) fprintf(stdout, "       sp_flag: [%d]\n", spd->sp_flag);
225 #endif /* DEBUG */
226 
227 result_spd2ent:
228 
229 	(void) __ns_ldap_freeResult(&be->result);
230 	return ((int)nss_result);
231 }
232 
233 /*
234  * getbynam gets a passwd entry by uid name. This function constructs an ldap
235  * search filter using the name invocation parameter and the getspnam search
236  * filter defined. Once the filter is constructed we search for a matching
237  * entry and marshal the data results into struct shadow for the frontend
238  * process. The function _nss_ldap_shadow2ent performs the data marshaling.
239  */
240 
241 static nss_status_t
242 getbynam(ldap_backend_ptr be, void *a)
243 {
244 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
245 	char		searchfilter[SEARCHFILTERLEN];
246 	char		userdata[SEARCHFILTERLEN];
247 	char		name[SEARCHFILTERLEN + 1];
248 	int		len;
249 	int		ret;
250 
251 #ifdef DEBUG
252 	(void) fprintf(stdout, "\n[getspent.c: getbynam]\n");
253 #endif /* DEBUG */
254 
255 	if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
256 		return ((nss_status_t)NSS_NOTFOUND);
257 
258 	ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETSPNAM, name);
259 	if (ret >= sizeof (searchfilter) || ret < 0)
260 		return ((nss_status_t)NSS_NOTFOUND);
261 
262 	ret = snprintf(userdata, sizeof (userdata), _F_GETSPNAM_SSD, name);
263 	if (ret >= sizeof (userdata) || ret < 0)
264 		return ((nss_status_t)NSS_NOTFOUND);
265 
266 	return (_nss_ldap_lookup(be, argp, _SHADOW, searchfilter, NULL,
267 		_merge_SSD_filter, userdata));
268 }
269 
270 static ldap_backend_op_t sp_ops[] = {
271     _nss_ldap_destr,
272     _nss_ldap_endent,
273     _nss_ldap_setent,
274     _nss_ldap_getent,
275     getbynam
276 };
277 
278 
279 /*
280  * _nss_ldap_passwd_constr is where life begins. This function calls the
281  * generic ldap constructor function to define and build the abstract
282  * data types required to support ldap operations.
283  */
284 
285 /*ARGSUSED0*/
286 nss_backend_t *
287 _nss_ldap_shadow_constr(const char *dummy1, const char *dummy2,
288 			const char *dummy3)
289 {
290 
291 #ifdef DEBUG
292 	(void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow_constr]\n");
293 #endif /* DEBUG */
294 
295 	return ((nss_backend_t *)_nss_ldap_constr(sp_ops,
296 		sizeof (sp_ops)/sizeof (sp_ops[0]),
297 		_SHADOW, sp_attrs, _nss_ldap_shadow2ent));
298 }
299