xref: /onnv-gate/usr/src/lib/libsldap/common/ns_common.c (revision 12969:9fda0aeb1cb6)
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*12969SJulian.Pullen@Sun.COM  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <libintl.h>
300Sstevel@tonic-gate #include <ctype.h>
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/stat.h>
330Sstevel@tonic-gate #include <sys/mman.h>
340Sstevel@tonic-gate #include <fcntl.h>
350Sstevel@tonic-gate #include <unistd.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <syslog.h>
380Sstevel@tonic-gate #include <sys/socket.h>
390Sstevel@tonic-gate #include <sys/sockio.h>
400Sstevel@tonic-gate #include <netinet/in.h>
410Sstevel@tonic-gate #include <arpa/inet.h>
420Sstevel@tonic-gate #include <net/if.h>
430Sstevel@tonic-gate #include <netdir.h>
440Sstevel@tonic-gate #include <lber.h>
450Sstevel@tonic-gate #include <ldap.h>
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #include "ns_sldap.h"
480Sstevel@tonic-gate #include "ns_internal.h"
490Sstevel@tonic-gate #include "ns_cache_door.h"
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #define	UDP	"/dev/udp"
520Sstevel@tonic-gate #define	MAXIFS	32
530Sstevel@tonic-gate 
540Sstevel@tonic-gate struct ifinfo {
550Sstevel@tonic-gate 	struct in_addr addr, netmask;
560Sstevel@tonic-gate };
570Sstevel@tonic-gate 
580Sstevel@tonic-gate static ns_service_map ns_def_map[] = {
590Sstevel@tonic-gate 	{ "passwd",	"ou=people,",		NULL },
600Sstevel@tonic-gate 	{ "shadow",	"ou=people,",		"passwd" },
610Sstevel@tonic-gate 	{ "user_attr",	"ou=people,",		"passwd" },
620Sstevel@tonic-gate 	{ "audit_user",	"ou=people,",		"passwd" },
630Sstevel@tonic-gate 	{ "group",	"ou=group,",		NULL },
640Sstevel@tonic-gate 	{ "rpc",	"ou=rpc,",		NULL },
650Sstevel@tonic-gate 	{ "project",	"ou=projects,",		NULL },
660Sstevel@tonic-gate 	{ "protocols",	"ou=protocols,",	NULL },
670Sstevel@tonic-gate 	{ "networks",	"ou=networks,",		NULL },
680Sstevel@tonic-gate 	{ "netmasks",	"ou=networks,",		"networks" },
690Sstevel@tonic-gate 	{ "netgroup",	"ou=netgroup,",		NULL },
700Sstevel@tonic-gate 	{ "aliases",	"ou=aliases,",		NULL },
710Sstevel@tonic-gate 	{ "Hosts",	"ou=Hosts,",		NULL },
720Sstevel@tonic-gate 	{ "ipnodes",	"ou=Hosts,",		"hosts" },
730Sstevel@tonic-gate 	{ "Services",	"ou=Services,",		NULL },
740Sstevel@tonic-gate 	{ "bootparams",	"ou=ethers,",		"ethers" },
750Sstevel@tonic-gate 	{ "ethers",	"ou=ethers,",		NULL },
760Sstevel@tonic-gate 	{ "auth_attr",	"ou=SolarisAuthAttr,",	NULL },
770Sstevel@tonic-gate 	{ "prof_attr",	"ou=SolarisProfAttr,",	NULL },
780Sstevel@tonic-gate 	{ "exec_attr",	"ou=SolarisProfAttr,",	"prof_attr" },
790Sstevel@tonic-gate 	{ "profile",	"ou=profile,",		NULL },
800Sstevel@tonic-gate 	{ "printers",	"ou=printers,",		NULL },
810Sstevel@tonic-gate 	{ "automount",	"",			NULL },
821676Sjpk 	{ "tnrhtp",	"ou=ipTnet,",		NULL },
831676Sjpk 	{ "tnrhdb",	"ou=ipTnet,",		"tnrhtp" },
840Sstevel@tonic-gate 	{ NULL, NULL, NULL }
850Sstevel@tonic-gate };
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 
880Sstevel@tonic-gate static char ** parseDN(const char *val, const char *service);
890Sstevel@tonic-gate static char ** sortServerNet(char **srvlist);
900Sstevel@tonic-gate static char ** sortServerPref(char **srvlist, char **preflist,
910Sstevel@tonic-gate 		boolean_t flag, int version, int *error);
920Sstevel@tonic-gate 
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate  * FUNCTION:	s_api_printResult
950Sstevel@tonic-gate  *	Given a ns_ldap_result structure print it.
960Sstevel@tonic-gate  */
970Sstevel@tonic-gate int
__s_api_printResult(ns_ldap_result_t * result)980Sstevel@tonic-gate __s_api_printResult(ns_ldap_result_t *result)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 	ns_ldap_entry_t	*curEntry;
1020Sstevel@tonic-gate 	int		i, j, k = 0;
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate #ifdef DEBUG
1050Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_printResult START\n");
1060Sstevel@tonic-gate #endif
1070Sstevel@tonic-gate 	(void) printf("--------------------------------------\n");
1080Sstevel@tonic-gate 	if (result == NULL) {
1090Sstevel@tonic-gate 		(void) printf("No result\n");
1100Sstevel@tonic-gate 		return (0);
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 	(void) printf("entries_count %d\n", result->entries_count);
1130Sstevel@tonic-gate 	curEntry = result->entry;
1140Sstevel@tonic-gate 	for (i = 0; i < result->entries_count; i++) {
1150Sstevel@tonic-gate 
1164522Schinlong 		(void) printf("entry %d has attr_count = %d \n", i,
1174522Schinlong 		    curEntry->attr_count);
1184522Schinlong 		for (j = 0; j < curEntry->attr_count; j++) {
1194522Schinlong 			(void) printf("entry %d has attr_pair[%d] = %s \n",
1204522Schinlong 			    i, j, curEntry->attr_pair[j]->attrname);
1214522Schinlong 			for (k = 0; k < 20 &&
1224522Schinlong 			    curEntry->attr_pair[j]->attrvalue[k]; k++)
1234522Schinlong 				(void) printf("entry %d has attr_pair[%d]->"
1244522Schinlong 				    "attrvalue[%d] = %s \n", i, j, k,
1254522Schinlong 				    curEntry->attr_pair[j]->attrvalue[k]);
1264522Schinlong 		}
1274522Schinlong 		(void) printf("\n--------------------------------------\n");
1284522Schinlong 		curEntry = curEntry->next;
1290Sstevel@tonic-gate 	}
1300Sstevel@tonic-gate 	return (1);
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate  * FUNCTION:	__s_api_getSearchScope
1350Sstevel@tonic-gate  *
1360Sstevel@tonic-gate  *	Retrieve the search scope for ldap search from the config module.
1370Sstevel@tonic-gate  *
1380Sstevel@tonic-gate  * RETURN VALUES:	NS_LDAP_SUCCESS, NS_LDAP_CONFIG
1390Sstevel@tonic-gate  * INPUT:		NONE
1400Sstevel@tonic-gate  * OUTPUT:		searchScope, errorp
1410Sstevel@tonic-gate  */
1420Sstevel@tonic-gate int
__s_api_getSearchScope(int * searchScope,ns_ldap_error_t ** errorp)1430Sstevel@tonic-gate __s_api_getSearchScope(
1440Sstevel@tonic-gate 	int *searchScope,
1450Sstevel@tonic-gate 	ns_ldap_error_t **errorp)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	char		errmsg[MAXERROR];
1490Sstevel@tonic-gate 	void		**paramVal = NULL;
1500Sstevel@tonic-gate 	int		rc = 0;
1510Sstevel@tonic-gate 	int		scope = 0;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate #ifdef DEBUG
1540Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_getSearchScope START\n");
1550Sstevel@tonic-gate #endif
1560Sstevel@tonic-gate 	if (*searchScope == 0) {
1570Sstevel@tonic-gate 		if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P,
1584522Schinlong 		    &paramVal, errorp)) != NS_LDAP_SUCCESS) {
1590Sstevel@tonic-gate 			return (rc);
1600Sstevel@tonic-gate 		}
1610Sstevel@tonic-gate 		if (paramVal && *paramVal)
1620Sstevel@tonic-gate 			scope = * (int *)(*paramVal);
1630Sstevel@tonic-gate 		else
1640Sstevel@tonic-gate 			scope = NS_LDAP_SCOPE_ONELEVEL;
1650Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
1660Sstevel@tonic-gate 	} else {
1670Sstevel@tonic-gate 		scope = *searchScope;
1680Sstevel@tonic-gate 	}
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	switch (scope) {
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 		case	NS_LDAP_SCOPE_ONELEVEL:
1730Sstevel@tonic-gate 			*searchScope = LDAP_SCOPE_ONELEVEL;
1740Sstevel@tonic-gate 			break;
1750Sstevel@tonic-gate 		case	NS_LDAP_SCOPE_BASE:
1760Sstevel@tonic-gate 			*searchScope = LDAP_SCOPE_BASE;
1770Sstevel@tonic-gate 			break;
1780Sstevel@tonic-gate 		case	NS_LDAP_SCOPE_SUBTREE:
1790Sstevel@tonic-gate 			*searchScope = LDAP_SCOPE_SUBTREE;
1800Sstevel@tonic-gate 			break;
1810Sstevel@tonic-gate 		default:
1820Sstevel@tonic-gate 			(void) snprintf(errmsg, sizeof (errmsg),
1834522Schinlong 			    gettext("Invalid search scope!"));
1840Sstevel@tonic-gate 			MKERROR(LOG_ERR, *errorp, NS_CONFIG_FILE,
1854522Schinlong 			    strdup(errmsg), NS_LDAP_CONFIG);
1860Sstevel@tonic-gate 			return (NS_LDAP_CONFIG);
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate  * FUNCTION:	__ns_ldap_dupAuth
1940Sstevel@tonic-gate  *
1950Sstevel@tonic-gate  *	Duplicates an authentication structure.
1960Sstevel@tonic-gate  *
1970Sstevel@tonic-gate  * RETURN VALUES:	copy of authp or NULL on error
1980Sstevel@tonic-gate  * INPUT:		authp
1990Sstevel@tonic-gate  */
2000Sstevel@tonic-gate ns_cred_t *
__ns_ldap_dupAuth(const ns_cred_t * authp)2010Sstevel@tonic-gate __ns_ldap_dupAuth(const ns_cred_t *authp)
2020Sstevel@tonic-gate {
2030Sstevel@tonic-gate 	ns_cred_t *ap;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate #ifdef DEBUG
2060Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_dupAuth START\n");
2070Sstevel@tonic-gate #endif
2080Sstevel@tonic-gate 	if (authp == NULL)
2090Sstevel@tonic-gate 		return (NULL);
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	ap = (ns_cred_t *)calloc(1, sizeof (ns_cred_t));
2120Sstevel@tonic-gate 	if (ap == NULL)
2130Sstevel@tonic-gate 		return (NULL);
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	if (authp->hostcertpath) {
2160Sstevel@tonic-gate 		ap->hostcertpath = strdup(authp->hostcertpath);
2170Sstevel@tonic-gate 		if (ap->hostcertpath == NULL) {
2180Sstevel@tonic-gate 			free(ap);
2190Sstevel@tonic-gate 			return (NULL);
2200Sstevel@tonic-gate 		}
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 	if (authp->cred.unix_cred.userID) {
2230Sstevel@tonic-gate 		ap->cred.unix_cred.userID =
2244522Schinlong 		    strdup(authp->cred.unix_cred.userID);
2250Sstevel@tonic-gate 		if (ap->cred.unix_cred.userID == NULL) {
2260Sstevel@tonic-gate 			(void) __ns_ldap_freeCred(&ap);
2270Sstevel@tonic-gate 			return (NULL);
2280Sstevel@tonic-gate 		}
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 	if (authp->cred.unix_cred.passwd) {
2310Sstevel@tonic-gate 		ap->cred.unix_cred.passwd =
2324522Schinlong 		    strdup(authp->cred.unix_cred.passwd);
2330Sstevel@tonic-gate 		if (ap->cred.unix_cred.passwd == NULL) {
2340Sstevel@tonic-gate 			(void) __ns_ldap_freeCred(&ap);
2350Sstevel@tonic-gate 			return (NULL);
2360Sstevel@tonic-gate 		}
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate 	if (authp->cred.cert_cred.nickname) {
2390Sstevel@tonic-gate 		ap->cred.cert_cred.nickname =
2404522Schinlong 		    strdup(authp->cred.cert_cred.nickname);
2410Sstevel@tonic-gate 		if (ap->cred.cert_cred.nickname == NULL) {
2420Sstevel@tonic-gate 			(void) __ns_ldap_freeCred(&ap);
2430Sstevel@tonic-gate 			return (NULL);
2440Sstevel@tonic-gate 		}
2450Sstevel@tonic-gate 	}
2460Sstevel@tonic-gate 	ap->auth.type = authp->auth.type;
2470Sstevel@tonic-gate 	ap->auth.tlstype = authp->auth.tlstype;
2480Sstevel@tonic-gate 	ap->auth.saslmech = authp->auth.saslmech;
2490Sstevel@tonic-gate 	ap->auth.saslopt = authp->auth.saslopt;
2500Sstevel@tonic-gate 	return (ap);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate /*
2549576SJulian.Pullen@Sun.COM  * FUNCTION:	__ns_ldap_freeUnixCred
2559576SJulian.Pullen@Sun.COM  *
2569576SJulian.Pullen@Sun.COM  *	Frees all the memory associated with a UnixCred_t structure.
2579576SJulian.Pullen@Sun.COM  *
2589576SJulian.Pullen@Sun.COM  * RETURN VALUES:	NS_LDAP_INVALID_PARAM, NS_LDAP_SUCCESS
2599576SJulian.Pullen@Sun.COM  * INPUT:		UnixCred
2609576SJulian.Pullen@Sun.COM  */
2619576SJulian.Pullen@Sun.COM int
__ns_ldap_freeUnixCred(UnixCred_t ** credp)2629576SJulian.Pullen@Sun.COM __ns_ldap_freeUnixCred(UnixCred_t ** credp)
2639576SJulian.Pullen@Sun.COM {
2649576SJulian.Pullen@Sun.COM 	UnixCred_t *ap;
2659576SJulian.Pullen@Sun.COM 
2669576SJulian.Pullen@Sun.COM #ifdef DEBUG
2679576SJulian.Pullen@Sun.COM 	(void) fprintf(stderr, "__ns_ldap_freeUnixCred START\n");
2689576SJulian.Pullen@Sun.COM #endif
2699576SJulian.Pullen@Sun.COM 	if (credp == NULL || *credp == NULL)
2709576SJulian.Pullen@Sun.COM 		return (NS_LDAP_INVALID_PARAM);
2719576SJulian.Pullen@Sun.COM 
2729576SJulian.Pullen@Sun.COM 	ap = *credp;
2739576SJulian.Pullen@Sun.COM 	if (ap->userID) {
2749576SJulian.Pullen@Sun.COM 		(void) memset(ap->userID, 0, strlen(ap->userID));
2759576SJulian.Pullen@Sun.COM 		free(ap->userID);
2769576SJulian.Pullen@Sun.COM 	}
2779576SJulian.Pullen@Sun.COM 
2789576SJulian.Pullen@Sun.COM 	if (ap->passwd) {
2799576SJulian.Pullen@Sun.COM 		(void) memset(ap->passwd, 0, strlen(ap->passwd));
2809576SJulian.Pullen@Sun.COM 		free(ap->passwd);
2819576SJulian.Pullen@Sun.COM 	}
2829576SJulian.Pullen@Sun.COM 
2839576SJulian.Pullen@Sun.COM 	free(ap);
2849576SJulian.Pullen@Sun.COM 	*credp = NULL;
2859576SJulian.Pullen@Sun.COM 	return (NS_LDAP_SUCCESS);
2869576SJulian.Pullen@Sun.COM }
2879576SJulian.Pullen@Sun.COM 
2889576SJulian.Pullen@Sun.COM /*
2890Sstevel@tonic-gate  * FUNCTION:	__ns_ldap_freeCred
2900Sstevel@tonic-gate  *
2910Sstevel@tonic-gate  *	Frees all the memory associated with a ns_cred_t structure.
2920Sstevel@tonic-gate  *
2939576SJulian.Pullen@Sun.COM  * RETURN VALUES:	NS_LDAP_INVALID_PARAM, NS_LDAP_SUCCESS
2940Sstevel@tonic-gate  * INPUT:		ns_cred_t
2950Sstevel@tonic-gate  */
2960Sstevel@tonic-gate int
__ns_ldap_freeCred(ns_cred_t ** credp)2970Sstevel@tonic-gate __ns_ldap_freeCred(ns_cred_t ** credp)
2980Sstevel@tonic-gate {
2990Sstevel@tonic-gate 	ns_cred_t *ap;
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate #ifdef DEBUG
3020Sstevel@tonic-gate 	(void) fprintf(stderr, "__ns_ldap_freeCred START\n");
3030Sstevel@tonic-gate #endif
3040Sstevel@tonic-gate 	if (credp == NULL || *credp == NULL)
3050Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	ap = *credp;
3080Sstevel@tonic-gate 	if (ap->hostcertpath) {
3090Sstevel@tonic-gate 		(void) memset(ap->hostcertpath, 0,
3104522Schinlong 		    strlen(ap->hostcertpath));
3110Sstevel@tonic-gate 		free(ap->hostcertpath);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	if (ap->cred.unix_cred.userID) {
3150Sstevel@tonic-gate 		(void) memset(ap->cred.unix_cred.userID, 0,
3164522Schinlong 		    strlen(ap->cred.unix_cred.userID));
3170Sstevel@tonic-gate 		free(ap->cred.unix_cred.userID);
3180Sstevel@tonic-gate 	}
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	if (ap->cred.unix_cred.passwd) {
3210Sstevel@tonic-gate 		(void) memset(ap->cred.unix_cred.passwd, 0,
3224522Schinlong 		    strlen(ap->cred.unix_cred.passwd));
3230Sstevel@tonic-gate 		free(ap->cred.unix_cred.passwd);
3240Sstevel@tonic-gate 	}
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	if (ap->cred.cert_cred.nickname) {
3270Sstevel@tonic-gate 		(void) memset(ap->cred.cert_cred.nickname, 0,
3284522Schinlong 		    strlen(ap->cred.cert_cred.nickname));
3290Sstevel@tonic-gate 		free(ap->cred.cert_cred.nickname);
3300Sstevel@tonic-gate 	}
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	free(ap);
3330Sstevel@tonic-gate 	*credp = NULL;
3340Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate /*
3386842Sth160488  * FUNCTION:	__s_api_is_auth_matched
3396842Sth160488  *
3406842Sth160488  *	Compare an authentication structure.
3416842Sth160488  *
3426842Sth160488  * RETURN VALUES:	B_TRUE if matched, B_FALSE otherwise.
3436842Sth160488  * INPUT:		auth1, auth2
3446842Sth160488  */
3456842Sth160488 boolean_t
__s_api_is_auth_matched(const ns_cred_t * auth1,const ns_cred_t * auth2)3466842Sth160488 __s_api_is_auth_matched(const ns_cred_t *auth1,
3476842Sth160488     const ns_cred_t *auth2)
3486842Sth160488 {
3496842Sth160488 	if ((auth1->auth.type != auth2->auth.type) ||
3506842Sth160488 	    (auth1->auth.tlstype != auth2->auth.tlstype) ||
3516842Sth160488 	    (auth1->auth.saslmech != auth2->auth.saslmech) ||
3526842Sth160488 	    (auth1->auth.saslopt != auth2->auth.saslopt))
3536842Sth160488 		return (B_FALSE);
3546842Sth160488 
3556842Sth160488 	if ((((auth1->auth.type == NS_LDAP_AUTH_SASL) &&
3566842Sth160488 	    ((auth1->auth.saslmech == NS_LDAP_SASL_CRAM_MD5) ||
3576842Sth160488 	    (auth1->auth.saslmech == NS_LDAP_SASL_DIGEST_MD5))) ||
3586842Sth160488 	    (auth1->auth.type == NS_LDAP_AUTH_SIMPLE)) &&
3596842Sth160488 	    ((auth1->cred.unix_cred.userID == NULL) ||
3606842Sth160488 	    (auth1->cred.unix_cred.passwd == NULL) ||
3616842Sth160488 	    ((strcasecmp(auth1->cred.unix_cred.userID,
3626842Sth160488 	    auth2->cred.unix_cred.userID) != 0)) ||
3636842Sth160488 	    ((strcmp(auth1->cred.unix_cred.passwd,
3646842Sth160488 	    auth2->cred.unix_cred.passwd) != 0))))
3656842Sth160488 		return (B_FALSE);
3666842Sth160488 
3676842Sth160488 	return (B_TRUE);
3686842Sth160488 }
3696842Sth160488 
3706842Sth160488 /*
3710Sstevel@tonic-gate  * FUNCTION:	__s_api_getDNs
3720Sstevel@tonic-gate  *
3730Sstevel@tonic-gate  *	Retrieves the default base dn for the given
3740Sstevel@tonic-gate  *	service.
3750Sstevel@tonic-gate  *
3760Sstevel@tonic-gate  * RETURN VALUES:	NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG
3770Sstevel@tonic-gate  * INPUT:		service
3780Sstevel@tonic-gate  * OUTPUT:		DN, error
3790Sstevel@tonic-gate  */
3804522Schinlong typedef int (*pf)(const char *, char **, ns_ldap_error_t **);
3810Sstevel@tonic-gate int
__s_api_getDNs(char *** DN,const char * service,ns_ldap_error_t ** error)3820Sstevel@tonic-gate __s_api_getDNs(
3830Sstevel@tonic-gate 	char *** DN,
3840Sstevel@tonic-gate 	const char *service,
3850Sstevel@tonic-gate 	ns_ldap_error_t ** error)
3860Sstevel@tonic-gate {
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	void	**paramVal = NULL;
3890Sstevel@tonic-gate 	char	**dns = NULL;
3900Sstevel@tonic-gate 	int	rc = 0;
3910Sstevel@tonic-gate 	int	i, len;
3924522Schinlong 	pf	prepend_auto2dn = __s_api_prepend_automountmapname_to_dn;
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate #ifdef DEBUG
3950Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_getDNs START\n");
3960Sstevel@tonic-gate #endif
3970Sstevel@tonic-gate 	if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3980Sstevel@tonic-gate 	    &paramVal, error)) != NS_LDAP_SUCCESS) {
3990Sstevel@tonic-gate 		return (rc);
4000Sstevel@tonic-gate 	}
4010Sstevel@tonic-gate 	if (!paramVal) {
4020Sstevel@tonic-gate 		char errmsg[MAXERROR];
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 		(void) snprintf(errmsg, sizeof (errmsg),
4054522Schinlong 		    gettext("BaseDN not defined"));
4060Sstevel@tonic-gate 		MKERROR(LOG_ERR, *error, NS_CONFIG_FILE, strdup(errmsg),
4070Sstevel@tonic-gate 		    NS_LDAP_CONFIG);
4080Sstevel@tonic-gate 		return (NS_LDAP_CONFIG);
4090Sstevel@tonic-gate 	}
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	dns = (char **)calloc(2, sizeof (char *));
4120Sstevel@tonic-gate 	if (dns == NULL) {
4130Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
4140Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
4150Sstevel@tonic-gate 	}
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	if (service == NULL) {
4180Sstevel@tonic-gate 		dns[0] = strdup((char *)*paramVal);
4190Sstevel@tonic-gate 		if (dns[0] == NULL) {
4200Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&paramVal);
4210Sstevel@tonic-gate 			free(dns);
4220Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
4230Sstevel@tonic-gate 		}
4240Sstevel@tonic-gate 	} else {
4250Sstevel@tonic-gate 		for (i = 0; ns_def_map[i].service != NULL; i++) {
4260Sstevel@tonic-gate 			if (strcasecmp(service,
4274522Schinlong 			    ns_def_map[i].service) == 0) {
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 				len = strlen((char *)*paramVal) +
4304522Schinlong 				    strlen(ns_def_map[i].rdn) + 1;
4310Sstevel@tonic-gate 				dns[0] = (char *)
4324522Schinlong 				    calloc(len, sizeof (char));
4330Sstevel@tonic-gate 				if (dns[0] == NULL) {
4340Sstevel@tonic-gate 					(void) __ns_ldap_freeParam(
4354522Schinlong 					    &paramVal);
4360Sstevel@tonic-gate 					free(dns);
4370Sstevel@tonic-gate 					return (NS_LDAP_MEMORY);
4380Sstevel@tonic-gate 				}
4390Sstevel@tonic-gate 				(void) strcpy(dns[0],
4404522Schinlong 				    ns_def_map[i].rdn);
4410Sstevel@tonic-gate 				(void) strcat(dns[0],
4424522Schinlong 				    (char *)*paramVal);
4430Sstevel@tonic-gate 				break;
4440Sstevel@tonic-gate 			}
4450Sstevel@tonic-gate 		}
4460Sstevel@tonic-gate 		if (ns_def_map[i].service == NULL) {
4470Sstevel@tonic-gate 			char *p = (char *)*paramVal;
4480Sstevel@tonic-gate 			char *buffer = NULL;
4490Sstevel@tonic-gate 			int  buflen = 0;
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 			if (strchr(service, '=') == NULL) {
4520Sstevel@tonic-gate 			    /* automount entries */
4534522Schinlong 				if (strncasecmp(service, "auto_", 5) == 0) {
4544522Schinlong 					buffer = strdup(p);
4554522Schinlong 					if (!buffer) {
4564522Schinlong 						free(dns);
4574522Schinlong 						(void) __ns_ldap_freeParam(
4584522Schinlong 						    &paramVal);
4594522Schinlong 						return (NS_LDAP_MEMORY);
4604522Schinlong 					}
4614522Schinlong 					/* shorten name to avoid cstyle error */
4624522Schinlong 					rc = prepend_auto2dn(
4634522Schinlong 					    service, &buffer, error);
4644522Schinlong 					if (rc != NS_LDAP_SUCCESS) {
4654522Schinlong 						free(dns);
4664522Schinlong 						free(buffer);
4674522Schinlong 						(void) __ns_ldap_freeParam(
4684522Schinlong 						    &paramVal);
4694522Schinlong 						return (rc);
4704522Schinlong 					}
4714522Schinlong 				} else {
4724522Schinlong 				/* strlen("nisMapName")+"="+","+'\0' = 13 */
4734522Schinlong 					buflen = strlen(service) + strlen(p) +
4744522Schinlong 					    13;
4754522Schinlong 					buffer = (char *)malloc(buflen);
4764522Schinlong 					if (buffer == NULL) {
4774522Schinlong 						free(dns);
4784522Schinlong 						(void) __ns_ldap_freeParam(
4794522Schinlong 						    &paramVal);
4804522Schinlong 						return (NS_LDAP_MEMORY);
4814522Schinlong 					}
4824522Schinlong 					(void) snprintf(buffer, buflen,
4834522Schinlong 					    "nisMapName=%s,%s", service, p);
4840Sstevel@tonic-gate 				}
4854522Schinlong 			} else {
4864522Schinlong 				buflen = strlen(service) + strlen(p) + 2;
4870Sstevel@tonic-gate 				buffer = (char *)malloc(buflen);
4880Sstevel@tonic-gate 				if (buffer == NULL) {
4890Sstevel@tonic-gate 					free(dns);
4900Sstevel@tonic-gate 					(void) __ns_ldap_freeParam(&paramVal);
4910Sstevel@tonic-gate 					return (NS_LDAP_MEMORY);
4920Sstevel@tonic-gate 				}
4930Sstevel@tonic-gate 				(void) snprintf(buffer, buflen,
4944522Schinlong 				    "%s,%s", service, p);
4950Sstevel@tonic-gate 			}
4960Sstevel@tonic-gate 			dns[0] = buffer;
4970Sstevel@tonic-gate 		}
4980Sstevel@tonic-gate 	}
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 	(void) __ns_ldap_freeParam(&paramVal);
5010Sstevel@tonic-gate 	*DN = dns;
5020Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate /*
5050Sstevel@tonic-gate  * FUNCTION:	__s_api_get_search_DNs_v1
5060Sstevel@tonic-gate  *
5070Sstevel@tonic-gate  *	Retrieves the list of search DNS from the V1 profile for the given
5080Sstevel@tonic-gate  *	service.
5090Sstevel@tonic-gate  *
5100Sstevel@tonic-gate  * RETURN VALUES:	NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG
5110Sstevel@tonic-gate  * INPUT:		service
5120Sstevel@tonic-gate  * OUTPUT:		DN, error
5130Sstevel@tonic-gate  */
5140Sstevel@tonic-gate int
__s_api_get_search_DNs_v1(char *** DN,const char * service,ns_ldap_error_t ** error)5150Sstevel@tonic-gate __s_api_get_search_DNs_v1(
5160Sstevel@tonic-gate 	char *** DN,
5170Sstevel@tonic-gate 	const char *service,
5180Sstevel@tonic-gate 	ns_ldap_error_t ** error)
5190Sstevel@tonic-gate {
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	void	**paramVal = NULL;
5220Sstevel@tonic-gate 	void	**temptr = NULL;
5230Sstevel@tonic-gate 	char	**dns = NULL;
5240Sstevel@tonic-gate 	int	rc = 0;
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_DN_P,
5270Sstevel@tonic-gate 	    &paramVal, error)) != NS_LDAP_SUCCESS) {
5280Sstevel@tonic-gate 		return (rc);
5290Sstevel@tonic-gate 	}
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	if (service && paramVal) {
5320Sstevel@tonic-gate 		for (temptr = paramVal; *temptr != NULL; temptr++) {
5330Sstevel@tonic-gate 			dns = parseDN((const char *)(*temptr),
5340Sstevel@tonic-gate 			    (const char *)service);
5350Sstevel@tonic-gate 			if (dns != NULL)
5360Sstevel@tonic-gate 				break;
5370Sstevel@tonic-gate 		}
5380Sstevel@tonic-gate 	}
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	(void) __ns_ldap_freeParam(&paramVal);
5410Sstevel@tonic-gate 	*DN = dns;
5420Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate  * FUNCTION:	parseDN
5470Sstevel@tonic-gate  *
5480Sstevel@tonic-gate  *	Parse a special formated list(val) into an array of char *.
5490Sstevel@tonic-gate  *
5500Sstevel@tonic-gate  * RETURN VALUE:	A char * pointer to the new list of dns.
5510Sstevel@tonic-gate  * INPUT:		val, service
5520Sstevel@tonic-gate  */
5530Sstevel@tonic-gate static char **
parseDN(const char * val,const char * service)5540Sstevel@tonic-gate parseDN(
5550Sstevel@tonic-gate 	const char *val,
5560Sstevel@tonic-gate 	const char *service)
5570Sstevel@tonic-gate {
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 	size_t		len = 0;
5600Sstevel@tonic-gate 	size_t		slen = 0;
5610Sstevel@tonic-gate 	char		**retVal = NULL;
5620Sstevel@tonic-gate 	const char	*temptr;
5630Sstevel@tonic-gate 	char		*temptr2;
5640Sstevel@tonic-gate 	const char	*valend;
5650Sstevel@tonic-gate 	int 		valNo = 0;
5660Sstevel@tonic-gate 	int		valSize = 0;
5670Sstevel@tonic-gate 	int		i;
5680Sstevel@tonic-gate 	char		*SSD_service = NULL;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate #ifdef DEBUG
5710Sstevel@tonic-gate 	(void) fprintf(stderr, "parseDN START\n");
5720Sstevel@tonic-gate #endif
5730Sstevel@tonic-gate 	if (val == NULL || *val == '\0')
5740Sstevel@tonic-gate 		return (NULL);
5750Sstevel@tonic-gate 	if (service == NULL || *service == '\0')
5760Sstevel@tonic-gate 		return (NULL);
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 	len = strlen(val);
5790Sstevel@tonic-gate 	slen = strlen(service);
5800Sstevel@tonic-gate 	if (strncasecmp(val, service, slen) != 0) {
5810Sstevel@tonic-gate 		/*
5820Sstevel@tonic-gate 		 * This routine is only called
5830Sstevel@tonic-gate 		 * to process V1 profile and
5840Sstevel@tonic-gate 		 * for V1 profile, map service
5850Sstevel@tonic-gate 		 * to the corresponding SSD_service
5860Sstevel@tonic-gate 		 * which is associated with a
5870Sstevel@tonic-gate 		 * real container in the LDAP directory
5880Sstevel@tonic-gate 		 * tree, e.g., map "shadow" to
5890Sstevel@tonic-gate 		 * "password". See function
5900Sstevel@tonic-gate 		 * __s_api_get_SSD_from_SSDtoUse_service
5910Sstevel@tonic-gate 		 * for similar service to SSD_service
5920Sstevel@tonic-gate 		 * mapping handling for V2 profile.
5930Sstevel@tonic-gate 		 */
5940Sstevel@tonic-gate 		for (i = 0; ns_def_map[i].service != NULL; i++) {
5950Sstevel@tonic-gate 			if (ns_def_map[i].SSDtoUse_service &&
5964522Schinlong 			    strcasecmp(service,
5974522Schinlong 			    ns_def_map[i].service) == 0) {
5980Sstevel@tonic-gate 				SSD_service =
5994522Schinlong 				    ns_def_map[i].SSDtoUse_service;
6000Sstevel@tonic-gate 				break;
6010Sstevel@tonic-gate 			}
6020Sstevel@tonic-gate 		}
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 		if (SSD_service == NULL)
6050Sstevel@tonic-gate 			return (NULL);
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 		slen = strlen(SSD_service);
6080Sstevel@tonic-gate 		if (strncasecmp(val, SSD_service, slen) != 0)
6090Sstevel@tonic-gate 			return (NULL);
6100Sstevel@tonic-gate 	}
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	temptr = val + slen;
6130Sstevel@tonic-gate 	while (*temptr == SPACETOK || *temptr == TABTOK)
6140Sstevel@tonic-gate 		temptr++;
6150Sstevel@tonic-gate 	if (*temptr != COLONTOK)
6160Sstevel@tonic-gate 		return (NULL);
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	while (*temptr) {
6190Sstevel@tonic-gate 		temptr2 = strchr(temptr, OPARATOK);
6200Sstevel@tonic-gate 		if (temptr2 == NULL)
6210Sstevel@tonic-gate 			break;
6220Sstevel@tonic-gate 		temptr2++;
6230Sstevel@tonic-gate 		temptr2 = strchr(temptr2, CPARATOK);
6240Sstevel@tonic-gate 		if (temptr2 == NULL)
6250Sstevel@tonic-gate 			break;
6260Sstevel@tonic-gate 		valNo++;
6270Sstevel@tonic-gate 		temptr = temptr2+1;
6280Sstevel@tonic-gate 	}
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 	retVal = (char **)calloc(valNo +1, sizeof (char *));
6310Sstevel@tonic-gate 	if (retVal == NULL)
6320Sstevel@tonic-gate 		return (NULL);
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	temptr = val;
6350Sstevel@tonic-gate 	valend = val+len;
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	for (i = 0; (i < valNo) && (temptr < valend); i++) {
6380Sstevel@tonic-gate 		temptr = strchr(temptr, OPARATOK);
6390Sstevel@tonic-gate 		if (temptr == NULL) {
6400Sstevel@tonic-gate 			__s_api_free2dArray(retVal);
6410Sstevel@tonic-gate 			return (NULL);
6420Sstevel@tonic-gate 		}
6430Sstevel@tonic-gate 		temptr++;
6440Sstevel@tonic-gate 		temptr2 = strchr(temptr, CPARATOK);
6450Sstevel@tonic-gate 		if (temptr2 == NULL) {
6460Sstevel@tonic-gate 			__s_api_free2dArray(retVal);
6470Sstevel@tonic-gate 			return (NULL);
6480Sstevel@tonic-gate 		}
6490Sstevel@tonic-gate 		valSize = temptr2 - temptr;
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate 		retVal[i] = (char *)calloc(valSize + 1, sizeof (char));
6520Sstevel@tonic-gate 		if (retVal[i] == NULL) {
6530Sstevel@tonic-gate 			__s_api_free2dArray(retVal);
6540Sstevel@tonic-gate 			return (NULL);
6550Sstevel@tonic-gate 		}
6560Sstevel@tonic-gate 		(void) strncpy(retVal[i], temptr, valSize);
6570Sstevel@tonic-gate 		retVal[i][valSize] = '\0';
6580Sstevel@tonic-gate 		temptr = temptr2 + 1;
6590Sstevel@tonic-gate 	}
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	return (retVal);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate /*
6660Sstevel@tonic-gate  * __s_api_get_local_interfaces
6670Sstevel@tonic-gate  *
6680Sstevel@tonic-gate  * Returns a pointer to an array of addresses and netmasks of all interfaces
6690Sstevel@tonic-gate  * configured on the system.
6700Sstevel@tonic-gate  *
6710Sstevel@tonic-gate  * NOTE: This function is very IPv4 centric.
6720Sstevel@tonic-gate  */
6730Sstevel@tonic-gate static struct ifinfo *
__s_api_get_local_interfaces()6740Sstevel@tonic-gate __s_api_get_local_interfaces()
6750Sstevel@tonic-gate {
6760Sstevel@tonic-gate 	struct ifconf		ifc;
6770Sstevel@tonic-gate 	struct ifreq		ifreq, *ifr;
6780Sstevel@tonic-gate 	struct ifinfo		*localinfo;
6790Sstevel@tonic-gate 	struct in_addr		netmask;
6800Sstevel@tonic-gate 	struct sockaddr_in	*sin;
6810Sstevel@tonic-gate 	void			*buf = NULL;
6820Sstevel@tonic-gate 	int			fd = 0;
6830Sstevel@tonic-gate 	int			numifs = 0;
6840Sstevel@tonic-gate 	int			i, n = 0;
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	if ((fd = open(UDP, O_RDONLY)) < 0)
6870Sstevel@tonic-gate 		return ((struct ifinfo *)NULL);
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 	if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) {
6900Sstevel@tonic-gate 		numifs = MAXIFS;
6910Sstevel@tonic-gate 	}
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	buf = malloc(numifs * sizeof (struct ifreq));
6940Sstevel@tonic-gate 	if (buf == NULL) {
6950Sstevel@tonic-gate 		(void) close(fd);
6960Sstevel@tonic-gate 		return ((struct ifinfo *)NULL);
6970Sstevel@tonic-gate 	}
6980Sstevel@tonic-gate 	ifc.ifc_len = numifs * (int)sizeof (struct ifreq);
6990Sstevel@tonic-gate 	ifc.ifc_buf = buf;
7000Sstevel@tonic-gate 	if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) {
7010Sstevel@tonic-gate 		(void) close(fd);
7020Sstevel@tonic-gate 		free(buf);
7030Sstevel@tonic-gate 		buf = NULL;
7040Sstevel@tonic-gate 		return ((struct ifinfo *)NULL);
7050Sstevel@tonic-gate 	}
7060Sstevel@tonic-gate 	ifr = (struct ifreq *)buf;
7070Sstevel@tonic-gate 	numifs = ifc.ifc_len/(int)sizeof (struct ifreq);
7080Sstevel@tonic-gate 	localinfo = (struct ifinfo *)malloc((numifs + 1) *
7090Sstevel@tonic-gate 	    sizeof (struct ifinfo));
7100Sstevel@tonic-gate 	if (localinfo == NULL) {
7110Sstevel@tonic-gate 		(void) close(fd);
7120Sstevel@tonic-gate 		free(buf);
7130Sstevel@tonic-gate 		buf = NULL;
7140Sstevel@tonic-gate 		return ((struct ifinfo *)NULL);
7150Sstevel@tonic-gate 	}
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	for (i = 0, n = numifs; n > 0; n--, ifr++) {
7180Sstevel@tonic-gate 		uint_t ifrflags;
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate 		ifreq = *ifr;
7210Sstevel@tonic-gate 		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifreq) < 0)
7220Sstevel@tonic-gate 			continue;
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 		ifrflags = ifreq.ifr_flags;
7250Sstevel@tonic-gate 		if (((ifrflags & IFF_UP) == 0) ||
7260Sstevel@tonic-gate 		    (ifr->ifr_addr.sa_family != AF_INET))
7270Sstevel@tonic-gate 			continue;
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 		if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifreq) < 0)
7300Sstevel@tonic-gate 			continue;
7310Sstevel@tonic-gate 		netmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
7320Sstevel@tonic-gate 
7330Sstevel@tonic-gate 		if (ioctl(fd, SIOCGIFADDR, (char *)&ifreq) < 0)
7340Sstevel@tonic-gate 			continue;
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 		sin = (struct sockaddr_in *)&ifreq.ifr_addr;
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 		localinfo[i].addr = sin->sin_addr;
7390Sstevel@tonic-gate 		localinfo[i].netmask = netmask;
7400Sstevel@tonic-gate 		i++;
7410Sstevel@tonic-gate 	}
7420Sstevel@tonic-gate 	localinfo[i].addr.s_addr = 0;
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	free(buf);
7450Sstevel@tonic-gate 	buf = NULL;
7460Sstevel@tonic-gate 	(void) close(fd);
7470Sstevel@tonic-gate 	return (localinfo);
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate /*
7520Sstevel@tonic-gate  * __s_api_samenet(char *, struct ifinfo *)
7530Sstevel@tonic-gate  *
7540Sstevel@tonic-gate  * Returns 1 if address is on the same subnet of the array of addresses
7550Sstevel@tonic-gate  * passed in.
7560Sstevel@tonic-gate  *
7570Sstevel@tonic-gate  * NOTE: This function is only valid for IPv4 addresses.
7580Sstevel@tonic-gate  */
7590Sstevel@tonic-gate static int
__s_api_IPv4sameNet(char * addr,struct ifinfo * ifs)7600Sstevel@tonic-gate __s_api_IPv4sameNet(char *addr, struct ifinfo *ifs)
7610Sstevel@tonic-gate {
7620Sstevel@tonic-gate 	int		answer = 0;
7630Sstevel@tonic-gate 
7640Sstevel@tonic-gate 	if (addr && ifs) {
7650Sstevel@tonic-gate 		char		*addr_raw;
7660Sstevel@tonic-gate 		unsigned long	iaddr;
7670Sstevel@tonic-gate 		int		i;
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 		if ((addr_raw = strdup(addr)) != NULL) {
7700Sstevel@tonic-gate 			char	*s;
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 			/* Remove port number. */
7730Sstevel@tonic-gate 			if ((s = strchr(addr_raw, ':')) != NULL)
7740Sstevel@tonic-gate 				*s = '\0';
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 			iaddr = inet_addr(addr_raw);
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 			/* Loop through interface list to find match. */
7790Sstevel@tonic-gate 			for (i = 0; ifs[i].addr.s_addr != 0; i++) {
7800Sstevel@tonic-gate 				if ((iaddr & ifs[i].netmask.s_addr) ==
7810Sstevel@tonic-gate 				    (ifs[i].addr.s_addr &
7820Sstevel@tonic-gate 				    ifs[i].netmask.s_addr))
7830Sstevel@tonic-gate 					answer++;
7840Sstevel@tonic-gate 			}
7850Sstevel@tonic-gate 			free(addr_raw);
7860Sstevel@tonic-gate 		}
7870Sstevel@tonic-gate 	}
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	return (answer);
7900Sstevel@tonic-gate }
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate /*
7930Sstevel@tonic-gate  * FUNCTION:	__s_api_getServers
7940Sstevel@tonic-gate  *
7950Sstevel@tonic-gate  *	Retrieve a list of ldap servers from the config module.
7960Sstevel@tonic-gate  *
7970Sstevel@tonic-gate  * RETURN VALUE:	NS_LDAP_SUCCESS, NS_LDAP_CONFIG, NS_LDAP_MEMORY
7980Sstevel@tonic-gate  * INPUT:		NONE
7990Sstevel@tonic-gate  * OUTPUT:		servers, error
8000Sstevel@tonic-gate  */
8010Sstevel@tonic-gate int
__s_api_getServers(char *** servers,ns_ldap_error_t ** error)8020Sstevel@tonic-gate __s_api_getServers(
8030Sstevel@tonic-gate 		char *** servers,
8040Sstevel@tonic-gate 		ns_ldap_error_t ** error)
8050Sstevel@tonic-gate {
8060Sstevel@tonic-gate 	void	**paramVal = NULL;
8070Sstevel@tonic-gate 	char	errmsg[MAXERROR];
8080Sstevel@tonic-gate 	char	**sortServers = NULL;
8090Sstevel@tonic-gate 	char	**netservers = NULL;
8100Sstevel@tonic-gate 	int	rc = 0, err = NS_LDAP_CONFIG, version = 1;
8110Sstevel@tonic-gate 	const 	char	*str, *str1;
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate #ifdef DEBUG
8140Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_getServers START\n");
8150Sstevel@tonic-gate #endif
8160Sstevel@tonic-gate 	*servers = NULL;
8170Sstevel@tonic-gate 	/* get profile version number */
8180Sstevel@tonic-gate 	if ((rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P,
8194522Schinlong 	    &paramVal, error)) != NS_LDAP_SUCCESS)
8200Sstevel@tonic-gate 		return (rc);
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	if (paramVal == NULL || *paramVal == NULL) {
8230Sstevel@tonic-gate 		(void) snprintf(errmsg, sizeof (errmsg),
8244522Schinlong 		    gettext("No file version"));
8250Sstevel@tonic-gate 		MKERROR(LOG_INFO, *error, NS_CONFIG_FILE, strdup(errmsg),
8264522Schinlong 		    NS_LDAP_CONFIG);
8270Sstevel@tonic-gate 		return (NS_LDAP_CONFIG);
8280Sstevel@tonic-gate 	}
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	if (strcasecmp((char *)*paramVal, NS_LDAP_VERSION_1) == 0)
8310Sstevel@tonic-gate 		version = 1;
8320Sstevel@tonic-gate 	else if (strcasecmp((char *)*paramVal, NS_LDAP_VERSION_2) == 0)
8330Sstevel@tonic-gate 		version = 2;
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 	(void) __ns_ldap_freeParam(&paramVal);
8360Sstevel@tonic-gate 	paramVal = NULL;
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate 	if ((rc = __ns_ldap_getParam(NS_LDAP_SERVERS_P,
8394522Schinlong 	    &paramVal, error)) != NS_LDAP_SUCCESS)
8400Sstevel@tonic-gate 		return (rc);
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 	/*
8430Sstevel@tonic-gate 	 * For version 2, default server list could be
8440Sstevel@tonic-gate 	 * empty.
8450Sstevel@tonic-gate 	 */
8460Sstevel@tonic-gate 	if ((paramVal == NULL || (char *)*paramVal == NULL) &&
8474522Schinlong 	    version == 1) {
8480Sstevel@tonic-gate 		str = NULL_OR_STR(__s_api_get_configname(NS_LDAP_SERVERS_P));
8490Sstevel@tonic-gate 		(void) snprintf(errmsg, sizeof (errmsg),
8504522Schinlong 		    gettext("Unable to retrieve the '%s' list"), str);
8510Sstevel@tonic-gate 		MKERROR(LOG_WARNING, *error, NS_CONFIG_FILE, strdup(errmsg),
8524522Schinlong 		    NS_LDAP_CONFIG);
8530Sstevel@tonic-gate 		return (NS_LDAP_CONFIG);
8540Sstevel@tonic-gate 	}
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 	/*
8570Sstevel@tonic-gate 	 * Get server address(es) and go through them.
8580Sstevel@tonic-gate 	 */
8590Sstevel@tonic-gate 	*servers = (char **)paramVal;
8600Sstevel@tonic-gate 	paramVal = NULL;
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate 	/* Sort servers based on network. */
8630Sstevel@tonic-gate 	if (*servers) {
8640Sstevel@tonic-gate 		netservers = sortServerNet(*servers);
8650Sstevel@tonic-gate 		if (netservers) {
8660Sstevel@tonic-gate 			free(*servers);
8670Sstevel@tonic-gate 			*servers = netservers;
8680Sstevel@tonic-gate 		} else {
8690Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
8700Sstevel@tonic-gate 		}
8710Sstevel@tonic-gate 	}
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 	/* Get preferred server list and sort servers based on that. */
8740Sstevel@tonic-gate 	if ((rc = __ns_ldap_getParam(NS_LDAP_SERVER_PREF_P,
8754522Schinlong 	    &paramVal, error)) != NS_LDAP_SUCCESS) {
8760Sstevel@tonic-gate 		if (*servers)
8770Sstevel@tonic-gate 			__s_api_free2dArray(*servers);
8780Sstevel@tonic-gate 		*servers = NULL;
8790Sstevel@tonic-gate 		return (rc);
8800Sstevel@tonic-gate 	}
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 	if (paramVal != NULL) {
8830Sstevel@tonic-gate 		char **prefServers;
8840Sstevel@tonic-gate 		void **val = NULL;
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 		if ((rc =  __ns_ldap_getParam(NS_LDAP_PREF_ONLY_P,
8874522Schinlong 		    &val, error)) != NS_LDAP_SUCCESS) {
8880Sstevel@tonic-gate 				if (*servers)
8890Sstevel@tonic-gate 					__s_api_free2dArray(*servers);
8900Sstevel@tonic-gate 				*servers = NULL;
8910Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&paramVal);
8920Sstevel@tonic-gate 			return (rc);
8930Sstevel@tonic-gate 		}
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 		prefServers = (char **)paramVal;
8960Sstevel@tonic-gate 		paramVal = NULL;
8970Sstevel@tonic-gate 		if (prefServers) {
8980Sstevel@tonic-gate 			if (val != NULL && (*val) != NULL &&
8994522Schinlong 			    *(int *)val[0] == 1)
9000Sstevel@tonic-gate 				sortServers = sortServerPref(*servers,
9014522Schinlong 				    prefServers, B_FALSE, version,
9024522Schinlong 				    &err);
9030Sstevel@tonic-gate 			else
9040Sstevel@tonic-gate 				sortServers = sortServerPref(*servers,
9054522Schinlong 				    prefServers, B_TRUE, version,
9064522Schinlong 				    &err);
9070Sstevel@tonic-gate 			if (sortServers) {
9080Sstevel@tonic-gate 				if (*servers)
9090Sstevel@tonic-gate 					free(*servers);
9100Sstevel@tonic-gate 				*servers = NULL;
9110Sstevel@tonic-gate 				free(prefServers);
9120Sstevel@tonic-gate 				prefServers = NULL;
9130Sstevel@tonic-gate 				*servers = sortServers;
9140Sstevel@tonic-gate 			} else {
9150Sstevel@tonic-gate 				if (*servers)
9160Sstevel@tonic-gate 					__s_api_free2dArray(*servers);
9170Sstevel@tonic-gate 				*servers = NULL;
9180Sstevel@tonic-gate 				__s_api_free2dArray(prefServers);
9190Sstevel@tonic-gate 				prefServers = NULL;
9200Sstevel@tonic-gate 			}
9210Sstevel@tonic-gate 		}
9220Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&val);
9230Sstevel@tonic-gate 	}
9240Sstevel@tonic-gate 	(void) __ns_ldap_freeParam(&paramVal);
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	if (*servers == NULL) {
9270Sstevel@tonic-gate 		if (err == NS_LDAP_CONFIG) {
9280Sstevel@tonic-gate 		str = NULL_OR_STR(__s_api_get_configname(
9294522Schinlong 		    NS_LDAP_SERVERS_P));
9300Sstevel@tonic-gate 		str1 = NULL_OR_STR(__s_api_get_configname(
9314522Schinlong 		    NS_LDAP_SERVER_PREF_P));
9320Sstevel@tonic-gate 			(void) snprintf(errmsg, sizeof (errmsg),
9334522Schinlong 			    gettext("Unable to generate a new server list "
9344522Schinlong 			    "based on '%s' and/or '%s'"), str, str1);
9350Sstevel@tonic-gate 			MKERROR(LOG_WARNING, *error, NS_CONFIG_FILE,
9364522Schinlong 			    strdup(errmsg), err);
9370Sstevel@tonic-gate 			return (err);
9380Sstevel@tonic-gate 		}
9390Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
9400Sstevel@tonic-gate 	}
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate }
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate /*
9470Sstevel@tonic-gate  * FUNCTION:	sortServerNet
9480Sstevel@tonic-gate  *	Sort the serverlist based on the distance from client as long
9490Sstevel@tonic-gate  *	as the list only contains IPv4 addresses.  Otherwise do nothing.
9500Sstevel@tonic-gate  */
9510Sstevel@tonic-gate static char **
sortServerNet(char ** srvlist)9520Sstevel@tonic-gate sortServerNet(char **srvlist)
9530Sstevel@tonic-gate {
9540Sstevel@tonic-gate 	int		count = 0;
9550Sstevel@tonic-gate 	int		all = 0;
9560Sstevel@tonic-gate 	int		ipv4only = 1;
9570Sstevel@tonic-gate 	struct ifinfo	*ifs = __s_api_get_local_interfaces();
9580Sstevel@tonic-gate 	char		**tsrvs;
9590Sstevel@tonic-gate 	char		**psrvs, **retsrvs;
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate 	/* Sanity check. */
9620Sstevel@tonic-gate 	if (srvlist == NULL || srvlist[0] == NULL)
9630Sstevel@tonic-gate 		return (NULL);
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 	/* Count the number of servers to sort. */
9660Sstevel@tonic-gate 	for (count = 0; srvlist[count] != NULL; count++) {
9670Sstevel@tonic-gate 		if (!__s_api_isipv4(srvlist[count]))
9680Sstevel@tonic-gate 			ipv4only = 0;
9690Sstevel@tonic-gate 	}
9700Sstevel@tonic-gate 	count++;
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	/* Make room for the returned list of servers. */
9730Sstevel@tonic-gate 	retsrvs = (char **)calloc(count, sizeof (char *));
9740Sstevel@tonic-gate 	if (retsrvs == NULL) {
9750Sstevel@tonic-gate 		free(ifs);
9760Sstevel@tonic-gate 		ifs = NULL;
9770Sstevel@tonic-gate 		return (NULL);
9780Sstevel@tonic-gate 	}
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate 	retsrvs[count - 1] = NULL;
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 	/* Make a temporary list of servers. */
9830Sstevel@tonic-gate 	psrvs = (char **)calloc(count, sizeof (char *));
9840Sstevel@tonic-gate 	if (psrvs == NULL) {
9850Sstevel@tonic-gate 		free(ifs);
9860Sstevel@tonic-gate 		ifs = NULL;
9870Sstevel@tonic-gate 		free(retsrvs);
9880Sstevel@tonic-gate 		retsrvs = NULL;
9890Sstevel@tonic-gate 		return (NULL);
9900Sstevel@tonic-gate 	}
9910Sstevel@tonic-gate 
9920Sstevel@tonic-gate 	/* Filter servers on the same subnet */
9930Sstevel@tonic-gate 	tsrvs = srvlist;
9940Sstevel@tonic-gate 	while (*tsrvs) {
9950Sstevel@tonic-gate 		if (ipv4only && __s_api_IPv4sameNet(*tsrvs, ifs)) {
9960Sstevel@tonic-gate 			psrvs[all] = *tsrvs;
9970Sstevel@tonic-gate 			retsrvs[all++] = *(tsrvs);
9980Sstevel@tonic-gate 		}
9990Sstevel@tonic-gate 		tsrvs++;
10000Sstevel@tonic-gate 	}
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate 	/* Filter remaining servers. */
10030Sstevel@tonic-gate 	tsrvs = srvlist;
10040Sstevel@tonic-gate 	while (*tsrvs) {
10050Sstevel@tonic-gate 		char	**ttsrvs = psrvs;
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 		while (*ttsrvs) {
10080Sstevel@tonic-gate 			if (strcmp(*tsrvs, *ttsrvs) == 0)
10090Sstevel@tonic-gate 				break;
10100Sstevel@tonic-gate 			ttsrvs++;
10110Sstevel@tonic-gate 		}
10120Sstevel@tonic-gate 
10130Sstevel@tonic-gate 		if (*ttsrvs == NULL)
10140Sstevel@tonic-gate 			retsrvs[all++] = *(tsrvs);
10150Sstevel@tonic-gate 		tsrvs++;
10160Sstevel@tonic-gate 	}
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate 	free(ifs);
10190Sstevel@tonic-gate 	ifs = NULL;
10200Sstevel@tonic-gate 	free(psrvs);
10210Sstevel@tonic-gate 	psrvs = NULL;
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 	return (retsrvs);
10240Sstevel@tonic-gate }
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate /*
10270Sstevel@tonic-gate  * FUNCTION:	sortServerPref
10280Sstevel@tonic-gate  *	Sort the serverlist based on the preferred server list.
10290Sstevel@tonic-gate  *
10300Sstevel@tonic-gate  * The sorting algorithm works as follows:
10310Sstevel@tonic-gate  *
10320Sstevel@tonic-gate  * If version 1, if flag is TRUE, find all the servers in both preflist
10330Sstevel@tonic-gate  * and srvlist, then append other servers in srvlist to this list
10340Sstevel@tonic-gate  * and return the list.
10350Sstevel@tonic-gate  * If flag is FALSE, just return srvlist.
10360Sstevel@tonic-gate  * srvlist can not be empty.
10370Sstevel@tonic-gate  *
10380Sstevel@tonic-gate  * If version 2, append all the servers in srvlist
10390Sstevel@tonic-gate  * but not in preflist to preflist, and return the merged list.
10400Sstevel@tonic-gate  * If srvlist is empty, just return preflist.
10410Sstevel@tonic-gate  * If preflist is empty, just return srvlist.
10420Sstevel@tonic-gate  */
10430Sstevel@tonic-gate static char **
sortServerPref(char ** srvlist,char ** preflist,boolean_t flag,int version,int * error)10440Sstevel@tonic-gate sortServerPref(char **srvlist, char **preflist,
10450Sstevel@tonic-gate 		boolean_t flag, int version, int *error)
10460Sstevel@tonic-gate {
10470Sstevel@tonic-gate 	int		i, scount = 0, pcount = 0;
10480Sstevel@tonic-gate 	int		all = 0, dup = 0;
10490Sstevel@tonic-gate 	char		**tsrvs;
10500Sstevel@tonic-gate 	char		**retsrvs;
10510Sstevel@tonic-gate 	char		**dupsrvs;
10520Sstevel@tonic-gate 
10530Sstevel@tonic-gate 	/* Count the number of servers to sort. */
10540Sstevel@tonic-gate 	if (srvlist && srvlist[0])
10550Sstevel@tonic-gate 		for (i = 0; srvlist[i] != NULL; i++)
10560Sstevel@tonic-gate 			scount++;
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate 	/* Sanity check. */
10590Sstevel@tonic-gate 	if (scount == 0 && version == 1) {
10600Sstevel@tonic-gate 		*error = NS_LDAP_CONFIG;
10610Sstevel@tonic-gate 		return (NULL);
10620Sstevel@tonic-gate 	}
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 	/* Count the number of preferred servers */
10650Sstevel@tonic-gate 	if (preflist && preflist[0])
10660Sstevel@tonic-gate 		for (i = 0; preflist[i] != NULL; i++)
10670Sstevel@tonic-gate 			pcount++;
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 	/* Sanity check. */
10700Sstevel@tonic-gate 	if (scount == 0 && pcount == 0) {
10710Sstevel@tonic-gate 		*error = NS_LDAP_CONFIG;
10720Sstevel@tonic-gate 		return (NULL);
10730Sstevel@tonic-gate 	}
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	/* Make room for the returned list of servers */
10760Sstevel@tonic-gate 	retsrvs = (char **)calloc(scount + pcount + 1, sizeof (char *));
10770Sstevel@tonic-gate 	if (retsrvs == NULL) {
10780Sstevel@tonic-gate 		*error = NS_LDAP_MEMORY;
10790Sstevel@tonic-gate 		return (NULL);
10800Sstevel@tonic-gate 	}
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate 	/*
10830Sstevel@tonic-gate 	 * if the preferred server list is empty,
10840Sstevel@tonic-gate 	 * just return a copy of the server list
10850Sstevel@tonic-gate 	 */
10860Sstevel@tonic-gate 	if (pcount == 0) {
10870Sstevel@tonic-gate 		tsrvs = srvlist;
10880Sstevel@tonic-gate 		while (*tsrvs)
10890Sstevel@tonic-gate 			retsrvs[all++] = *(tsrvs++);
10900Sstevel@tonic-gate 		return (retsrvs);
10910Sstevel@tonic-gate 	}
10920Sstevel@tonic-gate 	all = 0;
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 	/*
10950Sstevel@tonic-gate 	 * if the server list is empty,
10960Sstevel@tonic-gate 	 * just return a copy of the preferred server list
10970Sstevel@tonic-gate 	 */
10980Sstevel@tonic-gate 	if (scount == 0) {
10990Sstevel@tonic-gate 		tsrvs = preflist;
11000Sstevel@tonic-gate 		while (*tsrvs)
11010Sstevel@tonic-gate 			retsrvs[all++] = *(tsrvs++);
11020Sstevel@tonic-gate 		return (retsrvs);
11030Sstevel@tonic-gate 	}
11040Sstevel@tonic-gate 	all = 0;
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate 	/* Make room for the servers whose memory needs to be freed */
11070Sstevel@tonic-gate 	dupsrvs = (char **)calloc(scount + pcount + 1, sizeof (char *));
11080Sstevel@tonic-gate 	if (dupsrvs == NULL) {
11090Sstevel@tonic-gate 		free(retsrvs);
11100Sstevel@tonic-gate 		*error = NS_LDAP_MEMORY;
11110Sstevel@tonic-gate 		return (NULL);
11120Sstevel@tonic-gate 	}
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 	/*
11150Sstevel@tonic-gate 	 * If version 1,
11160Sstevel@tonic-gate 	 * throw out preferred servers not on server list.
11170Sstevel@tonic-gate 	 * If version 2, make a copy of the preferred server list.
11180Sstevel@tonic-gate 	 */
11190Sstevel@tonic-gate 	if (version == 1) {
11200Sstevel@tonic-gate 		tsrvs = preflist;
11210Sstevel@tonic-gate 		while (*tsrvs) {
11220Sstevel@tonic-gate 			char	**ttsrvs = srvlist;
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate 			while (*ttsrvs) {
11250Sstevel@tonic-gate 				if (strcmp(*tsrvs, *(ttsrvs)) == 0)
11260Sstevel@tonic-gate 					break;
11270Sstevel@tonic-gate 				ttsrvs++;
11280Sstevel@tonic-gate 			}
11290Sstevel@tonic-gate 			if (*ttsrvs != NULL)
11300Sstevel@tonic-gate 				retsrvs[all++] = *tsrvs;
11310Sstevel@tonic-gate 			else
11320Sstevel@tonic-gate 				dupsrvs[dup++] = *tsrvs;
11330Sstevel@tonic-gate 			tsrvs++;
11340Sstevel@tonic-gate 		}
11350Sstevel@tonic-gate 	} else {
11360Sstevel@tonic-gate 		tsrvs = preflist;
11370Sstevel@tonic-gate 		while (*tsrvs)
11380Sstevel@tonic-gate 			retsrvs[all++] = *(tsrvs++);
11390Sstevel@tonic-gate 	}
11400Sstevel@tonic-gate 	/*
11410Sstevel@tonic-gate 	 * If version 1,
11420Sstevel@tonic-gate 	 * if PREF_ONLY is false, we append the non-preferred servers
11430Sstevel@tonic-gate 	 * to bottom of list.
11440Sstevel@tonic-gate 	 * For version 2, always append.
11450Sstevel@tonic-gate 	 */
11460Sstevel@tonic-gate 	if (flag == B_TRUE || version != 1) {
11470Sstevel@tonic-gate 
11480Sstevel@tonic-gate 		tsrvs = srvlist;
11490Sstevel@tonic-gate 		while (*tsrvs) {
11500Sstevel@tonic-gate 			char	**ttsrvs = preflist;
11510Sstevel@tonic-gate 
11520Sstevel@tonic-gate 			while (*ttsrvs) {
11530Sstevel@tonic-gate 				if (strcmp(*tsrvs, *ttsrvs) == 0) {
11540Sstevel@tonic-gate 					break;
11550Sstevel@tonic-gate 				}
11560Sstevel@tonic-gate 				ttsrvs++;
11570Sstevel@tonic-gate 			}
11580Sstevel@tonic-gate 			if (*ttsrvs == NULL)
11590Sstevel@tonic-gate 				retsrvs[all++] = *tsrvs;
11600Sstevel@tonic-gate 			else
11610Sstevel@tonic-gate 				dupsrvs[dup++] = *tsrvs;
11620Sstevel@tonic-gate 			tsrvs++;
11630Sstevel@tonic-gate 		}
11640Sstevel@tonic-gate 	}
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 	/* free memory for duplicate servers */
11670Sstevel@tonic-gate 	if (dup) {
11680Sstevel@tonic-gate 		for (tsrvs = dupsrvs; *tsrvs; tsrvs++)
11690Sstevel@tonic-gate 			free(*tsrvs);
11700Sstevel@tonic-gate 	}
11710Sstevel@tonic-gate 	free(dupsrvs);
11720Sstevel@tonic-gate 
11730Sstevel@tonic-gate 	return (retsrvs);
11740Sstevel@tonic-gate }
11750Sstevel@tonic-gate 
11761687Sjanga /*
11771687Sjanga  * FUNCTION:	__s_api_removeBadServers
11781687Sjanga  *	Contacts the ldap cache manager for marking the
11791687Sjanga  *	problem servers as down, so that the server is
11801687Sjanga  *	not contacted until the TTL expires.
11811687Sjanga  */
11821687Sjanga void
__s_api_removeBadServers(char ** Servers)11831687Sjanga __s_api_removeBadServers(char ** Servers)
11841687Sjanga {
11851687Sjanga 
11861687Sjanga 	char	**host;
11871687Sjanga 
11881687Sjanga 	if (Servers == NULL)
11891687Sjanga 		return;
11901687Sjanga 
11911687Sjanga 	for (host = Servers; *host != NULL; host++) {
11921687Sjanga 		if (__s_api_removeServer(*host) < 0) {
11931687Sjanga 			/*
11941687Sjanga 			 * Couldn't remove server from
11951687Sjanga 			 * server list. Log a warning.
11961687Sjanga 			 */
11971687Sjanga 			syslog(LOG_WARNING, "libsldap: could "
11984522Schinlong 			    "not remove %s from servers list", *host);
11991687Sjanga 		}
12001687Sjanga 	}
12011687Sjanga }
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate /*
12040Sstevel@tonic-gate  * FUNCTION:	__s_api_free2dArray
12050Sstevel@tonic-gate  */
12060Sstevel@tonic-gate void
__s_api_free2dArray(char ** inarray)12070Sstevel@tonic-gate __s_api_free2dArray(char ** inarray)
12080Sstevel@tonic-gate {
12090Sstevel@tonic-gate 
12100Sstevel@tonic-gate 	char	**temptr;
12110Sstevel@tonic-gate 
12120Sstevel@tonic-gate 	if (inarray == NULL)
12130Sstevel@tonic-gate 		return;
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 	for (temptr = inarray; *temptr != NULL; temptr++) {
12160Sstevel@tonic-gate 		free(*temptr);
12170Sstevel@tonic-gate 	}
12180Sstevel@tonic-gate 	free(inarray);
12190Sstevel@tonic-gate }
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate /*
12220Sstevel@tonic-gate  * FUNCTION:	__s_api_cp2dArray
12230Sstevel@tonic-gate  */
12240Sstevel@tonic-gate char **
__s_api_cp2dArray(char ** inarray)12250Sstevel@tonic-gate __s_api_cp2dArray(char **inarray)
12260Sstevel@tonic-gate {
12270Sstevel@tonic-gate 	char	**newarray;
12280Sstevel@tonic-gate 	char	 **ttarray, *ret;
12290Sstevel@tonic-gate 	int	count;
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 	if (inarray == NULL)
12320Sstevel@tonic-gate 		return (NULL);
12330Sstevel@tonic-gate 
12344522Schinlong 	for (count = 0; inarray[count] != NULL; count++)
12354522Schinlong 		;
12360Sstevel@tonic-gate 
12370Sstevel@tonic-gate 	newarray = (char **)calloc(count + 1, sizeof (char *));
12380Sstevel@tonic-gate 	if (newarray == NULL)
12390Sstevel@tonic-gate 		return (NULL);
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 	ttarray = newarray;
12420Sstevel@tonic-gate 	for (; *inarray; inarray++) {
12430Sstevel@tonic-gate 		*(ttarray++) = ret = strdup(*inarray);
12440Sstevel@tonic-gate 		if (ret == NULL) {
12450Sstevel@tonic-gate 			__s_api_free2dArray(newarray);
12460Sstevel@tonic-gate 			return (NULL);
12470Sstevel@tonic-gate 		}
12480Sstevel@tonic-gate 	}
12490Sstevel@tonic-gate 	return (newarray);
12500Sstevel@tonic-gate }
12510Sstevel@tonic-gate 
12520Sstevel@tonic-gate /*
12530Sstevel@tonic-gate  * FUNCTION:	__s_api_isCtrlSupported
12540Sstevel@tonic-gate  *	Determines if the passed control is supported by the LDAP sever.
12550Sstevel@tonic-gate  * RETURNS:	NS_LDAP_SUCCESS if yes, NS_LDAP_OP_FAIL if not.
12560Sstevel@tonic-gate  */
12570Sstevel@tonic-gate int
__s_api_isCtrlSupported(Connection * con,char * ctrlString)12580Sstevel@tonic-gate __s_api_isCtrlSupported(Connection *con, char *ctrlString)
12590Sstevel@tonic-gate {
12600Sstevel@tonic-gate 	char		**ctrl;
12610Sstevel@tonic-gate 	int		len;
12620Sstevel@tonic-gate 
12630Sstevel@tonic-gate 	len = strlen(ctrlString);
12640Sstevel@tonic-gate 	for (ctrl = con->controls; ctrl && *ctrl; ctrl++) {
12650Sstevel@tonic-gate 		if (strncasecmp(*ctrl, ctrlString, len) == 0)
12660Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
12670Sstevel@tonic-gate 	}
12680Sstevel@tonic-gate 	return (NS_LDAP_OP_FAILED);
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate 
12710Sstevel@tonic-gate /*
12720Sstevel@tonic-gate  * FUNCTION:	__s_api_toFollowReferrals
12730Sstevel@tonic-gate  *	Determines if need to follow referral for an SLDAP API.
12740Sstevel@tonic-gate  * RETURN VALUES:	NS_LDAP_SUCCESS, NS_LDAP_INVALID_PARAM, or
12750Sstevel@tonic-gate  *			other rc from __ns_ldap_getParam()
12760Sstevel@tonic-gate  * INPUT:		flags
12770Sstevel@tonic-gate  * OUTPUT:		toFollow, errorp
12780Sstevel@tonic-gate  */
12790Sstevel@tonic-gate int
__s_api_toFollowReferrals(const int flags,int * toFollow,ns_ldap_error_t ** errorp)12800Sstevel@tonic-gate __s_api_toFollowReferrals(const int flags,
12810Sstevel@tonic-gate 	int *toFollow,
12820Sstevel@tonic-gate 	ns_ldap_error_t **errorp)
12830Sstevel@tonic-gate {
12840Sstevel@tonic-gate 	void		**paramVal = NULL;
12850Sstevel@tonic-gate 	int		rc = 0;
12860Sstevel@tonic-gate 	int		iflags = 0;
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate #ifdef DEBUG
12890Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_toFollowReferrals START\n");
12900Sstevel@tonic-gate #endif
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate 	/* Either NS_LDAP_NOREF or NS_LDAP_FOLLOWREF not both */
12930Sstevel@tonic-gate 	if ((flags & (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) ==
12944522Schinlong 	    (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) {
12950Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
12960Sstevel@tonic-gate 	}
12970Sstevel@tonic-gate 
12980Sstevel@tonic-gate 	/*
12990Sstevel@tonic-gate 	 * if the NS_LDAP_NOREF or NS_LDAP_FOLLOWREF is set
13000Sstevel@tonic-gate 	 * this will take precendence over the values specified
13010Sstevel@tonic-gate 	 * in the configuration file
13020Sstevel@tonic-gate 	 */
13030Sstevel@tonic-gate 	if (flags & (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) {
13040Sstevel@tonic-gate 			iflags = flags;
13050Sstevel@tonic-gate 	} else {
13060Sstevel@tonic-gate 		rc = __ns_ldap_getParam(NS_LDAP_SEARCH_REF_P,
13074522Schinlong 		    &paramVal, errorp);
13080Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS)
13090Sstevel@tonic-gate 			return (rc);
13100Sstevel@tonic-gate 		if (paramVal == NULL || *paramVal == NULL) {
13110Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&paramVal);
13120Sstevel@tonic-gate 			if (*errorp)
13130Sstevel@tonic-gate 				(void) __ns_ldap_freeError(errorp);
13140Sstevel@tonic-gate 			*toFollow = TRUE;
13150Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
13160Sstevel@tonic-gate 		}
13170Sstevel@tonic-gate 		iflags = (* (int *)(*paramVal));
13180Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
13190Sstevel@tonic-gate 	}
13200Sstevel@tonic-gate 
13210Sstevel@tonic-gate 	if (iflags & NS_LDAP_NOREF)
13220Sstevel@tonic-gate 		*toFollow = FALSE;
13230Sstevel@tonic-gate 	else
13240Sstevel@tonic-gate 		*toFollow = TRUE;
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
13270Sstevel@tonic-gate }
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate /*
13300Sstevel@tonic-gate  * FUNCTION:	__s_api_addRefInfo
13310Sstevel@tonic-gate  *	Insert a referral info into a referral info list.
13320Sstevel@tonic-gate  * RETURN VALUES:	NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_OP_FAILED
13330Sstevel@tonic-gate  * INPUT:		LDAP URL, pointer to the referral info list,
13340Sstevel@tonic-gate  *                      search baseDN, search scope, search filter,
13350Sstevel@tonic-gate  *                      previous connection
13360Sstevel@tonic-gate  */
13370Sstevel@tonic-gate int
__s_api_addRefInfo(ns_referral_info_t ** head,char * url,char * baseDN,int * scope,char * filter,LDAP * ld)13380Sstevel@tonic-gate __s_api_addRefInfo(ns_referral_info_t **head, char *url,
13390Sstevel@tonic-gate 			char *baseDN, int *scope,
13400Sstevel@tonic-gate 			char *filter, LDAP *ld)
13410Sstevel@tonic-gate {
13420Sstevel@tonic-gate 	char			errmsg[MAXERROR], *tmp;
13430Sstevel@tonic-gate 	ns_referral_info_t	*ref, *tmpref;
13440Sstevel@tonic-gate 	LDAPURLDesc		*ludp = NULL;
13450Sstevel@tonic-gate 	int			hostlen;
13460Sstevel@tonic-gate 	char *ld_defhost = NULL;
13470Sstevel@tonic-gate 
13480Sstevel@tonic-gate #ifdef DEBUG
13490Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_addRefInfo START\n");
13500Sstevel@tonic-gate #endif
13510Sstevel@tonic-gate 
13520Sstevel@tonic-gate 	/* sanity check */
13530Sstevel@tonic-gate 	if (head == NULL)
13540Sstevel@tonic-gate 		return (NS_LDAP_OP_FAILED);
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate 	/*
13570Sstevel@tonic-gate 	 * log error and return NS_LDAP_SUCCESS
13580Sstevel@tonic-gate 	 * if one of the following:
13590Sstevel@tonic-gate 	 * 1. non-LDAP URL
13600Sstevel@tonic-gate 	 * 2. LDAP URL which can not be parsed
13610Sstevel@tonic-gate 	 */
13620Sstevel@tonic-gate 	if (!ldap_is_ldap_url(url) ||
13634522Schinlong 	    ldap_url_parse_nodn(url, &ludp) != 0) {
13640Sstevel@tonic-gate 		(void) snprintf(errmsg, MAXERROR, "%s: %s",
13654522Schinlong 		    gettext("Invalid or non-LDAP URL when"
13664522Schinlong 		    " processing referrals URL"),
13674522Schinlong 		    url);
13680Sstevel@tonic-gate 		syslog(LOG_ERR, "libsldap: %s", errmsg);
13690Sstevel@tonic-gate 		if (ludp)
13700Sstevel@tonic-gate 				ldap_free_urldesc(ludp);
13710Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
13720Sstevel@tonic-gate 	}
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 	ref = (ns_referral_info_t *)calloc(1,
13754522Schinlong 	    sizeof (ns_referral_info_t));
13760Sstevel@tonic-gate 	if (ref == NULL) {
13770Sstevel@tonic-gate 		ldap_free_urldesc(ludp);
13780Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
13790Sstevel@tonic-gate 	}
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate 	/*
13820Sstevel@tonic-gate 	 * we do have a valid URL and we were able to parse it
13830Sstevel@tonic-gate 	 * however, we still need to find out what hostport to
13840Sstevel@tonic-gate 	 * use if none were provided in the LDAP URL
13850Sstevel@tonic-gate 	 * (e.g., ldap:///...)
13860Sstevel@tonic-gate 	 */
13870Sstevel@tonic-gate 	if ((ludp->lud_port == 0) && (ludp->lud_host == NULL)) {
13880Sstevel@tonic-gate 		if (ld == NULL) {
13894522Schinlong 			(void) snprintf(errmsg, MAXERROR, "%s: %s",
13904522Schinlong 			    gettext("no LDAP handle when"
13914522Schinlong 			    " processing referrals URL"),
13924522Schinlong 			    url);
13930Sstevel@tonic-gate 			syslog(LOG_WARNING, "libsldap: %s", errmsg);
13940Sstevel@tonic-gate 			ldap_free_urldesc(ludp);
13950Sstevel@tonic-gate 			free(ref);
13960Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
13970Sstevel@tonic-gate 		} else {
13980Sstevel@tonic-gate 			(void) ldap_get_option(ld, LDAP_OPT_HOST_NAME,
13994522Schinlong 			    &ld_defhost);
14000Sstevel@tonic-gate 			if (ld_defhost == NULL) {
14010Sstevel@tonic-gate 				(void) snprintf(errmsg, MAXERROR, "%s: %s",
14024522Schinlong 				    gettext("not able to retrieve default "
14034522Schinlong 				    "host when processing "
14044522Schinlong 				    "referrals URL"),
14054522Schinlong 				    url);
14060Sstevel@tonic-gate 				syslog(LOG_WARNING, "libsldap: %s", errmsg);
14070Sstevel@tonic-gate 				ldap_free_urldesc(ludp);
14080Sstevel@tonic-gate 				free(ref);
14090Sstevel@tonic-gate 				return (NS_LDAP_SUCCESS);
14100Sstevel@tonic-gate 			} else {
14110Sstevel@tonic-gate 				ref->refHost = strdup(ld_defhost);
14120Sstevel@tonic-gate 				if (ref->refHost == NULL) {
14130Sstevel@tonic-gate 					ldap_free_urldesc(ludp);
14140Sstevel@tonic-gate 					free(ref);
14150Sstevel@tonic-gate 					return (NS_LDAP_MEMORY);
14160Sstevel@tonic-gate 				}
14170Sstevel@tonic-gate 			}
14180Sstevel@tonic-gate 		}
14190Sstevel@tonic-gate 	} else {
14200Sstevel@tonic-gate 		/*
14210Sstevel@tonic-gate 		 * add 4 here:
14220Sstevel@tonic-gate 		 * 1 for the last '\0'.
14230Sstevel@tonic-gate 		 * 1 for host and prot separator ":"
14240Sstevel@tonic-gate 		 * and "[" & "]" for possible ipV6 addressing
14250Sstevel@tonic-gate 		 */
14260Sstevel@tonic-gate 		hostlen = strlen(ludp->lud_host) +
14274522Schinlong 		    sizeof (MAXPORTNUMBER_STR) + 4;
14280Sstevel@tonic-gate 		ref->refHost = (char *)malloc(hostlen);
14290Sstevel@tonic-gate 		if (ref->refHost == NULL) {
14300Sstevel@tonic-gate 			ldap_free_urldesc(ludp);
14310Sstevel@tonic-gate 			free(ref);
14320Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
14330Sstevel@tonic-gate 		}
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate 		if (ludp->lud_port != 0) {
14360Sstevel@tonic-gate 			/*
14370Sstevel@tonic-gate 			 * serverAddr = host:port
14380Sstevel@tonic-gate 			 * or
14390Sstevel@tonic-gate 			 * if host is an IPV6 address
14400Sstevel@tonic-gate 			 * [host]:port
14410Sstevel@tonic-gate 			 */
14420Sstevel@tonic-gate 			tmp = strstr(url, ludp->lud_host);
14430Sstevel@tonic-gate 			if (tmp && (tmp > url) && *(tmp - 1) == '[') {
14440Sstevel@tonic-gate 				(void) snprintf(ref->refHost, hostlen,
14454522Schinlong 				    "[%s]:%d",
14464522Schinlong 				    ludp->lud_host,
14474522Schinlong 				    ludp->lud_port);
14480Sstevel@tonic-gate 			} else {
14490Sstevel@tonic-gate 				(void) snprintf(ref->refHost, hostlen,
14504522Schinlong 				    "%s:%d",
14514522Schinlong 				    ludp->lud_host,
14524522Schinlong 				    ludp->lud_port);
14530Sstevel@tonic-gate 			}
14540Sstevel@tonic-gate 		} else {
14550Sstevel@tonic-gate 			/* serverAddr = host */
14560Sstevel@tonic-gate 			(void) snprintf(ref->refHost, hostlen, "%s",
14574522Schinlong 			    ludp->lud_host);
14580Sstevel@tonic-gate 		}
14590Sstevel@tonic-gate 	}
14600Sstevel@tonic-gate 
14610Sstevel@tonic-gate 	if (ludp->lud_dn) {
14620Sstevel@tonic-gate 		ref->refDN = strdup(ludp->lud_dn);
14630Sstevel@tonic-gate 		if (ref->refDN == NULL) {
14640Sstevel@tonic-gate 			ldap_free_urldesc(ludp);
14650Sstevel@tonic-gate 			free(ref->refHost);
14660Sstevel@tonic-gate 			free(ref);
14670Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
14680Sstevel@tonic-gate 		}
14690Sstevel@tonic-gate 	} else {
14700Sstevel@tonic-gate 		if (baseDN) {
14710Sstevel@tonic-gate 			ref->refDN = strdup(baseDN);
14720Sstevel@tonic-gate 			if (ref->refDN == NULL) {
14730Sstevel@tonic-gate 				ldap_free_urldesc(ludp);
14740Sstevel@tonic-gate 				free(ref->refHost);
14750Sstevel@tonic-gate 				free(ref);
14760Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
14770Sstevel@tonic-gate 			}
14780Sstevel@tonic-gate 		}
14790Sstevel@tonic-gate 	}
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 	if (filter)
14820Sstevel@tonic-gate 		ref->refFilter = strdup(filter);
14830Sstevel@tonic-gate 	else if (ludp->lud_filter)
14840Sstevel@tonic-gate 		ref->refFilter = strdup(ludp->lud_filter);
14850Sstevel@tonic-gate 	else
14860Sstevel@tonic-gate 		ref->refFilter = strdup("");
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 	if (ref->refFilter == NULL) {
14890Sstevel@tonic-gate 		ldap_free_urldesc(ludp);
14900Sstevel@tonic-gate 		free(ref->refHost);
14910Sstevel@tonic-gate 		if (ref->refDN)
14920Sstevel@tonic-gate 			free(ref->refDN);
14930Sstevel@tonic-gate 		free(ref);
14940Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
14950Sstevel@tonic-gate 	}
14960Sstevel@tonic-gate 
1497*12969SJulian.Pullen@Sun.COM 	/*
1498*12969SJulian.Pullen@Sun.COM 	 * If the scope is specified in the URL use it.
1499*12969SJulian.Pullen@Sun.COM 	 * Note if the scope is missing in the URL, ldap_url_parse_nodn()
1500*12969SJulian.Pullen@Sun.COM 	 * returns the scope BASE. We need to check that the scope of BASE
1501*12969SJulian.Pullen@Sun.COM 	 * is actually present in the URL.
1502*12969SJulian.Pullen@Sun.COM 	 * If the scope is missing in the URL then use the passed-in
1503*12969SJulian.Pullen@Sun.COM 	 * scope.
1504*12969SJulian.Pullen@Sun.COM 	 * If there is no passed-in scope, then use the scope SUBTREE.
1505*12969SJulian.Pullen@Sun.COM 	 */
1506*12969SJulian.Pullen@Sun.COM 	if (ludp->lud_dn && ludp->lud_scope != LDAP_SCOPE_BASE)
1507*12969SJulian.Pullen@Sun.COM 		ref->refScope = ludp->lud_scope;
1508*12969SJulian.Pullen@Sun.COM 	else if (ludp->lud_dn && strstr(url, "?base"))
1509*12969SJulian.Pullen@Sun.COM 		ref->refScope = LDAP_SCOPE_BASE;
1510*12969SJulian.Pullen@Sun.COM 	else if (scope)
15110Sstevel@tonic-gate 		ref->refScope = *scope;
1512*12969SJulian.Pullen@Sun.COM 	else
1513*12969SJulian.Pullen@Sun.COM 		ref->refScope = LDAP_SCOPE_SUBTREE;
15140Sstevel@tonic-gate 
15150Sstevel@tonic-gate 	ref->next = NULL;
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 	ldap_free_urldesc(ludp);
15180Sstevel@tonic-gate 
15190Sstevel@tonic-gate 	/* insert the referral info */
15200Sstevel@tonic-gate 	if (*head) {
15214522Schinlong 		for (tmpref = *head; tmpref->next; tmpref = tmpref->next)
15224522Schinlong 			;
15230Sstevel@tonic-gate 		tmpref->next = ref;
15240Sstevel@tonic-gate 	} else
15250Sstevel@tonic-gate 		*head = ref;
15260Sstevel@tonic-gate 
15270Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
15280Sstevel@tonic-gate }
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate /*
15310Sstevel@tonic-gate  * FUNCTION:	__s_api_deleteRefInfo
15320Sstevel@tonic-gate  *	Delete a referral info list.
15330Sstevel@tonic-gate  * INPUT:		pointer to the referral info list
15340Sstevel@tonic-gate  */
15350Sstevel@tonic-gate void
__s_api_deleteRefInfo(ns_referral_info_t * head)15360Sstevel@tonic-gate __s_api_deleteRefInfo(ns_referral_info_t *head)
15370Sstevel@tonic-gate {
15380Sstevel@tonic-gate 	ns_referral_info_t	*ref, *tmp;
15390Sstevel@tonic-gate 
15400Sstevel@tonic-gate #ifdef DEBUG
15410Sstevel@tonic-gate 	(void) fprintf(stderr, "__s_api_deleteRefInfo START\n");
15420Sstevel@tonic-gate #endif
15430Sstevel@tonic-gate 
15440Sstevel@tonic-gate 	for (ref = head; ref; ) {
15450Sstevel@tonic-gate 		if (ref->refHost)
15460Sstevel@tonic-gate 			free(ref->refHost);
15470Sstevel@tonic-gate 		if (ref->refDN)
15480Sstevel@tonic-gate 			free(ref->refDN);
15490Sstevel@tonic-gate 		if (ref->refFilter)
15500Sstevel@tonic-gate 			free(ref->refFilter);
15510Sstevel@tonic-gate 		tmp = ref->next;
15520Sstevel@tonic-gate 		free(ref);
15530Sstevel@tonic-gate 		ref = tmp;
15540Sstevel@tonic-gate 	}
15550Sstevel@tonic-gate 
15560Sstevel@tonic-gate }
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate /*
15590Sstevel@tonic-gate  * FUNCTION:	__s_api_get_SSD_from_SSDtoUse_service
15600Sstevel@tonic-gate  *
15610Sstevel@tonic-gate  *	Retrieves the Service Search Descriptors which should be used for
15620Sstevel@tonic-gate  *	the given service. For example, return all the "passwd" SSDs for
15630Sstevel@tonic-gate  *	service "shadow" if no SSD is defined for service "shadow" and
15640Sstevel@tonic-gate  *	no filter component is defined in all the "passwd" SSDs. This idea
15650Sstevel@tonic-gate  *	of sharing the SSDs defined for some other service is to reduce the
15660Sstevel@tonic-gate  *	configuration complexity. For a service, which does not have its own
15670Sstevel@tonic-gate  *	entries in the LDAP directory, SSD for it is useless, and should not
15680Sstevel@tonic-gate  *	be set. But since this service must share the container with at least
15690Sstevel@tonic-gate  *	one other service which does have it own entries, the SSD for
15700Sstevel@tonic-gate  *	this other service will be shared by this service.
15710Sstevel@tonic-gate  *	This other service is called the SSD-to-use service.
15720Sstevel@tonic-gate  *	The static data structure, ns_def_map[], in this file
15730Sstevel@tonic-gate  *	defines the SSD-to-use service for all the services supported.
15740Sstevel@tonic-gate  *
15750Sstevel@tonic-gate  * RETURN VALUES:	NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_INVALID_PARAM
15760Sstevel@tonic-gate  * INPUT:		service
15770Sstevel@tonic-gate  * OUTPUT:		*SSDlist, *errorp if error
15780Sstevel@tonic-gate  */
15790Sstevel@tonic-gate int
__s_api_get_SSD_from_SSDtoUse_service(const char * service,ns_ldap_search_desc_t *** SSDlist,ns_ldap_error_t ** errorp)15800Sstevel@tonic-gate __s_api_get_SSD_from_SSDtoUse_service(const char *service,
15810Sstevel@tonic-gate 		ns_ldap_search_desc_t ***SSDlist,
15820Sstevel@tonic-gate 		ns_ldap_error_t **errorp)
15830Sstevel@tonic-gate {
15840Sstevel@tonic-gate 	int 			i, rc;
15850Sstevel@tonic-gate 	int 			found = FALSE;
15860Sstevel@tonic-gate 	int 			filter_found = FALSE;
15870Sstevel@tonic-gate 	char			*SSD_service = NULL;
15880Sstevel@tonic-gate 	char			errmsg[MAXERROR];
15890Sstevel@tonic-gate 	ns_ldap_search_desc_t	**sdlist;
15900Sstevel@tonic-gate 	int			auto_service = FALSE;
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate #ifdef DEBUG
15930Sstevel@tonic-gate 	(void) fprintf(stderr,
15944522Schinlong 	    "__s_api_get_SSD_from_SSDtoUse_service START\n");
15950Sstevel@tonic-gate #endif
15960Sstevel@tonic-gate 
15970Sstevel@tonic-gate 	if (SSDlist == NULL || errorp == NULL)
15980Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate 	*SSDlist = NULL;
16010Sstevel@tonic-gate 	*errorp = NULL;
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate 	if (service == NULL)
16040Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate 	if (strncasecmp(service, "auto_", 5) == 0)
16070Sstevel@tonic-gate 		auto_service = TRUE;
16080Sstevel@tonic-gate 
16090Sstevel@tonic-gate 	/*
16100Sstevel@tonic-gate 	 * First try to return the configured SSDs for the input server
16110Sstevel@tonic-gate 	 */
16120Sstevel@tonic-gate 	rc = __ns_ldap_getSearchDescriptors(service, SSDlist, errorp);
16130Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS)
16140Sstevel@tonic-gate 		return (rc);
16150Sstevel@tonic-gate 	else {
16160Sstevel@tonic-gate 		if (*SSDlist != NULL)
16170Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
16180Sstevel@tonic-gate 	}
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate 	/*
16210Sstevel@tonic-gate 	 * If service == auto_* and SSD is not found,
16220Sstevel@tonic-gate 	 * then try automount to see if there is an SSD
16230Sstevel@tonic-gate 	 * for automount.
16240Sstevel@tonic-gate 	 */
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate 	if (auto_service) {
16270Sstevel@tonic-gate 		rc = __ns_ldap_getSearchDescriptors(
16284522Schinlong 		    "automount", SSDlist, errorp);
16290Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS)
16300Sstevel@tonic-gate 			return (rc);
16310Sstevel@tonic-gate 		else {
16320Sstevel@tonic-gate 			if (*SSDlist != NULL) {
16330Sstevel@tonic-gate 				/*
16340Sstevel@tonic-gate 				 * If SSDlist is found,
16350Sstevel@tonic-gate 				 * prepend automountMapName to the basedn
16360Sstevel@tonic-gate 				 * in the SSDlist
16370Sstevel@tonic-gate 				 *
16380Sstevel@tonic-gate 				 */
16390Sstevel@tonic-gate 				rc = __s_api_prepend_automountmapname(
16404522Schinlong 				    service,
16414522Schinlong 				    SSDlist,
16424522Schinlong 				    errorp);
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate 				if (rc != NS_LDAP_SUCCESS) {
16454522Schinlong 					(void) __ns_ldap_freeSearchDescriptors(
16464522Schinlong 					    SSDlist);
16474522Schinlong 					*SSDlist = NULL;
16480Sstevel@tonic-gate 				}
16490Sstevel@tonic-gate 
16500Sstevel@tonic-gate 				return (rc);
16510Sstevel@tonic-gate 			}
16520Sstevel@tonic-gate 		}
16530Sstevel@tonic-gate 	}
16540Sstevel@tonic-gate 
16550Sstevel@tonic-gate 	/*
16560Sstevel@tonic-gate 	 * Find the SSDtoUse service.
16570Sstevel@tonic-gate 	 * If none found, flag "found" remains FALSE.
16580Sstevel@tonic-gate 	 */
16590Sstevel@tonic-gate 	for (i = 0; ns_def_map[i].service != NULL; i++) {
16600Sstevel@tonic-gate 		if (ns_def_map[i].SSDtoUse_service &&
16614522Schinlong 		    strcasecmp(service,
16624522Schinlong 		    ns_def_map[i].service) == 0) {
16630Sstevel@tonic-gate 			found = TRUE;
16640Sstevel@tonic-gate 			SSD_service = ns_def_map[i].SSDtoUse_service;
16650Sstevel@tonic-gate 			break;
16660Sstevel@tonic-gate 		}
16670Sstevel@tonic-gate 	}
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate 	if (!found)
16700Sstevel@tonic-gate 		return (NS_LDAP_SUCCESS);
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 	/*
16730Sstevel@tonic-gate 	 * return the SSDs for SSD_service only if no optional filter
16740Sstevel@tonic-gate 	 * component is defined in the SSDs
16750Sstevel@tonic-gate 	 */
16760Sstevel@tonic-gate 	rc = __ns_ldap_getSearchDescriptors(SSD_service,
16774522Schinlong 	    SSDlist, errorp);
16780Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS) {
16790Sstevel@tonic-gate 		return (rc);
16800Sstevel@tonic-gate 	} else {
16810Sstevel@tonic-gate 		if (*SSDlist == NULL)
16820Sstevel@tonic-gate 			return (NS_LDAP_SUCCESS);
16830Sstevel@tonic-gate 
16840Sstevel@tonic-gate 		/* check to see if filter defined in SSD */
16850Sstevel@tonic-gate 		for (sdlist = *SSDlist; *sdlist; sdlist++) {
16860Sstevel@tonic-gate 			if ((*sdlist)->filter &&
16874522Schinlong 			    strlen((*sdlist)->filter) > 0) {
16880Sstevel@tonic-gate 				filter_found = TRUE;
16890Sstevel@tonic-gate 				break;
16900Sstevel@tonic-gate 			}
16910Sstevel@tonic-gate 		}
16920Sstevel@tonic-gate 		if (filter_found) {
16930Sstevel@tonic-gate 			(void) __ns_ldap_freeSearchDescriptors(SSDlist);
16940Sstevel@tonic-gate 			*SSDlist = NULL;
16950Sstevel@tonic-gate 			(void) snprintf(errmsg, sizeof (errmsg),
16964522Schinlong 			    gettext("Service search descriptor for "
16974522Schinlong 			    "service '%s' contains filter, "
16984522Schinlong 			    "which can not be used for "
16994522Schinlong 			    "service '%s'."),
17004522Schinlong 			    SSD_service, service);
17010Sstevel@tonic-gate 			MKERROR(LOG_WARNING, *errorp, NS_CONFIG_FILE,
17024522Schinlong 			    strdup(errmsg), NS_LDAP_CONFIG);
17030Sstevel@tonic-gate 			return (NS_LDAP_CONFIG);
17040Sstevel@tonic-gate 		}
17050Sstevel@tonic-gate 
17060Sstevel@tonic-gate 	}
17070Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
17080Sstevel@tonic-gate }
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate /*
17120Sstevel@tonic-gate  * verify addr is an IPv4 address with the optional [:portno]
17130Sstevel@tonic-gate  * RFC2373 & RFC2732 & RFC2396
17140Sstevel@tonic-gate  */
17150Sstevel@tonic-gate int
__s_api_isipv4(char * addr)17160Sstevel@tonic-gate __s_api_isipv4(char *addr)
17170Sstevel@tonic-gate {
17180Sstevel@tonic-gate 	int i, seg, digit, port;
17190Sstevel@tonic-gate 
17200Sstevel@tonic-gate 	if (!addr)
17210Sstevel@tonic-gate 		return (0);
17220Sstevel@tonic-gate 
17230Sstevel@tonic-gate 	digit = seg = port = 0;
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate 	for (i = 0; i < strlen(addr); i++) {
17260Sstevel@tonic-gate 		if (isdigit(addr[i])) {
17270Sstevel@tonic-gate 			digit++;
17280Sstevel@tonic-gate 			continue;
17290Sstevel@tonic-gate 		}
17300Sstevel@tonic-gate 		if (addr[i] == '.') {
17310Sstevel@tonic-gate 			if (digit > 3 || digit == 0)
17320Sstevel@tonic-gate 				return (0);
17330Sstevel@tonic-gate 			digit = 0;
17340Sstevel@tonic-gate 			seg++;
17350Sstevel@tonic-gate 			continue;
17360Sstevel@tonic-gate 		}
17370Sstevel@tonic-gate 		if (addr[i] == ':') {
17380Sstevel@tonic-gate 			if (digit > 3)
17390Sstevel@tonic-gate 				return (0);
17400Sstevel@tonic-gate 			port++;
17410Sstevel@tonic-gate 			digit = 0;
17420Sstevel@tonic-gate 			seg++;
17430Sstevel@tonic-gate 			continue;
17440Sstevel@tonic-gate 		}
17450Sstevel@tonic-gate 		return (0);
17460Sstevel@tonic-gate 	}
17470Sstevel@tonic-gate 
17480Sstevel@tonic-gate 	if ((seg == 3 && port == 0 && digit > 0 && digit < 4) ||
17494522Schinlong 	    (seg == 4 && port == 1 && digit > 0))
17500Sstevel@tonic-gate 		return (1);
17510Sstevel@tonic-gate 
17520Sstevel@tonic-gate 	return (0);
17530Sstevel@tonic-gate }
17540Sstevel@tonic-gate 
17550Sstevel@tonic-gate 
17560Sstevel@tonic-gate /*
17570Sstevel@tonic-gate  * verify addr is an IPv6 address with the optional [IPv6]:portno
17580Sstevel@tonic-gate  * RFC2373 & RFC2732 & RFC2396
17590Sstevel@tonic-gate  */
17600Sstevel@tonic-gate int
__s_api_isipv6(char * addr)17610Sstevel@tonic-gate __s_api_isipv6(char *addr)
17620Sstevel@tonic-gate {
17630Sstevel@tonic-gate 	int i, col, digit, port, dc, tc;
17640Sstevel@tonic-gate 	char *laddr, *c1, *s;
17650Sstevel@tonic-gate 
17660Sstevel@tonic-gate 	if (!addr)
17670Sstevel@tonic-gate 		return (0);
17680Sstevel@tonic-gate 
17690Sstevel@tonic-gate 	s = addr;
17700Sstevel@tonic-gate 	laddr = NULL;
17710Sstevel@tonic-gate 	digit = col = port = 0;
17720Sstevel@tonic-gate 	if (addr[0] == '[') {
17730Sstevel@tonic-gate 		laddr = strdup(addr);
17740Sstevel@tonic-gate 		if (!laddr)
17750Sstevel@tonic-gate 			return (0);
17760Sstevel@tonic-gate 		c1 = strchr(laddr, ']');
17770Sstevel@tonic-gate 		/* only 1 ']' should be in an addr */
17780Sstevel@tonic-gate 		if (!c1 || (strchr(c1+1, ']')))
17790Sstevel@tonic-gate 			goto bad;
17800Sstevel@tonic-gate 		switch (c1[1]) {
17810Sstevel@tonic-gate 			case ':':
17820Sstevel@tonic-gate 				port++;
17830Sstevel@tonic-gate 				for (i = 2; i < strlen(c1); i++) {
17840Sstevel@tonic-gate 					if (!isdigit(c1[i]))
17850Sstevel@tonic-gate 						goto bad;
17860Sstevel@tonic-gate 					digit++;
17870Sstevel@tonic-gate 				}
17880Sstevel@tonic-gate 				if (!digit)
17890Sstevel@tonic-gate 					goto bad;
17900Sstevel@tonic-gate 				c1[0] = '\0';
17910Sstevel@tonic-gate 				break;
17920Sstevel@tonic-gate 			case '\0':
17930Sstevel@tonic-gate 				c1[0] = '\0';
17940Sstevel@tonic-gate 				break;
17950Sstevel@tonic-gate 			default:
17960Sstevel@tonic-gate 				goto bad;
17970Sstevel@tonic-gate 		}
17980Sstevel@tonic-gate 		s = &laddr[1];
17990Sstevel@tonic-gate 	}
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate 	digit = dc = tc = 0;
18020Sstevel@tonic-gate 	for (i = 0; i < strlen(s); i++) {
18030Sstevel@tonic-gate 		if (isxdigit(s[i])) {
18040Sstevel@tonic-gate 			if (digit == 0)
18050Sstevel@tonic-gate 				dc = i;
18060Sstevel@tonic-gate 			digit++;
18070Sstevel@tonic-gate 			col = 0;
18080Sstevel@tonic-gate 			continue;
18090Sstevel@tonic-gate 		}
18100Sstevel@tonic-gate 		if (s[i] == ':') {
18110Sstevel@tonic-gate 			tc++;
18120Sstevel@tonic-gate 			if ((col > 1) || (i && !col && !digit))
18130Sstevel@tonic-gate 				goto bad;
18140Sstevel@tonic-gate 			digit = 0;
18150Sstevel@tonic-gate 			col++;
18160Sstevel@tonic-gate 			continue;
18170Sstevel@tonic-gate 		}
18180Sstevel@tonic-gate 		if (s[i] == '.') {
18190Sstevel@tonic-gate 			if (__s_api_isipv4(&s[dc]) && tc)
18200Sstevel@tonic-gate 				goto good;
18210Sstevel@tonic-gate 			else
18220Sstevel@tonic-gate 				goto bad;
18230Sstevel@tonic-gate 		}
18240Sstevel@tonic-gate 		goto bad;
18250Sstevel@tonic-gate 	}
18260Sstevel@tonic-gate 
18270Sstevel@tonic-gate good:
18280Sstevel@tonic-gate 	free(laddr);
18290Sstevel@tonic-gate 	return (1);
18300Sstevel@tonic-gate bad:
18310Sstevel@tonic-gate 	free(laddr);
18320Sstevel@tonic-gate 	return (0);
18330Sstevel@tonic-gate }
18340Sstevel@tonic-gate 
18350Sstevel@tonic-gate 
18360Sstevel@tonic-gate /*
18370Sstevel@tonic-gate  * verify addr is a valid hostname with the optional [:portno]
18380Sstevel@tonic-gate  * RFC2373 & RFC2732 & RFC2396
18390Sstevel@tonic-gate  */
18400Sstevel@tonic-gate int
__s_api_ishost(char * addr)18410Sstevel@tonic-gate __s_api_ishost(char *addr)
18420Sstevel@tonic-gate {
18430Sstevel@tonic-gate 	int i, seg, alpha, digit, port;
18440Sstevel@tonic-gate 
18450Sstevel@tonic-gate 	if (!addr)
18460Sstevel@tonic-gate 		return (0);
18470Sstevel@tonic-gate 
18480Sstevel@tonic-gate 	alpha = digit = seg = port = 0;
18490Sstevel@tonic-gate 
18500Sstevel@tonic-gate 	/* must start with alpha character */
18510Sstevel@tonic-gate 	if (!isalpha(addr[0]))
18520Sstevel@tonic-gate 		return (0);
18530Sstevel@tonic-gate 
18540Sstevel@tonic-gate 	for (i = 0; i < strlen(addr); i++) {
18550Sstevel@tonic-gate 		if (isalpha(addr[i]) || (i && addr[i] == '-')) {
18560Sstevel@tonic-gate 			alpha++;
18570Sstevel@tonic-gate 			continue;
18580Sstevel@tonic-gate 		}
18590Sstevel@tonic-gate 		if (isdigit(addr[i])) {
18600Sstevel@tonic-gate 			digit++;
18610Sstevel@tonic-gate 			continue;
18620Sstevel@tonic-gate 		}
18630Sstevel@tonic-gate 		if (addr[i] == '.') {
18640Sstevel@tonic-gate 			if (!alpha && !digit)
18650Sstevel@tonic-gate 				return (0);
18660Sstevel@tonic-gate 			alpha = digit = 0;
18670Sstevel@tonic-gate 			seg++;
18680Sstevel@tonic-gate 			continue;
18690Sstevel@tonic-gate 		}
18700Sstevel@tonic-gate 		if (addr[i] == ':') {
18710Sstevel@tonic-gate 			if (!alpha && !digit)
18720Sstevel@tonic-gate 				return (0);
18730Sstevel@tonic-gate 			alpha = digit = 0;
18740Sstevel@tonic-gate 			port++;
18750Sstevel@tonic-gate 			seg++;
18760Sstevel@tonic-gate 			continue;
18770Sstevel@tonic-gate 		}
18780Sstevel@tonic-gate 		return (0);
18790Sstevel@tonic-gate 	}
18800Sstevel@tonic-gate 
18810Sstevel@tonic-gate 	if ((port == 0 && (seg || alpha || digit)) ||
18824522Schinlong 	    (port == 1 && alpha == 0 && digit))
18830Sstevel@tonic-gate 		return (1);
18840Sstevel@tonic-gate 
18850Sstevel@tonic-gate 	return (0);
18860Sstevel@tonic-gate }
18870Sstevel@tonic-gate 
18880Sstevel@tonic-gate 
18890Sstevel@tonic-gate /*
18900Sstevel@tonic-gate  * Prepend automountMapName=auto_xxx to the basedn
18910Sstevel@tonic-gate  * in the SSDlist
18920Sstevel@tonic-gate  */
18930Sstevel@tonic-gate 
__s_api_prepend_automountmapname(const char * service,ns_ldap_search_desc_t *** SSDlist,ns_ldap_error_t ** errorp)18940Sstevel@tonic-gate int __s_api_prepend_automountmapname(
18950Sstevel@tonic-gate 	const char *service,
18960Sstevel@tonic-gate 	ns_ldap_search_desc_t ***SSDlist,
18970Sstevel@tonic-gate 	ns_ldap_error_t **errorp)
18980Sstevel@tonic-gate {
18990Sstevel@tonic-gate 	int			i, rc;
19000Sstevel@tonic-gate 	ns_ldap_search_desc_t	** ssdlist = NULL;
19010Sstevel@tonic-gate 
19020Sstevel@tonic-gate 	if (service == NULL || SSDlist == NULL || *SSDlist == NULL)
19030Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
19040Sstevel@tonic-gate 
19050Sstevel@tonic-gate 	ssdlist = *SSDlist;
19060Sstevel@tonic-gate 
19070Sstevel@tonic-gate 	for (i = 0; ssdlist[i] != NULL; i++) {
19080Sstevel@tonic-gate 		rc = __s_api_prepend_automountmapname_to_dn(
19094522Schinlong 		    service, &ssdlist[i]->basedn, errorp);
19100Sstevel@tonic-gate 
19110Sstevel@tonic-gate 		if (rc != NS_LDAP_SUCCESS)
19120Sstevel@tonic-gate 			return (rc);
19130Sstevel@tonic-gate 	}
19140Sstevel@tonic-gate 
19150Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
19160Sstevel@tonic-gate }
19170Sstevel@tonic-gate 
19180Sstevel@tonic-gate 
19190Sstevel@tonic-gate /*
19200Sstevel@tonic-gate  * Prepend automountMapName=auto_xxx to the DN
19210Sstevel@tonic-gate  * Construct a string of
19220Sstevel@tonic-gate  * "automountMapName=auto_xxx,dn"
19230Sstevel@tonic-gate  *
19240Sstevel@tonic-gate  * If automountMapName is mapped to some other attribute,
19250Sstevel@tonic-gate  * then use the mapping in the setup.
19260Sstevel@tonic-gate  *
19270Sstevel@tonic-gate  * If a version 1 profile is in use, use nisMapName for
19280Sstevel@tonic-gate  * backward compatibility (i.e. "nisMapName=auto_xxx,dn").
19290Sstevel@tonic-gate  */
19300Sstevel@tonic-gate 
19310Sstevel@tonic-gate int
__s_api_prepend_automountmapname_to_dn(const char * service,char ** dn,ns_ldap_error_t ** errorp)19320Sstevel@tonic-gate __s_api_prepend_automountmapname_to_dn(
19330Sstevel@tonic-gate 	const char *service,
19340Sstevel@tonic-gate 	char **dn,
19350Sstevel@tonic-gate 	ns_ldap_error_t **errorp)
19360Sstevel@tonic-gate {
19370Sstevel@tonic-gate 	int rc, len_s = 0, len_d = 0, len = 0;
19380Sstevel@tonic-gate 	char *buffer = NULL;
19390Sstevel@tonic-gate 	char *default_automountmapname = "automountMapName";
19400Sstevel@tonic-gate 	char *automountmapname = NULL;
19410Sstevel@tonic-gate 	char **mappedattrs = NULL;
19420Sstevel@tonic-gate 	char errstr[MAXERROR];
19430Sstevel@tonic-gate 	void **paramVal = NULL;
19440Sstevel@tonic-gate 
19450Sstevel@tonic-gate 	if (service == NULL || dn == NULL || *dn == NULL)
19460Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
19470Sstevel@tonic-gate 
19480Sstevel@tonic-gate 	rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, errorp);
19490Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) {
19500Sstevel@tonic-gate 		if (paramVal)
19510Sstevel@tonic-gate 			(void) __ns_ldap_freeParam(&paramVal);
19520Sstevel@tonic-gate 		return (rc);
19530Sstevel@tonic-gate 	}
19540Sstevel@tonic-gate 	if (strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) {
19550Sstevel@tonic-gate 		automountmapname = strdup("nisMapName");
19560Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
19570Sstevel@tonic-gate 		if (automountmapname == NULL) {
19580Sstevel@tonic-gate 			return (NS_LDAP_MEMORY);
19590Sstevel@tonic-gate 		}
19600Sstevel@tonic-gate 	} else {
19610Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
19620Sstevel@tonic-gate 
19630Sstevel@tonic-gate 		/* Find mapped attribute name of auto_xxx first */
19640Sstevel@tonic-gate 		mappedattrs = __ns_ldap_getMappedAttributes(
19654522Schinlong 		    service, default_automountmapname);
19660Sstevel@tonic-gate 		/*
19670Sstevel@tonic-gate 		 * if mapped attribute name of auto_xxx is not found,
19680Sstevel@tonic-gate 		 * find the mapped attribute name of automount
19690Sstevel@tonic-gate 		 */
19700Sstevel@tonic-gate 
19710Sstevel@tonic-gate 		if (mappedattrs == NULL)
19720Sstevel@tonic-gate 			mappedattrs = __ns_ldap_getMappedAttributes(
19730Sstevel@tonic-gate 			"automount", default_automountmapname);
19740Sstevel@tonic-gate 
19750Sstevel@tonic-gate 		/*
19760Sstevel@tonic-gate 		 * if mapped attr is not found, use the default automountmapname
19770Sstevel@tonic-gate 		 */
19780Sstevel@tonic-gate 
19790Sstevel@tonic-gate 		if (mappedattrs == NULL) {
19800Sstevel@tonic-gate 			automountmapname = strdup(default_automountmapname);
19810Sstevel@tonic-gate 			if (automountmapname == NULL)
19820Sstevel@tonic-gate 				return (NS_LDAP_MEMORY);
19830Sstevel@tonic-gate 		} else {
19840Sstevel@tonic-gate 			if (mappedattrs[0] != NULL) {
19850Sstevel@tonic-gate 				/*
19860Sstevel@tonic-gate 				 * Copy it from the mapped attr list
19870Sstevel@tonic-gate 				 * Assume it's 1 to 1 mapping
19880Sstevel@tonic-gate 				 * 1 to n does not make sense
19890Sstevel@tonic-gate 				 */
19900Sstevel@tonic-gate 				automountmapname = strdup(mappedattrs[0]);
19910Sstevel@tonic-gate 				__s_api_free2dArray(mappedattrs);
19920Sstevel@tonic-gate 				if (automountmapname == NULL) {
19930Sstevel@tonic-gate 					return (NS_LDAP_MEMORY);
19940Sstevel@tonic-gate 				}
19950Sstevel@tonic-gate 			} else {
19960Sstevel@tonic-gate 
19970Sstevel@tonic-gate 				/*
19980Sstevel@tonic-gate 				 * automountmapname is mapped to an empty string
19990Sstevel@tonic-gate 				 */
20000Sstevel@tonic-gate 
20010Sstevel@tonic-gate 				__s_api_free2dArray(mappedattrs);
20020Sstevel@tonic-gate 
20030Sstevel@tonic-gate 				(void) sprintf(errstr,
20044522Schinlong 				    gettext(
20054522Schinlong 				    "Attribute automountMapName is "
20064522Schinlong 				    "mapped to an empty string.\n"));
20070Sstevel@tonic-gate 
20080Sstevel@tonic-gate 				MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX,
20096842Sth160488 				    strdup(errstr), NS_LDAP_MEMORY);
20100Sstevel@tonic-gate 
20110Sstevel@tonic-gate 				return (NS_LDAP_CONFIG);
20120Sstevel@tonic-gate 			}
20130Sstevel@tonic-gate 		}
20140Sstevel@tonic-gate 	}
20150Sstevel@tonic-gate 
20160Sstevel@tonic-gate 	len_s = strlen(service);
20170Sstevel@tonic-gate 	len_d  = strlen(*dn);
20180Sstevel@tonic-gate 	/* automountMapName + "=" + service + "," + dn + '\0' */
20190Sstevel@tonic-gate 	len = strlen(automountmapname) + 1 + len_s + 1 + len_d + 1;
20200Sstevel@tonic-gate 	buffer = (char *)malloc(len);
20210Sstevel@tonic-gate 	if (buffer == NULL) {
20220Sstevel@tonic-gate 		free(automountmapname);
20230Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
20240Sstevel@tonic-gate 	}
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate 	(void) snprintf(buffer, len, "%s=%s,%s",
20274522Schinlong 	    automountmapname, service, *dn);
20280Sstevel@tonic-gate 
20290Sstevel@tonic-gate 	buffer[len-1] = '\0';
20300Sstevel@tonic-gate 
20310Sstevel@tonic-gate 	free(automountmapname);
20320Sstevel@tonic-gate 
20330Sstevel@tonic-gate 	/* free the original dn */
20340Sstevel@tonic-gate 	(void) free(*dn);
20350Sstevel@tonic-gate 
20360Sstevel@tonic-gate 	*dn = buffer;
20370Sstevel@tonic-gate 
20380Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
20390Sstevel@tonic-gate }
20400Sstevel@tonic-gate 
20410Sstevel@tonic-gate /*
20420Sstevel@tonic-gate  * Map the LDAP error code and error message from LDAP server
20430Sstevel@tonic-gate  * to a password status used for password aging/management.
20440Sstevel@tonic-gate  */
20450Sstevel@tonic-gate ns_ldap_passwd_status_t
__s_api_set_passwd_status(int errnum,char * errmsg)20460Sstevel@tonic-gate __s_api_set_passwd_status(int errnum, char *errmsg)
20470Sstevel@tonic-gate {
20488024SSerge.Dussud@Sun.COM 	syslog(LOG_DEBUG, "libsldap: got LDAP errnum %d & message: %s ", errnum,
20498024SSerge.Dussud@Sun.COM 	    (errmsg != NULL) ? errmsg : "error msg not available");
20500Sstevel@tonic-gate 	if (errmsg) {
20510Sstevel@tonic-gate 		if (errnum ==
20524522Schinlong 		    LDAP_INVALID_CREDENTIALS) {
20530Sstevel@tonic-gate 			/*
20540Sstevel@tonic-gate 			 * case 1 (Bind):
20550Sstevel@tonic-gate 			 * password expired
20560Sstevel@tonic-gate 			 */
20570Sstevel@tonic-gate 			if (strstr(errmsg,
20584522Schinlong 			    NS_PWDERR_EXPIRED))
20590Sstevel@tonic-gate 				return (NS_PASSWD_EXPIRED);
20600Sstevel@tonic-gate 		}
20610Sstevel@tonic-gate 
20620Sstevel@tonic-gate 		if (errnum ==
20634522Schinlong 		    LDAP_UNWILLING_TO_PERFORM) {
20640Sstevel@tonic-gate 			/*
20650Sstevel@tonic-gate 			 * case 1.1 (Bind):
20660Sstevel@tonic-gate 			 * password expired
20670Sstevel@tonic-gate 			 */
20680Sstevel@tonic-gate 			if (strstr(errmsg,
20694522Schinlong 			    NS_PWDERR_EXPIRED))
20700Sstevel@tonic-gate 				return (NS_PASSWD_EXPIRED);
20710Sstevel@tonic-gate 
20720Sstevel@tonic-gate 			/*
20730Sstevel@tonic-gate 			 * case 2 (Bind):
20740Sstevel@tonic-gate 			 * Account inactivated
20750Sstevel@tonic-gate 			 */
20760Sstevel@tonic-gate 			if (strstr(errmsg,
20774522Schinlong 			    NS_PWDERR_ACCT_INACTIVATED))
20780Sstevel@tonic-gate 				return (NS_PASSWD_EXPIRED);
20790Sstevel@tonic-gate 
20800Sstevel@tonic-gate 
20810Sstevel@tonic-gate 			/*
20820Sstevel@tonic-gate 			 * case 3 (Modify passwd):
20830Sstevel@tonic-gate 			 * the user is not allow to change
20840Sstevel@tonic-gate 			 * password; only admin can change it
20850Sstevel@tonic-gate 			 */
20860Sstevel@tonic-gate 			if (strstr(errmsg,
20874522Schinlong 			    NS_PWDERR_CHANGE_NOT_ALLOW))
20880Sstevel@tonic-gate 				return (NS_PASSWD_CHANGE_NOT_ALLOWED);
20890Sstevel@tonic-gate 		}
20900Sstevel@tonic-gate 
20910Sstevel@tonic-gate 		if (errnum ==
20924522Schinlong 		    LDAP_CONSTRAINT_VIOLATION) {
20930Sstevel@tonic-gate 			/*
20940Sstevel@tonic-gate 			 * case 4 (Bind):
20950Sstevel@tonic-gate 			 * the user account is locked due to
20960Sstevel@tonic-gate 			 * too many login failures.
20970Sstevel@tonic-gate 			 */
20980Sstevel@tonic-gate 			if (strstr(errmsg,
20994522Schinlong 			    NS_PWDERR_MAXTRIES))
21000Sstevel@tonic-gate 				return (NS_PASSWD_RETRY_EXCEEDED);
21010Sstevel@tonic-gate 			/*
21020Sstevel@tonic-gate 			 * case 5 (Modify passwd):
21030Sstevel@tonic-gate 			 * syntax error: the new password
21040Sstevel@tonic-gate 			 * has length less than defined
21050Sstevel@tonic-gate 			 * minimum
21068024SSerge.Dussud@Sun.COM 			 * Not true anymore with strong password
21078024SSerge.Dussud@Sun.COM 			 * policies on LDAP server: errmsg that
21088024SSerge.Dussud@Sun.COM 			 * contain NS_PWDERR_INVALID_SYNTAX may
21098024SSerge.Dussud@Sun.COM 			 * have different meanings.
21108024SSerge.Dussud@Sun.COM 			 * To keep compatibility with older password
21118024SSerge.Dussud@Sun.COM 			 * policy, check if errmsg is strictly equal
21128024SSerge.Dussud@Sun.COM 			 * to NS_PWDERR_INVALID_SYNTAX and if yes only,
21138024SSerge.Dussud@Sun.COM 			 * return NS_PASSWD_TOO_SHORT.
21140Sstevel@tonic-gate 			 */
21158024SSerge.Dussud@Sun.COM 			if (strcmp(errmsg,
21168024SSerge.Dussud@Sun.COM 			    NS_PWDERR_INVALID_SYNTAX) == 0)
21178024SSerge.Dussud@Sun.COM 				return (NS_PASSWD_TOO_SHORT);
21180Sstevel@tonic-gate 			if (strstr(errmsg,
21194522Schinlong 			    NS_PWDERR_INVALID_SYNTAX))
21208024SSerge.Dussud@Sun.COM 				return (NS_PASSWD_INVALID_SYNTAX);
21210Sstevel@tonic-gate 			/*
21220Sstevel@tonic-gate 			 * case 6 (Modify passwd):
21238024SSerge.Dussud@Sun.COM 			 * trivial password: same value as
21240Sstevel@tonic-gate 			 * that of attribute cn, sn, or uid ...
21250Sstevel@tonic-gate 			 */
21260Sstevel@tonic-gate 			if (strstr(errmsg,
21274522Schinlong 			    NS_PWDERR_TRIVIAL_PASSWD))
21280Sstevel@tonic-gate 				return (NS_PASSWD_INVALID_SYNTAX);
21290Sstevel@tonic-gate 			/*
21300Sstevel@tonic-gate 			 * case 7 (Modify passwd):
21310Sstevel@tonic-gate 			 * re-use one of the old passwords
21320Sstevel@tonic-gate 			 * in history list
21330Sstevel@tonic-gate 			 */
21340Sstevel@tonic-gate 			if (strstr(errmsg,
21354522Schinlong 			    NS_PWDERR_IN_HISTORY))
21360Sstevel@tonic-gate 				return (NS_PASSWD_IN_HISTORY);
21370Sstevel@tonic-gate 			/*
21380Sstevel@tonic-gate 			 * case 8 (Modify passwd):
21390Sstevel@tonic-gate 			 * password not allowed to be
21400Sstevel@tonic-gate 			 * changed yet; within minimum
21410Sstevel@tonic-gate 			 * age
21420Sstevel@tonic-gate 			 */
21430Sstevel@tonic-gate 			if (strstr(errmsg,
21444522Schinlong 			    NS_PWDERR_WITHIN_MIN_AGE))
21450Sstevel@tonic-gate 				return (NS_PASSWD_WITHIN_MIN_AGE);
21460Sstevel@tonic-gate 		}
21470Sstevel@tonic-gate 
21480Sstevel@tonic-gate 	}
21490Sstevel@tonic-gate 
21500Sstevel@tonic-gate 	return (NS_PASSWD_GOOD);
21510Sstevel@tonic-gate }
21520Sstevel@tonic-gate 
21530Sstevel@tonic-gate /*
21540Sstevel@tonic-gate  * Determine if the input OID list contains
21550Sstevel@tonic-gate  * one of the password control OIDs, which are:
21560Sstevel@tonic-gate  * LDAP_CONTROL_PWEXPIRED: 2.16.840.1.113730.3.4.4
21570Sstevel@tonic-gate  * LDAP_CONTROL_PWEXPIRING: 2.16.840.1.113730.3.4.5.
21580Sstevel@tonic-gate  * If yes, return 1, if no, 0.
21590Sstevel@tonic-gate  */
21600Sstevel@tonic-gate int
__s_api_contain_passwd_control_oid(char ** oids)21610Sstevel@tonic-gate __s_api_contain_passwd_control_oid(char **oids)
21620Sstevel@tonic-gate {
21630Sstevel@tonic-gate 	char **oid;
21640Sstevel@tonic-gate 
21650Sstevel@tonic-gate 	if (oids == NULL)
21660Sstevel@tonic-gate 		return (0);
21670Sstevel@tonic-gate 
21680Sstevel@tonic-gate 	for (oid = oids; *oid; oid++) {
21690Sstevel@tonic-gate 		if (strcmp(*oid, LDAP_CONTROL_PWEXPIRED) == 0 ||
21704522Schinlong 		    strcmp(*oid, LDAP_CONTROL_PWEXPIRING) == 0) {
21710Sstevel@tonic-gate 			return (1);
21720Sstevel@tonic-gate 		}
21730Sstevel@tonic-gate 	}
21740Sstevel@tonic-gate 
21750Sstevel@tonic-gate 	return (0);
21760Sstevel@tonic-gate }
21771179Svv149972 
21781179Svv149972 /*
21791179Svv149972  * Determine if the input OID list contains LDAP V3 password less
21801179Svv149972  * account management control OID, which is:
21811179Svv149972  * NS_LDAP_ACCOUNT_USABLE_CONTROL:1.3.6.1.4.1.42.2.27.9.5.8
21821179Svv149972  * If yes, return 1, if no, 0.
21831179Svv149972  */
21841179Svv149972 int
__s_api_contain_account_usable_control_oid(char ** oids)21851179Svv149972 __s_api_contain_account_usable_control_oid(char **oids)
21861179Svv149972 {
21871179Svv149972 	char **oid;
21881179Svv149972 
21891179Svv149972 	if (oids == NULL)
21901179Svv149972 		return (0);
21911179Svv149972 
21921179Svv149972 	for (oid = oids; *oid; oid++) {
21931179Svv149972 		if (strcmp(*oid, NS_LDAP_ACCOUNT_USABLE_CONTROL) == 0) {
21941179Svv149972 			return (1);
21951179Svv149972 		}
21961179Svv149972 	}
21971179Svv149972 
21981179Svv149972 	return (0);
21991179Svv149972 }
22001179Svv149972 
22010Sstevel@tonic-gate /*
22020Sstevel@tonic-gate  * For some databases in name switch, the name and aliases are saved
22030Sstevel@tonic-gate  * as "cn". When the "cn" valuse are retrieved, there is no distinction
22040Sstevel@tonic-gate  * which is  the name and which is(are) aliase(s).
22050Sstevel@tonic-gate  * This function is to parse RDN and find the value of the "cn" and
22060Sstevel@tonic-gate  * then find the matching value in "cn" attribute.
22070Sstevel@tonic-gate  * Also see RFC 2307 section 5.6.
22080Sstevel@tonic-gate  *
22090Sstevel@tonic-gate  * Input -
22100Sstevel@tonic-gate  *  entry:	An LDAP entry
22110Sstevel@tonic-gate  *  attrptr:	A attribute which value appears in RDN
22120Sstevel@tonic-gate  *		This should be "cn" for the name switch for now.
22130Sstevel@tonic-gate  *  case_ignore:    0 Case sensitive comparison on the attribute value
22140Sstevel@tonic-gate  *		    1 Case insensitive comparison
22150Sstevel@tonic-gate  *
22160Sstevel@tonic-gate  * Return -
22170Sstevel@tonic-gate  *		The value of an attrbute which is used as canonical name
22180Sstevel@tonic-gate  *		This is read only and the caller should not try to free it.
22190Sstevel@tonic-gate  *		If it's a NULL, it could be either an RDN parsing error
22200Sstevel@tonic-gate  *		or RDN value does not match any existing "cn" values.
22210Sstevel@tonic-gate  *		e.g.
22220Sstevel@tonic-gate  *		dn: cn=xx+ipserviceprotocol=udp,......
22230Sstevel@tonic-gate  *		cn: aa
22240Sstevel@tonic-gate  *		cn: bb
22250Sstevel@tonic-gate  *
22260Sstevel@tonic-gate  * Note:
22270Sstevel@tonic-gate  *  Although the name switch/ldap's  rdn is in "cn=xx" or "cn=xx+..."
22280Sstevel@tonic-gate  * format, this function makes no such assumption. If the DN
22290Sstevel@tonic-gate  * is saved as "dn: yy=...+sn=my_canocical_name, ..", then it can still work.
22300Sstevel@tonic-gate  * The comments use "cn" as an example only.
22310Sstevel@tonic-gate  *
22320Sstevel@tonic-gate  */
22330Sstevel@tonic-gate typedef int (*cmpfunc)(const char *, const char *);
22340Sstevel@tonic-gate 
22350Sstevel@tonic-gate char *
__s_api_get_canonical_name(ns_ldap_entry_t * entry,ns_ldap_attr_t * attrptr,int case_ignore)22360Sstevel@tonic-gate __s_api_get_canonical_name(ns_ldap_entry_t *entry, ns_ldap_attr_t *attrptr,
22370Sstevel@tonic-gate 			int case_ignore) {
22380Sstevel@tonic-gate 	uint_t			i;
22390Sstevel@tonic-gate 	char			*token, *lasts, *value = NULL;
22400Sstevel@tonic-gate 	char			**rdn = NULL, **attrs = NULL, **values = NULL;
22410Sstevel@tonic-gate 	char			*rdn_attr_value = NULL;
22420Sstevel@tonic-gate 	cmpfunc			cmp;
22430Sstevel@tonic-gate 
22440Sstevel@tonic-gate 	if (entry == NULL || attrptr == NULL)
22450Sstevel@tonic-gate 		return (NULL);
22460Sstevel@tonic-gate 
22470Sstevel@tonic-gate 	/* "values" is read-only */
22480Sstevel@tonic-gate 	if ((values = __ns_ldap_getAttr(entry, "dn")) == NULL ||
22494522Schinlong 	    values[0] == NULL)
22500Sstevel@tonic-gate 		return (NULL);
22510Sstevel@tonic-gate 
22520Sstevel@tonic-gate 	if ((rdn = ldap_explode_dn(values[0], 0)) == NULL ||
22534522Schinlong 	    rdn[0] == NULL)
22540Sstevel@tonic-gate 		return (NULL);
22550Sstevel@tonic-gate 
22560Sstevel@tonic-gate 	if ((attrs = ldap_explode_rdn(rdn[0], 0)) == NULL) {
22570Sstevel@tonic-gate 		ldap_value_free(rdn);
22580Sstevel@tonic-gate 		return (NULL);
22590Sstevel@tonic-gate 	}
22600Sstevel@tonic-gate 	/* Assume the rdn is normalized */
22610Sstevel@tonic-gate 	for (i = 0; attrs[i] != NULL; i++) {
22620Sstevel@tonic-gate 		/* parse attribute name and value, get attribute name first */
22630Sstevel@tonic-gate 		if ((token = strtok_r(attrs[i], "=", &lasts)) == NULL) {
22640Sstevel@tonic-gate 			goto cleanup;
22650Sstevel@tonic-gate 		}
22660Sstevel@tonic-gate 		if (strcasecmp(token, attrptr->attrname) == 0) {
22670Sstevel@tonic-gate 			/* get value */
22680Sstevel@tonic-gate 			rdn_attr_value = lasts;
22690Sstevel@tonic-gate 			break;
22700Sstevel@tonic-gate 		}
22710Sstevel@tonic-gate 	}
22720Sstevel@tonic-gate 	if (rdn_attr_value) {
22730Sstevel@tonic-gate 		if (case_ignore)
22740Sstevel@tonic-gate 			cmp = strcasecmp;
22750Sstevel@tonic-gate 		else
22760Sstevel@tonic-gate 			cmp = strcmp;
22770Sstevel@tonic-gate 		/*
22780Sstevel@tonic-gate 		 * After parsing RDN and find the matching attribute in RDN,
22790Sstevel@tonic-gate 		 * match rdn value with values in "cn".
22800Sstevel@tonic-gate 		 */
22810Sstevel@tonic-gate 		for (i = 0; i < attrptr->value_count; i++) {
22820Sstevel@tonic-gate 			if (attrptr->attrvalue[i] &&
22834522Schinlong 			    (*cmp)(rdn_attr_value,
22844522Schinlong 			    attrptr->attrvalue[i]) == 0) {
22850Sstevel@tonic-gate 				/* RDN "cn" value matches the "cn" value */
22860Sstevel@tonic-gate 				value = attrptr->attrvalue[i];
22870Sstevel@tonic-gate 				break;
22880Sstevel@tonic-gate 			}
22890Sstevel@tonic-gate 		}
22900Sstevel@tonic-gate 	}
22910Sstevel@tonic-gate cleanup:
22920Sstevel@tonic-gate 	ldap_value_free(rdn);
22930Sstevel@tonic-gate 	ldap_value_free(attrs);
22940Sstevel@tonic-gate 
22950Sstevel@tonic-gate 	return (value);
22960Sstevel@tonic-gate }
22970Sstevel@tonic-gate 
22980Sstevel@tonic-gate /*
22990Sstevel@tonic-gate  * This function requests a server to be removed from
23000Sstevel@tonic-gate  * the cache manager maintained server list. This is
23010Sstevel@tonic-gate  * done via the door functionality.
2302493Ssdussud  * Returns 0 if OK, else a negative value.
23030Sstevel@tonic-gate  */
23040Sstevel@tonic-gate 
2305493Ssdussud int
__s_api_removeServer(const char * server)23060Sstevel@tonic-gate __s_api_removeServer(const char *server)
23070Sstevel@tonic-gate {
23080Sstevel@tonic-gate 	union {
23090Sstevel@tonic-gate 		ldap_data_t	s_d;
23100Sstevel@tonic-gate 		char		s_b[DOORBUFFERSIZE];
23110Sstevel@tonic-gate 	} space;
23120Sstevel@tonic-gate 
23136842Sth160488 	ns_server_info_t		r, *ret = &r;
23140Sstevel@tonic-gate 	const char		*ireq;
23150Sstevel@tonic-gate 	ldap_data_t		*sptr;
23160Sstevel@tonic-gate 	int			ndata;
23170Sstevel@tonic-gate 	int			adata;
23180Sstevel@tonic-gate 	int			len;
2319493Ssdussud 	int			rc;
23206842Sth160488 	ns_ldap_error_t		*error = NULL;
23210Sstevel@tonic-gate 
23220Sstevel@tonic-gate 	if (server == NULL)
2323493Ssdussud 		return (-1);
23240Sstevel@tonic-gate 
23250Sstevel@tonic-gate 	ireq = NS_CACHE_NORESP;
23260Sstevel@tonic-gate 
23276842Sth160488 	if (__s_api_isStandalone()) {
23286842Sth160488 		/*
23296842Sth160488 		 * Remove 'server' from the standalone server list.
23306842Sth160488 		 * __s_api_findRootDSE() is the standalone version
23316842Sth160488 		 * of getldap_get_serverInfo() used in ldap_cachemgr.
23326842Sth160488 		 * Request NS_CACHE_NORESP indicates 'server' should
23336842Sth160488 		 * be removed.
23346842Sth160488 		 */
23356842Sth160488 		if (__s_api_findRootDSE(ireq,
23366842Sth160488 		    server,
23376842Sth160488 		    NS_CACHE_ADDR_IP,
23386842Sth160488 		    NULL,
23396842Sth160488 		    &error) != NS_LDAP_SUCCESS) {
23406842Sth160488 			syslog(LOG_WARNING,
23416842Sth160488 			    "libsldap (\"standalone\" mode): "
23426842Sth160488 			    " Unable to remove %s - %s",
23436842Sth160488 			    server,
23446842Sth160488 			    error != NULL && error->message != NULL ?
23456842Sth160488 			    error->message : " no error info");
23466842Sth160488 			if (error != NULL) {
23476842Sth160488 				(void) __ns_ldap_freeError(&error);
23486842Sth160488 			}
23496842Sth160488 
23507281Smichen 			return (NS_CACHE_NOSERVER);
23516842Sth160488 		}
23526842Sth160488 
23536842Sth160488 		return (0);
23546842Sth160488 	}
23556842Sth160488 
23560Sstevel@tonic-gate 	(void) memset(ret, 0, sizeof (ns_server_info_t));
23570Sstevel@tonic-gate 	(void) memset(space.s_b, 0, DOORBUFFERSIZE);
23580Sstevel@tonic-gate 
23592830Sdjl 	adata = (sizeof (ldap_call_t) + strlen(ireq) +
23604522Schinlong 	    strlen(NS_CACHE_ADDR_IP) + 1);
23610Sstevel@tonic-gate 	adata += strlen(DOORLINESEP) + 1;
23620Sstevel@tonic-gate 	adata += strlen(server) + 1;
23630Sstevel@tonic-gate 
23640Sstevel@tonic-gate 	ndata = sizeof (space);
23650Sstevel@tonic-gate 	space.s_d.ldap_call.ldap_callnumber = GETLDAPSERVER;
23660Sstevel@tonic-gate 	len = sizeof (space) - sizeof (space.s_d.ldap_call.ldap_callnumber);
23672830Sdjl 	if (strlcpy(space.s_d.ldap_call.ldap_u.domainname, ireq, len) >= len)
23682830Sdjl 		return (-1);
23692830Sdjl 	if (strlcat(space.s_d.ldap_call.ldap_u.domainname,
23704522Schinlong 	    NS_CACHE_ADDR_IP, len) >= len)
23712830Sdjl 		return (-1);
23722830Sdjl 	if (strlcat(space.s_d.ldap_call.ldap_u.domainname, DOORLINESEP, len) >=
23734522Schinlong 	    len)
23742830Sdjl 		return (-1);
23752830Sdjl 	if (strlcat(space.s_d.ldap_call.ldap_u.domainname, server, len) >= len)
23762830Sdjl 		return (-1);
23770Sstevel@tonic-gate 	sptr = &space.s_d;
23780Sstevel@tonic-gate 
23790Sstevel@tonic-gate 	/* try to remove the server via the door interface */
2380493Ssdussud 	rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
23810Sstevel@tonic-gate 
23820Sstevel@tonic-gate 	/* clean up the door call */
23830Sstevel@tonic-gate 	if (sptr != &space.s_d) {
23840Sstevel@tonic-gate 		(void) munmap((char *)sptr, ndata);
23850Sstevel@tonic-gate 	}
2386493Ssdussud 
2387493Ssdussud 	return (rc);
23880Sstevel@tonic-gate }
23894522Schinlong 
23904522Schinlong void
__s_api_free_server_info(ns_server_info_t * sinfo)23914522Schinlong __s_api_free_server_info(ns_server_info_t *sinfo) {
23924522Schinlong 	if (sinfo->server) {
23934522Schinlong 		free(sinfo->server);
23944522Schinlong 		sinfo->server = NULL;
23954522Schinlong 	}
23964522Schinlong 	if (sinfo->serverFQDN) {
23974522Schinlong 		free(sinfo->serverFQDN);
23984522Schinlong 		sinfo->serverFQDN = NULL;
23994522Schinlong 	}
24004522Schinlong 	__s_api_free2dArray(sinfo->saslMechanisms);
24014522Schinlong 	sinfo->saslMechanisms = NULL;
24024522Schinlong 	__s_api_free2dArray(sinfo->controls);
24034522Schinlong 	sinfo->controls = NULL;
24044522Schinlong }
24056842Sth160488 
24066842Sth160488 /*
24076842Sth160488  * Create an ns_ldap_error structure, set status to 'rc',
24086842Sth160488  * and copy in the error message 'msg'.
24096842Sth160488  */
24106842Sth160488 ns_ldap_error_t *
__s_api_make_error(int rc,char * msg)24116842Sth160488 __s_api_make_error(int rc, char *msg) {
24126842Sth160488 	ns_ldap_error_t *ep;
24136842Sth160488 
24146842Sth160488 	ep = (ns_ldap_error_t *)calloc(1, sizeof (*ep));
24156842Sth160488 	if (ep == NULL)
24166842Sth160488 		return (NULL);
24176842Sth160488 
24186842Sth160488 	ep->status = rc;
24196842Sth160488 	if (msg != NULL)
24206842Sth160488 		ep->message =  strdup(msg); /* OK if ep->message is NULL */
24216842Sth160488 
24226842Sth160488 	return (ep);
24236842Sth160488 }
24246842Sth160488 
24256842Sth160488 /*
24266842Sth160488  * Make a copy of the input ns_ldap_error.
24276842Sth160488  */
24286842Sth160488 ns_ldap_error_t *
__s_api_copy_error(ns_ldap_error_t * errorp)24296842Sth160488 __s_api_copy_error(ns_ldap_error_t *errorp) {
24306842Sth160488 	ns_ldap_error_t *ep;
24316842Sth160488 	char		*msg;
24326842Sth160488 
24336842Sth160488 	if (errorp == NULL)
24346842Sth160488 		return (NULL);
24356842Sth160488 
24366842Sth160488 	ep = (ns_ldap_error_t *)malloc(sizeof (*ep));
24376842Sth160488 	if (ep != NULL) {
24386842Sth160488 		*ep = *errorp;
24396842Sth160488 		if (ep->message != NULL) {
24406842Sth160488 			msg = strdup(ep->message);
24416842Sth160488 			if (msg == NULL) {
24426842Sth160488 				free(ep);
24436842Sth160488 				ep = NULL;
24446842Sth160488 			} else
24456842Sth160488 				ep->message = msg;
24466842Sth160488 		}
24476842Sth160488 	}
24486842Sth160488 	return (ep);
24496842Sth160488 }
2450