xref: /onnv-gate/usr/src/lib/nsswitch/ldap/common/ldap_common.c (revision 12758:996c46be076f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51676Sjpk  * Common Development and Distribution License (the "License").
61676Sjpk  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12758SJulian.Pullen@Sun.COM  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include "ldap_common.h"
260Sstevel@tonic-gate #include <malloc.h>
270Sstevel@tonic-gate #include <synch.h>
280Sstevel@tonic-gate #include <syslog.h>
290Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
300Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
310Sstevel@tonic-gate #include <thread.h>
320Sstevel@tonic-gate #include <ctype.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <signal.h>
350Sstevel@tonic-gate #include <sys/stat.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /* getent attributes filters */
380Sstevel@tonic-gate #define	_F_GETALIASENT		"(objectClass=rfc822MailGroup)"
390Sstevel@tonic-gate #define	_F_GETAUTHNAME		"(objectClass=SolarisAuthAttr)"
400Sstevel@tonic-gate #define	_F_GETAUUSERNAME	"(objectClass=SolarisAuditUser)"
410Sstevel@tonic-gate #define	_F_GETEXECNAME		"(objectClass=SolarisExecAttr)"
420Sstevel@tonic-gate #define	_F_GETGRENT		"(objectClass=posixGroup)"
430Sstevel@tonic-gate #define	_F_GETHOSTENT		"(objectClass=ipHost)"
440Sstevel@tonic-gate #define	_F_GETNETENT		"(objectClass=ipNetwork)"
452830Sdjl #define	_F_GETPROFNAME \
462830Sdjl "(&(objectClass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*)))"
470Sstevel@tonic-gate #define	_F_GETPROTOENT		"(objectClass=ipProtocol)"
480Sstevel@tonic-gate #define	_F_GETPWENT		"(objectClass=posixAccount)"
490Sstevel@tonic-gate #define	_F_GETPRINTERENT	"(objectClass=sunPrinter)"
500Sstevel@tonic-gate #define	_F_GETRPCENT		"(objectClass=oncRpc)"
510Sstevel@tonic-gate #define	_F_GETSERVENT		"(objectClass=ipService)"
520Sstevel@tonic-gate #define	_F_GETSPENT		"(objectclass=shadowAccount)"
530Sstevel@tonic-gate #define	_F_GETUSERNAME		"(objectClass=SolarisUserAttr)"
540Sstevel@tonic-gate #define	_F_GETPROJENT		"(objectClass=SolarisProject)"
551676Sjpk #define	_F_GETTNRHDB		"(objectClass=ipTnetHost)"
561676Sjpk #define	_F_GETTNRHTP		"(&(objectClass=ipTnetTemplate)"\
571676Sjpk 				"(SolarisAttrKeyValue=*))"
580Sstevel@tonic-gate #define	_F_GETENT_SSD		"(%s)"
590Sstevel@tonic-gate 
60*12758SJulian.Pullen@Sun.COM /* getent sort attributes */
61*12758SJulian.Pullen@Sun.COM #define	_A_UID			"uid"
62*12758SJulian.Pullen@Sun.COM #define	_A_GIDNUMBER		"gidnumber"
63*12758SJulian.Pullen@Sun.COM #define	_A_CN			"cn"
64*12758SJulian.Pullen@Sun.COM #define	_A_IPNETWORKNUM		"ipnetworknumber"
65*12758SJulian.Pullen@Sun.COM #define	_A_PROJECTNAM		"SolarisProjectName"
66*12758SJulian.Pullen@Sun.COM #define	_A_IPTNETNUM		"ipTnetNumber"
67*12758SJulian.Pullen@Sun.COM #define	_A_IPTNETTMPLNAM	"ipTnetTemplateName"
68*12758SJulian.Pullen@Sun.COM 
690Sstevel@tonic-gate static struct gettablefilter {
700Sstevel@tonic-gate 	char *tablename;
710Sstevel@tonic-gate 	char *tablefilter;
72*12758SJulian.Pullen@Sun.COM 	char *sortattr;
730Sstevel@tonic-gate } gettablefilterent[] = {
74*12758SJulian.Pullen@Sun.COM 	{(char *)_PASSWD,	(char *)_F_GETPWENT,	(char *)_A_UID},
75*12758SJulian.Pullen@Sun.COM 	{(char *)_SHADOW,	(char *)_F_GETSPENT,	(char *)_A_UID},
76*12758SJulian.Pullen@Sun.COM 	{(char *)_GROUP,	(char *)_F_GETGRENT,	(char *)_A_GIDNUMBER},
77*12758SJulian.Pullen@Sun.COM 	{(char *)_HOSTS,	(char *)_F_GETHOSTENT,	(char *)_A_CN},
78*12758SJulian.Pullen@Sun.COM 	{(char *)_NETWORKS,	(char *)_F_GETNETENT,
79*12758SJulian.Pullen@Sun.COM 						(char *)_A_IPNETWORKNUM},
80*12758SJulian.Pullen@Sun.COM 	{(char *)_PROTOCOLS,	(char *)_F_GETPROTOENT,	(char *)_A_CN},
81*12758SJulian.Pullen@Sun.COM 	{(char *)_RPC,		(char *)_F_GETRPCENT,	(char *)_A_CN},
82*12758SJulian.Pullen@Sun.COM 	{(char *)_ALIASES,	(char *)_F_GETALIASENT,	(char *)_A_CN},
83*12758SJulian.Pullen@Sun.COM 	{(char *)_SERVICES,	(char *)_F_GETSERVENT,	(char *)_A_CN},
84*12758SJulian.Pullen@Sun.COM 	{(char *)_AUUSER,	(char *)_F_GETAUUSERNAME,
85*12758SJulian.Pullen@Sun.COM 							(char *)_A_UID},
86*12758SJulian.Pullen@Sun.COM 	{(char *)_AUTHATTR,	(char *)_F_GETAUTHNAME,	(char *)_A_CN},
87*12758SJulian.Pullen@Sun.COM 	{(char *)_EXECATTR,	(char *)_F_GETEXECNAME,	(char *)_A_CN},
88*12758SJulian.Pullen@Sun.COM 	{(char *)_PROFATTR,	(char *)_F_GETPROFNAME,	(char *)_A_CN},
89*12758SJulian.Pullen@Sun.COM 	{(char *)_USERATTR,	(char *)_F_GETUSERNAME,	(char *)_A_UID},
90*12758SJulian.Pullen@Sun.COM 	{(char *)_PROJECT,	(char *)_F_GETPROJENT,	(char *)_A_PROJECTNAM},
91*12758SJulian.Pullen@Sun.COM 	{(char *)_PRINTERS,	(char *)_F_GETPRINTERENT, (char *)_A_CN},
92*12758SJulian.Pullen@Sun.COM 	{(char *)_TNRHDB,	(char *)_F_GETTNRHDB,	(char *)_A_IPTNETNUM},
93*12758SJulian.Pullen@Sun.COM 	{(char *)_TNRHTP,	(char *)_F_GETTNRHTP,
94*12758SJulian.Pullen@Sun.COM 						(char *)_A_IPTNETTMPLNAM},
95*12758SJulian.Pullen@Sun.COM 	{(char *)NULL,		(char *)NULL,		(char *)NULL}
960Sstevel@tonic-gate };
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 
994953Smichen nss_status_t
switch_err(int rc,ns_ldap_error_t * error)1000Sstevel@tonic-gate switch_err(int rc, ns_ldap_error_t *error)
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	switch (rc) {
1034953Smichen 	case NS_LDAP_SUCCESS:
1040Sstevel@tonic-gate 		return (NSS_SUCCESS);
1050Sstevel@tonic-gate 
1064953Smichen 	case NS_LDAP_NOTFOUND:
1070Sstevel@tonic-gate 		return (NSS_NOTFOUND);
1080Sstevel@tonic-gate 
1094953Smichen 	case NS_LDAP_PARTIAL:
1100Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
1110Sstevel@tonic-gate 
1124953Smichen 	case NS_LDAP_INTERNAL:
1134953Smichen 		if (error && (error->status == LDAP_SERVER_DOWN ||
1144953Smichen 		    error->status == LDAP_TIMEOUT))
1154953Smichen 			return (NSS_TRYAGAIN);
1164953Smichen 		else
1174953Smichen 			return (NSS_UNAVAIL);
1180Sstevel@tonic-gate 
1194953Smichen 	default:
1200Sstevel@tonic-gate 		return (NSS_UNAVAIL);
1210Sstevel@tonic-gate 	}
1220Sstevel@tonic-gate }
1232830Sdjl /* ARGSUSED */
1240Sstevel@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)1250Sstevel@tonic-gate _nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
1260Sstevel@tonic-gate 		char *database, char *searchfilter, char *domain,
1270Sstevel@tonic-gate 		int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
1280Sstevel@tonic-gate 		char **realfilter, const void *userdata),
1290Sstevel@tonic-gate 		const void *userdata)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	int		callbackstat = 0;
1320Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
1330Sstevel@tonic-gate 	int		rc;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate #ifdef	DEBUG
1360Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_lookup]\n");
1370Sstevel@tonic-gate 	(void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
1380Sstevel@tonic-gate 	(void) fprintf(stdout,
1394953Smichen 	    "\tuserdata: %s\n", userdata ? userdata : "NULL");
1400Sstevel@tonic-gate 	(void) fprintf(stdout, "\tdatabase: %s\n", database);
1410Sstevel@tonic-gate #endif	/* DEBUG */
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
1464953Smichen 	    be->attrs, NULL, 0, &be->result, &error, NULL,
1474953Smichen 	    userdata)) != NS_LDAP_SUCCESS) {
1480Sstevel@tonic-gate 		argp->returnval = 0;
1490Sstevel@tonic-gate 		rc = switch_err(rc, error);
1500Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
1512830Sdjl 
1520Sstevel@tonic-gate 		return (rc);
1530Sstevel@tonic-gate 	}
1542830Sdjl 		(void) __ns_ldap_freeError(&error);
1550Sstevel@tonic-gate 	/* callback function */
1560Sstevel@tonic-gate 	if ((callbackstat =
1574953Smichen 	    be->ldapobj2str(be, argp)) != NSS_STR_PARSE_SUCCESS) {
1582830Sdjl 		goto error_out;
1592830Sdjl 	}
1602830Sdjl 
1612830Sdjl 	/*
1622830Sdjl 	 * publickey does not have a front end marshaller and expects
1632830Sdjl 	 * a string to be returned in NSS.
1642830Sdjl 	 * No need to convert file format -> struct.
1652830Sdjl 	 *
1662830Sdjl 	 */
1672830Sdjl 	if (be->db_type == NSS_LDAP_DB_PUBLICKEY) {
1682830Sdjl 		argp->returnval = argp->buf.buffer;
1692830Sdjl 		argp->returnlen = strlen(argp->buf.buffer);
1702830Sdjl 		be->db_type = NSS_LDAP_DB_NONE;
1712830Sdjl 		return (NSS_SUCCESS);
1720Sstevel@tonic-gate 	}
1732830Sdjl 	/*
1742830Sdjl 	 *  Assume the switch engine wants the returned data in the file
1752830Sdjl 	 *  format when argp->buf.result == NULL.
1762830Sdjl 	 *  The front-end marshaller str2ether(ethers) uses
1772830Sdjl 	 *  ent (argp->buf.result) and buffer (argp->buf.buffer)
1782830Sdjl 	 *  for different purpose so ethers has to be treated differently.
1792830Sdjl 	 */
1802830Sdjl 	if (argp->buf.result != NULL ||
1814953Smichen 	    be->db_type == NSS_LDAP_DB_ETHERS) {
1822830Sdjl 		/* file format -> struct */
1832830Sdjl 		if (argp->str2ent == NULL) {
1842830Sdjl 			callbackstat = NSS_STR_PARSE_PARSE;
1852830Sdjl 			goto error_out;
1862830Sdjl 		}
1870Sstevel@tonic-gate 
1882830Sdjl 		callbackstat = (*argp->str2ent)(be->buffer,
1894953Smichen 		    be->buflen,
1904953Smichen 		    argp->buf.result,
1914953Smichen 		    argp->buf.buffer,
1924953Smichen 		    argp->buf.buflen);
1932830Sdjl 		if (callbackstat == NSS_STR_PARSE_SUCCESS) {
1942830Sdjl 			if (be->db_type == NSS_LDAP_DB_ETHERS &&
1954953Smichen 			    argp->buf.buffer != NULL) {
1962830Sdjl 				argp->returnval = argp->buf.buffer;
1972830Sdjl 				argp->returnlen = strlen(argp->buf.buffer);
1982830Sdjl 			} else {
1992830Sdjl 				argp->returnval = argp->buf.result;
2002830Sdjl 				argp->returnlen = 1; /* irrelevant */
2012830Sdjl 			}
2022830Sdjl 			if (be->buffer != NULL) {
2032830Sdjl 				free(be->buffer);
2042830Sdjl 				be->buffer = NULL;
2052830Sdjl 				be->buflen = 0;
2062830Sdjl 				be->db_type = NSS_LDAP_DB_NONE;
2072830Sdjl 			}
2082830Sdjl 			return ((nss_status_t)NSS_SUCCESS);
2092830Sdjl 		}
2102830Sdjl 	} else {
2112830Sdjl 			/* return file format in argp->buf.buffer */
2122830Sdjl 			argp->returnval = argp->buf.buffer;
2132830Sdjl 			argp->returnlen = strlen(argp->buf.buffer);
2142830Sdjl 			return ((nss_status_t)NSS_SUCCESS);
2152830Sdjl 	}
2162830Sdjl 
2172830Sdjl error_out:
2182830Sdjl 	if (be->buffer != NULL) {
2192830Sdjl 		free(be->buffer);
2202830Sdjl 		be->buffer = NULL;
2212830Sdjl 		be->buflen = 0;
2222830Sdjl 		be->db_type = NSS_LDAP_DB_NONE;
2232830Sdjl 	}
2240Sstevel@tonic-gate 	/* error */
2250Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_PARSE) {
2260Sstevel@tonic-gate 		argp->returnval = 0;
2270Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2280Sstevel@tonic-gate 	}
2290Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_ERANGE) {
2300Sstevel@tonic-gate 		argp->erange = 1;
2310Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 	if (callbackstat == NSS_STR_PARSE_NO_ADDR) {
2340Sstevel@tonic-gate 		/* No IPV4 address is found */
2350Sstevel@tonic-gate 		argp->h_errno = HOST_NOT_FOUND;
2360Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate 	return ((nss_status_t)NSS_UNAVAIL);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate /*
2420Sstevel@tonic-gate  *  This function is similar to _nss_ldap_lookup except it does not
2430Sstevel@tonic-gate  *  do a callback.  It is only used by getnetgrent.c
2440Sstevel@tonic-gate  */
2450Sstevel@tonic-gate 
2462830Sdjl /* ARGSUSED */
2470Sstevel@tonic-gate nss_status_t
_nss_ldap_nocb_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)2480Sstevel@tonic-gate _nss_ldap_nocb_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
2490Sstevel@tonic-gate 		char *database, char *searchfilter, char *domain,
2500Sstevel@tonic-gate 		int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
2510Sstevel@tonic-gate 		char **realfilter, const void *userdata),
2520Sstevel@tonic-gate 		const void *userdata)
2530Sstevel@tonic-gate {
2540Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
2550Sstevel@tonic-gate 	int		rc;
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate #ifdef	DEBUG
2580Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_nocb_lookup]\n");
2590Sstevel@tonic-gate 	(void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
2600Sstevel@tonic-gate 	(void) fprintf(stdout, "\tdatabase: %s\n", database);
2610Sstevel@tonic-gate 	(void) fprintf(stdout,
2624953Smichen 	    "\tuserdata: %s\n", userdata ? userdata : "NULL");
2630Sstevel@tonic-gate #endif	/* DEBUG */
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
2684953Smichen 	    be->attrs, NULL, 0, &be->result, &error, NULL,
2694953Smichen 	    userdata)) != NS_LDAP_SUCCESS) {
2705362Smichen 		if (argp != NULL)
2715362Smichen 			argp->returnval = 0;
2720Sstevel@tonic-gate 		rc = switch_err(rc, error);
2730Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
2740Sstevel@tonic-gate 		return (rc);
2750Sstevel@tonic-gate 	}
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate /*
2820Sstevel@tonic-gate  *
2830Sstevel@tonic-gate  */
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate void
_clean_ldap_backend(ldap_backend_ptr be)2860Sstevel@tonic-gate _clean_ldap_backend(ldap_backend_ptr be)
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate 	ns_ldap_error_t *error;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate #ifdef	DEBUG
2910Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _clean_ldap_backend]\n");
2920Sstevel@tonic-gate #endif	/* DEBUG */
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	if (be->tablename != NULL)
2950Sstevel@tonic-gate 		free(be->tablename);
2960Sstevel@tonic-gate 	if (be->result != NULL)
2970Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&be->result);
2980Sstevel@tonic-gate 	if (be->enumcookie != NULL)
2990Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
3000Sstevel@tonic-gate 	if (be->services_cookie != NULL)
3010Sstevel@tonic-gate 		_nss_services_cookie_free((void **)&be->services_cookie);
3020Sstevel@tonic-gate 	if (be->toglue != NULL) {
3030Sstevel@tonic-gate 		free(be->toglue);
3040Sstevel@tonic-gate 		be->toglue = NULL;
3050Sstevel@tonic-gate 	}
3062830Sdjl 	if (be->buffer != NULL) {
3072830Sdjl 		free(be->buffer);
3082830Sdjl 		be->buffer = NULL;
3092830Sdjl 	}
3100Sstevel@tonic-gate 	free(be);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate /*
3150Sstevel@tonic-gate  * _nss_ldap_destr will free all smalloc'ed variable strings and structures
3160Sstevel@tonic-gate  * before exiting this nsswitch shared backend library. This function is
3170Sstevel@tonic-gate  * called before returning control back to nsswitch.
3180Sstevel@tonic-gate  */
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate /*ARGSUSED1*/
3210Sstevel@tonic-gate nss_status_t
_nss_ldap_destr(ldap_backend_ptr be,void * a)3220Sstevel@tonic-gate _nss_ldap_destr(ldap_backend_ptr be, void *a)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate #ifdef DEBUG
3260Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_destr]\n");
3270Sstevel@tonic-gate #endif /* DEBUG */
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	(void) _clean_ldap_backend(be);
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate /*
3360Sstevel@tonic-gate  * _nss_ldap_setent called before _nss_ldap_getent. This function is
3370Sstevel@tonic-gate  * required by POSIX.
3380Sstevel@tonic-gate  */
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate nss_status_t
_nss_ldap_setent(ldap_backend_ptr be,void * a)3410Sstevel@tonic-gate _nss_ldap_setent(ldap_backend_ptr be, void *a)
3420Sstevel@tonic-gate {
3430Sstevel@tonic-gate 	struct gettablefilter	*gtf;
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate #ifdef DEBUG
3460Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_setent]\n");
3470Sstevel@tonic-gate #endif /* DEBUG */
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	if (be->setcalled == 1)
3500Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
3510Sstevel@tonic-gate 	be->filter = NULL;
352*12758SJulian.Pullen@Sun.COM 	be->sortattr = NULL;
3530Sstevel@tonic-gate 	for (gtf = gettablefilterent; gtf->tablename != (char *)NULL; gtf++) {
3540Sstevel@tonic-gate 		if (strcmp(gtf->tablename, be->tablename))
3550Sstevel@tonic-gate 			continue;
3560Sstevel@tonic-gate 		be->filter = (char *)gtf->tablefilter;
357*12758SJulian.Pullen@Sun.COM 		be->sortattr = (char *)gtf->sortattr;
3580Sstevel@tonic-gate 		break;
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	be->setcalled = 1;
3620Sstevel@tonic-gate 	be->enumcookie = NULL;
3630Sstevel@tonic-gate 	be->result = NULL;
3640Sstevel@tonic-gate 	be->services_cookie = NULL;
3652830Sdjl 	be->buffer = NULL;
3660Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate /*
3710Sstevel@tonic-gate  * _nss_ldap_endent called after _nss_ldap_getent. This function is
3720Sstevel@tonic-gate  * required by POSIX.
3730Sstevel@tonic-gate  */
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate /*ARGSUSED1*/
3760Sstevel@tonic-gate nss_status_t
_nss_ldap_endent(ldap_backend_ptr be,void * a)3770Sstevel@tonic-gate _nss_ldap_endent(ldap_backend_ptr be, void *a)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate #ifdef DEBUG
3820Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_endent]\n");
3830Sstevel@tonic-gate #endif /* DEBUG */
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	be->setcalled = 0;
3860Sstevel@tonic-gate 	be->filter = NULL;
387*12758SJulian.Pullen@Sun.COM 	be->sortattr = NULL;
3880Sstevel@tonic-gate 	if (be->enumcookie != NULL) {
3890Sstevel@tonic-gate 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
3900Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
3910Sstevel@tonic-gate 	}
3920Sstevel@tonic-gate 	if (be->result != NULL) {
3930Sstevel@tonic-gate 		(void) __ns_ldap_freeResult(&be->result);
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 	if (be->services_cookie != NULL) {
3960Sstevel@tonic-gate 		_nss_services_cookie_free((void **)&be->services_cookie);
3970Sstevel@tonic-gate 	}
3982830Sdjl 	if (be->buffer != NULL) {
3992830Sdjl 		free(be->buffer);
4002830Sdjl 		be->buffer = NULL;
4012830Sdjl 	}
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate /*
4080Sstevel@tonic-gate  *
4090Sstevel@tonic-gate  */
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate nss_status_t
_nss_ldap_getent(ldap_backend_ptr be,void * a)4120Sstevel@tonic-gate _nss_ldap_getent(ldap_backend_ptr be, void *a)
4130Sstevel@tonic-gate {
4140Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
4150Sstevel@tonic-gate 	ns_ldap_error_t	*error = NULL;
4160Sstevel@tonic-gate 	int		parsestat = 0;
4170Sstevel@tonic-gate 	int		retcode = 0;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate #ifdef	DEBUG
4200Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_getent]\n");
4210Sstevel@tonic-gate #endif	/* DEBUG */
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	if (be->setcalled == 0)
4240Sstevel@tonic-gate 		(void) _nss_ldap_setent(be, a);
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate next_entry:
4270Sstevel@tonic-gate 	if (be->enumcookie == NULL) {
4280Sstevel@tonic-gate 		retcode = __ns_ldap_firstEntry(be->tablename,
429*12758SJulian.Pullen@Sun.COM 		    be->filter, be->sortattr, _merge_SSD_filter, be->attrs,
430*12758SJulian.Pullen@Sun.COM 		    NULL, 0, &be->enumcookie,
4314953Smichen 		    &be->result, &error, _F_GETENT_SSD);
4320Sstevel@tonic-gate 	} else {
4330Sstevel@tonic-gate 		if (be->services_cookie == NULL) {
4340Sstevel@tonic-gate 			retcode = __ns_ldap_nextEntry(be->enumcookie,
4354953Smichen 			    &be->result, &error);
4360Sstevel@tonic-gate 		}
4370Sstevel@tonic-gate 	}
4380Sstevel@tonic-gate 	if (retcode != NS_LDAP_SUCCESS) {
4390Sstevel@tonic-gate 		retcode = switch_err(retcode, error);
4400Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&error);
4410Sstevel@tonic-gate 		(void) _nss_ldap_endent(be, a);
4420Sstevel@tonic-gate 		return (retcode);
443*12758SJulian.Pullen@Sun.COM 	}
444*12758SJulian.Pullen@Sun.COM 
445*12758SJulian.Pullen@Sun.COM 	if (be->result == NULL) {
446*12758SJulian.Pullen@Sun.COM 		parsestat = NSS_STR_PARSE_NO_RESULT;
447*12758SJulian.Pullen@Sun.COM 		goto error_out;
448*12758SJulian.Pullen@Sun.COM 	}
449*12758SJulian.Pullen@Sun.COM 	/* ns_ldap_entry_t -> file format */
450*12758SJulian.Pullen@Sun.COM 	if ((parsestat = be->ldapobj2str(be, argp))
451*12758SJulian.Pullen@Sun.COM 	    == NSS_STR_PARSE_SUCCESS) {
452*12758SJulian.Pullen@Sun.COM 		if (argp->buf.result != NULL) {
453*12758SJulian.Pullen@Sun.COM 			/* file format -> struct */
454*12758SJulian.Pullen@Sun.COM 			if (argp->str2ent == NULL) {
455*12758SJulian.Pullen@Sun.COM 				parsestat = NSS_STR_PARSE_NO_RESULT;
456*12758SJulian.Pullen@Sun.COM 				goto error_out;
457*12758SJulian.Pullen@Sun.COM 			}
458*12758SJulian.Pullen@Sun.COM 			parsestat = (*argp->str2ent)(be->buffer,
459*12758SJulian.Pullen@Sun.COM 			    be->buflen,
460*12758SJulian.Pullen@Sun.COM 			    argp->buf.result,
461*12758SJulian.Pullen@Sun.COM 			    argp->buf.buffer,
462*12758SJulian.Pullen@Sun.COM 			    argp->buf.buflen);
463*12758SJulian.Pullen@Sun.COM 			if (parsestat == NSS_STR_PARSE_SUCCESS) {
464*12758SJulian.Pullen@Sun.COM 				if (be->buffer != NULL) {
465*12758SJulian.Pullen@Sun.COM 					free(be->buffer);
466*12758SJulian.Pullen@Sun.COM 					be->buffer = NULL;
467*12758SJulian.Pullen@Sun.COM 					be->buflen = 0;
4682830Sdjl 				}
469*12758SJulian.Pullen@Sun.COM 				be->result = NULL;
470*12758SJulian.Pullen@Sun.COM 				argp->returnval = argp->buf.result;
471*12758SJulian.Pullen@Sun.COM 				argp->returnlen = 1; /* irrevelant */
472*12758SJulian.Pullen@Sun.COM 				return ((nss_status_t)NSS_SUCCESS);
4732830Sdjl 			}
474*12758SJulian.Pullen@Sun.COM 		} else {
475*12758SJulian.Pullen@Sun.COM 			/*
476*12758SJulian.Pullen@Sun.COM 			 * nscd is not caching the enumerated
477*12758SJulian.Pullen@Sun.COM 			 * entries. This code path would be dormant.
478*12758SJulian.Pullen@Sun.COM 			 * Keep this path for the future references.
479*12758SJulian.Pullen@Sun.COM 			 */
480*12758SJulian.Pullen@Sun.COM 			argp->returnval = argp->buf.buffer;
481*12758SJulian.Pullen@Sun.COM 			argp->returnlen =
482*12758SJulian.Pullen@Sun.COM 			    strlen(argp->buf.buffer) + 1;
4830Sstevel@tonic-gate 		}
484*12758SJulian.Pullen@Sun.COM 	}
485*12758SJulian.Pullen@Sun.COM error_out:
486*12758SJulian.Pullen@Sun.COM 	if (be->buffer != NULL) {
487*12758SJulian.Pullen@Sun.COM 		free(be->buffer);
488*12758SJulian.Pullen@Sun.COM 		be->buffer = NULL;
489*12758SJulian.Pullen@Sun.COM 		be->buflen = 0;
490*12758SJulian.Pullen@Sun.COM 	}
491*12758SJulian.Pullen@Sun.COM 	be->result = NULL;
492*12758SJulian.Pullen@Sun.COM 	if (parsestat == NSS_STR_PARSE_NO_RESULT) {
493*12758SJulian.Pullen@Sun.COM 		argp->returnval = 0;
494*12758SJulian.Pullen@Sun.COM 		(void) _nss_ldap_endent(be, a);
495*12758SJulian.Pullen@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
496*12758SJulian.Pullen@Sun.COM 	}
4970Sstevel@tonic-gate 
498*12758SJulian.Pullen@Sun.COM 	if (parsestat == NSS_STR_PARSE_ERANGE) {
499*12758SJulian.Pullen@Sun.COM 		argp->erange = 1;
500*12758SJulian.Pullen@Sun.COM 		(void) _nss_ldap_endent(be, a);
501*12758SJulian.Pullen@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
5020Sstevel@tonic-gate 	}
503*12758SJulian.Pullen@Sun.COM 	if (parsestat == NSS_STR_PARSE_NO_ADDR)
504*12758SJulian.Pullen@Sun.COM 		/*
505*12758SJulian.Pullen@Sun.COM 		 * No IPV4 address is found in the current entry.
506*12758SJulian.Pullen@Sun.COM 		 * It indicates that the entry contains IPV6 addresses
507*12758SJulian.Pullen@Sun.COM 		 * only. Instead of calling _nss_ldap_endent to
508*12758SJulian.Pullen@Sun.COM 		 * terminate, get next entry to continue enumeration.
509*12758SJulian.Pullen@Sun.COM 		 * If it returned NSS_NOTFOUND here,
510*12758SJulian.Pullen@Sun.COM 		 * gethostent() would return NULL
511*12758SJulian.Pullen@Sun.COM 		 * and the enumeration would stop prematurely.
512*12758SJulian.Pullen@Sun.COM 		 */
513*12758SJulian.Pullen@Sun.COM 		goto next_entry;
514*12758SJulian.Pullen@Sun.COM 
515*12758SJulian.Pullen@Sun.COM 	if (parsestat == NSS_STR_PARSE_PARSE)
516*12758SJulian.Pullen@Sun.COM 		/*
517*12758SJulian.Pullen@Sun.COM 		 * There has been a parse error. Most likely some
518*12758SJulian.Pullen@Sun.COM 		 * mandatory attributes are missing. Ignore the error
519*12758SJulian.Pullen@Sun.COM 		 * and get the next entry. If we returned an error the
520*12758SJulian.Pullen@Sun.COM 		 * enumeration would stop prematurely.
521*12758SJulian.Pullen@Sun.COM 		 */
522*12758SJulian.Pullen@Sun.COM 		goto next_entry;
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate /*
5290Sstevel@tonic-gate  *
5300Sstevel@tonic-gate  */
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate nss_backend_t *
_nss_ldap_constr(ldap_backend_op_t ops[],int nops,char * tablename,const char ** attrs,fnf ldapobj2str)5330Sstevel@tonic-gate _nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename,
5342830Sdjl 		const char **attrs, fnf ldapobj2str)
5350Sstevel@tonic-gate {
5360Sstevel@tonic-gate 	ldap_backend_ptr	be;
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate #ifdef	DEBUG
5390Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_constr]\n");
5400Sstevel@tonic-gate #endif	/* DEBUG */
5410Sstevel@tonic-gate 
5422830Sdjl 	if ((be = (ldap_backend_ptr) calloc(1, sizeof (*be))) == 0)
5430Sstevel@tonic-gate 		return (0);
5440Sstevel@tonic-gate 	be->ops = ops;
5450Sstevel@tonic-gate 	be->nops = (nss_dbop_t)nops;
5460Sstevel@tonic-gate 	be->tablename = (char *)strdup(tablename);
5470Sstevel@tonic-gate 	be->attrs = attrs;
5482830Sdjl 	be->ldapobj2str = ldapobj2str;
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	return ((nss_backend_t *)be);
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate /*
5550Sstevel@tonic-gate  *
5560Sstevel@tonic-gate  */
5570Sstevel@tonic-gate int
chophostdomain(char * string,char * host,char * domain)5580Sstevel@tonic-gate chophostdomain(char *string, char *host, char *domain)
5590Sstevel@tonic-gate {
5600Sstevel@tonic-gate 	char	*dot;
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	if (string == NULL)
5630Sstevel@tonic-gate 		return (-1);
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	if ((dot = strchr(string, '.')) == NULL) {
5660Sstevel@tonic-gate 		return (0);
5670Sstevel@tonic-gate 	}
5680Sstevel@tonic-gate 	*dot = '\0';
5692830Sdjl 	(void) strcpy(host, string);
5702830Sdjl 	(void) strcpy(domain, ++dot);
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	return (0);
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate /*
5770Sstevel@tonic-gate  *
5780Sstevel@tonic-gate  */
5790Sstevel@tonic-gate int
propersubdomain(char * domain,char * subdomain)5800Sstevel@tonic-gate propersubdomain(char *domain, char *subdomain)
5810Sstevel@tonic-gate {
5820Sstevel@tonic-gate 	int	domainlen, subdomainlen;
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	/* sanity check */
5850Sstevel@tonic-gate 	if (domain == NULL || subdomain == NULL)
5860Sstevel@tonic-gate 		return (-1);
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	domainlen = strlen(domain);
5890Sstevel@tonic-gate 	subdomainlen = strlen(subdomain);
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	/* is afterdot a substring of domain? */
5920Sstevel@tonic-gate 	if ((strncasecmp(domain, subdomain, subdomainlen)) != 0)
5930Sstevel@tonic-gate 		return (-1);
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	if (domainlen == subdomainlen)
5960Sstevel@tonic-gate 		return (1);
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	if (subdomainlen > domainlen)
5990Sstevel@tonic-gate 		return (-1);
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	if (*(domain + subdomainlen) != '.')
6020Sstevel@tonic-gate 		return (-1);
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	return (1);
6050Sstevel@tonic-gate }
606