xref: /titanic_51/usr/src/lib/nsswitch/ldap/common/ldap_common.c (revision 9f2fd570dfad3c35512617ae887140b15e3ec4c5)
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
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * 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*9f2fd570SJulian Pullen  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include "ldap_common.h"
267c478bd9Sstevel@tonic-gate #include <malloc.h>
277c478bd9Sstevel@tonic-gate #include <synch.h>
287c478bd9Sstevel@tonic-gate #include <syslog.h>
297c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
307c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
317c478bd9Sstevel@tonic-gate #include <thread.h>
327c478bd9Sstevel@tonic-gate #include <ctype.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <signal.h>
357c478bd9Sstevel@tonic-gate #include <sys/stat.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /* getent attributes filters */
387c478bd9Sstevel@tonic-gate #define	_F_GETALIASENT		"(objectClass=rfc822MailGroup)"
397c478bd9Sstevel@tonic-gate #define	_F_GETAUTHNAME		"(objectClass=SolarisAuthAttr)"
407c478bd9Sstevel@tonic-gate #define	_F_GETAUUSERNAME	"(objectClass=SolarisAuditUser)"
417c478bd9Sstevel@tonic-gate #define	_F_GETEXECNAME		"(objectClass=SolarisExecAttr)"
427c478bd9Sstevel@tonic-gate #define	_F_GETGRENT		"(objectClass=posixGroup)"
437c478bd9Sstevel@tonic-gate #define	_F_GETHOSTENT		"(objectClass=ipHost)"
447c478bd9Sstevel@tonic-gate #define	_F_GETNETENT		"(objectClass=ipNetwork)"
45cb5caa98Sdjl #define	_F_GETPROFNAME \
46cb5caa98Sdjl "(&(objectClass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*)))"
477c478bd9Sstevel@tonic-gate #define	_F_GETPROTOENT		"(objectClass=ipProtocol)"
487c478bd9Sstevel@tonic-gate #define	_F_GETPWENT		"(objectClass=posixAccount)"
497c478bd9Sstevel@tonic-gate #define	_F_GETPRINTERENT	"(objectClass=sunPrinter)"
507c478bd9Sstevel@tonic-gate #define	_F_GETRPCENT		"(objectClass=oncRpc)"
517c478bd9Sstevel@tonic-gate #define	_F_GETSERVENT		"(objectClass=ipService)"
527c478bd9Sstevel@tonic-gate #define	_F_GETSPENT		"(objectclass=shadowAccount)"
537c478bd9Sstevel@tonic-gate #define	_F_GETUSERNAME		"(objectClass=SolarisUserAttr)"
547c478bd9Sstevel@tonic-gate #define	_F_GETPROJENT		"(objectClass=SolarisProject)"
5545916cd2Sjpk #define	_F_GETTNRHDB		"(objectClass=ipTnetHost)"
5645916cd2Sjpk #define	_F_GETTNRHTP		"(&(objectClass=ipTnetTemplate)"\
5745916cd2Sjpk 				"(SolarisAttrKeyValue=*))"
587c478bd9Sstevel@tonic-gate #define	_F_GETENT_SSD		"(%s)"
597c478bd9Sstevel@tonic-gate 
60*9f2fd570SJulian Pullen /* getent sort attributes */
61*9f2fd570SJulian Pullen #define	_A_UID			"uid"
62*9f2fd570SJulian Pullen #define	_A_GIDNUMBER		"gidnumber"
63*9f2fd570SJulian Pullen #define	_A_CN			"cn"
64*9f2fd570SJulian Pullen #define	_A_IPNETWORKNUM		"ipnetworknumber"
65*9f2fd570SJulian Pullen #define	_A_PROJECTNAM		"SolarisProjectName"
66*9f2fd570SJulian Pullen #define	_A_IPTNETNUM		"ipTnetNumber"
67*9f2fd570SJulian Pullen #define	_A_IPTNETTMPLNAM	"ipTnetTemplateName"
68*9f2fd570SJulian Pullen 
697c478bd9Sstevel@tonic-gate static struct gettablefilter {
707c478bd9Sstevel@tonic-gate 	char *tablename;
717c478bd9Sstevel@tonic-gate 	char *tablefilter;
72*9f2fd570SJulian Pullen 	char *sortattr;
737c478bd9Sstevel@tonic-gate } gettablefilterent[] = {
74*9f2fd570SJulian Pullen 	{(char *)_PASSWD,	(char *)_F_GETPWENT,	(char *)_A_UID},
75*9f2fd570SJulian Pullen 	{(char *)_SHADOW,	(char *)_F_GETSPENT,	(char *)_A_UID},
76*9f2fd570SJulian Pullen 	{(char *)_GROUP,	(char *)_F_GETGRENT,	(char *)_A_GIDNUMBER},
77*9f2fd570SJulian Pullen 	{(char *)_HOSTS,	(char *)_F_GETHOSTENT,	(char *)_A_CN},
78*9f2fd570SJulian Pullen 	{(char *)_NETWORKS,	(char *)_F_GETNETENT,
79*9f2fd570SJulian Pullen 						(char *)_A_IPNETWORKNUM},
80*9f2fd570SJulian Pullen 	{(char *)_PROTOCOLS,	(char *)_F_GETPROTOENT,	(char *)_A_CN},
81*9f2fd570SJulian Pullen 	{(char *)_RPC,		(char *)_F_GETRPCENT,	(char *)_A_CN},
82*9f2fd570SJulian Pullen 	{(char *)_ALIASES,	(char *)_F_GETALIASENT,	(char *)_A_CN},
83*9f2fd570SJulian Pullen 	{(char *)_SERVICES,	(char *)_F_GETSERVENT,	(char *)_A_CN},
84*9f2fd570SJulian Pullen 	{(char *)_AUUSER,	(char *)_F_GETAUUSERNAME,
85*9f2fd570SJulian Pullen 							(char *)_A_UID},
86*9f2fd570SJulian Pullen 	{(char *)_AUTHATTR,	(char *)_F_GETAUTHNAME,	(char *)_A_CN},
87*9f2fd570SJulian Pullen 	{(char *)_EXECATTR,	(char *)_F_GETEXECNAME,	(char *)_A_CN},
88*9f2fd570SJulian Pullen 	{(char *)_PROFATTR,	(char *)_F_GETPROFNAME,	(char *)_A_CN},
89*9f2fd570SJulian Pullen 	{(char *)_USERATTR,	(char *)_F_GETUSERNAME,	(char *)_A_UID},
90*9f2fd570SJulian Pullen 	{(char *)_PROJECT,	(char *)_F_GETPROJENT,	(char *)_A_PROJECTNAM},
91*9f2fd570SJulian Pullen 	{(char *)_PRINTERS,	(char *)_F_GETPRINTERENT, (char *)_A_CN},
92*9f2fd570SJulian Pullen 	{(char *)_TNRHDB,	(char *)_F_GETTNRHDB,	(char *)_A_IPTNETNUM},
93*9f2fd570SJulian Pullen 	{(char *)_TNRHTP,	(char *)_F_GETTNRHTP,
94*9f2fd570SJulian Pullen 						(char *)_A_IPTNETTMPLNAM},
95*9f2fd570SJulian Pullen 	{(char *)NULL,		(char *)NULL,		(char *)NULL}
967c478bd9Sstevel@tonic-gate };
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 
993d047983Smichen nss_status_t
1007c478bd9Sstevel@tonic-gate switch_err(int rc, ns_ldap_error_t *error)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	switch (rc) {
1037c478bd9Sstevel@tonic-gate 	case NS_LDAP_SUCCESS:
1047c478bd9Sstevel@tonic-gate 		return (NSS_SUCCESS);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	case NS_LDAP_NOTFOUND:
1077c478bd9Sstevel@tonic-gate 		return (NSS_NOTFOUND);
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	case NS_LDAP_PARTIAL:
1107c478bd9Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	case NS_LDAP_INTERNAL:
1137c478bd9Sstevel@tonic-gate 		if (error && (error->status == LDAP_SERVER_DOWN ||
1147c478bd9Sstevel@tonic-gate 		    error->status == LDAP_TIMEOUT))
1157c478bd9Sstevel@tonic-gate 			return (NSS_TRYAGAIN);
1167c478bd9Sstevel@tonic-gate 		else
1177c478bd9Sstevel@tonic-gate 			return (NSS_UNAVAIL);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	default:
1207c478bd9Sstevel@tonic-gate 		return (NSS_UNAVAIL);
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate }
123cb5caa98Sdjl /* ARGSUSED */
1247c478bd9Sstevel@tonic-gate nss_status_t
1257c478bd9Sstevel@tonic-gate _nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
1267c478bd9Sstevel@tonic-gate 		char *database, char *searchfilter, char *domain,
1277c478bd9Sstevel@tonic-gate 		int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
1287c478bd9Sstevel@tonic-gate 		char **realfilter, const void *userdata),
1297c478bd9Sstevel@tonic-gate 		const void *userdata)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	int		callbackstat = 0;
1327c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
1337c478bd9Sstevel@tonic-gate 	int		rc;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate #ifdef	DEBUG
1367c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_lookup]\n");
1377c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
1387c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout,
1397c478bd9Sstevel@tonic-gate 	    "\tuserdata: %s\n", userdata ? userdata : "NULL");
1407c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tdatabase: %s\n", database);
1417c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
1467c478bd9Sstevel@tonic-gate 	    be->attrs, NULL, 0, &be->result, &error, NULL,
1477c478bd9Sstevel@tonic-gate 	    userdata)) != NS_LDAP_SUCCESS) {
1487c478bd9Sstevel@tonic-gate 		argp->returnval = 0;
1497c478bd9Sstevel@tonic-gate 		rc = switch_err(rc, error);
1507c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
151cb5caa98Sdjl 
1527c478bd9Sstevel@tonic-gate 		return (rc);
1537c478bd9Sstevel@tonic-gate 	}
154cb5caa98Sdjl 		(void) __ns_ldap_freeError(&error);
1557c478bd9Sstevel@tonic-gate 	/* callback function */
1567c478bd9Sstevel@tonic-gate 	if ((callbackstat =
157cb5caa98Sdjl 	    be->ldapobj2str(be, argp)) != NSS_STR_PARSE_SUCCESS) {
158cb5caa98Sdjl 		goto error_out;
159cb5caa98Sdjl 	}
160cb5caa98Sdjl 
161cb5caa98Sdjl 	/*
162cb5caa98Sdjl 	 * publickey does not have a front end marshaller and expects
163cb5caa98Sdjl 	 * a string to be returned in NSS.
164cb5caa98Sdjl 	 * No need to convert file format -> struct.
165cb5caa98Sdjl 	 *
166cb5caa98Sdjl 	 */
167cb5caa98Sdjl 	if (be->db_type == NSS_LDAP_DB_PUBLICKEY) {
168cb5caa98Sdjl 		argp->returnval = argp->buf.buffer;
169cb5caa98Sdjl 		argp->returnlen = strlen(argp->buf.buffer);
170cb5caa98Sdjl 		be->db_type = NSS_LDAP_DB_NONE;
171cb5caa98Sdjl 		return (NSS_SUCCESS);
172cb5caa98Sdjl 	}
173cb5caa98Sdjl 	/*
174cb5caa98Sdjl 	 *  Assume the switch engine wants the returned data in the file
175cb5caa98Sdjl 	 *  format when argp->buf.result == NULL.
176cb5caa98Sdjl 	 *  The front-end marshaller str2ether(ethers) uses
177cb5caa98Sdjl 	 *  ent (argp->buf.result) and buffer (argp->buf.buffer)
178cb5caa98Sdjl 	 *  for different purpose so ethers has to be treated differently.
179cb5caa98Sdjl 	 */
180cb5caa98Sdjl 	if (argp->buf.result != NULL ||
181cb5caa98Sdjl 	    be->db_type == NSS_LDAP_DB_ETHERS) {
182cb5caa98Sdjl 		/* file format -> struct */
183cb5caa98Sdjl 		if (argp->str2ent == NULL) {
184cb5caa98Sdjl 			callbackstat = NSS_STR_PARSE_PARSE;
185cb5caa98Sdjl 			goto error_out;
186cb5caa98Sdjl 		}
187cb5caa98Sdjl 
188cb5caa98Sdjl 		callbackstat = (*argp->str2ent)(be->buffer,
189cb5caa98Sdjl 		    be->buflen,
190cb5caa98Sdjl 		    argp->buf.result,
191cb5caa98Sdjl 		    argp->buf.buffer,
192cb5caa98Sdjl 		    argp->buf.buflen);
193cb5caa98Sdjl 		if (callbackstat == NSS_STR_PARSE_SUCCESS) {
194cb5caa98Sdjl 			if (be->db_type == NSS_LDAP_DB_ETHERS &&
195cb5caa98Sdjl 			    argp->buf.buffer != NULL) {
196cb5caa98Sdjl 				argp->returnval = argp->buf.buffer;
197cb5caa98Sdjl 				argp->returnlen = strlen(argp->buf.buffer);
198cb5caa98Sdjl 			} else {
1997c478bd9Sstevel@tonic-gate 				argp->returnval = argp->buf.result;
200cb5caa98Sdjl 				argp->returnlen = 1; /* irrelevant */
201cb5caa98Sdjl 			}
202cb5caa98Sdjl 			if (be->buffer != NULL) {
203cb5caa98Sdjl 				free(be->buffer);
204cb5caa98Sdjl 				be->buffer = NULL;
205cb5caa98Sdjl 				be->buflen = 0;
206cb5caa98Sdjl 				be->db_type = NSS_LDAP_DB_NONE;
207cb5caa98Sdjl 			}
2087c478bd9Sstevel@tonic-gate 			return ((nss_status_t)NSS_SUCCESS);
2097c478bd9Sstevel@tonic-gate 		}
210cb5caa98Sdjl 	} else {
211cb5caa98Sdjl 			/* return file format in argp->buf.buffer */
212cb5caa98Sdjl 			argp->returnval = argp->buf.buffer;
213cb5caa98Sdjl 			argp->returnlen = strlen(argp->buf.buffer);
214cb5caa98Sdjl 			return ((nss_status_t)NSS_SUCCESS);
215cb5caa98Sdjl 	}
2167c478bd9Sstevel@tonic-gate 
217cb5caa98Sdjl error_out:
218cb5caa98Sdjl 	if (be->buffer != NULL) {
219cb5caa98Sdjl 		free(be->buffer);
220cb5caa98Sdjl 		be->buffer = NULL;
221cb5caa98Sdjl 		be->buflen = 0;
222cb5caa98Sdjl 		be->db_type = NSS_LDAP_DB_NONE;
223cb5caa98Sdjl 	}
2247c478bd9Sstevel@tonic-gate 	/* error */
2257c478bd9Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_PARSE) {
2267c478bd9Sstevel@tonic-gate 		argp->returnval = 0;
2277c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_ERANGE) {
2307c478bd9Sstevel@tonic-gate 		argp->erange = 1;
2317c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_NO_ADDR) {
2347c478bd9Sstevel@tonic-gate 		/* No IPV4 address is found */
2357c478bd9Sstevel@tonic-gate 		argp->h_errno = HOST_NOT_FOUND;
2367c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_UNAVAIL);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate  *  This function is similar to _nss_ldap_lookup except it does not
2437c478bd9Sstevel@tonic-gate  *  do a callback.  It is only used by getnetgrent.c
2447c478bd9Sstevel@tonic-gate  */
2457c478bd9Sstevel@tonic-gate 
246cb5caa98Sdjl /* ARGSUSED */
2477c478bd9Sstevel@tonic-gate nss_status_t
2487c478bd9Sstevel@tonic-gate _nss_ldap_nocb_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
2497c478bd9Sstevel@tonic-gate 		char *database, char *searchfilter, char *domain,
2507c478bd9Sstevel@tonic-gate 		int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
2517c478bd9Sstevel@tonic-gate 		char **realfilter, const void *userdata),
2527c478bd9Sstevel@tonic-gate 		const void *userdata)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
2557c478bd9Sstevel@tonic-gate 	int		rc;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate #ifdef	DEBUG
2587c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_nocb_lookup]\n");
2597c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
2607c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tdatabase: %s\n", database);
2617c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout,
2627c478bd9Sstevel@tonic-gate 	    "\tuserdata: %s\n", userdata ? userdata : "NULL");
2637c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
2687c478bd9Sstevel@tonic-gate 	    be->attrs, NULL, 0, &be->result, &error, NULL,
2697c478bd9Sstevel@tonic-gate 	    userdata)) != NS_LDAP_SUCCESS) {
27018bdb8a7Smichen 		if (argp != NULL)
2717c478bd9Sstevel@tonic-gate 			argp->returnval = 0;
2727c478bd9Sstevel@tonic-gate 		rc = switch_err(rc, error);
2737c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
2747c478bd9Sstevel@tonic-gate 		return (rc);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate  *
2837c478bd9Sstevel@tonic-gate  */
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate void
2867c478bd9Sstevel@tonic-gate _clean_ldap_backend(ldap_backend_ptr be)
2877c478bd9Sstevel@tonic-gate {
2887c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *error;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate #ifdef	DEBUG
2917c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _clean_ldap_backend]\n");
2927c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	if (be->tablename != NULL)
2957c478bd9Sstevel@tonic-gate 		free(be->tablename);
2967c478bd9Sstevel@tonic-gate 	if (be->result != NULL)
2977c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&be->result);
2987c478bd9Sstevel@tonic-gate 	if (be->enumcookie != NULL)
2997c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
3007c478bd9Sstevel@tonic-gate 	if (be->services_cookie != NULL)
3017c478bd9Sstevel@tonic-gate 		_nss_services_cookie_free((void **)&be->services_cookie);
3027c478bd9Sstevel@tonic-gate 	if (be->toglue != NULL) {
3037c478bd9Sstevel@tonic-gate 		free(be->toglue);
3047c478bd9Sstevel@tonic-gate 		be->toglue = NULL;
3057c478bd9Sstevel@tonic-gate 	}
306cb5caa98Sdjl 	if (be->buffer != NULL) {
307cb5caa98Sdjl 		free(be->buffer);
308cb5caa98Sdjl 		be->buffer = NULL;
309cb5caa98Sdjl 	}
3107c478bd9Sstevel@tonic-gate 	free(be);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate /*
3157c478bd9Sstevel@tonic-gate  * _nss_ldap_destr will free all smalloc'ed variable strings and structures
3167c478bd9Sstevel@tonic-gate  * before exiting this nsswitch shared backend library. This function is
3177c478bd9Sstevel@tonic-gate  * called before returning control back to nsswitch.
3187c478bd9Sstevel@tonic-gate  */
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
3217c478bd9Sstevel@tonic-gate nss_status_t
3227c478bd9Sstevel@tonic-gate _nss_ldap_destr(ldap_backend_ptr be, void *a)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate #ifdef DEBUG
3267c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_destr]\n");
3277c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	(void) _clean_ldap_backend(be);
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate /*
3367c478bd9Sstevel@tonic-gate  * _nss_ldap_setent called before _nss_ldap_getent. This function is
3377c478bd9Sstevel@tonic-gate  * required by POSIX.
3387c478bd9Sstevel@tonic-gate  */
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate nss_status_t
3417c478bd9Sstevel@tonic-gate _nss_ldap_setent(ldap_backend_ptr be, void *a)
3427c478bd9Sstevel@tonic-gate {
3437c478bd9Sstevel@tonic-gate 	struct gettablefilter	*gtf;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate #ifdef DEBUG
3467c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_setent]\n");
3477c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	if (be->setcalled == 1)
3507c478bd9Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
3517c478bd9Sstevel@tonic-gate 	be->filter = NULL;
352*9f2fd570SJulian Pullen 	be->sortattr = NULL;
3537c478bd9Sstevel@tonic-gate 	for (gtf = gettablefilterent; gtf->tablename != (char *)NULL; gtf++) {
3547c478bd9Sstevel@tonic-gate 		if (strcmp(gtf->tablename, be->tablename))
3557c478bd9Sstevel@tonic-gate 			continue;
3567c478bd9Sstevel@tonic-gate 		be->filter = (char *)gtf->tablefilter;
357*9f2fd570SJulian Pullen 		be->sortattr = (char *)gtf->sortattr;
3587c478bd9Sstevel@tonic-gate 		break;
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	be->setcalled = 1;
3627c478bd9Sstevel@tonic-gate 	be->enumcookie = NULL;
3637c478bd9Sstevel@tonic-gate 	be->result = NULL;
3647c478bd9Sstevel@tonic-gate 	be->services_cookie = NULL;
365cb5caa98Sdjl 	be->buffer = NULL;
3667c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate /*
3717c478bd9Sstevel@tonic-gate  * _nss_ldap_endent called after _nss_ldap_getent. This function is
3727c478bd9Sstevel@tonic-gate  * required by POSIX.
3737c478bd9Sstevel@tonic-gate  */
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
3767c478bd9Sstevel@tonic-gate nss_status_t
3777c478bd9Sstevel@tonic-gate _nss_ldap_endent(ldap_backend_ptr be, void *a)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate #ifdef DEBUG
3827c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_endent]\n");
3837c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	be->setcalled = 0;
3867c478bd9Sstevel@tonic-gate 	be->filter = NULL;
387*9f2fd570SJulian Pullen 	be->sortattr = NULL;
3887c478bd9Sstevel@tonic-gate 	if (be->enumcookie != NULL) {
3897c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
3907c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 	if (be->result != NULL) {
3937c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&be->result);
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 	if (be->services_cookie != NULL) {
3967c478bd9Sstevel@tonic-gate 		_nss_services_cookie_free((void **)&be->services_cookie);
3977c478bd9Sstevel@tonic-gate 	}
398cb5caa98Sdjl 	if (be->buffer != NULL) {
399cb5caa98Sdjl 		free(be->buffer);
400cb5caa98Sdjl 		be->buffer = NULL;
401cb5caa98Sdjl 	}
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate  *
4097c478bd9Sstevel@tonic-gate  */
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate nss_status_t
4127c478bd9Sstevel@tonic-gate _nss_ldap_getent(ldap_backend_ptr be, void *a)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
4157c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
4167c478bd9Sstevel@tonic-gate 	int		parsestat = 0;
4177c478bd9Sstevel@tonic-gate 	int		retcode = 0;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4207c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_getent]\n");
4217c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	if (be->setcalled == 0)
4247c478bd9Sstevel@tonic-gate 		(void) _nss_ldap_setent(be, a);
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate next_entry:
4277c478bd9Sstevel@tonic-gate 	if (be->enumcookie == NULL) {
4287c478bd9Sstevel@tonic-gate 		retcode = __ns_ldap_firstEntry(be->tablename,
429*9f2fd570SJulian Pullen 		    be->filter, be->sortattr, _merge_SSD_filter, be->attrs,
430*9f2fd570SJulian Pullen 		    NULL, 0, &be->enumcookie,
4317c478bd9Sstevel@tonic-gate 		    &be->result, &error, _F_GETENT_SSD);
4327c478bd9Sstevel@tonic-gate 	} else {
4337c478bd9Sstevel@tonic-gate 		if (be->services_cookie == NULL) {
4347c478bd9Sstevel@tonic-gate 			retcode = __ns_ldap_nextEntry(be->enumcookie,
4357c478bd9Sstevel@tonic-gate 			    &be->result, &error);
4367c478bd9Sstevel@tonic-gate 		}
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate 	if (retcode != NS_LDAP_SUCCESS) {
4397c478bd9Sstevel@tonic-gate 		retcode = switch_err(retcode, error);
4407c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
4417c478bd9Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
4427c478bd9Sstevel@tonic-gate 		return (retcode);
443*9f2fd570SJulian Pullen 	}
444*9f2fd570SJulian Pullen 
445*9f2fd570SJulian Pullen 	if (be->result == NULL) {
446*9f2fd570SJulian Pullen 		parsestat = NSS_STR_PARSE_NO_RESULT;
447*9f2fd570SJulian Pullen 		goto error_out;
448*9f2fd570SJulian Pullen 	}
449cb5caa98Sdjl 	/* ns_ldap_entry_t -> file format */
450cb5caa98Sdjl 	if ((parsestat = be->ldapobj2str(be, argp))
4517c478bd9Sstevel@tonic-gate 	    == NSS_STR_PARSE_SUCCESS) {
452cb5caa98Sdjl 		if (argp->buf.result != NULL) {
453cb5caa98Sdjl 			/* file format -> struct */
454cb5caa98Sdjl 			if (argp->str2ent == NULL) {
455*9f2fd570SJulian Pullen 				parsestat = NSS_STR_PARSE_NO_RESULT;
456cb5caa98Sdjl 				goto error_out;
457cb5caa98Sdjl 			}
458cb5caa98Sdjl 			parsestat = (*argp->str2ent)(be->buffer,
459cb5caa98Sdjl 			    be->buflen,
460cb5caa98Sdjl 			    argp->buf.result,
461cb5caa98Sdjl 			    argp->buf.buffer,
462cb5caa98Sdjl 			    argp->buf.buflen);
463cb5caa98Sdjl 			if (parsestat == NSS_STR_PARSE_SUCCESS) {
464cb5caa98Sdjl 				if (be->buffer != NULL) {
465cb5caa98Sdjl 					free(be->buffer);
466cb5caa98Sdjl 					be->buffer = NULL;
467cb5caa98Sdjl 					be->buflen = 0;
468cb5caa98Sdjl 				}
4697c478bd9Sstevel@tonic-gate 				be->result = NULL;
4707c478bd9Sstevel@tonic-gate 				argp->returnval = argp->buf.result;
471cb5caa98Sdjl 				argp->returnlen = 1; /* irrevelant */
4727c478bd9Sstevel@tonic-gate 				return ((nss_status_t)NSS_SUCCESS);
4737c478bd9Sstevel@tonic-gate 			}
474cb5caa98Sdjl 		} else {
475cb5caa98Sdjl 			/*
476cb5caa98Sdjl 			 * nscd is not caching the enumerated
477cb5caa98Sdjl 			 * entries. This code path would be dormant.
478cb5caa98Sdjl 			 * Keep this path for the future references.
479cb5caa98Sdjl 			 */
480cb5caa98Sdjl 			argp->returnval = argp->buf.buffer;
481cb5caa98Sdjl 			argp->returnlen =
482cb5caa98Sdjl 			    strlen(argp->buf.buffer) + 1;
483cb5caa98Sdjl 		}
484cb5caa98Sdjl 	}
485cb5caa98Sdjl error_out:
486cb5caa98Sdjl 	if (be->buffer != NULL) {
487cb5caa98Sdjl 		free(be->buffer);
488cb5caa98Sdjl 		be->buffer = NULL;
489cb5caa98Sdjl 		be->buflen = 0;
490cb5caa98Sdjl 	}
4917c478bd9Sstevel@tonic-gate 	be->result = NULL;
492*9f2fd570SJulian Pullen 	if (parsestat == NSS_STR_PARSE_NO_RESULT) {
4937c478bd9Sstevel@tonic-gate 		argp->returnval = 0;
4947c478bd9Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
4957c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_ERANGE) {
4997c478bd9Sstevel@tonic-gate 		argp->erange = 1;
5007c478bd9Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
5017c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_NO_ADDR)
5047c478bd9Sstevel@tonic-gate 		/*
5057c478bd9Sstevel@tonic-gate 		 * No IPV4 address is found in the current entry.
5067c478bd9Sstevel@tonic-gate 		 * It indicates that the entry contains IPV6 addresses
5077c478bd9Sstevel@tonic-gate 		 * only. Instead of calling _nss_ldap_endent to
5087c478bd9Sstevel@tonic-gate 		 * terminate, get next entry to continue enumeration.
5097c478bd9Sstevel@tonic-gate 		 * If it returned NSS_NOTFOUND here,
5107c478bd9Sstevel@tonic-gate 		 * gethostent() would return NULL
5117c478bd9Sstevel@tonic-gate 		 * and the enumeration would stop prematurely.
5127c478bd9Sstevel@tonic-gate 		 */
5137c478bd9Sstevel@tonic-gate 		goto next_entry;
514*9f2fd570SJulian Pullen 
515*9f2fd570SJulian Pullen 	if (parsestat == NSS_STR_PARSE_PARSE)
516*9f2fd570SJulian Pullen 		/*
517*9f2fd570SJulian Pullen 		 * There has been a parse error. Most likely some
518*9f2fd570SJulian Pullen 		 * mandatory attributes are missing. Ignore the error
519*9f2fd570SJulian Pullen 		 * and get the next entry. If we returned an error the
520*9f2fd570SJulian Pullen 		 * enumeration would stop prematurely.
521*9f2fd570SJulian Pullen 		 */
522*9f2fd570SJulian Pullen 		goto next_entry;
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate  *
5307c478bd9Sstevel@tonic-gate  */
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate nss_backend_t *
5337c478bd9Sstevel@tonic-gate _nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename,
534cb5caa98Sdjl 		const char **attrs, fnf ldapobj2str)
5357c478bd9Sstevel@tonic-gate {
5367c478bd9Sstevel@tonic-gate 	ldap_backend_ptr	be;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate #ifdef	DEBUG
5397c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_constr]\n");
5407c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
5417c478bd9Sstevel@tonic-gate 
542cb5caa98Sdjl 	if ((be = (ldap_backend_ptr) calloc(1, sizeof (*be))) == 0)
5437c478bd9Sstevel@tonic-gate 		return (0);
5447c478bd9Sstevel@tonic-gate 	be->ops = ops;
5457c478bd9Sstevel@tonic-gate 	be->nops = (nss_dbop_t)nops;
5467c478bd9Sstevel@tonic-gate 	be->tablename = (char *)strdup(tablename);
5477c478bd9Sstevel@tonic-gate 	be->attrs = attrs;
548cb5caa98Sdjl 	be->ldapobj2str = ldapobj2str;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	return ((nss_backend_t *)be);
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate /*
5557c478bd9Sstevel@tonic-gate  *
5567c478bd9Sstevel@tonic-gate  */
5577c478bd9Sstevel@tonic-gate int
5587c478bd9Sstevel@tonic-gate chophostdomain(char *string, char *host, char *domain)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate 	char	*dot;
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	if (string == NULL)
5637c478bd9Sstevel@tonic-gate 		return (-1);
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	if ((dot = strchr(string, '.')) == NULL) {
5667c478bd9Sstevel@tonic-gate 		return (0);
5677c478bd9Sstevel@tonic-gate 	}
5687c478bd9Sstevel@tonic-gate 	*dot = '\0';
569cb5caa98Sdjl 	(void) strcpy(host, string);
570cb5caa98Sdjl 	(void) strcpy(domain, ++dot);
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	return (0);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate /*
5777c478bd9Sstevel@tonic-gate  *
5787c478bd9Sstevel@tonic-gate  */
5797c478bd9Sstevel@tonic-gate int
5807c478bd9Sstevel@tonic-gate propersubdomain(char *domain, char *subdomain)
5817c478bd9Sstevel@tonic-gate {
5827c478bd9Sstevel@tonic-gate 	int	domainlen, subdomainlen;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	/* sanity check */
5857c478bd9Sstevel@tonic-gate 	if (domain == NULL || subdomain == NULL)
5867c478bd9Sstevel@tonic-gate 		return (-1);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	domainlen = strlen(domain);
5897c478bd9Sstevel@tonic-gate 	subdomainlen = strlen(subdomain);
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	/* is afterdot a substring of domain? */
5927c478bd9Sstevel@tonic-gate 	if ((strncasecmp(domain, subdomain, subdomainlen)) != 0)
5937c478bd9Sstevel@tonic-gate 		return (-1);
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	if (domainlen == subdomainlen)
5967c478bd9Sstevel@tonic-gate 		return (1);
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	if (subdomainlen > domainlen)
5997c478bd9Sstevel@tonic-gate 		return (-1);
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	if (*(domain + subdomainlen) != '.')
6027c478bd9Sstevel@tonic-gate 		return (-1);
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	return (1);
6057c478bd9Sstevel@tonic-gate }
606