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 ¶mVal, 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(¶mVal);
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 ¶mVal, 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(¶mVal);
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(¶mVal);
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 ¶mVal);
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 ¶mVal);
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 ¶mVal);
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 ¶mVal);
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(¶mVal);
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(¶mVal);
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 ¶mVal, 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(¶mVal);
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 ¶mVal, 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(¶mVal);
8360Sstevel@tonic-gate paramVal = NULL;
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_SERVERS_P,
8394522Schinlong ¶mVal, 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 ¶mVal, 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(¶mVal);
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(¶mVal);
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 ¶mVal, 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(¶mVal);
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(¶mVal);
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, ¶mVal, errorp);
19490Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) {
19500Sstevel@tonic-gate if (paramVal)
19510Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal);
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(¶mVal);
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(¶mVal);
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