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 /*
229f2fd570SJulian Pullen  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23*6a9f1673SMatt Barden  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include "ldap_common.h"
277c478bd9Sstevel@tonic-gate #include <malloc.h>
287c478bd9Sstevel@tonic-gate #include <synch.h>
297c478bd9Sstevel@tonic-gate #include <syslog.h>
307c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
317c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
327c478bd9Sstevel@tonic-gate #include <thread.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
357c478bd9Sstevel@tonic-gate #include <signal.h>
367c478bd9Sstevel@tonic-gate #include <sys/stat.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /* getent attributes filters */
397c478bd9Sstevel@tonic-gate #define	_F_GETALIASENT		"(objectClass=rfc822MailGroup)"
407c478bd9Sstevel@tonic-gate #define	_F_GETAUTHNAME		"(objectClass=SolarisAuthAttr)"
417c478bd9Sstevel@tonic-gate #define	_F_GETAUUSERNAME	"(objectClass=SolarisAuditUser)"
427c478bd9Sstevel@tonic-gate #define	_F_GETEXECNAME		"(objectClass=SolarisExecAttr)"
437c478bd9Sstevel@tonic-gate #define	_F_GETGRENT		"(objectClass=posixGroup)"
447c478bd9Sstevel@tonic-gate #define	_F_GETHOSTENT		"(objectClass=ipHost)"
457c478bd9Sstevel@tonic-gate #define	_F_GETNETENT		"(objectClass=ipNetwork)"
46cb5caa98Sdjl #define	_F_GETPROFNAME \
47cb5caa98Sdjl "(&(objectClass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*)))"
487c478bd9Sstevel@tonic-gate #define	_F_GETPROTOENT		"(objectClass=ipProtocol)"
497c478bd9Sstevel@tonic-gate #define	_F_GETPWENT		"(objectClass=posixAccount)"
507c478bd9Sstevel@tonic-gate #define	_F_GETPRINTERENT	"(objectClass=sunPrinter)"
517c478bd9Sstevel@tonic-gate #define	_F_GETRPCENT		"(objectClass=oncRpc)"
527c478bd9Sstevel@tonic-gate #define	_F_GETSERVENT		"(objectClass=ipService)"
537c478bd9Sstevel@tonic-gate #define	_F_GETSPENT		"(objectclass=shadowAccount)"
547c478bd9Sstevel@tonic-gate #define	_F_GETUSERNAME		"(objectClass=SolarisUserAttr)"
557c478bd9Sstevel@tonic-gate #define	_F_GETPROJENT		"(objectClass=SolarisProject)"
5645916cd2Sjpk #define	_F_GETTNRHDB		"(objectClass=ipTnetHost)"
5745916cd2Sjpk #define	_F_GETTNRHTP		"(&(objectClass=ipTnetTemplate)"\
5845916cd2Sjpk 				"(SolarisAttrKeyValue=*))"
597c478bd9Sstevel@tonic-gate #define	_F_GETENT_SSD		"(%s)"
607c478bd9Sstevel@tonic-gate 
619f2fd570SJulian Pullen /* getent sort attributes */
629f2fd570SJulian Pullen #define	_A_UID			"uid"
639f2fd570SJulian Pullen #define	_A_GIDNUMBER		"gidnumber"
649f2fd570SJulian Pullen #define	_A_CN			"cn"
659f2fd570SJulian Pullen #define	_A_IPNETWORKNUM		"ipnetworknumber"
669f2fd570SJulian Pullen #define	_A_PROJECTNAM		"SolarisProjectName"
679f2fd570SJulian Pullen #define	_A_IPTNETNUM		"ipTnetNumber"
689f2fd570SJulian Pullen #define	_A_IPTNETTMPLNAM	"ipTnetTemplateName"
699f2fd570SJulian Pullen 
707c478bd9Sstevel@tonic-gate static struct gettablefilter {
717c478bd9Sstevel@tonic-gate 	char *tablename;
727c478bd9Sstevel@tonic-gate 	char *tablefilter;
739f2fd570SJulian Pullen 	char *sortattr;
747c478bd9Sstevel@tonic-gate } gettablefilterent[] = {
759f2fd570SJulian Pullen 	{(char *)_PASSWD,	(char *)_F_GETPWENT,	(char *)_A_UID},
769f2fd570SJulian Pullen 	{(char *)_SHADOW,	(char *)_F_GETSPENT,	(char *)_A_UID},
779f2fd570SJulian Pullen 	{(char *)_GROUP,	(char *)_F_GETGRENT,	(char *)_A_GIDNUMBER},
789f2fd570SJulian Pullen 	{(char *)_HOSTS,	(char *)_F_GETHOSTENT,	(char *)_A_CN},
799f2fd570SJulian Pullen 	{(char *)_NETWORKS,	(char *)_F_GETNETENT,
809f2fd570SJulian Pullen 						(char *)_A_IPNETWORKNUM},
819f2fd570SJulian Pullen 	{(char *)_PROTOCOLS,	(char *)_F_GETPROTOENT,	(char *)_A_CN},
829f2fd570SJulian Pullen 	{(char *)_RPC,		(char *)_F_GETRPCENT,	(char *)_A_CN},
839f2fd570SJulian Pullen 	{(char *)_ALIASES,	(char *)_F_GETALIASENT,	(char *)_A_CN},
849f2fd570SJulian Pullen 	{(char *)_SERVICES,	(char *)_F_GETSERVENT,	(char *)_A_CN},
859f2fd570SJulian Pullen 	{(char *)_AUUSER,	(char *)_F_GETAUUSERNAME,
869f2fd570SJulian Pullen 							(char *)_A_UID},
879f2fd570SJulian Pullen 	{(char *)_AUTHATTR,	(char *)_F_GETAUTHNAME,	(char *)_A_CN},
889f2fd570SJulian Pullen 	{(char *)_EXECATTR,	(char *)_F_GETEXECNAME,	(char *)_A_CN},
899f2fd570SJulian Pullen 	{(char *)_PROFATTR,	(char *)_F_GETPROFNAME,	(char *)_A_CN},
909f2fd570SJulian Pullen 	{(char *)_USERATTR,	(char *)_F_GETUSERNAME,	(char *)_A_UID},
919f2fd570SJulian Pullen 	{(char *)_PROJECT,	(char *)_F_GETPROJENT,	(char *)_A_PROJECTNAM},
929f2fd570SJulian Pullen 	{(char *)_PRINTERS,	(char *)_F_GETPRINTERENT, (char *)_A_CN},
939f2fd570SJulian Pullen 	{(char *)_TNRHDB,	(char *)_F_GETTNRHDB,	(char *)_A_IPTNETNUM},
949f2fd570SJulian Pullen 	{(char *)_TNRHTP,	(char *)_F_GETTNRHTP,
959f2fd570SJulian Pullen 						(char *)_A_IPTNETTMPLNAM},
969f2fd570SJulian Pullen 	{(char *)NULL,		(char *)NULL,		(char *)NULL}
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 
1003d047983Smichen nss_status_t
switch_err(int rc,ns_ldap_error_t * error)1017c478bd9Sstevel@tonic-gate switch_err(int rc, ns_ldap_error_t *error)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	switch (rc) {
1043d047983Smichen 	case NS_LDAP_SUCCESS:
1057c478bd9Sstevel@tonic-gate 		return (NSS_SUCCESS);
1067c478bd9Sstevel@tonic-gate 
1073d047983Smichen 	case NS_LDAP_NOTFOUND:
108*6a9f1673SMatt Barden 		errno = 0;
1097c478bd9Sstevel@tonic-gate 		return (NSS_NOTFOUND);
1107c478bd9Sstevel@tonic-gate 
1113d047983Smichen 	case NS_LDAP_PARTIAL:
1127c478bd9Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
1137c478bd9Sstevel@tonic-gate 
1143d047983Smichen 	case NS_LDAP_INTERNAL:
1153d047983Smichen 		if (error && (error->status == LDAP_SERVER_DOWN ||
1163d047983Smichen 		    error->status == LDAP_TIMEOUT))
1173d047983Smichen 			return (NSS_TRYAGAIN);
1183d047983Smichen 		else
1193d047983Smichen 			return (NSS_UNAVAIL);
1207c478bd9Sstevel@tonic-gate 
1213d047983Smichen 	default:
1227c478bd9Sstevel@tonic-gate 		return (NSS_UNAVAIL);
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate }
125cb5caa98Sdjl /* ARGSUSED */
1267c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_lookup(ldap_backend_ptr be,nss_XbyY_args_t * argp,char * database,char * searchfilter,char * domain,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const void * userdata)1277c478bd9Sstevel@tonic-gate _nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
128*6a9f1673SMatt Barden     char *database, char *searchfilter, char *domain,
129*6a9f1673SMatt Barden     int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
130*6a9f1673SMatt Barden     char **realfilter, const void *userdata),
131*6a9f1673SMatt Barden     const void *userdata)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	int		callbackstat = 0;
1347c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
1357c478bd9Sstevel@tonic-gate 	int		rc;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate #ifdef	DEBUG
1387c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_lookup]\n");
1397c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
1407c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout,
1413d047983Smichen 	    "\tuserdata: %s\n", userdata ? userdata : "NULL");
1427c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tdatabase: %s\n", database);
1437c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
1483d047983Smichen 	    be->attrs, NULL, 0, &be->result, &error, NULL,
1493d047983Smichen 	    userdata)) != NS_LDAP_SUCCESS) {
1507c478bd9Sstevel@tonic-gate 		argp->returnval = 0;
1517c478bd9Sstevel@tonic-gate 		rc = switch_err(rc, error);
1527c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
153cb5caa98Sdjl 
1547c478bd9Sstevel@tonic-gate 		return (rc);
1557c478bd9Sstevel@tonic-gate 	}
156cb5caa98Sdjl 		(void) __ns_ldap_freeError(&error);
1577c478bd9Sstevel@tonic-gate 	/* callback function */
1587c478bd9Sstevel@tonic-gate 	if ((callbackstat =
1593d047983Smichen 	    be->ldapobj2str(be, argp)) != NSS_STR_PARSE_SUCCESS) {
160cb5caa98Sdjl 		goto error_out;
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 
163cb5caa98Sdjl 	/*
164cb5caa98Sdjl 	 * publickey does not have a front end marshaller and expects
165cb5caa98Sdjl 	 * a string to be returned in NSS.
166cb5caa98Sdjl 	 * No need to convert file format -> struct.
167cb5caa98Sdjl 	 *
168cb5caa98Sdjl 	 */
169cb5caa98Sdjl 	if (be->db_type == NSS_LDAP_DB_PUBLICKEY) {
170cb5caa98Sdjl 		argp->returnval = argp->buf.buffer;
171cb5caa98Sdjl 		argp->returnlen = strlen(argp->buf.buffer);
172cb5caa98Sdjl 		be->db_type = NSS_LDAP_DB_NONE;
173cb5caa98Sdjl 		return (NSS_SUCCESS);
174cb5caa98Sdjl 	}
175cb5caa98Sdjl 	/*
176cb5caa98Sdjl 	 *  Assume the switch engine wants the returned data in the file
177cb5caa98Sdjl 	 *  format when argp->buf.result == NULL.
178cb5caa98Sdjl 	 *  The front-end marshaller str2ether(ethers) uses
179cb5caa98Sdjl 	 *  ent (argp->buf.result) and buffer (argp->buf.buffer)
180cb5caa98Sdjl 	 *  for different purpose so ethers has to be treated differently.
181cb5caa98Sdjl 	 */
182cb5caa98Sdjl 	if (argp->buf.result != NULL ||
1833d047983Smichen 	    be->db_type == NSS_LDAP_DB_ETHERS) {
184cb5caa98Sdjl 		/* file format -> struct */
185cb5caa98Sdjl 		if (argp->str2ent == NULL) {
186cb5caa98Sdjl 			callbackstat = NSS_STR_PARSE_PARSE;
187cb5caa98Sdjl 			goto error_out;
188cb5caa98Sdjl 		}
189cb5caa98Sdjl 
190cb5caa98Sdjl 		callbackstat = (*argp->str2ent)(be->buffer,
1913d047983Smichen 		    be->buflen,
1923d047983Smichen 		    argp->buf.result,
1933d047983Smichen 		    argp->buf.buffer,
1943d047983Smichen 		    argp->buf.buflen);
195cb5caa98Sdjl 		if (callbackstat == NSS_STR_PARSE_SUCCESS) {
196cb5caa98Sdjl 			if (be->db_type == NSS_LDAP_DB_ETHERS &&
1973d047983Smichen 			    argp->buf.buffer != NULL) {
198cb5caa98Sdjl 				argp->returnval = argp->buf.buffer;
199cb5caa98Sdjl 				argp->returnlen = strlen(argp->buf.buffer);
200cb5caa98Sdjl 			} else {
201cb5caa98Sdjl 				argp->returnval = argp->buf.result;
202cb5caa98Sdjl 				argp->returnlen = 1; /* irrelevant */
203cb5caa98Sdjl 			}
204cb5caa98Sdjl 			if (be->buffer != NULL) {
205cb5caa98Sdjl 				free(be->buffer);
206cb5caa98Sdjl 				be->buffer = NULL;
207cb5caa98Sdjl 				be->buflen = 0;
208cb5caa98Sdjl 				be->db_type = NSS_LDAP_DB_NONE;
209cb5caa98Sdjl 			}
210cb5caa98Sdjl 			return ((nss_status_t)NSS_SUCCESS);
211cb5caa98Sdjl 		}
212cb5caa98Sdjl 	} else {
213cb5caa98Sdjl 			/* return file format in argp->buf.buffer */
214cb5caa98Sdjl 			argp->returnval = argp->buf.buffer;
215cb5caa98Sdjl 			argp->returnlen = strlen(argp->buf.buffer);
216cb5caa98Sdjl 			return ((nss_status_t)NSS_SUCCESS);
217cb5caa98Sdjl 	}
218cb5caa98Sdjl 
219cb5caa98Sdjl error_out:
220cb5caa98Sdjl 	if (be->buffer != NULL) {
221cb5caa98Sdjl 		free(be->buffer);
222cb5caa98Sdjl 		be->buffer = NULL;
223cb5caa98Sdjl 		be->buflen = 0;
224cb5caa98Sdjl 		be->db_type = NSS_LDAP_DB_NONE;
225cb5caa98Sdjl 	}
2267c478bd9Sstevel@tonic-gate 	/* error */
2277c478bd9Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_PARSE) {
2287c478bd9Sstevel@tonic-gate 		argp->returnval = 0;
2297c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_ERANGE) {
2327c478bd9Sstevel@tonic-gate 		argp->erange = 1;
2337c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_NO_ADDR) {
2367c478bd9Sstevel@tonic-gate 		/* No IPV4 address is found */
2377c478bd9Sstevel@tonic-gate 		argp->h_errno = HOST_NOT_FOUND;
2387c478bd9Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_UNAVAIL);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate /*
2447c478bd9Sstevel@tonic-gate  *  This function is similar to _nss_ldap_lookup except it does not
2457c478bd9Sstevel@tonic-gate  *  do a callback.  It is only used by getnetgrent.c
2467c478bd9Sstevel@tonic-gate  */
2477c478bd9Sstevel@tonic-gate 
248cb5caa98Sdjl /* ARGSUSED */
2497c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_nocb_lookup(ldap_backend_ptr be,nss_XbyY_args_t * argp,char * database,char * searchfilter,const char * const * attrs,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const void * userdata)2507c478bd9Sstevel@tonic-gate _nss_ldap_nocb_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
251*6a9f1673SMatt Barden     char *database, char *searchfilter, const char * const *attrs,
252*6a9f1673SMatt Barden     int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
253*6a9f1673SMatt Barden     char **realfilter, const void *userdata),
254*6a9f1673SMatt Barden     const void *userdata)
2557c478bd9Sstevel@tonic-gate {
2567c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
2577c478bd9Sstevel@tonic-gate 	int		rc;
2587c478bd9Sstevel@tonic-gate 
259695ef821SGordon Ross 	if (attrs == NULL)
260695ef821SGordon Ross 		attrs = be->attrs;
261695ef821SGordon Ross 
2627c478bd9Sstevel@tonic-gate #ifdef	DEBUG
2637c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_nocb_lookup]\n");
2647c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
2657c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\tdatabase: %s\n", database);
2667c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout,
2673d047983Smichen 	    "\tuserdata: %s\n", userdata ? userdata : "NULL");
2687c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
273695ef821SGordon Ross 	    attrs, NULL, 0, &be->result, &error, NULL,
2743d047983Smichen 	    userdata)) != NS_LDAP_SUCCESS) {
27518bdb8a7Smichen 		if (argp != NULL)
27618bdb8a7Smichen 			argp->returnval = 0;
2777c478bd9Sstevel@tonic-gate 		rc = switch_err(rc, error);
2787c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
2797c478bd9Sstevel@tonic-gate 		return (rc);
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate  *
2887c478bd9Sstevel@tonic-gate  */
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate void
_clean_ldap_backend(ldap_backend_ptr be)2917c478bd9Sstevel@tonic-gate _clean_ldap_backend(ldap_backend_ptr be)
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate 	ns_ldap_error_t *error;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate #ifdef	DEBUG
2967c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _clean_ldap_backend]\n");
2977c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	if (be->tablename != NULL)
3007c478bd9Sstevel@tonic-gate 		free(be->tablename);
3017c478bd9Sstevel@tonic-gate 	if (be->result != NULL)
3027c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&be->result);
3037c478bd9Sstevel@tonic-gate 	if (be->enumcookie != NULL)
3047c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
3057c478bd9Sstevel@tonic-gate 	if (be->services_cookie != NULL)
3067c478bd9Sstevel@tonic-gate 		_nss_services_cookie_free((void **)&be->services_cookie);
3077c478bd9Sstevel@tonic-gate 	if (be->toglue != NULL) {
3087c478bd9Sstevel@tonic-gate 		free(be->toglue);
3097c478bd9Sstevel@tonic-gate 		be->toglue = NULL;
3107c478bd9Sstevel@tonic-gate 	}
311cb5caa98Sdjl 	if (be->buffer != NULL) {
312cb5caa98Sdjl 		free(be->buffer);
313cb5caa98Sdjl 		be->buffer = NULL;
314cb5caa98Sdjl 	}
3157c478bd9Sstevel@tonic-gate 	free(be);
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate  * _nss_ldap_destr will free all smalloc'ed variable strings and structures
3217c478bd9Sstevel@tonic-gate  * before exiting this nsswitch shared backend library. This function is
3227c478bd9Sstevel@tonic-gate  * called before returning control back to nsswitch.
3237c478bd9Sstevel@tonic-gate  */
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
3267c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_destr(ldap_backend_ptr be,void * a)3277c478bd9Sstevel@tonic-gate _nss_ldap_destr(ldap_backend_ptr be, void *a)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate #ifdef DEBUG
3317c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_destr]\n");
3327c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	(void) _clean_ldap_backend(be);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate /*
3417c478bd9Sstevel@tonic-gate  * _nss_ldap_setent called before _nss_ldap_getent. This function is
3427c478bd9Sstevel@tonic-gate  * required by POSIX.
3437c478bd9Sstevel@tonic-gate  */
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_setent(ldap_backend_ptr be,void * a)3467c478bd9Sstevel@tonic-gate _nss_ldap_setent(ldap_backend_ptr be, void *a)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate 	struct gettablefilter	*gtf;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate #ifdef DEBUG
3517c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_setent]\n");
3527c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	if (be->setcalled == 1)
3557c478bd9Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
3567c478bd9Sstevel@tonic-gate 	be->filter = NULL;
3579f2fd570SJulian Pullen 	be->sortattr = NULL;
3587c478bd9Sstevel@tonic-gate 	for (gtf = gettablefilterent; gtf->tablename != (char *)NULL; gtf++) {
3597c478bd9Sstevel@tonic-gate 		if (strcmp(gtf->tablename, be->tablename))
3607c478bd9Sstevel@tonic-gate 			continue;
3617c478bd9Sstevel@tonic-gate 		be->filter = (char *)gtf->tablefilter;
3629f2fd570SJulian Pullen 		be->sortattr = (char *)gtf->sortattr;
3637c478bd9Sstevel@tonic-gate 		break;
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	be->setcalled = 1;
3677c478bd9Sstevel@tonic-gate 	be->enumcookie = NULL;
3687c478bd9Sstevel@tonic-gate 	be->result = NULL;
3697c478bd9Sstevel@tonic-gate 	be->services_cookie = NULL;
370cb5caa98Sdjl 	be->buffer = NULL;
3717c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate  * _nss_ldap_endent called after _nss_ldap_getent. This function is
3777c478bd9Sstevel@tonic-gate  * required by POSIX.
3787c478bd9Sstevel@tonic-gate  */
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
3817c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_endent(ldap_backend_ptr be,void * a)3827c478bd9Sstevel@tonic-gate _nss_ldap_endent(ldap_backend_ptr be, void *a)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate #ifdef DEBUG
3877c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_endent]\n");
3887c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	be->setcalled = 0;
3917c478bd9Sstevel@tonic-gate 	be->filter = NULL;
3929f2fd570SJulian Pullen 	be->sortattr = NULL;
3937c478bd9Sstevel@tonic-gate 	if (be->enumcookie != NULL) {
3947c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
3957c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 	if (be->result != NULL) {
3987c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&be->result);
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 	if (be->services_cookie != NULL) {
4017c478bd9Sstevel@tonic-gate 		_nss_services_cookie_free((void **)&be->services_cookie);
4027c478bd9Sstevel@tonic-gate 	}
403cb5caa98Sdjl 	if (be->buffer != NULL) {
404cb5caa98Sdjl 		free(be->buffer);
405cb5caa98Sdjl 		be->buffer = NULL;
406cb5caa98Sdjl 	}
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate  *
4147c478bd9Sstevel@tonic-gate  */
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_getent(ldap_backend_ptr be,void * a)4177c478bd9Sstevel@tonic-gate _nss_ldap_getent(ldap_backend_ptr be, void *a)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
4207c478bd9Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
4217c478bd9Sstevel@tonic-gate 	int		parsestat = 0;
4227c478bd9Sstevel@tonic-gate 	int		retcode = 0;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4257c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_getent]\n");
4267c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	if (be->setcalled == 0)
4297c478bd9Sstevel@tonic-gate 		(void) _nss_ldap_setent(be, a);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate next_entry:
4327c478bd9Sstevel@tonic-gate 	if (be->enumcookie == NULL) {
4337c478bd9Sstevel@tonic-gate 		retcode = __ns_ldap_firstEntry(be->tablename,
4349f2fd570SJulian Pullen 		    be->filter, be->sortattr, _merge_SSD_filter, be->attrs,
4359f2fd570SJulian Pullen 		    NULL, 0, &be->enumcookie,
4363d047983Smichen 		    &be->result, &error, _F_GETENT_SSD);
4377c478bd9Sstevel@tonic-gate 	} else {
4387c478bd9Sstevel@tonic-gate 		if (be->services_cookie == NULL) {
4397c478bd9Sstevel@tonic-gate 			retcode = __ns_ldap_nextEntry(be->enumcookie,
4403d047983Smichen 			    &be->result, &error);
4417c478bd9Sstevel@tonic-gate 		}
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 	if (retcode != NS_LDAP_SUCCESS) {
4447c478bd9Sstevel@tonic-gate 		retcode = switch_err(retcode, error);
4457c478bd9Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
4467c478bd9Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
4477c478bd9Sstevel@tonic-gate 		return (retcode);
4489f2fd570SJulian Pullen 	}
4499f2fd570SJulian Pullen 
4509f2fd570SJulian Pullen 	if (be->result == NULL) {
4519f2fd570SJulian Pullen 		parsestat = NSS_STR_PARSE_NO_RESULT;
4529f2fd570SJulian Pullen 		goto error_out;
4539f2fd570SJulian Pullen 	}
4549f2fd570SJulian Pullen 	/* ns_ldap_entry_t -> file format */
4559f2fd570SJulian Pullen 	if ((parsestat = be->ldapobj2str(be, argp))
4569f2fd570SJulian Pullen 	    == NSS_STR_PARSE_SUCCESS) {
4579f2fd570SJulian Pullen 		if (argp->buf.result != NULL) {
4589f2fd570SJulian Pullen 			/* file format -> struct */
4599f2fd570SJulian Pullen 			if (argp->str2ent == NULL) {
4609f2fd570SJulian Pullen 				parsestat = NSS_STR_PARSE_NO_RESULT;
4619f2fd570SJulian Pullen 				goto error_out;
4629f2fd570SJulian Pullen 			}
4639f2fd570SJulian Pullen 			parsestat = (*argp->str2ent)(be->buffer,
4649f2fd570SJulian Pullen 			    be->buflen,
4659f2fd570SJulian Pullen 			    argp->buf.result,
4669f2fd570SJulian Pullen 			    argp->buf.buffer,
4679f2fd570SJulian Pullen 			    argp->buf.buflen);
4689f2fd570SJulian Pullen 			if (parsestat == NSS_STR_PARSE_SUCCESS) {
4699f2fd570SJulian Pullen 				if (be->buffer != NULL) {
4709f2fd570SJulian Pullen 					free(be->buffer);
4719f2fd570SJulian Pullen 					be->buffer = NULL;
4729f2fd570SJulian Pullen 					be->buflen = 0;
473cb5caa98Sdjl 				}
4749f2fd570SJulian Pullen 				be->result = NULL;
4759f2fd570SJulian Pullen 				argp->returnval = argp->buf.result;
4769f2fd570SJulian Pullen 				argp->returnlen = 1; /* irrevelant */
4779f2fd570SJulian Pullen 				return ((nss_status_t)NSS_SUCCESS);
478cb5caa98Sdjl 			}
4799f2fd570SJulian Pullen 		} else {
4809f2fd570SJulian Pullen 			/*
4819f2fd570SJulian Pullen 			 * nscd is not caching the enumerated
4829f2fd570SJulian Pullen 			 * entries. This code path would be dormant.
4839f2fd570SJulian Pullen 			 * Keep this path for the future references.
4849f2fd570SJulian Pullen 			 */
4859f2fd570SJulian Pullen 			argp->returnval = argp->buf.buffer;
4869f2fd570SJulian Pullen 			argp->returnlen =
4879f2fd570SJulian Pullen 			    strlen(argp->buf.buffer) + 1;
488cb5caa98Sdjl 		}
4899f2fd570SJulian Pullen 	}
490cb5caa98Sdjl error_out:
4919f2fd570SJulian Pullen 	if (be->buffer != NULL) {
4929f2fd570SJulian Pullen 		free(be->buffer);
4939f2fd570SJulian Pullen 		be->buffer = NULL;
4949f2fd570SJulian Pullen 		be->buflen = 0;
4959f2fd570SJulian Pullen 	}
4969f2fd570SJulian Pullen 	be->result = NULL;
4979f2fd570SJulian Pullen 	if (parsestat == NSS_STR_PARSE_NO_RESULT) {
4989f2fd570SJulian Pullen 		argp->returnval = 0;
4999f2fd570SJulian Pullen 		(void) _nss_ldap_endent(be, a);
5009f2fd570SJulian Pullen 		return ((nss_status_t)NSS_NOTFOUND);
5019f2fd570SJulian Pullen 	}
5027c478bd9Sstevel@tonic-gate 
5039f2fd570SJulian Pullen 	if (parsestat == NSS_STR_PARSE_ERANGE) {
5049f2fd570SJulian Pullen 		argp->erange = 1;
5059f2fd570SJulian Pullen 		(void) _nss_ldap_endent(be, a);
5069f2fd570SJulian Pullen 		return ((nss_status_t)NSS_NOTFOUND);
5077c478bd9Sstevel@tonic-gate 	}
5089f2fd570SJulian Pullen 	if (parsestat == NSS_STR_PARSE_NO_ADDR)
5099f2fd570SJulian Pullen 		/*
5109f2fd570SJulian Pullen 		 * No IPV4 address is found in the current entry.
5119f2fd570SJulian Pullen 		 * It indicates that the entry contains IPV6 addresses
5129f2fd570SJulian Pullen 		 * only. Instead of calling _nss_ldap_endent to
5139f2fd570SJulian Pullen 		 * terminate, get next entry to continue enumeration.
5149f2fd570SJulian Pullen 		 * If it returned NSS_NOTFOUND here,
5159f2fd570SJulian Pullen 		 * gethostent() would return NULL
5169f2fd570SJulian Pullen 		 * and the enumeration would stop prematurely.
5179f2fd570SJulian Pullen 		 */
5189f2fd570SJulian Pullen 		goto next_entry;
5199f2fd570SJulian Pullen 
5209f2fd570SJulian Pullen 	if (parsestat == NSS_STR_PARSE_PARSE)
5219f2fd570SJulian Pullen 		/*
5229f2fd570SJulian Pullen 		 * There has been a parse error. Most likely some
5239f2fd570SJulian Pullen 		 * mandatory attributes are missing. Ignore the error
5249f2fd570SJulian Pullen 		 * and get the next entry. If we returned an error the
5259f2fd570SJulian Pullen 		 * enumeration would stop prematurely.
5269f2fd570SJulian Pullen 		 */
5279f2fd570SJulian Pullen 		goto next_entry;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate  *
5357c478bd9Sstevel@tonic-gate  */
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate nss_backend_t *
_nss_ldap_constr(ldap_backend_op_t ops[],int nops,char * tablename,const char ** attrs,fnf ldapobj2str)5387c478bd9Sstevel@tonic-gate _nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename,
539*6a9f1673SMatt Barden     const char **attrs, fnf ldapobj2str)
5407c478bd9Sstevel@tonic-gate {
5417c478bd9Sstevel@tonic-gate 	ldap_backend_ptr	be;
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate #ifdef	DEBUG
5447c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_constr]\n");
5457c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
5467c478bd9Sstevel@tonic-gate 
547cb5caa98Sdjl 	if ((be = (ldap_backend_ptr) calloc(1, sizeof (*be))) == 0)
5487c478bd9Sstevel@tonic-gate 		return (0);
5497c478bd9Sstevel@tonic-gate 	be->ops = ops;
5507c478bd9Sstevel@tonic-gate 	be->nops = (nss_dbop_t)nops;
5517c478bd9Sstevel@tonic-gate 	be->tablename = (char *)strdup(tablename);
5527c478bd9Sstevel@tonic-gate 	be->attrs = attrs;
553cb5caa98Sdjl 	be->ldapobj2str = ldapobj2str;
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	return ((nss_backend_t *)be);
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate  *
5617c478bd9Sstevel@tonic-gate  */
5627c478bd9Sstevel@tonic-gate int
chophostdomain(char * string,char * host,char * domain)5637c478bd9Sstevel@tonic-gate chophostdomain(char *string, char *host, char *domain)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate 	char	*dot;
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	if (string == NULL)
5687c478bd9Sstevel@tonic-gate 		return (-1);
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	if ((dot = strchr(string, '.')) == NULL) {
5717c478bd9Sstevel@tonic-gate 		return (0);
5727c478bd9Sstevel@tonic-gate 	}
5737c478bd9Sstevel@tonic-gate 	*dot = '\0';
574cb5caa98Sdjl 	(void) strcpy(host, string);
575cb5caa98Sdjl 	(void) strcpy(domain, ++dot);
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	return (0);
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate /*
5827c478bd9Sstevel@tonic-gate  *
5837c478bd9Sstevel@tonic-gate  */
5847c478bd9Sstevel@tonic-gate int
propersubdomain(char * domain,char * subdomain)5857c478bd9Sstevel@tonic-gate propersubdomain(char *domain, char *subdomain)
5867c478bd9Sstevel@tonic-gate {
5877c478bd9Sstevel@tonic-gate 	int	domainlen, subdomainlen;
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	/* sanity check */
5907c478bd9Sstevel@tonic-gate 	if (domain == NULL || subdomain == NULL)
5917c478bd9Sstevel@tonic-gate 		return (-1);
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	domainlen = strlen(domain);
5947c478bd9Sstevel@tonic-gate 	subdomainlen = strlen(subdomain);
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/* is afterdot a substring of domain? */
5977c478bd9Sstevel@tonic-gate 	if ((strncasecmp(domain, subdomain, subdomainlen)) != 0)
5987c478bd9Sstevel@tonic-gate 		return (-1);
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	if (domainlen == subdomainlen)
6017c478bd9Sstevel@tonic-gate 		return (1);
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	if (subdomainlen > domainlen)
6047c478bd9Sstevel@tonic-gate 		return (-1);
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	if (*(domain + subdomainlen) != '.')
6077c478bd9Sstevel@tonic-gate 		return (-1);
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	return (1);
6107c478bd9Sstevel@tonic-gate }
611