1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include "ldap_common.h"
30*0Sstevel@tonic-gate #include <malloc.h>
31*0Sstevel@tonic-gate #include <synch.h>
32*0Sstevel@tonic-gate #include <syslog.h>
33*0Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
34*0Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
35*0Sstevel@tonic-gate #include <thread.h>
36*0Sstevel@tonic-gate #include <ctype.h>
37*0Sstevel@tonic-gate #include <stdlib.h>
38*0Sstevel@tonic-gate #include <signal.h>
39*0Sstevel@tonic-gate #include <sys/stat.h>
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate /* getent attributes filters */
42*0Sstevel@tonic-gate #define	_F_GETALIASENT		"(objectClass=rfc822MailGroup)"
43*0Sstevel@tonic-gate #define	_F_GETAUTHNAME		"(objectClass=SolarisAuthAttr)"
44*0Sstevel@tonic-gate #define	_F_GETAUUSERNAME	"(objectClass=SolarisAuditUser)"
45*0Sstevel@tonic-gate #define	_F_GETEXECNAME		"(objectClass=SolarisExecAttr)"
46*0Sstevel@tonic-gate #define	_F_GETGRENT		"(objectClass=posixGroup)"
47*0Sstevel@tonic-gate #define	_F_GETHOSTENT		"(objectClass=ipHost)"
48*0Sstevel@tonic-gate #define	_F_GETNETENT		"(objectClass=ipNetwork)"
49*0Sstevel@tonic-gate #define	_F_GETPROFNAME		"(objectClass=SolarisProfAttr)"
50*0Sstevel@tonic-gate #define	_F_GETPROTOENT		"(objectClass=ipProtocol)"
51*0Sstevel@tonic-gate #define	_F_GETPWENT		"(objectClass=posixAccount)"
52*0Sstevel@tonic-gate #define	_F_GETPRINTERENT	"(objectClass=sunPrinter)"
53*0Sstevel@tonic-gate #define	_F_GETRPCENT		"(objectClass=oncRpc)"
54*0Sstevel@tonic-gate #define	_F_GETSERVENT		"(objectClass=ipService)"
55*0Sstevel@tonic-gate #define	_F_GETSPENT		"(objectclass=shadowAccount)"
56*0Sstevel@tonic-gate #define	_F_GETUSERNAME		"(objectClass=SolarisUserAttr)"
57*0Sstevel@tonic-gate #define	_F_GETPROJENT		"(objectClass=SolarisProject)"
58*0Sstevel@tonic-gate #define	_F_GETENT_SSD		"(%s)"
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate static struct gettablefilter {
61*0Sstevel@tonic-gate 	char *tablename;
62*0Sstevel@tonic-gate 	char *tablefilter;
63*0Sstevel@tonic-gate } gettablefilterent[] = {
64*0Sstevel@tonic-gate 	{(char *)_PASSWD,	(char *)_F_GETPWENT},
65*0Sstevel@tonic-gate 	{(char *)_SHADOW,	(char *)_F_GETSPENT},
66*0Sstevel@tonic-gate 	{(char *)_GROUP,	(char *)_F_GETGRENT},
67*0Sstevel@tonic-gate 	{(char *)_HOSTS,	(char *)_F_GETHOSTENT},
68*0Sstevel@tonic-gate 	{(char *)_NETWORKS,	(char *)_F_GETNETENT},
69*0Sstevel@tonic-gate 	{(char *)_PROTOCOLS,	(char *)_F_GETPROTOENT},
70*0Sstevel@tonic-gate 	{(char *)_RPC,		(char *)_F_GETRPCENT},
71*0Sstevel@tonic-gate 	{(char *)_ALIASES,	(char *)_F_GETALIASENT},
72*0Sstevel@tonic-gate 	{(char *)_SERVICES,	(char *)_F_GETSERVENT},
73*0Sstevel@tonic-gate 	{(char *)_AUUSER,	(char *)_F_GETAUUSERNAME},
74*0Sstevel@tonic-gate 	{(char *)_AUTHATTR,	(char *)_F_GETAUTHNAME},
75*0Sstevel@tonic-gate 	{(char *)_EXECATTR,	(char *)_F_GETEXECNAME},
76*0Sstevel@tonic-gate 	{(char *)_PROFATTR,	(char *)_F_GETPROFNAME},
77*0Sstevel@tonic-gate 	{(char *)_USERATTR,	(char *)_F_GETUSERNAME},
78*0Sstevel@tonic-gate 	{(char *)_PROJECT,	(char *)_F_GETPROJENT},
79*0Sstevel@tonic-gate 	{(char *)_PRINTERS,	(char *)_F_GETPRINTERENT},
80*0Sstevel@tonic-gate 	{(char *)NULL,		(char *)NULL}
81*0Sstevel@tonic-gate };
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate nss_status_t
85*0Sstevel@tonic-gate switch_err(int rc, ns_ldap_error_t *error)
86*0Sstevel@tonic-gate {
87*0Sstevel@tonic-gate 	switch (rc) {
88*0Sstevel@tonic-gate 	    case NS_LDAP_SUCCESS:
89*0Sstevel@tonic-gate 		return (NSS_SUCCESS);
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate 	    case NS_LDAP_NOTFOUND:
92*0Sstevel@tonic-gate 		return (NSS_NOTFOUND);
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	    case NS_LDAP_PARTIAL:
95*0Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	    case NS_LDAP_INTERNAL:
98*0Sstevel@tonic-gate 		    if (error && (error->status == LDAP_SERVER_DOWN ||
99*0Sstevel@tonic-gate 				error->status == LDAP_TIMEOUT))
100*0Sstevel@tonic-gate 			    return (NSS_TRYAGAIN);
101*0Sstevel@tonic-gate 		    else
102*0Sstevel@tonic-gate 			    return (NSS_UNAVAIL);
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	    default:
105*0Sstevel@tonic-gate 		return (NSS_UNAVAIL);
106*0Sstevel@tonic-gate 	}
107*0Sstevel@tonic-gate }
108*0Sstevel@tonic-gate nss_status_t
109*0Sstevel@tonic-gate _nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
110*0Sstevel@tonic-gate 		char *database, char *searchfilter, char *domain,
111*0Sstevel@tonic-gate 		int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
112*0Sstevel@tonic-gate 		char **realfilter, const void *userdata),
113*0Sstevel@tonic-gate 		const void *userdata)
114*0Sstevel@tonic-gate {
115*0Sstevel@tonic-gate 	int		callbackstat = 0;
116*0Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
117*0Sstevel@tonic-gate 	int		rc;
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate #ifdef	DEBUG
120*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_lookup]\n");
121*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
122*0Sstevel@tonic-gate 	(void) fprintf(stdout,
123*0Sstevel@tonic-gate 		"\tuserdata: %s\n", userdata ? userdata : "NULL");
124*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\tdatabase: %s\n", database);
125*0Sstevel@tonic-gate #endif	/* DEBUG */
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 	if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
130*0Sstevel@tonic-gate 		be->attrs, NULL, 0, &be->result, &error, NULL,
131*0Sstevel@tonic-gate 		userdata)) != NS_LDAP_SUCCESS) {
132*0Sstevel@tonic-gate 		argp->returnval = 0;
133*0Sstevel@tonic-gate 		rc = switch_err(rc, error);
134*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
135*0Sstevel@tonic-gate 		return (rc);
136*0Sstevel@tonic-gate 	}
137*0Sstevel@tonic-gate 	/* callback function */
138*0Sstevel@tonic-gate 	if ((callbackstat =
139*0Sstevel@tonic-gate 		    be->ldapobj2ent(be, argp)) == NSS_STR_PARSE_SUCCESS) {
140*0Sstevel@tonic-gate 		argp->returnval = argp->buf.result;
141*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_SUCCESS);
142*0Sstevel@tonic-gate 	}
143*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	/* error */
146*0Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_PARSE) {
147*0Sstevel@tonic-gate 		argp->returnval = 0;
148*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_ERANGE) {
151*0Sstevel@tonic-gate 		argp->erange = 1;
152*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
153*0Sstevel@tonic-gate 	}
154*0Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_NO_ADDR) {
155*0Sstevel@tonic-gate 		/* No IPV4 address is found */
156*0Sstevel@tonic-gate 		argp->h_errno = HOST_NOT_FOUND;
157*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
158*0Sstevel@tonic-gate 	}
159*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_UNAVAIL);
160*0Sstevel@tonic-gate }
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate /*
164*0Sstevel@tonic-gate  *  This function is similar to _nss_ldap_lookup except it does not
165*0Sstevel@tonic-gate  *  do a callback.  It is only used by getnetgrent.c
166*0Sstevel@tonic-gate  */
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate nss_status_t
169*0Sstevel@tonic-gate _nss_ldap_nocb_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
170*0Sstevel@tonic-gate 		char *database, char *searchfilter, char *domain,
171*0Sstevel@tonic-gate 		int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
172*0Sstevel@tonic-gate 		char **realfilter, const void *userdata),
173*0Sstevel@tonic-gate 		const void *userdata)
174*0Sstevel@tonic-gate {
175*0Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
176*0Sstevel@tonic-gate 	int		rc;
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate #ifdef	DEBUG
179*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_nocb_lookup]\n");
180*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
181*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\tdatabase: %s\n", database);
182*0Sstevel@tonic-gate 	(void) fprintf(stdout,
183*0Sstevel@tonic-gate 		"\tuserdata: %s\n", userdata ? userdata : "NULL");
184*0Sstevel@tonic-gate #endif	/* DEBUG */
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
189*0Sstevel@tonic-gate 		be->attrs, NULL, 0, &be->result, &error, NULL,
190*0Sstevel@tonic-gate 		userdata)) != NS_LDAP_SUCCESS) {
191*0Sstevel@tonic-gate 		argp->returnval = 0;
192*0Sstevel@tonic-gate 		rc = switch_err(rc, error);
193*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
194*0Sstevel@tonic-gate 		return (rc);
195*0Sstevel@tonic-gate 	}
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
198*0Sstevel@tonic-gate }
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate /*
202*0Sstevel@tonic-gate  *
203*0Sstevel@tonic-gate  */
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate void
206*0Sstevel@tonic-gate _clean_ldap_backend(ldap_backend_ptr be)
207*0Sstevel@tonic-gate {
208*0Sstevel@tonic-gate 	ns_ldap_error_t *error;
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate #ifdef	DEBUG
211*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _clean_ldap_backend]\n");
212*0Sstevel@tonic-gate #endif	/* DEBUG */
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate 	if (be->tablename != NULL)
215*0Sstevel@tonic-gate 		free(be->tablename);
216*0Sstevel@tonic-gate 	if (be->result != NULL)
217*0Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&be->result);
218*0Sstevel@tonic-gate 	if (be->enumcookie != NULL)
219*0Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
220*0Sstevel@tonic-gate 	if (be->services_cookie != NULL)
221*0Sstevel@tonic-gate 		_nss_services_cookie_free((void **)&be->services_cookie);
222*0Sstevel@tonic-gate 	if (be->toglue != NULL) {
223*0Sstevel@tonic-gate 		free(be->toglue);
224*0Sstevel@tonic-gate 		be->toglue = NULL;
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate 	free(be);
227*0Sstevel@tonic-gate }
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate /*
231*0Sstevel@tonic-gate  * _nss_ldap_destr will free all smalloc'ed variable strings and structures
232*0Sstevel@tonic-gate  * before exiting this nsswitch shared backend library. This function is
233*0Sstevel@tonic-gate  * called before returning control back to nsswitch.
234*0Sstevel@tonic-gate  */
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate /*ARGSUSED1*/
237*0Sstevel@tonic-gate nss_status_t
238*0Sstevel@tonic-gate _nss_ldap_destr(ldap_backend_ptr be, void *a)
239*0Sstevel@tonic-gate {
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate #ifdef DEBUG
242*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_destr]\n");
243*0Sstevel@tonic-gate #endif /* DEBUG */
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 	(void) _clean_ldap_backend(be);
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
248*0Sstevel@tonic-gate }
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate /*
252*0Sstevel@tonic-gate  * _nss_ldap_setent called before _nss_ldap_getent. This function is
253*0Sstevel@tonic-gate  * required by POSIX.
254*0Sstevel@tonic-gate  */
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate nss_status_t
257*0Sstevel@tonic-gate _nss_ldap_setent(ldap_backend_ptr be, void *a)
258*0Sstevel@tonic-gate {
259*0Sstevel@tonic-gate 	struct gettablefilter	*gtf;
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate #ifdef DEBUG
262*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_setent]\n");
263*0Sstevel@tonic-gate #endif /* DEBUG */
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 	if (be->setcalled == 1)
266*0Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
267*0Sstevel@tonic-gate 	be->filter = NULL;
268*0Sstevel@tonic-gate 	for (gtf = gettablefilterent; gtf->tablename != (char *)NULL; gtf++) {
269*0Sstevel@tonic-gate 		if (strcmp(gtf->tablename, be->tablename))
270*0Sstevel@tonic-gate 			continue;
271*0Sstevel@tonic-gate 		be->filter = (char *)gtf->tablefilter;
272*0Sstevel@tonic-gate 		break;
273*0Sstevel@tonic-gate 	}
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	be->setcalled = 1;
276*0Sstevel@tonic-gate 	be->enumcookie = NULL;
277*0Sstevel@tonic-gate 	be->result = NULL;
278*0Sstevel@tonic-gate 	be->services_cookie = NULL;
279*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
280*0Sstevel@tonic-gate }
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 
283*0Sstevel@tonic-gate /*
284*0Sstevel@tonic-gate  * _nss_ldap_endent called after _nss_ldap_getent. This function is
285*0Sstevel@tonic-gate  * required by POSIX.
286*0Sstevel@tonic-gate  */
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate /*ARGSUSED1*/
289*0Sstevel@tonic-gate nss_status_t
290*0Sstevel@tonic-gate _nss_ldap_endent(ldap_backend_ptr be, void *a)
291*0Sstevel@tonic-gate {
292*0Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate #ifdef DEBUG
295*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_endent]\n");
296*0Sstevel@tonic-gate #endif /* DEBUG */
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	be->setcalled = 0;
299*0Sstevel@tonic-gate 	be->filter = NULL;
300*0Sstevel@tonic-gate 	if (be->enumcookie != NULL) {
301*0Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
302*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
303*0Sstevel@tonic-gate 	}
304*0Sstevel@tonic-gate 	if (be->result != NULL) {
305*0Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&be->result);
306*0Sstevel@tonic-gate 	}
307*0Sstevel@tonic-gate 	if (be->services_cookie != NULL) {
308*0Sstevel@tonic-gate 		_nss_services_cookie_free((void **)&be->services_cookie);
309*0Sstevel@tonic-gate 	}
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
312*0Sstevel@tonic-gate }
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate /*
316*0Sstevel@tonic-gate  *
317*0Sstevel@tonic-gate  */
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate nss_status_t
320*0Sstevel@tonic-gate _nss_ldap_getent(ldap_backend_ptr be, void *a)
321*0Sstevel@tonic-gate {
322*0Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
323*0Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
324*0Sstevel@tonic-gate 	int		parsestat = 0;
325*0Sstevel@tonic-gate 	int		retcode = 0;
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate #ifdef	DEBUG
328*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_getent]\n");
329*0Sstevel@tonic-gate #endif	/* DEBUG */
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate 	if (be->setcalled == 0)
332*0Sstevel@tonic-gate 		(void) _nss_ldap_setent(be, a);
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate next_entry:
335*0Sstevel@tonic-gate 	if (be->enumcookie == NULL) {
336*0Sstevel@tonic-gate 		retcode = __ns_ldap_firstEntry(be->tablename,
337*0Sstevel@tonic-gate 		be->filter, _merge_SSD_filter, be->attrs, NULL,
338*0Sstevel@tonic-gate 		0, &be->enumcookie,
339*0Sstevel@tonic-gate 		&be->result, &error, _F_GETENT_SSD);
340*0Sstevel@tonic-gate 	} else {
341*0Sstevel@tonic-gate 		if (be->services_cookie == NULL) {
342*0Sstevel@tonic-gate 			retcode = __ns_ldap_nextEntry(be->enumcookie,
343*0Sstevel@tonic-gate 				&be->result, &error);
344*0Sstevel@tonic-gate 		}
345*0Sstevel@tonic-gate 	}
346*0Sstevel@tonic-gate 	if (retcode != NS_LDAP_SUCCESS) {
347*0Sstevel@tonic-gate 		retcode = switch_err(retcode, error);
348*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
349*0Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
350*0Sstevel@tonic-gate 		return (retcode);
351*0Sstevel@tonic-gate 	} else {
352*0Sstevel@tonic-gate 		if ((parsestat = be->ldapobj2ent(be, argp))
353*0Sstevel@tonic-gate 			== NSS_STR_PARSE_SUCCESS) {
354*0Sstevel@tonic-gate 			be->result = NULL;
355*0Sstevel@tonic-gate 			argp->returnval = argp->buf.result;
356*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_SUCCESS);
357*0Sstevel@tonic-gate 		}
358*0Sstevel@tonic-gate 		be->result = NULL;
359*0Sstevel@tonic-gate 		if (parsestat == NSS_STR_PARSE_PARSE) {
360*0Sstevel@tonic-gate 			argp->returnval = 0;
361*0Sstevel@tonic-gate 			(void) _nss_ldap_endent(be, a);
362*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
363*0Sstevel@tonic-gate 		}
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 		if (parsestat == NSS_STR_PARSE_ERANGE) {
366*0Sstevel@tonic-gate 			argp->erange = 1;
367*0Sstevel@tonic-gate 			(void) _nss_ldap_endent(be, a);
368*0Sstevel@tonic-gate 			return ((nss_status_t)NSS_NOTFOUND);
369*0Sstevel@tonic-gate 		}
370*0Sstevel@tonic-gate 		if (parsestat == NSS_STR_PARSE_NO_ADDR)
371*0Sstevel@tonic-gate 			/*
372*0Sstevel@tonic-gate 			 * No IPV4 address is found in the current entry.
373*0Sstevel@tonic-gate 			 * It indicates that the entry contains IPV6 addresses
374*0Sstevel@tonic-gate 			 * only. Instead of calling _nss_ldap_endent to
375*0Sstevel@tonic-gate 			 * terminate, get next entry to continue enumeration.
376*0Sstevel@tonic-gate 			 * If it returned NSS_NOTFOUND here,
377*0Sstevel@tonic-gate 			 * gethostent() would return NULL
378*0Sstevel@tonic-gate 			 * and the enumeration would stop prematurely.
379*0Sstevel@tonic-gate 			 */
380*0Sstevel@tonic-gate 			goto next_entry;
381*0Sstevel@tonic-gate 	}
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
384*0Sstevel@tonic-gate }
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate /*
388*0Sstevel@tonic-gate  *
389*0Sstevel@tonic-gate  */
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate nss_backend_t *
392*0Sstevel@tonic-gate _nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename,
393*0Sstevel@tonic-gate 		const char **attrs, fnf ldapobj2ent)
394*0Sstevel@tonic-gate {
395*0Sstevel@tonic-gate 	ldap_backend_ptr	be;
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate #ifdef	DEBUG
398*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_constr]\n");
399*0Sstevel@tonic-gate #endif	/* DEBUG */
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate 	if ((be = (ldap_backend_ptr) malloc(sizeof (*be))) == 0)
402*0Sstevel@tonic-gate 		return (0);
403*0Sstevel@tonic-gate 	be->ops = ops;
404*0Sstevel@tonic-gate 	be->nops = (nss_dbop_t)nops;
405*0Sstevel@tonic-gate 	be->tablename = (char *)strdup(tablename);
406*0Sstevel@tonic-gate 	be->attrs = attrs;
407*0Sstevel@tonic-gate 	be->result = NULL;
408*0Sstevel@tonic-gate 	be->ldapobj2ent = ldapobj2ent;
409*0Sstevel@tonic-gate 	be->setcalled = 0;
410*0Sstevel@tonic-gate 	be->filter = NULL;
411*0Sstevel@tonic-gate 	be->enumcookie = NULL;
412*0Sstevel@tonic-gate 	be->netgroup_cookie = NULL;
413*0Sstevel@tonic-gate 	be->services_cookie = NULL;
414*0Sstevel@tonic-gate 	be->toglue = NULL;
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 	return ((nss_backend_t *)be);
417*0Sstevel@tonic-gate }
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate /*
421*0Sstevel@tonic-gate  *
422*0Sstevel@tonic-gate  */
423*0Sstevel@tonic-gate int
424*0Sstevel@tonic-gate chophostdomain(char *string, char *host, char *domain)
425*0Sstevel@tonic-gate {
426*0Sstevel@tonic-gate 	char	*dot;
427*0Sstevel@tonic-gate 
428*0Sstevel@tonic-gate 	if (string == NULL)
429*0Sstevel@tonic-gate 		return (-1);
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate 	if ((dot = strchr(string, '.')) == NULL) {
432*0Sstevel@tonic-gate 		return (0);
433*0Sstevel@tonic-gate 	}
434*0Sstevel@tonic-gate 	*dot = '\0';
435*0Sstevel@tonic-gate 	strcpy(host, string);
436*0Sstevel@tonic-gate 	strcpy(domain, ++dot);
437*0Sstevel@tonic-gate 
438*0Sstevel@tonic-gate 	return (0);
439*0Sstevel@tonic-gate }
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate /*
443*0Sstevel@tonic-gate  *
444*0Sstevel@tonic-gate  */
445*0Sstevel@tonic-gate int
446*0Sstevel@tonic-gate propersubdomain(char *domain, char *subdomain)
447*0Sstevel@tonic-gate {
448*0Sstevel@tonic-gate 	int	domainlen, subdomainlen;
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	/* sanity check */
451*0Sstevel@tonic-gate 	if (domain == NULL || subdomain == NULL)
452*0Sstevel@tonic-gate 		return (-1);
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate 	domainlen = strlen(domain);
455*0Sstevel@tonic-gate 	subdomainlen = strlen(subdomain);
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 	/* is afterdot a substring of domain? */
458*0Sstevel@tonic-gate 	if ((strncasecmp(domain, subdomain, subdomainlen)) != 0)
459*0Sstevel@tonic-gate 		return (-1);
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate 	if (domainlen == subdomainlen)
462*0Sstevel@tonic-gate 		return (1);
463*0Sstevel@tonic-gate 
464*0Sstevel@tonic-gate 	if (subdomainlen > domainlen)
465*0Sstevel@tonic-gate 		return (-1);
466*0Sstevel@tonic-gate 
467*0Sstevel@tonic-gate 	if (*(domain + subdomainlen) != '.')
468*0Sstevel@tonic-gate 		return (-1);
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate 	return (1);
471*0Sstevel@tonic-gate }
472