ns_common.c revision 689c2bf45cbd08f8feb29c8c945a57f48267abd9
1N/A/*
1N/A * CDDL HEADER START
1N/A *
1N/A * The contents of this file are subject to the terms of the
1N/A * Common Development and Distribution License (the "License").
1N/A * You may not use this file except in compliance with the License.
1N/A *
1N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1N/A * or http://www.opensolaris.org/os/licensing.
1N/A * See the License for the specific language governing permissions
1N/A * and limitations under the License.
1N/A *
1N/A * When distributing Covered Code, include this CDDL HEADER in each
1N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1N/A * If applicable, add the following below this CDDL HEADER, with the
1N/A * fields enclosed by brackets "[]" replaced with your own identifying
1N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1N/A *
1N/A * CDDL HEADER END
1N/A */
1N/A/*
1N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A#pragma ident "%Z%%M% %I% %E% SMI"
1N/A
1N/A#include <stdio.h>
1N/A#include <sys/types.h>
1N/A#include <stdlib.h>
1N/A#include <libintl.h>
1N/A#include <ctype.h>
1N/A
1N/A#include <sys/stat.h>
1N/A#include <sys/mman.h>
1N/A#include <fcntl.h>
1N/A#include <unistd.h>
1N/A#include <string.h>
1N/A#include <syslog.h>
1N/A#include <sys/socket.h>
1N/A#include <sys/sockio.h>
1N/A#include <netinet/in.h>
1N/A#include <arpa/inet.h>
1N/A#include <net/if.h>
1N/A#include <netdir.h>
1N/A#include <lber.h>
1N/A#include <ldap.h>
1N/A
1N/A#include "ns_sldap.h"
1N/A#include "ns_internal.h"
1N/A#include "ns_cache_door.h"
1N/A
1N/A#define UDP "/dev/udp"
1N/A#define MAXIFS 32
1N/A
1N/Astruct ifinfo {
1N/A struct in_addr addr, netmask;
1N/A};
1N/A
1N/Astatic ns_service_map ns_def_map[] = {
1N/A { "passwd", "ou=people,", NULL },
1N/A { "shadow", "ou=people,", "passwd" },
1N/A { "user_attr", "ou=people,", "passwd" },
1N/A { "audit_user", "ou=people,", "passwd" },
1N/A { "group", "ou=group,", NULL },
1N/A { "rpc", "ou=rpc,", NULL },
1N/A { "project", "ou=projects,", NULL },
1N/A { "protocols", "ou=protocols,", NULL },
1N/A { "networks", "ou=networks,", NULL },
1N/A { "netmasks", "ou=networks,", "networks" },
1N/A { "netgroup", "ou=netgroup,", NULL },
1N/A { "aliases", "ou=aliases,", NULL },
1N/A { "Hosts", "ou=Hosts,", NULL },
1N/A { "ipnodes", "ou=Hosts,", "hosts" },
1N/A { "Services", "ou=Services,", NULL },
1N/A { "bootparams", "ou=ethers,", "ethers" },
1N/A { "ethers", "ou=ethers,", NULL },
1N/A { "auth_attr", "ou=SolarisAuthAttr,", NULL },
1N/A { "prof_attr", "ou=SolarisProfAttr,", NULL },
1N/A { "exec_attr", "ou=SolarisProfAttr,", "prof_attr" },
1N/A { "profile", "ou=profile,", NULL },
1N/A { "printers", "ou=printers,", NULL },
1N/A { "automount", "", NULL },
1N/A { "tnrhtp", "ou=ipTnet,", NULL },
1N/A { "tnrhdb", "ou=ipTnet,", "tnrhtp" },
1N/A { NULL, NULL, NULL }
1N/A};
1N/A
1N/A
1N/Astatic char ** parseDN(const char *val, const char *service);
1N/Astatic char ** sortServerNet(char **srvlist);
1N/Astatic char ** sortServerPref(char **srvlist, char **preflist,
1N/A boolean_t flag, int version, int *error);
1N/A
1N/A/*
1N/A * FUNCTION: s_api_printResult
1N/A * Given a ns_ldap_result structure print it.
1N/A */
1N/Aint
1N/A__s_api_printResult(ns_ldap_result_t *result)
1N/A{
1N/A
1N/A ns_ldap_entry_t *curEntry;
1N/A int i, j, k = 0;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__s_api_printResult START\n");
1N/A#endif
1N/A (void) printf("--------------------------------------\n");
1N/A if (result == NULL) {
1N/A (void) printf("No result\n");
1N/A return (0);
1N/A }
1N/A (void) printf("entries_count %d\n", result->entries_count);
1N/A curEntry = result->entry;
1N/A for (i = 0; i < result->entries_count; i++) {
1N/A
1N/A (void) printf("entry %d has attr_count = %d \n", i,
1N/A curEntry->attr_count);
1N/A for (j = 0; j < curEntry->attr_count; j++) {
1N/A (void) printf("entry %d has attr_pair[%d] = %s \n", i, j,
1N/A curEntry->attr_pair[j]->attrname);
1N/A for (k = 0; k < 20 && curEntry->attr_pair[j]->attrvalue[k]; k++)
1N/A (void) printf(
1N/A "entry %d has attr_pair[%d]->attrvalue[%d] = %s \n",
1N/A i, j, k, curEntry->attr_pair[j]->attrvalue[k]);
1N/A }
1N/A (void) printf("\n--------------------------------------\n");
1N/A curEntry = curEntry->next;
1N/A }
1N/A return (1);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_getSearchScope
1N/A *
1N/A * Retrieve the search scope for ldap search from the config module.
1N/A *
1N/A * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_CONFIG
1N/A * INPUT: NONE
1N/A * OUTPUT: searchScope, errorp
1N/A */
1N/Aint
1N/A__s_api_getSearchScope(
1N/A int *searchScope,
1N/A ns_ldap_error_t **errorp)
1N/A{
1N/A
1N/A char errmsg[MAXERROR];
1N/A void **paramVal = NULL;
1N/A int rc = 0;
1N/A int scope = 0;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__s_api_getSearchScope START\n");
1N/A#endif
1N/A if (*searchScope == 0) {
1N/A if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P,
1N/A &paramVal, errorp)) != NS_LDAP_SUCCESS) {
1N/A return (rc);
1N/A }
1N/A if (paramVal && *paramVal)
1N/A scope = * (int *)(*paramVal);
1N/A else
1N/A scope = NS_LDAP_SCOPE_ONELEVEL;
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A } else {
1N/A scope = *searchScope;
1N/A }
1N/A
1N/A switch (scope) {
1N/A
1N/A case NS_LDAP_SCOPE_ONELEVEL:
1N/A *searchScope = LDAP_SCOPE_ONELEVEL;
1N/A break;
1N/A case NS_LDAP_SCOPE_BASE:
1N/A *searchScope = LDAP_SCOPE_BASE;
1N/A break;
1N/A case NS_LDAP_SCOPE_SUBTREE:
1N/A *searchScope = LDAP_SCOPE_SUBTREE;
1N/A break;
1N/A default:
1N/A (void) snprintf(errmsg, sizeof (errmsg),
1N/A gettext("Invalid search scope!"));
1N/A MKERROR(LOG_ERR, *errorp, NS_CONFIG_FILE,
1N/A strdup(errmsg), NS_LDAP_CONFIG);
1N/A return (NS_LDAP_CONFIG);
1N/A }
1N/A
1N/A return (NS_LDAP_SUCCESS);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __ns_ldap_dupAuth
1N/A *
1N/A * Duplicates an authentication structure.
1N/A *
1N/A * RETURN VALUES: copy of authp or NULL on error
1N/A * INPUT: authp
1N/A */
1N/Ans_cred_t *
1N/A__ns_ldap_dupAuth(const ns_cred_t *authp)
1N/A{
1N/A ns_cred_t *ap;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__ns_ldap_dupAuth START\n");
1N/A#endif
1N/A if (authp == NULL)
1N/A return (NULL);
1N/A
1N/A ap = (ns_cred_t *)calloc(1, sizeof (ns_cred_t));
1N/A if (ap == NULL)
1N/A return (NULL);
1N/A
1N/A if (authp->hostcertpath) {
1N/A ap->hostcertpath = strdup(authp->hostcertpath);
1N/A if (ap->hostcertpath == NULL) {
1N/A free(ap);
1N/A return (NULL);
1N/A }
1N/A }
1N/A if (authp->cred.unix_cred.userID) {
1N/A ap->cred.unix_cred.userID =
1N/A strdup(authp->cred.unix_cred.userID);
1N/A if (ap->cred.unix_cred.userID == NULL) {
1N/A (void) __ns_ldap_freeCred(&ap);
1N/A return (NULL);
1N/A }
1N/A }
1N/A if (authp->cred.unix_cred.passwd) {
1N/A ap->cred.unix_cred.passwd =
1N/A strdup(authp->cred.unix_cred.passwd);
1N/A if (ap->cred.unix_cred.passwd == NULL) {
1N/A (void) __ns_ldap_freeCred(&ap);
1N/A return (NULL);
1N/A }
1N/A }
1N/A if (authp->cred.cert_cred.nickname) {
1N/A ap->cred.cert_cred.nickname =
1N/A strdup(authp->cred.cert_cred.nickname);
1N/A if (ap->cred.cert_cred.nickname == NULL) {
1N/A (void) __ns_ldap_freeCred(&ap);
1N/A return (NULL);
1N/A }
1N/A }
1N/A ap->auth.type = authp->auth.type;
1N/A ap->auth.tlstype = authp->auth.tlstype;
1N/A ap->auth.saslmech = authp->auth.saslmech;
1N/A ap->auth.saslopt = authp->auth.saslopt;
1N/A return (ap);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __ns_ldap_freeCred
1N/A *
1N/A * Frees all the memory associated with a ns_cred_t structure.
1N/A *
1N/A * RETURN VALUES: NS_LDAP_INVALID_PARAM, NS_LDAP_SUCCESS, NS_LDAP_CONFIG
1N/A * INPUT: ns_cred_t
1N/A */
1N/Aint
1N/A__ns_ldap_freeCred(ns_cred_t ** credp)
1N/A{
1N/A ns_cred_t *ap;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__ns_ldap_freeCred START\n");
1N/A#endif
1N/A if (credp == NULL || *credp == NULL)
1N/A return (NS_LDAP_INVALID_PARAM);
1N/A
1N/A ap = *credp;
1N/A if (ap->hostcertpath) {
1N/A (void) memset(ap->hostcertpath, 0,
1N/A strlen(ap->hostcertpath));
1N/A free(ap->hostcertpath);
1N/A }
1N/A
1N/A if (ap->cred.unix_cred.userID) {
1N/A (void) memset(ap->cred.unix_cred.userID, 0,
1N/A strlen(ap->cred.unix_cred.userID));
1N/A free(ap->cred.unix_cred.userID);
1N/A }
1N/A
1N/A if (ap->cred.unix_cred.passwd) {
1N/A (void) memset(ap->cred.unix_cred.passwd, 0,
1N/A strlen(ap->cred.unix_cred.passwd));
1N/A free(ap->cred.unix_cred.passwd);
1N/A }
1N/A
1N/A if (ap->cred.cert_cred.nickname) {
1N/A (void) memset(ap->cred.cert_cred.nickname, 0,
1N/A strlen(ap->cred.cert_cred.nickname));
1N/A free(ap->cred.cert_cred.nickname);
1N/A }
1N/A
1N/A free(ap);
1N/A *credp = NULL;
1N/A return (NS_LDAP_SUCCESS);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_getDNs
1N/A *
1N/A * Retrieves the default base dn for the given
1N/A * service.
1N/A *
1N/A * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG
1N/A * INPUT: service
1N/A * OUTPUT: DN, error
1N/A */
1N/Aint
1N/A__s_api_getDNs(
1N/A char *** DN,
1N/A const char *service,
1N/A ns_ldap_error_t ** error)
1N/A{
1N/A
1N/A void **paramVal = NULL;
1N/A char **dns = NULL;
1N/A int rc = 0;
1N/A int i, len;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__s_api_getDNs START\n");
1N/A#endif
1N/A if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
1N/A &paramVal, error)) != NS_LDAP_SUCCESS) {
1N/A return (rc);
1N/A }
1N/A if (!paramVal) {
1N/A char errmsg[MAXERROR];
1N/A
1N/A (void) snprintf(errmsg, sizeof (errmsg),
1N/A gettext("BaseDN not defined"));
1N/A MKERROR(LOG_ERR, *error, NS_CONFIG_FILE, strdup(errmsg),
1N/A NS_LDAP_CONFIG);
1N/A return (NS_LDAP_CONFIG);
1N/A }
1N/A
1N/A dns = (char **)calloc(2, sizeof (char *));
1N/A if (dns == NULL) {
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A
1N/A if (service == NULL) {
1N/A dns[0] = strdup((char *)*paramVal);
1N/A if (dns[0] == NULL) {
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A free(dns);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A } else {
1N/A for (i = 0; ns_def_map[i].service != NULL; i++) {
1N/A if (strcasecmp(service,
1N/A ns_def_map[i].service) == 0) {
1N/A
1N/A len = strlen((char *)*paramVal) +
1N/A strlen(ns_def_map[i].rdn) + 1;
1N/A dns[0] = (char *)
1N/A calloc(len, sizeof (char));
1N/A if (dns[0] == NULL) {
1N/A (void) __ns_ldap_freeParam(
1N/A &paramVal);
1N/A free(dns);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A (void) strcpy(dns[0],
1N/A ns_def_map[i].rdn);
1N/A (void) strcat(dns[0],
1N/A (char *)*paramVal);
1N/A break;
1N/A }
1N/A }
1N/A if (ns_def_map[i].service == NULL) {
1N/A char *p = (char *)*paramVal;
1N/A char *buffer = NULL;
1N/A int buflen = 0;
1N/A
1N/A if (strchr(service, '=') == NULL) {
1N/A /* automount entries */
1N/A if (strncasecmp(service, "auto_", 5) == 0) {
1N/A buffer = strdup(p);
1N/A if (!buffer) {
1N/A free(dns);
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A rc = __s_api_prepend_automountmapname_to_dn(
1N/A service, &buffer, error);
1N/A if (rc != NS_LDAP_SUCCESS) {
1N/A free(dns);
1N/A free(buffer);
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A return (rc);
1N/A }
1N/A } else {
1N/A /* strlen("nisMapName")+"="+","+'\0' = 13 */
1N/A buflen = strlen(service) + strlen(p) + 13;
1N/A buffer = (char *)malloc(buflen);
1N/A if (buffer == NULL) {
1N/A free(dns);
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A (void) snprintf(buffer, buflen,
1N/A "nisMapName=%s,%s", service, p);
1N/A }
1N/A } else {
1N/A buflen = strlen(service) + strlen(p) + 2;
1N/A buffer = (char *)malloc(buflen);
1N/A if (buffer == NULL) {
1N/A free(dns);
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A (void) snprintf(buffer, buflen,
1N/A "%s,%s", service, p);
1N/A }
1N/A dns[0] = buffer;
1N/A }
1N/A }
1N/A
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A *DN = dns;
1N/A return (NS_LDAP_SUCCESS);
1N/A}
1N/A/*
1N/A * FUNCTION: __s_api_get_search_DNs_v1
1N/A *
1N/A * Retrieves the list of search DNS from the V1 profile for the given
1N/A * service.
1N/A *
1N/A * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG
1N/A * INPUT: service
1N/A * OUTPUT: DN, error
1N/A */
1N/Aint
1N/A__s_api_get_search_DNs_v1(
1N/A char *** DN,
1N/A const char *service,
1N/A ns_ldap_error_t ** error)
1N/A{
1N/A
1N/A void **paramVal = NULL;
1N/A void **temptr = NULL;
1N/A char **dns = NULL;
1N/A int rc = 0;
1N/A
1N/A if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_DN_P,
1N/A &paramVal, error)) != NS_LDAP_SUCCESS) {
1N/A return (rc);
1N/A }
1N/A
1N/A if (service && paramVal) {
1N/A for (temptr = paramVal; *temptr != NULL; temptr++) {
1N/A dns = parseDN((const char *)(*temptr),
1N/A (const char *)service);
1N/A if (dns != NULL)
1N/A break;
1N/A }
1N/A }
1N/A
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A *DN = dns;
1N/A return (NS_LDAP_SUCCESS);
1N/A
1N/A}
1N/A/*
1N/A * FUNCTION: parseDN
1N/A *
1N/A * Parse a special formated list(val) into an array of char *.
1N/A *
1N/A * RETURN VALUE: A char * pointer to the new list of dns.
1N/A * INPUT: val, service
1N/A */
1N/Astatic char **
1N/AparseDN(
1N/A const char *val,
1N/A const char *service)
1N/A{
1N/A
1N/A size_t len = 0;
1N/A size_t slen = 0;
1N/A char **retVal = NULL;
1N/A const char *temptr;
1N/A char *temptr2;
1N/A const char *valend;
1N/A int valNo = 0;
1N/A int valSize = 0;
1N/A int i;
1N/A char *SSD_service = NULL;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "parseDN START\n");
1N/A#endif
1N/A if (val == NULL || *val == '\0')
1N/A return (NULL);
1N/A if (service == NULL || *service == '\0')
1N/A return (NULL);
1N/A
1N/A len = strlen(val);
1N/A slen = strlen(service);
1N/A if (strncasecmp(val, service, slen) != 0) {
1N/A /*
1N/A * This routine is only called
1N/A * to process V1 profile and
1N/A * for V1 profile, map service
1N/A * to the corresponding SSD_service
1N/A * which is associated with a
1N/A * real container in the LDAP directory
1N/A * tree, e.g., map "shadow" to
1N/A * "password". See function
1N/A * __s_api_get_SSD_from_SSDtoUse_service
1N/A * for similar service to SSD_service
1N/A * mapping handling for V2 profile.
1N/A */
1N/A for (i = 0; ns_def_map[i].service != NULL; i++) {
1N/A if (ns_def_map[i].SSDtoUse_service &&
1N/A strcasecmp(service,
1N/A ns_def_map[i].service) == 0) {
1N/A SSD_service =
1N/A ns_def_map[i].SSDtoUse_service;
1N/A break;
1N/A }
1N/A }
1N/A
1N/A if (SSD_service == NULL)
1N/A return (NULL);
1N/A
1N/A slen = strlen(SSD_service);
1N/A if (strncasecmp(val, SSD_service, slen) != 0)
1N/A return (NULL);
1N/A }
1N/A
1N/A temptr = val + slen;
1N/A while (*temptr == SPACETOK || *temptr == TABTOK)
1N/A temptr++;
1N/A if (*temptr != COLONTOK)
1N/A return (NULL);
1N/A
1N/A while (*temptr) {
1N/A temptr2 = strchr(temptr, OPARATOK);
1N/A if (temptr2 == NULL)
1N/A break;
1N/A temptr2++;
1N/A temptr2 = strchr(temptr2, CPARATOK);
1N/A if (temptr2 == NULL)
1N/A break;
1N/A valNo++;
1N/A temptr = temptr2+1;
1N/A }
1N/A
1N/A retVal = (char **)calloc(valNo +1, sizeof (char *));
1N/A if (retVal == NULL)
1N/A return (NULL);
1N/A
1N/A temptr = val;
1N/A valend = val+len;
1N/A
1N/A for (i = 0; (i < valNo) && (temptr < valend); i++) {
1N/A temptr = strchr(temptr, OPARATOK);
1N/A if (temptr == NULL) {
1N/A __s_api_free2dArray(retVal);
1N/A return (NULL);
1N/A }
1N/A temptr++;
1N/A temptr2 = strchr(temptr, CPARATOK);
1N/A if (temptr2 == NULL) {
1N/A __s_api_free2dArray(retVal);
1N/A return (NULL);
1N/A }
1N/A valSize = temptr2 - temptr;
1N/A
1N/A retVal[i] = (char *)calloc(valSize + 1, sizeof (char));
1N/A if (retVal[i] == NULL) {
1N/A __s_api_free2dArray(retVal);
1N/A return (NULL);
1N/A }
1N/A (void) strncpy(retVal[i], temptr, valSize);
1N/A retVal[i][valSize] = '\0';
1N/A temptr = temptr2 + 1;
1N/A }
1N/A
1N/A return (retVal);
1N/A}
1N/A
1N/A
1N/A/*
1N/A * __s_api_get_local_interfaces
1N/A *
1N/A * Returns a pointer to an array of addresses and netmasks of all interfaces
1N/A * configured on the system.
1N/A *
1N/A * NOTE: This function is very IPv4 centric.
1N/A */
1N/Astatic struct ifinfo *
1N/A__s_api_get_local_interfaces()
1N/A{
1N/A struct ifconf ifc;
1N/A struct ifreq ifreq, *ifr;
1N/A struct ifinfo *localinfo;
1N/A struct in_addr netmask;
1N/A struct sockaddr_in *sin;
1N/A void *buf = NULL;
1N/A int fd = 0;
1N/A int numifs = 0;
1N/A int i, n = 0;
1N/A
1N/A if ((fd = open(UDP, O_RDONLY)) < 0)
1N/A return ((struct ifinfo *)NULL);
1N/A
1N/A if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) {
1N/A numifs = MAXIFS;
1N/A }
1N/A
1N/A buf = malloc(numifs * sizeof (struct ifreq));
1N/A if (buf == NULL) {
1N/A (void) close(fd);
1N/A return ((struct ifinfo *)NULL);
1N/A }
1N/A ifc.ifc_len = numifs * (int)sizeof (struct ifreq);
1N/A ifc.ifc_buf = buf;
1N/A if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) {
1N/A (void) close(fd);
1N/A free(buf);
1N/A buf = NULL;
1N/A return ((struct ifinfo *)NULL);
1N/A }
1N/A ifr = (struct ifreq *)buf;
1N/A numifs = ifc.ifc_len/(int)sizeof (struct ifreq);
1N/A localinfo = (struct ifinfo *)malloc((numifs + 1) *
1N/A sizeof (struct ifinfo));
1N/A if (localinfo == NULL) {
1N/A (void) close(fd);
1N/A free(buf);
1N/A buf = NULL;
1N/A return ((struct ifinfo *)NULL);
1N/A }
1N/A
1N/A for (i = 0, n = numifs; n > 0; n--, ifr++) {
1N/A uint_t ifrflags;
1N/A
1N/A ifreq = *ifr;
1N/A if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifreq) < 0)
1N/A continue;
1N/A
1N/A ifrflags = ifreq.ifr_flags;
1N/A if (((ifrflags & IFF_UP) == 0) ||
1N/A (ifr->ifr_addr.sa_family != AF_INET))
1N/A continue;
1N/A
1N/A if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifreq) < 0)
1N/A continue;
1N/A netmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
1N/A
1N/A if (ioctl(fd, SIOCGIFADDR, (char *)&ifreq) < 0)
1N/A continue;
1N/A
1N/A sin = (struct sockaddr_in *)&ifreq.ifr_addr;
1N/A
1N/A localinfo[i].addr = sin->sin_addr;
1N/A localinfo[i].netmask = netmask;
1N/A i++;
1N/A }
1N/A localinfo[i].addr.s_addr = 0;
1N/A
1N/A free(buf);
1N/A buf = NULL;
1N/A (void) close(fd);
1N/A return (localinfo);
1N/A}
1N/A
1N/A
1N/A/*
1N/A * __s_api_samenet(char *, struct ifinfo *)
1N/A *
1N/A * Returns 1 if address is on the same subnet of the array of addresses
1N/A * passed in.
1N/A *
1N/A * NOTE: This function is only valid for IPv4 addresses.
1N/A */
1N/Astatic int
1N/A__s_api_IPv4sameNet(char *addr, struct ifinfo *ifs)
1N/A{
1N/A int answer = 0;
1N/A
1N/A if (addr && ifs) {
1N/A char *addr_raw;
1N/A unsigned long iaddr;
1N/A int i;
1N/A
1N/A if ((addr_raw = strdup(addr)) != NULL) {
1N/A char *s;
1N/A
1N/A /* Remove port number. */
1N/A if ((s = strchr(addr_raw, ':')) != NULL)
1N/A *s = '\0';
1N/A
1N/A iaddr = inet_addr(addr_raw);
1N/A
1N/A /* Loop through interface list to find match. */
1N/A for (i = 0; ifs[i].addr.s_addr != 0; i++) {
1N/A if ((iaddr & ifs[i].netmask.s_addr) ==
1N/A (ifs[i].addr.s_addr &
1N/A ifs[i].netmask.s_addr))
1N/A answer++;
1N/A }
1N/A free(addr_raw);
1N/A }
1N/A }
1N/A
1N/A return (answer);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_getServers
1N/A *
1N/A * Retrieve a list of ldap servers from the config module.
1N/A *
1N/A * RETURN VALUE: NS_LDAP_SUCCESS, NS_LDAP_CONFIG, NS_LDAP_MEMORY
1N/A * INPUT: NONE
1N/A * OUTPUT: servers, error
1N/A */
1N/Aint
1N/A__s_api_getServers(
1N/A char *** servers,
1N/A ns_ldap_error_t ** error)
1N/A{
1N/A void **paramVal = NULL;
1N/A char errmsg[MAXERROR];
1N/A char **sortServers = NULL;
1N/A char **netservers = NULL;
1N/A int rc = 0, err = NS_LDAP_CONFIG, version = 1;
1N/A const char *str, *str1;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__s_api_getServers START\n");
1N/A#endif
1N/A *servers = NULL;
1N/A /* get profile version number */
1N/A if ((rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P,
1N/A &paramVal, error)) != NS_LDAP_SUCCESS)
1N/A return (rc);
1N/A
1N/A if (paramVal == NULL || *paramVal == NULL) {
1N/A (void) snprintf(errmsg, sizeof (errmsg),
1N/A gettext("No file version"));
1N/A MKERROR(LOG_INFO, *error, NS_CONFIG_FILE, strdup(errmsg),
1N/A NS_LDAP_CONFIG);
1N/A return (NS_LDAP_CONFIG);
1N/A }
1N/A
1N/A if (strcasecmp((char *)*paramVal, NS_LDAP_VERSION_1) == 0)
1N/A version = 1;
1N/A else if (strcasecmp((char *)*paramVal, NS_LDAP_VERSION_2) == 0)
1N/A version = 2;
1N/A
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A paramVal = NULL;
1N/A
1N/A if ((rc = __ns_ldap_getParam(NS_LDAP_SERVERS_P,
1N/A &paramVal, error)) != NS_LDAP_SUCCESS)
1N/A return (rc);
1N/A
1N/A /*
1N/A * For version 2, default server list could be
1N/A * empty.
1N/A */
1N/A if ((paramVal == NULL || (char *)*paramVal == NULL) &&
1N/A version == 1) {
1N/A str = NULL_OR_STR(__s_api_get_configname(NS_LDAP_SERVERS_P));
1N/A (void) snprintf(errmsg, sizeof (errmsg),
1N/A gettext("Unable to retrieve the '%s' list"), str);
1N/A MKERROR(LOG_WARNING, *error, NS_CONFIG_FILE, strdup(errmsg),
1N/A NS_LDAP_CONFIG);
1N/A return (NS_LDAP_CONFIG);
1N/A }
1N/A
1N/A /*
1N/A * Get server address(es) and go through them.
1N/A */
1N/A *servers = (char **)paramVal;
1N/A paramVal = NULL;
1N/A
1N/A /* Sort servers based on network. */
1N/A if (*servers) {
1N/A netservers = sortServerNet(*servers);
1N/A if (netservers) {
1N/A free(*servers);
1N/A *servers = netservers;
1N/A } else {
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A }
1N/A
1N/A /* Get preferred server list and sort servers based on that. */
1N/A if ((rc = __ns_ldap_getParam(NS_LDAP_SERVER_PREF_P,
1N/A &paramVal, error)) != NS_LDAP_SUCCESS) {
1N/A if (*servers)
1N/A __s_api_free2dArray(*servers);
1N/A *servers = NULL;
1N/A return (rc);
1N/A }
1N/A
1N/A if (paramVal != NULL) {
1N/A char **prefServers;
1N/A void **val = NULL;
1N/A
1N/A if ((rc = __ns_ldap_getParam(NS_LDAP_PREF_ONLY_P,
1N/A &val, error)) != NS_LDAP_SUCCESS) {
1N/A if (*servers)
1N/A __s_api_free2dArray(*servers);
1N/A *servers = NULL;
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A return (rc);
1N/A }
1N/A
1N/A prefServers = (char **)paramVal;
1N/A paramVal = NULL;
1N/A if (prefServers) {
1N/A if (val != NULL && (*val) != NULL &&
1N/A *(int *)val[0] == 1)
1N/A sortServers = sortServerPref(*servers,
1N/A prefServers, B_FALSE, version,
1N/A &err);
1N/A else
1N/A sortServers = sortServerPref(*servers,
1N/A prefServers, B_TRUE, version,
1N/A &err);
1N/A if (sortServers) {
1N/A if (*servers)
1N/A free(*servers);
1N/A *servers = NULL;
1N/A free(prefServers);
1N/A prefServers = NULL;
1N/A *servers = sortServers;
1N/A } else {
1N/A if (*servers)
1N/A __s_api_free2dArray(*servers);
1N/A *servers = NULL;
1N/A __s_api_free2dArray(prefServers);
1N/A prefServers = NULL;
1N/A }
1N/A }
1N/A (void) __ns_ldap_freeParam(&val);
1N/A }
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A
1N/A if (*servers == NULL) {
1N/A if (err == NS_LDAP_CONFIG) {
1N/A str = NULL_OR_STR(__s_api_get_configname(
1N/A NS_LDAP_SERVERS_P));
1N/A str1 = NULL_OR_STR(__s_api_get_configname(
1N/A NS_LDAP_SERVER_PREF_P));
1N/A (void) snprintf(errmsg, sizeof (errmsg),
1N/A gettext("Unable to generate a new server list "
1N/A "based on '%s' and/or '%s'"), str, str1);
1N/A MKERROR(LOG_WARNING, *error, NS_CONFIG_FILE,
1N/A strdup(errmsg), err);
1N/A return (err);
1N/A }
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A
1N/A return (NS_LDAP_SUCCESS);
1N/A
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: sortServerNet
1N/A * Sort the serverlist based on the distance from client as long
1N/A * as the list only contains IPv4 addresses. Otherwise do nothing.
1N/A */
1N/Astatic char **
1N/AsortServerNet(char **srvlist)
1N/A{
1N/A int count = 0;
1N/A int all = 0;
1N/A int ipv4only = 1;
1N/A struct ifinfo *ifs = __s_api_get_local_interfaces();
1N/A char **tsrvs;
1N/A char **psrvs, **retsrvs;
1N/A
1N/A /* Sanity check. */
1N/A if (srvlist == NULL || srvlist[0] == NULL)
1N/A return (NULL);
1N/A
1N/A /* Count the number of servers to sort. */
1N/A for (count = 0; srvlist[count] != NULL; count++) {
1N/A if (!__s_api_isipv4(srvlist[count]))
1N/A ipv4only = 0;
1N/A }
1N/A count++;
1N/A
1N/A /* Make room for the returned list of servers. */
1N/A retsrvs = (char **)calloc(count, sizeof (char *));
1N/A if (retsrvs == NULL) {
1N/A free(ifs);
1N/A ifs = NULL;
1N/A return (NULL);
1N/A }
1N/A
1N/A retsrvs[count - 1] = NULL;
1N/A
1N/A /* Make a temporary list of servers. */
1N/A psrvs = (char **)calloc(count, sizeof (char *));
1N/A if (psrvs == NULL) {
1N/A free(ifs);
1N/A ifs = NULL;
1N/A free(retsrvs);
1N/A retsrvs = NULL;
1N/A return (NULL);
1N/A }
1N/A
1N/A /* Filter servers on the same subnet */
1N/A tsrvs = srvlist;
1N/A while (*tsrvs) {
1N/A if (ipv4only && __s_api_IPv4sameNet(*tsrvs, ifs)) {
1N/A psrvs[all] = *tsrvs;
1N/A retsrvs[all++] = *(tsrvs);
1N/A }
1N/A tsrvs++;
1N/A }
1N/A
1N/A /* Filter remaining servers. */
1N/A tsrvs = srvlist;
1N/A while (*tsrvs) {
1N/A char **ttsrvs = psrvs;
1N/A
1N/A while (*ttsrvs) {
1N/A if (strcmp(*tsrvs, *ttsrvs) == 0)
1N/A break;
1N/A ttsrvs++;
1N/A }
1N/A
1N/A if (*ttsrvs == NULL)
1N/A retsrvs[all++] = *(tsrvs);
1N/A tsrvs++;
1N/A }
1N/A
1N/A free(ifs);
1N/A ifs = NULL;
1N/A free(psrvs);
1N/A psrvs = NULL;
1N/A
1N/A return (retsrvs);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: sortServerPref
1N/A * Sort the serverlist based on the preferred server list.
1N/A *
1N/A * The sorting algorithm works as follows:
1N/A *
1N/A * If version 1, if flag is TRUE, find all the servers in both preflist
1N/A * and srvlist, then append other servers in srvlist to this list
1N/A * and return the list.
1N/A * If flag is FALSE, just return srvlist.
1N/A * srvlist can not be empty.
1N/A *
1N/A * If version 2, append all the servers in srvlist
1N/A * but not in preflist to preflist, and return the merged list.
1N/A * If srvlist is empty, just return preflist.
1N/A * If preflist is empty, just return srvlist.
1N/A */
1N/Astatic char **
1N/AsortServerPref(char **srvlist, char **preflist,
1N/A boolean_t flag, int version, int *error)
1N/A{
1N/A int i, scount = 0, pcount = 0;
1N/A int all = 0, dup = 0;
1N/A char **tsrvs;
1N/A char **retsrvs;
1N/A char **dupsrvs;
1N/A
1N/A /* Count the number of servers to sort. */
1N/A if (srvlist && srvlist[0])
1N/A for (i = 0; srvlist[i] != NULL; i++)
1N/A scount++;
1N/A
1N/A /* Sanity check. */
1N/A if (scount == 0 && version == 1) {
1N/A *error = NS_LDAP_CONFIG;
1N/A return (NULL);
1N/A }
1N/A
1N/A /* Count the number of preferred servers */
1N/A if (preflist && preflist[0])
1N/A for (i = 0; preflist[i] != NULL; i++)
1N/A pcount++;
1N/A
1N/A /* Sanity check. */
1N/A if (scount == 0 && pcount == 0) {
1N/A *error = NS_LDAP_CONFIG;
1N/A return (NULL);
1N/A }
1N/A
1N/A /* Make room for the returned list of servers */
1N/A retsrvs = (char **)calloc(scount + pcount + 1, sizeof (char *));
1N/A if (retsrvs == NULL) {
1N/A *error = NS_LDAP_MEMORY;
1N/A return (NULL);
1N/A }
1N/A
1N/A /*
1N/A * if the preferred server list is empty,
1N/A * just return a copy of the server list
1N/A */
1N/A if (pcount == 0) {
1N/A tsrvs = srvlist;
1N/A while (*tsrvs)
1N/A retsrvs[all++] = *(tsrvs++);
1N/A return (retsrvs);
1N/A }
1N/A all = 0;
1N/A
1N/A /*
1N/A * if the server list is empty,
1N/A * just return a copy of the preferred server list
1N/A */
1N/A if (scount == 0) {
1N/A tsrvs = preflist;
1N/A while (*tsrvs)
1N/A retsrvs[all++] = *(tsrvs++);
1N/A return (retsrvs);
1N/A }
1N/A all = 0;
1N/A
1N/A /* Make room for the servers whose memory needs to be freed */
1N/A dupsrvs = (char **)calloc(scount + pcount + 1, sizeof (char *));
1N/A if (dupsrvs == NULL) {
1N/A free(retsrvs);
1N/A *error = NS_LDAP_MEMORY;
1N/A return (NULL);
1N/A }
1N/A
1N/A /*
1N/A * If version 1,
1N/A * throw out preferred servers not on server list.
1N/A * If version 2, make a copy of the preferred server list.
1N/A */
1N/A if (version == 1) {
1N/A tsrvs = preflist;
1N/A while (*tsrvs) {
1N/A char **ttsrvs = srvlist;
1N/A
1N/A while (*ttsrvs) {
1N/A if (strcmp(*tsrvs, *(ttsrvs)) == 0)
1N/A break;
1N/A ttsrvs++;
1N/A }
1N/A if (*ttsrvs != NULL)
1N/A retsrvs[all++] = *tsrvs;
1N/A else
1N/A dupsrvs[dup++] = *tsrvs;
1N/A tsrvs++;
1N/A }
1N/A } else {
1N/A tsrvs = preflist;
1N/A while (*tsrvs)
1N/A retsrvs[all++] = *(tsrvs++);
1N/A }
1N/A /*
1N/A * If version 1,
1N/A * if PREF_ONLY is false, we append the non-preferred servers
1N/A * to bottom of list.
1N/A * For version 2, always append.
1N/A */
1N/A if (flag == B_TRUE || version != 1) {
1N/A
1N/A tsrvs = srvlist;
1N/A while (*tsrvs) {
1N/A char **ttsrvs = preflist;
1N/A
1N/A while (*ttsrvs) {
1N/A if (strcmp(*tsrvs, *ttsrvs) == 0) {
1N/A break;
1N/A }
1N/A ttsrvs++;
1N/A }
1N/A if (*ttsrvs == NULL)
1N/A retsrvs[all++] = *tsrvs;
1N/A else
1N/A dupsrvs[dup++] = *tsrvs;
1N/A tsrvs++;
1N/A }
1N/A }
1N/A
1N/A /* free memory for duplicate servers */
1N/A if (dup) {
1N/A for (tsrvs = dupsrvs; *tsrvs; tsrvs++)
1N/A free(*tsrvs);
1N/A }
1N/A free(dupsrvs);
1N/A
1N/A return (retsrvs);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_removeBadServers
1N/A * Contacts the ldap cache manager for marking the
1N/A * problem servers as down, so that the server is
1N/A * not contacted until the TTL expires.
1N/A */
1N/Avoid
1N/A__s_api_removeBadServers(char ** Servers)
1N/A{
1N/A
1N/A char **host;
1N/A
1N/A if (Servers == NULL)
1N/A return;
1N/A
1N/A for (host = Servers; *host != NULL; host++) {
1N/A if (__s_api_removeServer(*host) < 0) {
1N/A /*
1N/A * Couldn't remove server from
1N/A * server list. Log a warning.
1N/A */
1N/A syslog(LOG_WARNING, "libsldap: could "
1N/A "not remove %s from servers list", *host);
1N/A }
1N/A }
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_free2dArray
1N/A */
1N/Avoid
1N/A__s_api_free2dArray(char ** inarray)
1N/A{
1N/A
1N/A char **temptr;
1N/A
1N/A if (inarray == NULL)
1N/A return;
1N/A
1N/A for (temptr = inarray; *temptr != NULL; temptr++) {
1N/A free(*temptr);
1N/A }
1N/A free(inarray);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_cp2dArray
1N/A */
1N/Achar **
1N/A__s_api_cp2dArray(char **inarray)
1N/A{
1N/A char **newarray;
1N/A char **ttarray, *ret;
1N/A int count;
1N/A
1N/A if (inarray == NULL)
1N/A return (NULL);
1N/A
1N/A for (count = 0; inarray[count] != NULL; count++);
1N/A
1N/A newarray = (char **)calloc(count + 1, sizeof (char *));
1N/A if (newarray == NULL)
1N/A return (NULL);
1N/A
1N/A ttarray = newarray;
1N/A for (; *inarray; inarray++) {
1N/A *(ttarray++) = ret = strdup(*inarray);
1N/A if (ret == NULL) {
1N/A __s_api_free2dArray(newarray);
1N/A return (NULL);
1N/A }
1N/A }
1N/A return (newarray);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_isCtrlSupported
1N/A * Determines if the passed control is supported by the LDAP sever.
1N/A * RETURNS: NS_LDAP_SUCCESS if yes, NS_LDAP_OP_FAIL if not.
1N/A */
1N/Aint
1N/A__s_api_isCtrlSupported(Connection *con, char *ctrlString)
1N/A{
1N/A char **ctrl;
1N/A int len;
1N/A
1N/A len = strlen(ctrlString);
1N/A for (ctrl = con->controls; ctrl && *ctrl; ctrl++) {
1N/A if (strncasecmp(*ctrl, ctrlString, len) == 0)
1N/A return (NS_LDAP_SUCCESS);
1N/A }
1N/A return (NS_LDAP_OP_FAILED);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_toFollowReferrals
1N/A * Determines if need to follow referral for an SLDAP API.
1N/A * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_INVALID_PARAM, or
1N/A * other rc from __ns_ldap_getParam()
1N/A * INPUT: flags
1N/A * OUTPUT: toFollow, errorp
1N/A */
1N/Aint
1N/A__s_api_toFollowReferrals(const int flags,
1N/A int *toFollow,
1N/A ns_ldap_error_t **errorp)
1N/A{
1N/A void **paramVal = NULL;
1N/A int rc = 0;
1N/A int iflags = 0;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__s_api_toFollowReferrals START\n");
1N/A#endif
1N/A
1N/A /* Either NS_LDAP_NOREF or NS_LDAP_FOLLOWREF not both */
1N/A if ((flags & (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) ==
1N/A (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) {
1N/A return (NS_LDAP_INVALID_PARAM);
1N/A }
1N/A
1N/A /*
1N/A * if the NS_LDAP_NOREF or NS_LDAP_FOLLOWREF is set
1N/A * this will take precendence over the values specified
1N/A * in the configuration file
1N/A */
1N/A if (flags & (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) {
1N/A iflags = flags;
1N/A } else {
1N/A rc = __ns_ldap_getParam(NS_LDAP_SEARCH_REF_P,
1N/A &paramVal, errorp);
1N/A if (rc != NS_LDAP_SUCCESS)
1N/A return (rc);
1N/A if (paramVal == NULL || *paramVal == NULL) {
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A if (*errorp)
1N/A (void) __ns_ldap_freeError(errorp);
1N/A *toFollow = TRUE;
1N/A return (NS_LDAP_SUCCESS);
1N/A }
1N/A iflags = (* (int *)(*paramVal));
1N/A (void) __ns_ldap_freeParam(&paramVal);
1N/A }
1N/A
1N/A if (iflags & NS_LDAP_NOREF)
1N/A *toFollow = FALSE;
1N/A else
1N/A *toFollow = TRUE;
1N/A
1N/A return (NS_LDAP_SUCCESS);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_addRefInfo
1N/A * Insert a referral info into a referral info list.
1N/A * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_OP_FAILED
1N/A * INPUT: LDAP URL, pointer to the referral info list,
1N/A * search baseDN, search scope, search filter,
1N/A * previous connection
1N/A */
1N/Aint
1N/A__s_api_addRefInfo(ns_referral_info_t **head, char *url,
1N/A char *baseDN, int *scope,
1N/A char *filter, LDAP *ld)
1N/A{
1N/A char errmsg[MAXERROR], *tmp;
1N/A ns_referral_info_t *ref, *tmpref;
1N/A LDAPURLDesc *ludp = NULL;
1N/A int hostlen;
1N/A char *ld_defhost = NULL;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__s_api_addRefInfo START\n");
1N/A#endif
1N/A
1N/A /* sanity check */
1N/A if (head == NULL)
1N/A return (NS_LDAP_OP_FAILED);
1N/A
1N/A /*
1N/A * log error and return NS_LDAP_SUCCESS
1N/A * if one of the following:
1N/A * 1. non-LDAP URL
1N/A * 2. LDAP URL which can not be parsed
1N/A */
1N/A if (!ldap_is_ldap_url(url) ||
1N/A ldap_url_parse_nodn(url, &ludp) != 0) {
1N/A (void) snprintf(errmsg, MAXERROR, "%s: %s",
1N/A gettext("Invalid or non-LDAP URL when"
1N/A " processing referrals URL"),
1N/A url);
1N/A syslog(LOG_ERR, "libsldap: %s", errmsg);
1N/A if (ludp)
1N/A ldap_free_urldesc(ludp);
1N/A return (NS_LDAP_SUCCESS);
1N/A }
1N/A
1N/A ref = (ns_referral_info_t *)calloc(1,
1N/A sizeof (ns_referral_info_t));
1N/A if (ref == NULL) {
1N/A ldap_free_urldesc(ludp);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A
1N/A /*
1N/A * we do have a valid URL and we were able to parse it
1N/A * however, we still need to find out what hostport to
1N/A * use if none were provided in the LDAP URL
1N/A * (e.g., ldap:///...)
1N/A */
1N/A if ((ludp->lud_port == 0) && (ludp->lud_host == NULL)) {
1N/A if (ld == NULL) {
1N/A (void) snprintf(errmsg, MAXERROR, "%s: %s",
1N/A gettext("no LDAP handle when"
1N/A " processing referrals URL"),
1N/A url);
1N/A syslog(LOG_WARNING, "libsldap: %s", errmsg);
1N/A ldap_free_urldesc(ludp);
1N/A free(ref);
1N/A return (NS_LDAP_SUCCESS);
1N/A } else {
1N/A (void) ldap_get_option(ld, LDAP_OPT_HOST_NAME,
1N/A &ld_defhost);
1N/A if (ld_defhost == NULL) {
1N/A (void) snprintf(errmsg, MAXERROR, "%s: %s",
1N/A gettext("not able to retrieve default "
1N/A "host when processing "
1N/A "referrals URL"),
1N/A url);
1N/A syslog(LOG_WARNING, "libsldap: %s", errmsg);
1N/A ldap_free_urldesc(ludp);
1N/A free(ref);
1N/A return (NS_LDAP_SUCCESS);
1N/A } else {
1N/A ref->refHost = strdup(ld_defhost);
1N/A if (ref->refHost == NULL) {
1N/A ldap_free_urldesc(ludp);
1N/A free(ref);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A }
1N/A }
1N/A } else {
1N/A /*
1N/A * add 4 here:
1N/A * 1 for the last '\0'.
1N/A * 1 for host and prot separator ":"
1N/A * and "[" & "]" for possible ipV6 addressing
1N/A */
1N/A hostlen = strlen(ludp->lud_host) +
1N/A sizeof (MAXPORTNUMBER_STR) + 4;
1N/A ref->refHost = (char *)malloc(hostlen);
1N/A if (ref->refHost == NULL) {
1N/A ldap_free_urldesc(ludp);
1N/A free(ref);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A
1N/A if (ludp->lud_port != 0) {
1N/A /*
1N/A * serverAddr = host:port
1N/A * or
1N/A * if host is an IPV6 address
1N/A * [host]:port
1N/A */
1N/A tmp = strstr(url, ludp->lud_host);
1N/A if (tmp && (tmp > url) && *(tmp - 1) == '[') {
1N/A (void) snprintf(ref->refHost, hostlen,
1N/A "[%s]:%d",
1N/A ludp->lud_host,
1N/A ludp->lud_port);
1N/A } else {
1N/A (void) snprintf(ref->refHost, hostlen,
1N/A "%s:%d",
1N/A ludp->lud_host,
1N/A ludp->lud_port);
1N/A }
1N/A } else {
1N/A /* serverAddr = host */
1N/A (void) snprintf(ref->refHost, hostlen, "%s",
1N/A ludp->lud_host);
1N/A }
1N/A }
1N/A
1N/A if (ludp->lud_dn) {
1N/A ref->refDN = strdup(ludp->lud_dn);
1N/A if (ref->refDN == NULL) {
1N/A ldap_free_urldesc(ludp);
1N/A free(ref->refHost);
1N/A free(ref);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A } else {
1N/A if (baseDN) {
1N/A ref->refDN = strdup(baseDN);
1N/A if (ref->refDN == NULL) {
1N/A ldap_free_urldesc(ludp);
1N/A free(ref->refHost);
1N/A free(ref);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A }
1N/A }
1N/A
1N/A if (filter)
1N/A ref->refFilter = strdup(filter);
1N/A else if (ludp->lud_filter)
1N/A ref->refFilter = strdup(ludp->lud_filter);
1N/A else
1N/A ref->refFilter = strdup("");
1N/A
1N/A if (ref->refFilter == NULL) {
1N/A ldap_free_urldesc(ludp);
1N/A free(ref->refHost);
1N/A if (ref->refDN)
1N/A free(ref->refDN);
1N/A free(ref);
1N/A return (NS_LDAP_MEMORY);
1N/A }
1N/A
1N/A if (scope)
1N/A ref->refScope = *scope;
1N/A
1N/A ref->next = NULL;
1N/A
1N/A ldap_free_urldesc(ludp);
1N/A
1N/A /* insert the referral info */
1N/A if (*head) {
1N/A for (tmpref = *head; tmpref->next;
1N/A tmpref = tmpref->next);
1N/A tmpref->next = ref;
1N/A } else
1N/A *head = ref;
1N/A
1N/A return (NS_LDAP_SUCCESS);
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_deleteRefInfo
1N/A * Delete a referral info list.
1N/A * INPUT: pointer to the referral info list
1N/A */
1N/Avoid
1N/A__s_api_deleteRefInfo(ns_referral_info_t *head)
1N/A{
1N/A ns_referral_info_t *ref, *tmp;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr, "__s_api_deleteRefInfo START\n");
1N/A#endif
1N/A
1N/A for (ref = head; ref; ) {
1N/A if (ref->refHost)
1N/A free(ref->refHost);
1N/A if (ref->refDN)
1N/A free(ref->refDN);
1N/A if (ref->refFilter)
1N/A free(ref->refFilter);
1N/A tmp = ref->next;
1N/A free(ref);
1N/A ref = tmp;
1N/A }
1N/A
1N/A}
1N/A
1N/A/*
1N/A * FUNCTION: __s_api_get_SSD_from_SSDtoUse_service
1N/A *
1N/A * Retrieves the Service Search Descriptors which should be used for
1N/A * the given service. For example, return all the "passwd" SSDs for
1N/A * service "shadow" if no SSD is defined for service "shadow" and
1N/A * no filter component is defined in all the "passwd" SSDs. This idea
1N/A * of sharing the SSDs defined for some other service is to reduce the
1N/A * configuration complexity. For a service, which does not have its own
1N/A * entries in the LDAP directory, SSD for it is useless, and should not
1N/A * be set. But since this service must share the container with at least
1N/A * one other service which does have it own entries, the SSD for
1N/A * this other service will be shared by this service.
1N/A * This other service is called the SSD-to-use service.
1N/A * The static data structure, ns_def_map[], in this file
1N/A * defines the SSD-to-use service for all the services supported.
1N/A *
1N/A * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_INVALID_PARAM
1N/A * INPUT: service
1N/A * OUTPUT: *SSDlist, *errorp if error
1N/A */
1N/Aint
1N/A__s_api_get_SSD_from_SSDtoUse_service(const char *service,
1N/A ns_ldap_search_desc_t ***SSDlist,
1N/A ns_ldap_error_t **errorp)
1N/A{
1N/A int i, rc;
1N/A int found = FALSE;
1N/A int filter_found = FALSE;
1N/A char *SSD_service = NULL;
1N/A char errmsg[MAXERROR];
1N/A ns_ldap_search_desc_t **sdlist;
1N/A int auto_service = FALSE;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stderr,
1N/A "__s_api_get_SSD_from_SSDtoUse_service START\n");
1N/A#endif
1N/A
1N/A if (SSDlist == NULL || errorp == NULL)
1N/A return (NS_LDAP_INVALID_PARAM);
1N/A
1N/A *SSDlist = NULL;
1N/A *errorp = NULL;
1N/A
1N/A if (service == NULL)
1N/A return (NS_LDAP_SUCCESS);
1N/A
1N/A if (strncasecmp(service, "auto_", 5) == 0)
1N/A auto_service = TRUE;
1N/A
1N/A /*
1N/A * First try to return the configured SSDs for the input server
1N/A */
1N/A rc = __ns_ldap_getSearchDescriptors(service, SSDlist, errorp);
1N/A if (rc != NS_LDAP_SUCCESS)
1N/A return (rc);
1N/A else {
1N/A if (*SSDlist != NULL)
1N/A return (NS_LDAP_SUCCESS);
1N/A }
1N/A
1N/A /*
1N/A * If service == auto_* and SSD is not found,
1N/A * then try automount to see if there is an SSD
1N/A * for automount.
1N/A */
1N/A
1N/A if (auto_service) {
1N/A rc = __ns_ldap_getSearchDescriptors(
1N/A "automount", SSDlist, errorp);
1N/A if (rc != NS_LDAP_SUCCESS)
1N/A return (rc);
1N/A else {
1N/A if (*SSDlist != NULL) {
1N/A /*
1N/A * If SSDlist is found,
1N/A * prepend automountMapName to the basedn
1N/A * in the SSDlist
1N/A *
1N/A */
1N/A rc = __s_api_prepend_automountmapname(
1N/A service,
1N/A SSDlist,
1N/A errorp);
1N/A
1N/A if (rc != NS_LDAP_SUCCESS) {
1N/A (void) __ns_ldap_freeSearchDescriptors(
1N/A SSDlist);
1N/A *SSDlist = NULL;
1N/A }
1N/A
1N/A return (rc);
1N/A }
1N/A }
1N/A }
1N/A
1N/A /*
1N/A * Find the SSDtoUse service.
1N/A * If none found, flag "found" remains FALSE.
1N/A */
1N/A for (i = 0; ns_def_map[i].service != NULL; i++) {
1N/A if (ns_def_map[i].SSDtoUse_service &&
1N/A strcasecmp(service,
1N/A ns_def_map[i].service) == 0) {
1N/A found = TRUE;
1N/A SSD_service = ns_def_map[i].SSDtoUse_service;
1N/A break;
1N/A }
1N/A }
1N/A
1N/A if (!found)
1N/A return (NS_LDAP_SUCCESS);
1N/A
1N/A /*
1N/A * return the SSDs for SSD_service only if no optional filter
1N/A * component is defined in the SSDs
1N/A */
1N/A rc = __ns_ldap_getSearchDescriptors(SSD_service,
1N/A SSDlist, errorp);
1N/A if (rc != NS_LDAP_SUCCESS) {
1N/A return (rc);
1N/A } else {
1N/A if (*SSDlist == NULL)
1N/A return (NS_LDAP_SUCCESS);
1N/A
1N/A /* check to see if filter defined in SSD */
1N/A for (sdlist = *SSDlist; *sdlist; sdlist++) {
1N/A if ((*sdlist)->filter &&
1N/A strlen((*sdlist)->filter) > 0) {
1N/A filter_found = TRUE;
1N/A break;
1N/A }
1N/A }
1N/A if (filter_found) {
1N/A (void) __ns_ldap_freeSearchDescriptors(SSDlist);
1N/A *SSDlist = NULL;
1N/A (void) snprintf(errmsg, sizeof (errmsg),
1N/A gettext("Service search descriptor for "
1N/A "service '%s' contains filter, "
1N/A "which can not be used for "
1N/A "service '%s'."),
1N/A SSD_service, service);
1N/A MKERROR(LOG_WARNING, *errorp, NS_CONFIG_FILE,
1N/A strdup(errmsg), NS_LDAP_CONFIG);
1N/A return (NS_LDAP_CONFIG);
1N/A }
1N/A
1N/A }
1N/A return (NS_LDAP_SUCCESS);
1N/A}
1N/A
1N/A
1N/A/*
1N/A * verify addr is an IPv4 address with the optional [:portno]
1N/A * RFC2373 & RFC2732 & RFC2396
1N/A */
1N/Aint
1N/A__s_api_isipv4(char *addr)
1N/A{
1N/A int i, seg, digit, port;
1N/A
1N/A if (!addr)
1N/A return (0);
1N/A
1N/A digit = seg = port = 0;
1N/A
1N/A for (i = 0; i < strlen(addr); i++) {
1N/A if (isdigit(addr[i])) {
1N/A digit++;
1N/A continue;
1N/A }
1N/A if (addr[i] == '.') {
1N/A if (digit > 3 || digit == 0)
1N/A return (0);
1N/A digit = 0;
1N/A seg++;
1N/A continue;
1N/A }
1N/A if (addr[i] == ':') {
1N/A if (digit > 3)
1N/A return (0);
1N/A port++;
1N/A digit = 0;
1N/A seg++;
1N/A continue;
1N/A }
1N/A return (0);
1N/A }
1N/A
1N/A if ((seg == 3 && port == 0 && digit > 0 && digit < 4) ||
1N/A (seg == 4 && port == 1 && digit > 0))
1N/A return (1);
1N/A
1N/A return (0);
1N/A}
1N/A
1N/A
1N/A/*
1N/A * verify addr is an IPv6 address with the optional [IPv6]:portno
1N/A * RFC2373 & RFC2732 & RFC2396
1N/A */
1N/Aint
1N/A__s_api_isipv6(char *addr)
1N/A{
1N/A int i, col, digit, port, dc, tc;
1N/A char *laddr, *c1, *s;
1N/A
1N/A if (!addr)
1N/A return (0);
1N/A
1N/A s = addr;
1N/A laddr = NULL;
1N/A digit = col = port = 0;
1N/A if (addr[0] == '[') {
1N/A laddr = strdup(addr);
1N/A if (!laddr)
1N/A return (0);
1N/A c1 = strchr(laddr, ']');
1N/A /* only 1 ']' should be in an addr */
1N/A if (!c1 || (strchr(c1+1, ']')))
1N/A goto bad;
1N/A switch (c1[1]) {
1N/A case ':':
1N/A port++;
1N/A for (i = 2; i < strlen(c1); i++) {
1N/A if (!isdigit(c1[i]))
1N/A goto bad;
1N/A digit++;
1N/A }
1N/A if (!digit)
1N/A goto bad;
1N/A c1[0] = '\0';
1N/A break;
1N/A case '\0':
1N/A c1[0] = '\0';
1N/A break;
1N/A default:
1N/A goto bad;
1N/A }
1N/A s = &laddr[1];
1N/A }
1N/A
1N/A digit = dc = tc = 0;
1N/A for (i = 0; i < strlen(s); i++) {
1N/A if (isxdigit(s[i])) {
1N/A if (digit == 0)
1N/A dc = i;
1N/A digit++;
1N/A col = 0;
1N/A continue;
1N/A }
1N/A if (s[i] == ':') {
1N/A tc++;
if ((col > 1) || (i && !col && !digit))
goto bad;
digit = 0;
col++;
continue;
}
if (s[i] == '.') {
if (__s_api_isipv4(&s[dc]) && tc)
goto good;
else
goto bad;
}
goto bad;
}
good:
free(laddr);
return (1);
bad:
free(laddr);
return (0);
}
/*
* verify addr is a valid hostname with the optional [:portno]
* RFC2373 & RFC2732 & RFC2396
*/
int
__s_api_ishost(char *addr)
{
int i, seg, alpha, digit, port;
if (!addr)
return (0);
alpha = digit = seg = port = 0;
/* must start with alpha character */
if (!isalpha(addr[0]))
return (0);
for (i = 0; i < strlen(addr); i++) {
if (isalpha(addr[i]) || (i && addr[i] == '-')) {
alpha++;
continue;
}
if (isdigit(addr[i])) {
digit++;
continue;
}
if (addr[i] == '.') {
if (!alpha && !digit)
return (0);
alpha = digit = 0;
seg++;
continue;
}
if (addr[i] == ':') {
if (!alpha && !digit)
return (0);
alpha = digit = 0;
port++;
seg++;
continue;
}
return (0);
}
if ((port == 0 && (seg || alpha || digit)) ||
(port == 1 && alpha == 0 && digit))
return (1);
return (0);
}
/*
* Prepend automountMapName=auto_xxx to the basedn
* in the SSDlist
*/
int __s_api_prepend_automountmapname(
const char *service,
ns_ldap_search_desc_t ***SSDlist,
ns_ldap_error_t **errorp)
{
int i, rc;
ns_ldap_search_desc_t ** ssdlist = NULL;
if (service == NULL || SSDlist == NULL || *SSDlist == NULL)
return (NS_LDAP_INVALID_PARAM);
ssdlist = *SSDlist;
for (i = 0; ssdlist[i] != NULL; i++) {
rc = __s_api_prepend_automountmapname_to_dn(
service, &ssdlist[i]->basedn, errorp);
if (rc != NS_LDAP_SUCCESS)
return (rc);
}
return (NS_LDAP_SUCCESS);
}
/*
* Prepend automountMapName=auto_xxx to the DN
* Construct a string of
* "automountMapName=auto_xxx,dn"
*
* If automountMapName is mapped to some other attribute,
* then use the mapping in the setup.
*
* If a version 1 profile is in use, use nisMapName for
* backward compatibility (i.e. "nisMapName=auto_xxx,dn").
*/
int
__s_api_prepend_automountmapname_to_dn(
const char *service,
char **dn,
ns_ldap_error_t **errorp)
{
int rc, len_s = 0, len_d = 0, len = 0;
char *buffer = NULL;
char *default_automountmapname = "automountMapName";
char *automountmapname = NULL;
char **mappedattrs = NULL;
char errstr[MAXERROR];
void **paramVal = NULL;
if (service == NULL || dn == NULL || *dn == NULL)
return (NS_LDAP_INVALID_PARAM);
rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, errorp);
if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) {
if (paramVal)
(void) __ns_ldap_freeParam(&paramVal);
return (rc);
}
if (strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) {
automountmapname = strdup("nisMapName");
(void) __ns_ldap_freeParam(&paramVal);
if (automountmapname == NULL) {
return (NS_LDAP_MEMORY);
}
} else {
(void) __ns_ldap_freeParam(&paramVal);
/* Find mapped attribute name of auto_xxx first */
mappedattrs = __ns_ldap_getMappedAttributes(
service, default_automountmapname);
/*
* if mapped attribute name of auto_xxx is not found,
* find the mapped attribute name of automount
*/
if (mappedattrs == NULL)
mappedattrs = __ns_ldap_getMappedAttributes(
"automount", default_automountmapname);
/*
* if mapped attr is not found, use the default automountmapname
*/
if (mappedattrs == NULL) {
automountmapname = strdup(default_automountmapname);
if (automountmapname == NULL)
return (NS_LDAP_MEMORY);
} else {
if (mappedattrs[0] != NULL) {
/*
* Copy it from the mapped attr list
* Assume it's 1 to 1 mapping
* 1 to n does not make sense
*/
automountmapname = strdup(mappedattrs[0]);
__s_api_free2dArray(mappedattrs);
if (automountmapname == NULL) {
return (NS_LDAP_MEMORY);
}
} else {
/*
* automountmapname is mapped to an empty string
*/
__s_api_free2dArray(mappedattrs);
(void) sprintf(errstr,
gettext(
"Attribute automountMapName is "
"mapped to an empty string.\n"));
MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX,
strdup(errstr), NULL);
return (NS_LDAP_CONFIG);
}
}
}
len_s = strlen(service);
len_d = strlen(*dn);
/* automountMapName + "=" + service + "," + dn + '\0' */
len = strlen(automountmapname) + 1 + len_s + 1 + len_d + 1;
buffer = (char *)malloc(len);
if (buffer == NULL) {
free(automountmapname);
return (NS_LDAP_MEMORY);
}
(void) snprintf(buffer, len, "%s=%s,%s",
automountmapname, service, *dn);
buffer[len-1] = '\0';
free(automountmapname);
/* free the original dn */
(void) free(*dn);
*dn = buffer;
return (NS_LDAP_SUCCESS);
}
/*
* Map the LDAP error code and error message from LDAP server
* to a password status used for password aging/management.
*/
ns_ldap_passwd_status_t
__s_api_set_passwd_status(int errnum, char *errmsg)
{
if (errmsg) {
if (errnum ==
LDAP_INVALID_CREDENTIALS) {
/*
* case 1 (Bind):
* password expired
*/
if (strstr(errmsg,
NS_PWDERR_EXPIRED))
return (NS_PASSWD_EXPIRED);
}
if (errnum ==
LDAP_UNWILLING_TO_PERFORM) {
/*
* case 1.1 (Bind):
* password expired
*/
if (strstr(errmsg,
NS_PWDERR_EXPIRED))
return (NS_PASSWD_EXPIRED);
/*
* case 2 (Bind):
* Account inactivated
*/
if (strstr(errmsg,
NS_PWDERR_ACCT_INACTIVATED))
return (NS_PASSWD_EXPIRED);
/*
* case 3 (Modify passwd):
* the user is not allow to change
* password; only admin can change it
*/
if (strstr(errmsg,
NS_PWDERR_CHANGE_NOT_ALLOW))
return (NS_PASSWD_CHANGE_NOT_ALLOWED);
}
if (errnum ==
LDAP_CONSTRAINT_VIOLATION) {
/*
* case 4 (Bind):
* the user account is locked due to
* too many login failures.
*/
if (strstr(errmsg,
NS_PWDERR_MAXTRIES))
return (NS_PASSWD_RETRY_EXCEEDED);
/*
* case 5 (Modify passwd):
* syntax error: the new password
* has length less than defined
* minimum
*/
if (strstr(errmsg,
NS_PWDERR_INVALID_SYNTAX))
return (NS_PASSWD_TOO_SHORT);
/*
* case 6 (Modify passwd):
* trivial password: same valule as
* that of attribute cn, sn, or uid ...
*/
if (strstr(errmsg,
NS_PWDERR_TRIVIAL_PASSWD))
return (NS_PASSWD_INVALID_SYNTAX);
/*
* case 7 (Modify passwd):
* re-use one of the old passwords
* in history list
*/
if (strstr(errmsg,
NS_PWDERR_IN_HISTORY))
return (NS_PASSWD_IN_HISTORY);
/*
* case 8 (Modify passwd):
* password not allowed to be
* changed yet; within minimum
* age
*/
if (strstr(errmsg,
NS_PWDERR_WITHIN_MIN_AGE))
return (NS_PASSWD_WITHIN_MIN_AGE);
}
}
return (NS_PASSWD_GOOD);
}
/*
* Determine if the input OID list contains
* one of the password control OIDs, which are:
* LDAP_CONTROL_PWEXPIRED: 2.16.840.1.113730.3.4.4
* LDAP_CONTROL_PWEXPIRING: 2.16.840.1.113730.3.4.5.
* If yes, return 1, if no, 0.
*/
int
__s_api_contain_passwd_control_oid(char **oids)
{
char **oid;
if (oids == NULL)
return (0);
for (oid = oids; *oid; oid++) {
if (strcmp(*oid, LDAP_CONTROL_PWEXPIRED) == 0 ||
strcmp(*oid, LDAP_CONTROL_PWEXPIRING) == 0) {
return (1);
}
}
return (0);
}
/*
* Determine if the input OID list contains LDAP V3 password less
* account management control OID, which is:
* NS_LDAP_ACCOUNT_USABLE_CONTROL:1.3.6.1.4.1.42.2.27.9.5.8
* If yes, return 1, if no, 0.
*/
int
__s_api_contain_account_usable_control_oid(char **oids)
{
char **oid;
if (oids == NULL)
return (0);
for (oid = oids; *oid; oid++) {
if (strcmp(*oid, NS_LDAP_ACCOUNT_USABLE_CONTROL) == 0) {
return (1);
}
}
return (0);
}
/*
* For some databases in name switch, the name and aliases are saved
* as "cn". When the "cn" valuse are retrieved, there is no distinction
* which is the name and which is(are) aliase(s).
* This function is to parse RDN and find the value of the "cn" and
* then find the matching value in "cn" attribute.
* Also see RFC 2307 section 5.6.
*
* Input -
* entry: An LDAP entry
* attrptr: A attribute which value appears in RDN
* This should be "cn" for the name switch for now.
* case_ignore: 0 Case sensitive comparison on the attribute value
* 1 Case insensitive comparison
*
* Return -
* The value of an attrbute which is used as canonical name
* This is read only and the caller should not try to free it.
* If it's a NULL, it could be either an RDN parsing error
* or RDN value does not match any existing "cn" values.
* e.g.
* dn: cn=xx+ipserviceprotocol=udp,......
* cn: aa
* cn: bb
*
* Note:
* Although the name switch/ldap's rdn is in "cn=xx" or "cn=xx+..."
* format, this function makes no such assumption. If the DN
* is saved as "dn: yy=...+sn=my_canocical_name, ..", then it can still work.
* The comments use "cn" as an example only.
*
*/
typedef int (*cmpfunc)(const char *, const char *);
char *
__s_api_get_canonical_name(ns_ldap_entry_t *entry, ns_ldap_attr_t *attrptr,
int case_ignore) {
uint_t i;
char *token, *lasts, *value = NULL;
char **rdn = NULL, **attrs = NULL, **values = NULL;
char *rdn_attr_value = NULL;
cmpfunc cmp;
if (entry == NULL || attrptr == NULL)
return (NULL);
/* "values" is read-only */
if ((values = __ns_ldap_getAttr(entry, "dn")) == NULL ||
values[0] == NULL)
return (NULL);
if ((rdn = ldap_explode_dn(values[0], 0)) == NULL ||
rdn[0] == NULL)
return (NULL);
if ((attrs = ldap_explode_rdn(rdn[0], 0)) == NULL) {
ldap_value_free(rdn);
return (NULL);
}
/* Assume the rdn is normalized */
for (i = 0; attrs[i] != NULL; i++) {
/* parse attribute name and value, get attribute name first */
if ((token = strtok_r(attrs[i], "=", &lasts)) == NULL) {
goto cleanup;
}
if (strcasecmp(token, attrptr->attrname) == 0) {
/* get value */
rdn_attr_value = lasts;
break;
}
}
if (rdn_attr_value) {
if (case_ignore)
cmp = strcasecmp;
else
cmp = strcmp;
/*
* After parsing RDN and find the matching attribute in RDN,
* match rdn value with values in "cn".
*/
for (i = 0; i < attrptr->value_count; i++) {
if (attrptr->attrvalue[i] &&
(*cmp)(rdn_attr_value,
attrptr->attrvalue[i]) == 0) {
/* RDN "cn" value matches the "cn" value */
value = attrptr->attrvalue[i];
break;
}
}
}
cleanup:
ldap_value_free(rdn);
ldap_value_free(attrs);
return (value);
}
/*
* This function requests a server to be removed from
* the cache manager maintained server list. This is
* done via the door functionality.
* Returns 0 if OK, else a negative value.
*/
int
__s_api_removeServer(const char *server)
{
union {
ldap_data_t s_d;
char s_b[DOORBUFFERSIZE];
} space;
ns_server_info_t r, *ret = &r;
const char *ireq;
ldap_data_t *sptr;
int ndata;
int adata;
int len;
int rc;
if (server == NULL)
return (-1);
ireq = NS_CACHE_NORESP;
(void) memset(ret, 0, sizeof (ns_server_info_t));
(void) memset(space.s_b, 0, DOORBUFFERSIZE);
adata = (sizeof (ldap_call_t) + strlen(ireq) +1);
adata += strlen(DOORLINESEP) + 1;
adata += strlen(server) + 1;
ndata = sizeof (space);
space.s_d.ldap_call.ldap_callnumber = GETLDAPSERVER;
len = sizeof (space) - sizeof (space.s_d.ldap_call.ldap_callnumber);
(void) strlcpy(space.s_d.ldap_call.ldap_u.domainname, ireq, len);
(void) strlcat(space.s_d.ldap_call.ldap_u.domainname, DOORLINESEP, len);
(void) strlcat(space.s_d.ldap_call.ldap_u.domainname, server, len);
sptr = &space.s_d;
/* try to remove the server via the door interface */
rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
/* clean up the door call */
if (sptr != &space.s_d) {
(void) munmap((char *)sptr, ndata);
}
return (rc);
}