xref: /titanic_44/usr/src/lib/libnisdb/ldap_map.c (revision 36e852a172cba914383d7341c988128b2c667fbd)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*36e852a1SRaja Andra  * Common Development and Distribution License (the "License").
6*36e852a1SRaja Andra  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*36e852a1SRaja Andra  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <strings.h>
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <sys/stat.h>
297c478bd9Sstevel@tonic-gate #include <errno.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
327c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include "ldap_util.h"
357c478bd9Sstevel@tonic-gate #include "ldap_attr.h"
367c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h"
377c478bd9Sstevel@tonic-gate #include "ldap_op.h"
387c478bd9Sstevel@tonic-gate #include "ldap_map.h"
397c478bd9Sstevel@tonic-gate #include "ldap_glob.h"
407c478bd9Sstevel@tonic-gate #include "ldap_xdr.h"
417c478bd9Sstevel@tonic-gate #include "ldap_val.h"
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /* From yptol/dit_access_utils.h */
447c478bd9Sstevel@tonic-gate #define	N2LKEY		"rf_key"
457c478bd9Sstevel@tonic-gate #define	N2LIPKEY	"rf_ipkey"
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate __nis_hash_table_mt	ldapMappingList = NIS_HASH_TABLE_MT_INIT;
487c478bd9Sstevel@tonic-gate extern	int yp2ldap;
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate int
setColumnNames(__nis_table_mapping_t * t)527c478bd9Sstevel@tonic-gate setColumnNames(__nis_table_mapping_t *t) {
53*36e852a1SRaja Andra 	int	i, j, nic, noc;
547c478bd9Sstevel@tonic-gate 	char	**col;
557c478bd9Sstevel@tonic-gate 	zotypes	type;
567c478bd9Sstevel@tonic-gate 	char	*myself = "setColumnNames";
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	if (t == 0)
597c478bd9Sstevel@tonic-gate 		return (0);
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 	type = t->objType;
627c478bd9Sstevel@tonic-gate 	col = t->column;
637c478bd9Sstevel@tonic-gate 	nic = (col != 0) ? t->numColumns : -1;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	t->objType = NIS_BOGUS_OBJ;
667c478bd9Sstevel@tonic-gate 	t->obj = 0;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	/*
697c478bd9Sstevel@tonic-gate 	 * If it's a table object, but there are no translation rules,
707c478bd9Sstevel@tonic-gate 	 * this mapping is for the table object itself. In that case,
717c478bd9Sstevel@tonic-gate 	 * we throw away the column names (if any).
727c478bd9Sstevel@tonic-gate 	 */
737c478bd9Sstevel@tonic-gate 	if (t->objType == NIS_TABLE_OBJ && t->numRulesFromLDAP == 0 &&
747c478bd9Sstevel@tonic-gate 			t->numRulesToLDAP == 0) {
757c478bd9Sstevel@tonic-gate 		for (i = 0; i < t->numColumns; i++)
767c478bd9Sstevel@tonic-gate 			sfree(t->column[i]);
777c478bd9Sstevel@tonic-gate 		sfree(t->column);
787c478bd9Sstevel@tonic-gate 		t->column = 0;
797c478bd9Sstevel@tonic-gate 		t->numColumns = 0;
807c478bd9Sstevel@tonic-gate 		noc = 0;
817c478bd9Sstevel@tonic-gate 	}
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	/*
847c478bd9Sstevel@tonic-gate 	 * Verify that all column names found by the parser
857c478bd9Sstevel@tonic-gate 	 * are present in the actual column list.
867c478bd9Sstevel@tonic-gate 	 */
877c478bd9Sstevel@tonic-gate 	if (verbose) {
887c478bd9Sstevel@tonic-gate 		for (i = 0, noc = 0; i < nic; i++) {
897c478bd9Sstevel@tonic-gate 			int	found = 0;
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 			if (col[i] == 0)
927c478bd9Sstevel@tonic-gate 				continue;
937c478bd9Sstevel@tonic-gate 			/* Skip the 'zo_*' special column names */
947c478bd9Sstevel@tonic-gate 			if (isObjAttrString(col[i]))
957c478bd9Sstevel@tonic-gate 				continue;
967c478bd9Sstevel@tonic-gate 			for (j = 0; j < t->numColumns; j++) {
977c478bd9Sstevel@tonic-gate 				if (strcmp(col[i], t->column[j]) == 0) {
987c478bd9Sstevel@tonic-gate 					noc++;
997c478bd9Sstevel@tonic-gate 					found = 1;
1007c478bd9Sstevel@tonic-gate 					break;
1017c478bd9Sstevel@tonic-gate 				}
1027c478bd9Sstevel@tonic-gate 			}
1037c478bd9Sstevel@tonic-gate 			if (!found) {
1047c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1057c478bd9Sstevel@tonic-gate 					"%s: No column \"%s\" in \"%s\"",
1067c478bd9Sstevel@tonic-gate 					myself, NIL(col[i]), NIL(t->objName));
1077c478bd9Sstevel@tonic-gate 			}
1087c478bd9Sstevel@tonic-gate 		}
1097c478bd9Sstevel@tonic-gate 	}
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	/* Remove any setup by the parser */
1127c478bd9Sstevel@tonic-gate 	for (i = 0; i < nic; i++) {
1137c478bd9Sstevel@tonic-gate 		sfree(col[i]);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 	sfree(col);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	return (0);
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate void
freeSingleObjAttr(__nis_obj_attr_t * attr)1217c478bd9Sstevel@tonic-gate freeSingleObjAttr(__nis_obj_attr_t *attr) {
1227c478bd9Sstevel@tonic-gate 	if (attr == 0)
1237c478bd9Sstevel@tonic-gate 		return;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	sfree(attr->zo_owner);
1267c478bd9Sstevel@tonic-gate 	sfree(attr->zo_group);
1277c478bd9Sstevel@tonic-gate 	sfree(attr->zo_domain);
1287c478bd9Sstevel@tonic-gate 	sfree(attr);
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate void
freeObjAttr(__nis_obj_attr_t ** attr,int numAttr)1327c478bd9Sstevel@tonic-gate freeObjAttr(__nis_obj_attr_t **attr, int numAttr) {
1337c478bd9Sstevel@tonic-gate 	int	i;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	if (attr == 0)
1367c478bd9Sstevel@tonic-gate 		return;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	for (i = 0; i < numAttr; i++) {
1397c478bd9Sstevel@tonic-gate 		freeSingleObjAttr(attr[i]);
1407c478bd9Sstevel@tonic-gate 	}
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	sfree(attr);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate __nis_obj_attr_t *
cloneObjAttr(__nis_obj_attr_t * old)1467c478bd9Sstevel@tonic-gate cloneObjAttr(__nis_obj_attr_t *old) {
1477c478bd9Sstevel@tonic-gate 	__nis_obj_attr_t	*new;
1487c478bd9Sstevel@tonic-gate 	char			*myself = "cloneObjAttr";
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if (old == 0)
1517c478bd9Sstevel@tonic-gate 		return (0);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	new = am(myself, sizeof (*new));
1547c478bd9Sstevel@tonic-gate 	if (new == 0)
1557c478bd9Sstevel@tonic-gate 		return (0);
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	new->zo_owner = sdup(myself, T, old->zo_owner);
1587c478bd9Sstevel@tonic-gate 	if (new->zo_owner == 0 && old->zo_owner != 0)
1597c478bd9Sstevel@tonic-gate 		goto cleanup;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	new->zo_group = sdup(myself, T, old->zo_group);
1627c478bd9Sstevel@tonic-gate 	if (new->zo_group == 0 && old->zo_group != 0)
1637c478bd9Sstevel@tonic-gate 		goto cleanup;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	new->zo_domain = sdup(myself, T, old->zo_domain);
1667c478bd9Sstevel@tonic-gate 	if (new->zo_domain == 0 && old->zo_domain != 0)
1677c478bd9Sstevel@tonic-gate 		goto cleanup;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	new->zo_access = old->zo_access;
1707c478bd9Sstevel@tonic-gate 	new->zo_ttl = old->zo_ttl;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	return (new);
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate cleanup:
1757c478bd9Sstevel@tonic-gate 	freeSingleObjAttr(new);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	return (0);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate  * Obtain NIS+ entries (in the form of db_query's) from the supplied table
1837c478bd9Sstevel@tonic-gate  * mapping and db_query.
1847c478bd9Sstevel@tonic-gate  *
1857c478bd9Sstevel@tonic-gate  * If 'qin' is NULL, enumeration is desired.
1867c478bd9Sstevel@tonic-gate  *
1877c478bd9Sstevel@tonic-gate  * On exit, '*numQueries' contains the number of (db_query *)'s in the
1887c478bd9Sstevel@tonic-gate  * return array, '*ldapStat' the LDAP operation status, and '*objAttr'
1897c478bd9Sstevel@tonic-gate  * a pointer to an array (of '*numQueries elements) of object attributes
1907c478bd9Sstevel@tonic-gate  * (zo_owner, etc.). If no object attributes were retrieved, '*objAttr'
1917c478bd9Sstevel@tonic-gate  * is NULL; any and all of the (*objAttr)[i]'s may be NULL.
1927c478bd9Sstevel@tonic-gate  */
1937c478bd9Sstevel@tonic-gate db_query **
mapFromLDAP(__nis_table_mapping_t * t,db_query * qin,int * numQueries,char * dbId,int * ldapStat,__nis_obj_attr_t *** objAttr)1947c478bd9Sstevel@tonic-gate mapFromLDAP(__nis_table_mapping_t *t, db_query *qin, int *numQueries,
1957c478bd9Sstevel@tonic-gate 		char *dbId, int *ldapStat, __nis_obj_attr_t ***objAttr) {
1967c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	**tp;
1977c478bd9Sstevel@tonic-gate 	db_query		**q;
1987c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
1997c478bd9Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
2007c478bd9Sstevel@tonic-gate 	int			n, numVals, numMatches = 0;
2017c478bd9Sstevel@tonic-gate 	int			stat;
2027c478bd9Sstevel@tonic-gate 	__nis_obj_attr_t	**attr;
2037c478bd9Sstevel@tonic-gate 	char			*myself = "mapFromLDAP";
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	if (ldapStat == 0)
2067c478bd9Sstevel@tonic-gate 		ldapStat = &stat;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	if (t == 0 || numQueries == 0) {
2097c478bd9Sstevel@tonic-gate 		*ldapStat = LDAP_PARAM_ERROR;
2107c478bd9Sstevel@tonic-gate 		return (0);
2117c478bd9Sstevel@tonic-gate 	}
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	/* Select the correct table mapping(s) */
2147c478bd9Sstevel@tonic-gate 	tp = selectTableMapping(t, qin, 0, 0, dbId, &numMatches);
2157c478bd9Sstevel@tonic-gate 	if (tp == 0 || numMatches <= 0) {
2167c478bd9Sstevel@tonic-gate 		/*
2177c478bd9Sstevel@tonic-gate 		 * Not really an error; just no matching mapping
2187c478bd9Sstevel@tonic-gate 		 * for the query.
2197c478bd9Sstevel@tonic-gate 		 */
2207c478bd9Sstevel@tonic-gate 		*ldapStat = LDAP_SUCCESS;
2217c478bd9Sstevel@tonic-gate 		return (0);
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	q = 0;
2257c478bd9Sstevel@tonic-gate 	attr = 0;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/* For each mapping */
2287c478bd9Sstevel@tonic-gate 	for (numVals = 0, n = 0; n < numMatches; n++) {
2297c478bd9Sstevel@tonic-gate 		db_query		**qt;
2307c478bd9Sstevel@tonic-gate 		int			i, nqt = 0, filterOnQin, res = 0;
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 		t = tp[n];
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 		if (qin != 0) {
2357c478bd9Sstevel@tonic-gate 			rv = buildNisPlusRuleValue(t, qin, 0);
2367c478bd9Sstevel@tonic-gate 			if (rv != 0) {
2377c478bd9Sstevel@tonic-gate 				/*
2387c478bd9Sstevel@tonic-gate 				 * Depending on the value of res, we shall
2397c478bd9Sstevel@tonic-gate 				 * proceed to next table mapping.
2407c478bd9Sstevel@tonic-gate 				 */
2417c478bd9Sstevel@tonic-gate 				ls = createLdapRequest(t, rv, 0, 1, &res, NULL);
2427c478bd9Sstevel@tonic-gate 			}
2437c478bd9Sstevel@tonic-gate 			else
2447c478bd9Sstevel@tonic-gate 				ls = 0;
2457c478bd9Sstevel@tonic-gate 		} else {
2467c478bd9Sstevel@tonic-gate 			/* Build enumeration request */
2477c478bd9Sstevel@tonic-gate 			rv = 0;
2487c478bd9Sstevel@tonic-gate 			ls = createLdapRequest(t, 0, 0, 1, NULL, NULL);
2497c478bd9Sstevel@tonic-gate 		}
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, 1);
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 		if (ls == 0) {
2547c478bd9Sstevel@tonic-gate 			/*
2557c478bd9Sstevel@tonic-gate 			 * if the res is NP_LDAP_RULES_NO_VALUE, that means we
2567c478bd9Sstevel@tonic-gate 			 * have enough NIS+ columns for the rules to produce
2577c478bd9Sstevel@tonic-gate 			 * values, but none of them did, so continue to the
2587c478bd9Sstevel@tonic-gate 			 * next table mapping. Otherwise do cleanup and return
2597c478bd9Sstevel@tonic-gate 			 * error.
2607c478bd9Sstevel@tonic-gate 			 */
2617c478bd9Sstevel@tonic-gate 			if (res == NP_LDAP_RULES_NO_VALUE)
2627c478bd9Sstevel@tonic-gate 				continue;
2637c478bd9Sstevel@tonic-gate 			for (i = 0; i < numVals; i++)
2647c478bd9Sstevel@tonic-gate 				freeQuery(q[i]);
2657c478bd9Sstevel@tonic-gate 			sfree(q);
2667c478bd9Sstevel@tonic-gate 			free(tp);
2677c478bd9Sstevel@tonic-gate 			*ldapStat = LDAP_OPERATIONS_ERROR;
2687c478bd9Sstevel@tonic-gate 			return (0);
2697c478bd9Sstevel@tonic-gate 		}
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 		/* Query LDAP */
2727c478bd9Sstevel@tonic-gate 		nqt = (ls->isDN || qin != 0) ? 0 : -1;
2737c478bd9Sstevel@tonic-gate 		rv = ldapSearch(ls, &nqt, 0, ldapStat);
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 		/*
2767c478bd9Sstevel@tonic-gate 		 * If qin != 0, then we need to make sure that the
2777c478bd9Sstevel@tonic-gate 		 * LDAP search is filtered so that only entries that
2787c478bd9Sstevel@tonic-gate 		 * are compatible with 'qin' are retained. This will
2797c478bd9Sstevel@tonic-gate 		 * happen automatically if we do a DN search (in which
2807c478bd9Sstevel@tonic-gate 		 * case, no need to filter on 'qin').
2817c478bd9Sstevel@tonic-gate 		 */
2827c478bd9Sstevel@tonic-gate 		if (ls->isDN || qin == 0)
2837c478bd9Sstevel@tonic-gate 			filterOnQin = 0;
2847c478bd9Sstevel@tonic-gate 		else
2857c478bd9Sstevel@tonic-gate 			filterOnQin = 1;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 		freeLdapSearch(ls);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 		/* Convert rule-values to db_query's */
2907c478bd9Sstevel@tonic-gate 		if (rv != 0 && nqt > 0) {
2917c478bd9Sstevel@tonic-gate 			int			nrv = nqt;
2927c478bd9Sstevel@tonic-gate 			__nis_obj_attr_t	**at = 0;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 			qt = ruleValue2Query(t, rv,
2957c478bd9Sstevel@tonic-gate 				(filterOnQin) ? qin : 0, &at, &nqt);
2967c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, nrv);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 			if (qt != 0 && q == 0) {
2997c478bd9Sstevel@tonic-gate 				q = qt;
3007c478bd9Sstevel@tonic-gate 				attr = at;
3017c478bd9Sstevel@tonic-gate 				numVals = nqt;
3027c478bd9Sstevel@tonic-gate 			} else if (qt != 0) {
3037c478bd9Sstevel@tonic-gate 				db_query		**tmp;
3047c478bd9Sstevel@tonic-gate 				__nis_obj_attr_t	**atmp;
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 				/* Extend the 'q' array */
3077c478bd9Sstevel@tonic-gate 				tmp = realloc(q,
3087c478bd9Sstevel@tonic-gate 					(numVals+nqt) * sizeof (q[0]));
3097c478bd9Sstevel@tonic-gate 				/* ... and the 'attr' array */
3107c478bd9Sstevel@tonic-gate 				atmp = realloc(attr,
3117c478bd9Sstevel@tonic-gate 					(numVals+nqt) * sizeof (attr[0]));
3127c478bd9Sstevel@tonic-gate 				if (tmp == 0 || atmp == 0) {
3137c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOMEM, LOG_ERR,
3147c478bd9Sstevel@tonic-gate 						"%s: realloc(%d) => NULL",
3157c478bd9Sstevel@tonic-gate 						myself,
3167c478bd9Sstevel@tonic-gate 						(numVals+nqt) * sizeof (q[0]));
3177c478bd9Sstevel@tonic-gate 					for (i = 0; i < numVals; i++)
3187c478bd9Sstevel@tonic-gate 						freeQuery(q[i]);
3197c478bd9Sstevel@tonic-gate 					for (i = 0; i < nqt; i++)
3207c478bd9Sstevel@tonic-gate 						freeQuery(qt[i]);
3217c478bd9Sstevel@tonic-gate 					sfree(tmp);
3227c478bd9Sstevel@tonic-gate 					sfree(atmp);
3237c478bd9Sstevel@tonic-gate 					sfree(q);
3247c478bd9Sstevel@tonic-gate 					sfree(qt);
3257c478bd9Sstevel@tonic-gate 					sfree(tp);
3267c478bd9Sstevel@tonic-gate 					freeObjAttr(at, nqt);
3277c478bd9Sstevel@tonic-gate 					freeObjAttr(attr, numVals);
3287c478bd9Sstevel@tonic-gate 					*ldapStat = LDAP_NO_MEMORY;
3297c478bd9Sstevel@tonic-gate 					return (0);
3307c478bd9Sstevel@tonic-gate 				}
3317c478bd9Sstevel@tonic-gate 				q = tmp;
3327c478bd9Sstevel@tonic-gate 				attr = atmp;
3337c478bd9Sstevel@tonic-gate 				/* Add the results for this 't' */
3347c478bd9Sstevel@tonic-gate 				(void) memcpy(&q[numVals], qt,
3357c478bd9Sstevel@tonic-gate 						nqt * sizeof (qt[0]));
3367c478bd9Sstevel@tonic-gate 				(void) memcpy(&attr[numVals], at,
3377c478bd9Sstevel@tonic-gate 						nqt * sizeof (at[0]));
3387c478bd9Sstevel@tonic-gate 				numVals += nqt;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 				sfree(qt);
3417c478bd9Sstevel@tonic-gate 				sfree(at);
3427c478bd9Sstevel@tonic-gate 			}
3437c478bd9Sstevel@tonic-gate 		}
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	*numQueries = numVals;
3477c478bd9Sstevel@tonic-gate 	if (objAttr != 0)
3487c478bd9Sstevel@tonic-gate 		*objAttr = attr;
3497c478bd9Sstevel@tonic-gate 	else
3507c478bd9Sstevel@tonic-gate 		freeObjAttr(attr, numVals);
3517c478bd9Sstevel@tonic-gate 	sfree(tp);
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	return (q);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate /*
3577c478bd9Sstevel@tonic-gate  * Add the object attributes (zo_owner, etc.) to the rule-value 'rv'.
3587c478bd9Sstevel@tonic-gate  * Returns a pointer to the (possibly newly allocated) rule-value,
3597c478bd9Sstevel@tonic-gate  * or NULL in case of failure. If not returning 'rvIn', the latter
3607c478bd9Sstevel@tonic-gate  * will have been freed.
3617c478bd9Sstevel@tonic-gate  */
3627c478bd9Sstevel@tonic-gate __nis_rule_value_t *
addObjAttr2RuleValue(nis_object * obj,__nis_rule_value_t * rvIn)3637c478bd9Sstevel@tonic-gate addObjAttr2RuleValue(nis_object *obj, __nis_rule_value_t *rvIn) {
3647c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
3657c478bd9Sstevel@tonic-gate 	char			abuf[2 * sizeof (obj->zo_access) + 1];
3667c478bd9Sstevel@tonic-gate 	char			tbuf[2 * sizeof (obj->zo_ttl) + 1];
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (obj == 0)
3697c478bd9Sstevel@tonic-gate 		return (0);
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	if (rvIn != 0) {
3727c478bd9Sstevel@tonic-gate 		rv = rvIn;
3737c478bd9Sstevel@tonic-gate 	} else {
3747c478bd9Sstevel@tonic-gate 		rv = initRuleValue(1, 0);
3757c478bd9Sstevel@tonic-gate 		if (rv == 0)
3767c478bd9Sstevel@tonic-gate 			return (0);
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if (obj->zo_owner != 0) {
3807c478bd9Sstevel@tonic-gate 		if (addSCol2RuleValue("zo_owner", obj->zo_owner, rv) != 0) {
3817c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, 1);
3827c478bd9Sstevel@tonic-gate 			return (0);
3837c478bd9Sstevel@tonic-gate 		}
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	if (obj->zo_group != 0) {
3877c478bd9Sstevel@tonic-gate 		if (addSCol2RuleValue("zo_group", obj->zo_group, rv) != 0) {
3887c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, 1);
3897c478bd9Sstevel@tonic-gate 			return (0);
3907c478bd9Sstevel@tonic-gate 		}
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	if (obj->zo_domain != 0) {
3947c478bd9Sstevel@tonic-gate 		if (addSCol2RuleValue("zo_domain", obj->zo_domain, rv) != 0) {
3957c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, 1);
3967c478bd9Sstevel@tonic-gate 			return (0);
3977c478bd9Sstevel@tonic-gate 		}
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	(void) memset(abuf, 0, sizeof (abuf));
4017c478bd9Sstevel@tonic-gate 	(void) memset(tbuf, 0, sizeof (tbuf));
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	sprintf(abuf, "%x", obj->zo_access);
4047c478bd9Sstevel@tonic-gate 	sprintf(tbuf, "%x", obj->zo_ttl);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	if (addSCol2RuleValue("zo_access", abuf, rv) != 0) {
4077c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, 1);
4087c478bd9Sstevel@tonic-gate 		return (0);
4097c478bd9Sstevel@tonic-gate 	}
4107c478bd9Sstevel@tonic-gate 	if (addSCol2RuleValue("zo_ttl", tbuf, rv) != 0) {
4117c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, 1);
4127c478bd9Sstevel@tonic-gate 		return (0);
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	return (rv);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate /*
4197c478bd9Sstevel@tonic-gate  * Returns a pointer to (NOT a copy of) the value for the specified
4207c478bd9Sstevel@tonic-gate  * column 'col' in the rule-value 'rv'.
4217c478bd9Sstevel@tonic-gate  */
4227c478bd9Sstevel@tonic-gate __nis_value_t *
findColValue(char * col,__nis_rule_value_t * rv)4237c478bd9Sstevel@tonic-gate findColValue(char *col, __nis_rule_value_t *rv) {
4247c478bd9Sstevel@tonic-gate 	int		i;
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	if (col == 0 || rv == 0 || rv->numColumns <= 0)
4277c478bd9Sstevel@tonic-gate 		return (0);
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	for (i = 0; i < rv->numColumns; i++) {
4307c478bd9Sstevel@tonic-gate 		if (strcmp(col, rv->colName[i]) == 0)
4317c478bd9Sstevel@tonic-gate 			return (&rv->colVal[i]);
4327c478bd9Sstevel@tonic-gate 	}
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	return (0);
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate /*
4387c478bd9Sstevel@tonic-gate  * Return the NIS+ object attributes (if any) in the rule-value 'rv'.
4397c478bd9Sstevel@tonic-gate  */
4407c478bd9Sstevel@tonic-gate __nis_obj_attr_t *
ruleValue2ObjAttr(__nis_rule_value_t * rv)4417c478bd9Sstevel@tonic-gate ruleValue2ObjAttr(__nis_rule_value_t *rv) {
4427c478bd9Sstevel@tonic-gate 	__nis_obj_attr_t	*attr;
4437c478bd9Sstevel@tonic-gate 	__nis_value_t		*val;
4447c478bd9Sstevel@tonic-gate 	char			*myself = "ruleValue2ObjAttr";
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if (rv == 0 || rv->numColumns <= 0)
4477c478bd9Sstevel@tonic-gate 		return (0);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	attr = am(myself, sizeof (*attr));
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	if ((val = findColValue("zo_owner", rv)) != 0 &&
4527c478bd9Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4537c478bd9Sstevel@tonic-gate 			val->val[0].value != 0) {
4547c478bd9Sstevel@tonic-gate 		attr->zo_owner = sdup(myself, T, val->val[0].value);
4557c478bd9Sstevel@tonic-gate 		if (attr->zo_owner == 0) {
4567c478bd9Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4577c478bd9Sstevel@tonic-gate 			return (0);
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 	}
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	if ((val = findColValue("zo_group", rv)) != 0 &&
4627c478bd9Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4637c478bd9Sstevel@tonic-gate 			val->val[0].value != 0) {
4647c478bd9Sstevel@tonic-gate 		attr->zo_group = sdup(myself, T, val->val[0].value);
4657c478bd9Sstevel@tonic-gate 		if (attr->zo_group == 0) {
4667c478bd9Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4677c478bd9Sstevel@tonic-gate 			return (0);
4687c478bd9Sstevel@tonic-gate 		}
4697c478bd9Sstevel@tonic-gate 	}
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	if ((val = findColValue("zo_domain", rv)) != 0 &&
4727c478bd9Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4737c478bd9Sstevel@tonic-gate 			val->val[0].value != 0) {
4747c478bd9Sstevel@tonic-gate 		attr->zo_domain = sdup(myself, T, val->val[0].value);
4757c478bd9Sstevel@tonic-gate 		if (attr->zo_domain == 0) {
4767c478bd9Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4777c478bd9Sstevel@tonic-gate 			return (0);
4787c478bd9Sstevel@tonic-gate 		}
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if ((val = findColValue("zo_access", rv)) != 0 &&
4827c478bd9Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4837c478bd9Sstevel@tonic-gate 			val->val[0].value != 0) {
4847c478bd9Sstevel@tonic-gate 		if (sscanf(val->val[0].value, "%x", &attr->zo_access) != 1) {
4857c478bd9Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4867c478bd9Sstevel@tonic-gate 			return (0);
4877c478bd9Sstevel@tonic-gate 		}
4887c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	if ((val = findColValue("zo_ttl", rv)) != 0 &&
4917c478bd9Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4927c478bd9Sstevel@tonic-gate 			val->val[0].value != 0) {
4937c478bd9Sstevel@tonic-gate 		if (sscanf(val->val[0].value, "%x", &attr->zo_ttl) != 1) {
4947c478bd9Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4957c478bd9Sstevel@tonic-gate 			return (0);
4967c478bd9Sstevel@tonic-gate 		}
4977c478bd9Sstevel@tonic-gate 	}
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	return (attr);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate  * If the supplied string is one of the object attributes, return one.
5047c478bd9Sstevel@tonic-gate  * Otherwise, return zero.
5057c478bd9Sstevel@tonic-gate  */
5067c478bd9Sstevel@tonic-gate int
isObjAttrString(char * str)5077c478bd9Sstevel@tonic-gate isObjAttrString(char *str) {
5087c478bd9Sstevel@tonic-gate 	if (str == 0)
5097c478bd9Sstevel@tonic-gate 		return (0);
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	if (strcmp("zo_owner", str) == 0 ||
5127c478bd9Sstevel@tonic-gate 		strcmp("zo_group", str) == 0 ||
5137c478bd9Sstevel@tonic-gate 		strcmp("zo_domain", str) == 0 ||
5147c478bd9Sstevel@tonic-gate 		strcmp("zo_access", str) == 0 ||
5157c478bd9Sstevel@tonic-gate 		strcmp("zo_ttl", str) == 0)
5167c478bd9Sstevel@tonic-gate 		return (1);
5177c478bd9Sstevel@tonic-gate 	else
5187c478bd9Sstevel@tonic-gate 		return (0);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate /*
5237c478bd9Sstevel@tonic-gate  * If the supplied value is one of the object attribute strings, return
5247c478bd9Sstevel@tonic-gate  * a pointer to the string. Otherwise, return NULL.
5257c478bd9Sstevel@tonic-gate  */
5267c478bd9Sstevel@tonic-gate char *
isObjAttr(__nis_single_value_t * val)5277c478bd9Sstevel@tonic-gate isObjAttr(__nis_single_value_t *val) {
5287c478bd9Sstevel@tonic-gate 	if (val == 0 || val->length <= 0 || val->value == 0)
5297c478bd9Sstevel@tonic-gate 		return (0);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	if (isObjAttrString(val->value))
5327c478bd9Sstevel@tonic-gate 		return (val->value);
5337c478bd9Sstevel@tonic-gate 	else
5347c478bd9Sstevel@tonic-gate 		return (0);
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate int
setObjAttrField(char * attrName,__nis_single_value_t * val,__nis_obj_attr_t ** objAttr)5387c478bd9Sstevel@tonic-gate setObjAttrField(char *attrName, __nis_single_value_t *val,
5397c478bd9Sstevel@tonic-gate 		__nis_obj_attr_t **objAttr) {
5407c478bd9Sstevel@tonic-gate 	__nis_obj_attr_t	*attr;
5417c478bd9Sstevel@tonic-gate 	char			*myself = "setObjAttrField";
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	if (attrName == 0 || val == 0 || objAttr == 0 ||
5447c478bd9Sstevel@tonic-gate 			val->value == 0 || val->length <= 0)
5457c478bd9Sstevel@tonic-gate 		return (-1);
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	if (*objAttr != 0) {
5487c478bd9Sstevel@tonic-gate 		attr = *objAttr;
5497c478bd9Sstevel@tonic-gate 	} else {
5507c478bd9Sstevel@tonic-gate 		attr = am(myself, sizeof (*attr));
5517c478bd9Sstevel@tonic-gate 		if (attr == 0)
5527c478bd9Sstevel@tonic-gate 			return (-2);
5537c478bd9Sstevel@tonic-gate 		*objAttr = attr;
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	if (strcmp("zo_owner", attrName) == 0) {
5577c478bd9Sstevel@tonic-gate 		if (attr->zo_owner == 0) {
5587c478bd9Sstevel@tonic-gate 			attr->zo_owner = sdup(myself, T, val->value);
5597c478bd9Sstevel@tonic-gate 			if (attr->zo_owner == 0)
5607c478bd9Sstevel@tonic-gate 				return (-11);
5617c478bd9Sstevel@tonic-gate 		}
5627c478bd9Sstevel@tonic-gate 	} else if (strcmp("zo_group", attrName) == 0) {
5637c478bd9Sstevel@tonic-gate 		if (attr->zo_group == 0) {
5647c478bd9Sstevel@tonic-gate 			attr->zo_group = sdup(myself, T, val->value);
5657c478bd9Sstevel@tonic-gate 			if (attr->zo_group == 0)
5667c478bd9Sstevel@tonic-gate 				return (-12);
5677c478bd9Sstevel@tonic-gate 		}
5687c478bd9Sstevel@tonic-gate 	} else if (strcmp("zo_domain", attrName) == 0) {
5697c478bd9Sstevel@tonic-gate 		if (attr->zo_domain == 0) {
5707c478bd9Sstevel@tonic-gate 			attr->zo_domain = sdup(myself, T, val->value);
5717c478bd9Sstevel@tonic-gate 			if (attr->zo_domain == 0)
5727c478bd9Sstevel@tonic-gate 				return (-13);
5737c478bd9Sstevel@tonic-gate 		}
5747c478bd9Sstevel@tonic-gate 	} else if (strcmp("zo_access", attrName) == 0) {
5757c478bd9Sstevel@tonic-gate 		if (attr->zo_access == 0) {
5767c478bd9Sstevel@tonic-gate 			if (sscanf(val->value, "%x", &attr->zo_access) != 1)
5777c478bd9Sstevel@tonic-gate 				return (-14);
5787c478bd9Sstevel@tonic-gate 		}
5797c478bd9Sstevel@tonic-gate 	} else if (strcmp("zo_ttl", attrName) == 0) {
5807c478bd9Sstevel@tonic-gate 		if (attr->zo_ttl == 0) {
5817c478bd9Sstevel@tonic-gate 			if (sscanf(val->value, "%x", &attr->zo_ttl) != 1)
5827c478bd9Sstevel@tonic-gate 				return (-15);
5837c478bd9Sstevel@tonic-gate 		}
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	return (0);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate /*
5907c478bd9Sstevel@tonic-gate  * Return a DN and rule-value for the supplied mapping, db_query's, and
5917c478bd9Sstevel@tonic-gate  * input rule-value. This function only works on a single mapping. See
5927c478bd9Sstevel@tonic-gate  * mapToLDAP() below for a description of the action depending on the
5937c478bd9Sstevel@tonic-gate  * values of 'old' and 'new'.
5947c478bd9Sstevel@tonic-gate  *
5957c478bd9Sstevel@tonic-gate  * If both 'old' and 'new' are supplied, and the modify would result
5967c478bd9Sstevel@tonic-gate  * in a change to the DN, '*oldDN' will contain the old DN. Otherwise
5977c478bd9Sstevel@tonic-gate  * (and normally), '*oldDN' will be NULL.
5987c478bd9Sstevel@tonic-gate  */
5997c478bd9Sstevel@tonic-gate char *
map1qToLDAP(__nis_table_mapping_t * t,db_query * old,db_query * new,__nis_rule_value_t * rvIn,__nis_rule_value_t ** rvOutP,char ** oldDnP)6007c478bd9Sstevel@tonic-gate map1qToLDAP(__nis_table_mapping_t *t, db_query *old, db_query *new,
6017c478bd9Sstevel@tonic-gate 		__nis_rule_value_t *rvIn, __nis_rule_value_t **rvOutP,
6027c478bd9Sstevel@tonic-gate 		char **oldDnP) {
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv, *rvt;
6057c478bd9Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
6067c478bd9Sstevel@tonic-gate 	char			*dn = 0, *oldDn = 0;
6077c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	del;
6087c478bd9Sstevel@tonic-gate 	char			*myself = "map1qToLDAP";
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	if (t == 0 || (old == 0 && new == 0) || rvOutP == 0)
6117c478bd9Sstevel@tonic-gate 		return (0);
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	/*
6147c478bd9Sstevel@tonic-gate 	 * If entry should be deleted, we look at the delete
6157c478bd9Sstevel@tonic-gate 	 * policy in the table mapping. Should it specify a
6167c478bd9Sstevel@tonic-gate 	 * rule set, we use that rule set to build a rule-
6177c478bd9Sstevel@tonic-gate 	 * value, and the delete actually becomes a modify
6187c478bd9Sstevel@tonic-gate 	 * operation.
6197c478bd9Sstevel@tonic-gate 	 */
6207c478bd9Sstevel@tonic-gate 	if (old != 0 && new == 0) {
6217c478bd9Sstevel@tonic-gate 		if (t->objectDN->delDisp == dd_perDbId) {
6227c478bd9Sstevel@tonic-gate 			/*
6237c478bd9Sstevel@tonic-gate 			 * The functions that build a rule-value from a
6247c478bd9Sstevel@tonic-gate 			 * rule set expect a __nis_table_mapping_t, but the
6257c478bd9Sstevel@tonic-gate 			 * rule set in the __nis_object_dn_t isn't of that
6267c478bd9Sstevel@tonic-gate 			 * form. So, build a pseudo-__nis_table_mapping_t that
6277c478bd9Sstevel@tonic-gate 			 * borrows heavily from 't'.
6287c478bd9Sstevel@tonic-gate 			 */
6297c478bd9Sstevel@tonic-gate 			del = *t;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 			del.numRulesToLDAP = del.objectDN->numDbIds;
6327c478bd9Sstevel@tonic-gate 			del.ruleToLDAP = del.objectDN->dbId;
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 			/*
6357c478bd9Sstevel@tonic-gate 			 * Do a modify with the pseudo-table
6367c478bd9Sstevel@tonic-gate 			 * mapping, and the 'old' db_query
6377c478bd9Sstevel@tonic-gate 			 * supplying input to the delete rule
6387c478bd9Sstevel@tonic-gate 			 * set.
6397c478bd9Sstevel@tonic-gate 			 */
6407c478bd9Sstevel@tonic-gate 			t = &del;
6417c478bd9Sstevel@tonic-gate 			new = old;
6427c478bd9Sstevel@tonic-gate 		} else if (t->objectDN->delDisp == dd_always) {
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 			/* Nothing to do here; all handled below */
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 		} else if (t->objectDN->delDisp == dd_never) {
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 			return (0);
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 		} else {
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 			logmsg(MSG_INVALIDDELDISP, LOG_WARNING,
6537c478bd9Sstevel@tonic-gate 				"%s: Invalid delete disposition %d for \"%s\"",
6547c478bd9Sstevel@tonic-gate 				myself, t->objectDN->delDisp,
6557c478bd9Sstevel@tonic-gate 				NIL(t->dbId));
6567c478bd9Sstevel@tonic-gate 			return (0);
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 		}
6597c478bd9Sstevel@tonic-gate 	}
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	/* Make a copy of the input rule-value */
6627c478bd9Sstevel@tonic-gate 	if (rvIn != 0) {
6637c478bd9Sstevel@tonic-gate 		rv = initRuleValue(1, rvIn);
6647c478bd9Sstevel@tonic-gate 		if (rv == 0)
6657c478bd9Sstevel@tonic-gate 			return (0);
6667c478bd9Sstevel@tonic-gate 	} else {
6677c478bd9Sstevel@tonic-gate 		rv = 0;
6687c478bd9Sstevel@tonic-gate 	}
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	/* First get a rule-value from the supplied NIS+ entry. */
6717c478bd9Sstevel@tonic-gate 	rvt = rv;
6727c478bd9Sstevel@tonic-gate 	rv = buildNisPlusRuleValue(t, ((old != 0) ? old : new), rvt);
6737c478bd9Sstevel@tonic-gate 	freeRuleValue(rvt, 1);
6747c478bd9Sstevel@tonic-gate 	if (rv == 0) {
6757c478bd9Sstevel@tonic-gate 		logmsg(MSG_NORULEVALUE, LOG_WARNING,
6767c478bd9Sstevel@tonic-gate 			"%s: No in-query rule-value derived for \"%s\"",
6777c478bd9Sstevel@tonic-gate 			myself, NIL(t->dbId));
6787c478bd9Sstevel@tonic-gate 		return (0);
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	/*
6827c478bd9Sstevel@tonic-gate 	 * Create a request (really only care about the DN) from the
6837c478bd9Sstevel@tonic-gate 	 * supplied NIS+ entry data.
6847c478bd9Sstevel@tonic-gate 	 */
6857c478bd9Sstevel@tonic-gate 	ls = createLdapRequest(t, rv, &dn, 0, NULL, NULL);
6867c478bd9Sstevel@tonic-gate 	if (ls == 0 || dn == 0) {
6877c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
6887c478bd9Sstevel@tonic-gate 			"%s: Unable to create LDAP request for %s: %s",
6897c478bd9Sstevel@tonic-gate 			myself, NIL(t->dbId),
6907c478bd9Sstevel@tonic-gate 			(dn != 0) ? dn : rvId(rv, mit_nisplus));
6917c478bd9Sstevel@tonic-gate 		sfree(dn);
6927c478bd9Sstevel@tonic-gate 		freeLdapSearch(ls);
6937c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, 1);
6947c478bd9Sstevel@tonic-gate 		return (0);
6957c478bd9Sstevel@tonic-gate 	}
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	freeLdapSearch(ls);
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	if (new != 0) {
7007c478bd9Sstevel@tonic-gate 		/*
7017c478bd9Sstevel@tonic-gate 		 * Create a rule-value from the new NIS+ entry.
7027c478bd9Sstevel@tonic-gate 		 * Don't want to mix in the rule-value derived
7037c478bd9Sstevel@tonic-gate 		 * from 'old', so delete it. However, we still
7047c478bd9Sstevel@tonic-gate 		 * want the owner, group, etc., from 'rvIn'.
7057c478bd9Sstevel@tonic-gate 		 */
7067c478bd9Sstevel@tonic-gate 		if (old != 0) {
7077c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, 1);
7087c478bd9Sstevel@tonic-gate 			if (rvIn != 0) {
7097c478bd9Sstevel@tonic-gate 				rv = initRuleValue(1, rvIn);
7107c478bd9Sstevel@tonic-gate 				if (rv == 0) {
7117c478bd9Sstevel@tonic-gate 					sfree(dn);
7127c478bd9Sstevel@tonic-gate 					return (0);
7137c478bd9Sstevel@tonic-gate 				}
7147c478bd9Sstevel@tonic-gate 			} else {
7157c478bd9Sstevel@tonic-gate 				rv = 0;
7167c478bd9Sstevel@tonic-gate 			}
7177c478bd9Sstevel@tonic-gate 		}
7187c478bd9Sstevel@tonic-gate 		rvt = rv;
7197c478bd9Sstevel@tonic-gate 		rv = buildNisPlusRuleValue(t, new, rvt);
7207c478bd9Sstevel@tonic-gate 		freeRuleValue(rvt, 1);
7217c478bd9Sstevel@tonic-gate 		if (rv == 0) {
7227c478bd9Sstevel@tonic-gate 			logmsg(MSG_NORULEVALUE, LOG_WARNING,
7237c478bd9Sstevel@tonic-gate 				"%s: No new rule-value derived for \"%s: %s\"",
7247c478bd9Sstevel@tonic-gate 				myself, NIL(t->dbId), dn);
7257c478bd9Sstevel@tonic-gate 			sfree(dn);
7267c478bd9Sstevel@tonic-gate 			return (0);
7277c478bd9Sstevel@tonic-gate 		}
7287c478bd9Sstevel@tonic-gate 		/*
7297c478bd9Sstevel@tonic-gate 		 * Check if the proposed modification would result in a
7307c478bd9Sstevel@tonic-gate 		 * a change to the DN.
7317c478bd9Sstevel@tonic-gate 		 */
7327c478bd9Sstevel@tonic-gate 		if (old != 0) {
7337c478bd9Sstevel@tonic-gate 			oldDn = dn;
7347c478bd9Sstevel@tonic-gate 			dn = 0;
7357c478bd9Sstevel@tonic-gate 			ls = createLdapRequest(t, rv, &dn, 0, NULL, NULL);
7367c478bd9Sstevel@tonic-gate 			if (ls == 0 || dn == 0) {
7377c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
7387c478bd9Sstevel@tonic-gate 				"%s: Unable to create new DN for \"%s: %s\"",
7397c478bd9Sstevel@tonic-gate 					myself, NIL(t->dbId), oldDn);
7407c478bd9Sstevel@tonic-gate 				sfree(oldDn);
7417c478bd9Sstevel@tonic-gate 				freeLdapSearch(ls);
7427c478bd9Sstevel@tonic-gate 				freeRuleValue(rv, 1);
7437c478bd9Sstevel@tonic-gate 				return (0);
7447c478bd9Sstevel@tonic-gate 			}
7457c478bd9Sstevel@tonic-gate 			freeLdapSearch(ls);
7467c478bd9Sstevel@tonic-gate 			if (strcasecmp(oldDn, dn) == 0) {
7477c478bd9Sstevel@tonic-gate 				sfree(oldDn);
7487c478bd9Sstevel@tonic-gate 				oldDn = 0;
7497c478bd9Sstevel@tonic-gate 			}
7507c478bd9Sstevel@tonic-gate 		}
7517c478bd9Sstevel@tonic-gate 	}
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	*rvOutP = rv;
7557c478bd9Sstevel@tonic-gate 	if (oldDnP != 0)
7567c478bd9Sstevel@tonic-gate 		*oldDnP = oldDn;
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	return (dn);
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate /*
7627c478bd9Sstevel@tonic-gate  * Since the DN hash list is an automatic variable, there's no need for
7637c478bd9Sstevel@tonic-gate  * locking, and we remove the locking overhead by using the libnsl
7647c478bd9Sstevel@tonic-gate  * hash functions.
7657c478bd9Sstevel@tonic-gate  */
7667c478bd9Sstevel@tonic-gate #undef  NIS_HASH_ITEM
7677c478bd9Sstevel@tonic-gate #undef  NIS_HASH_TABLE
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate typedef struct {
7707c478bd9Sstevel@tonic-gate 	NIS_HASH_ITEM	item;
7717c478bd9Sstevel@tonic-gate 	int		index;
7727c478bd9Sstevel@tonic-gate 	char		*oldDn;
7737c478bd9Sstevel@tonic-gate } __dn_item_t;
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate /*
7767c478bd9Sstevel@tonic-gate  * Update LDAP per the supplied table mapping and db_query's.
7777c478bd9Sstevel@tonic-gate  *
7787c478bd9Sstevel@tonic-gate  * 'nq' is the number of elements in the 'old', 'new', and 'rvIn'
7797c478bd9Sstevel@tonic-gate  * arrays. mapToLDAP() generally performs one update for each
7807c478bd9Sstevel@tonic-gate  * element; however, if one or more of the individual queries
7817c478bd9Sstevel@tonic-gate  * produce the same DN, they're merged into a single update.
7827c478bd9Sstevel@tonic-gate  *
7837c478bd9Sstevel@tonic-gate  * There are four cases, depending on the values of 'old[iq]' and
7847c478bd9Sstevel@tonic-gate  * 'new[iq]':
7857c478bd9Sstevel@tonic-gate  *
7867c478bd9Sstevel@tonic-gate  * (1)	old[iq] == 0 && new[iq] == 0
7877c478bd9Sstevel@tonic-gate  *	No action; skip to next query
7887c478bd9Sstevel@tonic-gate  *
7897c478bd9Sstevel@tonic-gate  * (2)	old[iq] == 0 && new[iq] != 0
7907c478bd9Sstevel@tonic-gate  *	Attempt to use the 'new' db_query to get a DN, and try to create
7917c478bd9Sstevel@tonic-gate  *	the corresponding LDAP entry.
7927c478bd9Sstevel@tonic-gate  *
7937c478bd9Sstevel@tonic-gate  * (3)	old[iq] != 0 && new[iq] == 0
7947c478bd9Sstevel@tonic-gate  *	Use the 'old' db_query to get a DN, and try to delete the LDAP
7957c478bd9Sstevel@tonic-gate  *	entry per the table mapping.
7967c478bd9Sstevel@tonic-gate  *
7977c478bd9Sstevel@tonic-gate  * (4)	old[iq] != 0 && new[iq] != 0
7987c478bd9Sstevel@tonic-gate  *	Use the 'old' db_query to get a DN, and update (possibly create)
7997c478bd9Sstevel@tonic-gate  *	the corresponding LDAP entry per the 'new' db_query.
8007c478bd9Sstevel@tonic-gate  *
8017c478bd9Sstevel@tonic-gate  * If 'rvIn' is non-NULL, it is expected to contain the object attributes
8027c478bd9Sstevel@tonic-gate  * (zo_owner, etc.) to be written to LDAP. 'rvIn' is an array with 'nq'
8037c478bd9Sstevel@tonic-gate  * elements.
8047c478bd9Sstevel@tonic-gate  *
8057c478bd9Sstevel@tonic-gate  * If 'firstOnly' is set, only the first old[iq]/new[iq] pair is used
8067c478bd9Sstevel@tonic-gate  * to perform the actual update. Any additional queries specified will
8077c478bd9Sstevel@tonic-gate  * have their values folded in, but are not used to derive update targets.
8087c478bd9Sstevel@tonic-gate  * This mode is inteded to support the case where multiple NIS+ entries
8097c478bd9Sstevel@tonic-gate  * map to one and the same LDAP entry. Note that 'rvIn' must still be
8107c478bd9Sstevel@tonic-gate  * an array of 'nq' elements, though if 'firstOnly' is set, it should be
8117c478bd9Sstevel@tonic-gate  * OK to leave all but 'rvIn[0]' empty.
8127c478bd9Sstevel@tonic-gate  *
8137c478bd9Sstevel@tonic-gate  * 'dbId' is used to further narow down the selection of mapping candidates
8147c478bd9Sstevel@tonic-gate  * to those matching the 'dbId' value.
8157c478bd9Sstevel@tonic-gate  */
8167c478bd9Sstevel@tonic-gate int
mapToLDAP(__nis_table_mapping_t * tm,int nq,db_query ** old,db_query ** new,__nis_rule_value_t * rvIn,int firstOnly,char * dbId)8177c478bd9Sstevel@tonic-gate mapToLDAP(__nis_table_mapping_t *tm, int nq, db_query **old, db_query **new,
8187c478bd9Sstevel@tonic-gate 		__nis_rule_value_t *rvIn, int firstOnly, char *dbId) {
8197c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	**tp, **tpa;
8207c478bd9Sstevel@tonic-gate 	int			i, n, rnq, iq, r, ret = LDAP_SUCCESS;
8217c478bd9Sstevel@tonic-gate 	int			maxMatches, numMatches = 0;
8227c478bd9Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
8237c478bd9Sstevel@tonic-gate 	char			**dn = 0, **odn = 0;
8247c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	**rv;
8257c478bd9Sstevel@tonic-gate 	__dn_item_t		*dni;
8267c478bd9Sstevel@tonic-gate 	char			*myself = "mapToLDAP";
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	if (tm == 0 || (old == 0 && new == 0) || nq <= 0)
8307c478bd9Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 	/* Determine maximum number of table mapping matches */
8337c478bd9Sstevel@tonic-gate 	if (nq == 1) {
8347c478bd9Sstevel@tonic-gate 		tp = selectTableMapping(tm,
8357c478bd9Sstevel@tonic-gate 			(old != 0 && old[0] != 0) ? old[0] : new[0], 1, 0,
8367c478bd9Sstevel@tonic-gate 				dbId, &maxMatches);
8377c478bd9Sstevel@tonic-gate 		numMatches = maxMatches;
8387c478bd9Sstevel@tonic-gate 	} else {
8397c478bd9Sstevel@tonic-gate 		tp = selectTableMapping(tm, 0, 1, 0, dbId, &maxMatches);
8407c478bd9Sstevel@tonic-gate 	}
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	/*
8437c478bd9Sstevel@tonic-gate 	 * If no matching mapping, we're not mapping to LDAP in this
8447c478bd9Sstevel@tonic-gate 	 * particular case.
8457c478bd9Sstevel@tonic-gate 	 */
8467c478bd9Sstevel@tonic-gate 	if (tp == 0 || maxMatches == 0) {
8477c478bd9Sstevel@tonic-gate 		sfree(tp);
8487c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
8497c478bd9Sstevel@tonic-gate 	}
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	/*
8527c478bd9Sstevel@tonic-gate 	 * Allocate the 'rv', 'dn', and 'tpa' arrays. Worst case is that
8537c478bd9Sstevel@tonic-gate 	 * we need nq * maxMatches elements in each array. However, if
8547c478bd9Sstevel@tonic-gate 	 * 'firstOnly' is set, we only need one element per matching
8557c478bd9Sstevel@tonic-gate 	 * mapping in each.
8567c478bd9Sstevel@tonic-gate 	 */
8577c478bd9Sstevel@tonic-gate 	dn = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (dn[0]));
8587c478bd9Sstevel@tonic-gate 	odn = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (odn[0]));
8597c478bd9Sstevel@tonic-gate 	rv = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (rv[0]));
8607c478bd9Sstevel@tonic-gate 	tpa = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (tpa[0]));
8617c478bd9Sstevel@tonic-gate 	if (dn == 0 || odn == 0 || rv == 0 || tpa == 0) {
8627c478bd9Sstevel@tonic-gate 		sfree(tp);
8637c478bd9Sstevel@tonic-gate 		sfree(dn);
8647c478bd9Sstevel@tonic-gate 		sfree(odn);
8657c478bd9Sstevel@tonic-gate 		sfree(rv);
8667c478bd9Sstevel@tonic-gate 		sfree(tpa);
8677c478bd9Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
8687c478bd9Sstevel@tonic-gate 	}
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	/* Unless nq == 1, we don't need the 'tp' value */
8717c478bd9Sstevel@tonic-gate 	if (nq != 1)
8727c478bd9Sstevel@tonic-gate 		sfree(tp);
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
8757c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
8767c478bd9Sstevel@tonic-gate 		LOG_WARNING,
8777c478bd9Sstevel@tonic-gate #else
8787c478bd9Sstevel@tonic-gate 		LOG_INFO,
8797c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
8807c478bd9Sstevel@tonic-gate 		"%s: %s: %d * %d potential updates",
8817c478bd9Sstevel@tonic-gate 		myself, NIL(tm->objName), nq, maxMatches);
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	/*
8847c478bd9Sstevel@tonic-gate 	 * Create DNs, column and attribute values, and merge duplicate DNs.
8857c478bd9Sstevel@tonic-gate 	 */
8867c478bd9Sstevel@tonic-gate 	for (iq = 0, rnq = 0; iq < nq; iq++) {
8877c478bd9Sstevel@tonic-gate 		int	idx;
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 		if ((old == 0 || old[iq] == 0) &&
8907c478bd9Sstevel@tonic-gate 				(new == 0 || new[iq] == 0))
8917c478bd9Sstevel@tonic-gate 			continue;
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 		/*
8947c478bd9Sstevel@tonic-gate 		 * Select matching table mappings; if nq == 1, we've already
8957c478bd9Sstevel@tonic-gate 		 * got the 'tp' array from above. We expect this to be the
8967c478bd9Sstevel@tonic-gate 		 * most common case, so it's worth special treatment.
8977c478bd9Sstevel@tonic-gate 		 */
8987c478bd9Sstevel@tonic-gate 		if (nq != 1)
8997c478bd9Sstevel@tonic-gate 			tp = selectTableMapping(tm,
9007c478bd9Sstevel@tonic-gate 			(old != 0 && old[iq] != 0) ? old[iq] : new[iq], 1, 0,
9017c478bd9Sstevel@tonic-gate 					dbId, &numMatches);
9027c478bd9Sstevel@tonic-gate 		if (tp == 0)
9037c478bd9Sstevel@tonic-gate 			continue;
9047c478bd9Sstevel@tonic-gate 		else if (numMatches <= 0) {
9057c478bd9Sstevel@tonic-gate 			sfree(tp);
9067c478bd9Sstevel@tonic-gate 			continue;
9077c478bd9Sstevel@tonic-gate 		}
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 		idx = iq * maxMatches;
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 		if (idx == 0 || !firstOnly)
9127c478bd9Sstevel@tonic-gate 			(void) memcpy(&tpa[idx], tp,
9137c478bd9Sstevel@tonic-gate 					numMatches * sizeof (tpa[idx]));
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 		for (n = 0; n < numMatches; n++) {
9167c478bd9Sstevel@tonic-gate 			char			*dnt, *odnt;
9177c478bd9Sstevel@tonic-gate 			__nis_rule_value_t	*rvt = 0;
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 			if (tp[n] == 0)
9207c478bd9Sstevel@tonic-gate 				continue;
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 			dnt = map1qToLDAP(tp[n],
9237c478bd9Sstevel@tonic-gate 					(old != 0) ? old[iq] : 0,
9247c478bd9Sstevel@tonic-gate 					(new != 0) ? new[iq] : 0,
9257c478bd9Sstevel@tonic-gate 					(rvIn != 0) ? &rvIn[iq] : 0,
9267c478bd9Sstevel@tonic-gate 					&rvt, &odnt);
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 			if (dnt == 0)
9297c478bd9Sstevel@tonic-gate 				continue;
9307c478bd9Sstevel@tonic-gate 			if (rvt == 0) {
9317c478bd9Sstevel@tonic-gate #ifdef  NISDB_LDAP_DEBUG
9327c478bd9Sstevel@tonic-gate 				abort();
9337c478bd9Sstevel@tonic-gate #else
9347c478bd9Sstevel@tonic-gate 				sfree(dnt);
9357c478bd9Sstevel@tonic-gate 				sfree(odnt);
9367c478bd9Sstevel@tonic-gate 				continue;
9377c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
9387c478bd9Sstevel@tonic-gate 			}
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 			/*
9417c478bd9Sstevel@tonic-gate 			 * Create a request to get a rule-value with
9427c478bd9Sstevel@tonic-gate 			 * NIS+ data translated to LDAP equivalents.
9437c478bd9Sstevel@tonic-gate 			 */
9447c478bd9Sstevel@tonic-gate 			ls = createLdapRequest(tp[n], rvt, 0, 0, NULL, NULL);
9457c478bd9Sstevel@tonic-gate 			if (ls == 0) {
9467c478bd9Sstevel@tonic-gate 				if (ret == LDAP_SUCCESS)
9477c478bd9Sstevel@tonic-gate 					ret = LDAP_OPERATIONS_ERROR;
9487c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9497c478bd9Sstevel@tonic-gate 				"%s: Unable to map to LDAP attrs for %s:dn=%s",
9507c478bd9Sstevel@tonic-gate 				myself, NIL(tp[n]->dbId), dnt);
9517c478bd9Sstevel@tonic-gate 				sfree(dnt);
9527c478bd9Sstevel@tonic-gate 				freeRuleValue(rvt, 1);
9537c478bd9Sstevel@tonic-gate 				continue;
9547c478bd9Sstevel@tonic-gate 			}
9557c478bd9Sstevel@tonic-gate 			freeLdapSearch(ls);
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 			/*
9587c478bd9Sstevel@tonic-gate 			 * If the DN is the same as one we already know
9597c478bd9Sstevel@tonic-gate 			 * about, merge the rule-values.
9607c478bd9Sstevel@tonic-gate 			 */
9617c478bd9Sstevel@tonic-gate 
962*36e852a1SRaja Andra 			if ((iq == 0 || !firstOnly) && dnt != 0) {
9637c478bd9Sstevel@tonic-gate 				dni = am(myself, sizeof (*dni));
9647c478bd9Sstevel@tonic-gate 				if (dni != 0) {
9657c478bd9Sstevel@tonic-gate 					dni->item.name = dnt;
9667c478bd9Sstevel@tonic-gate 					dni->index = idx + n;
9677c478bd9Sstevel@tonic-gate 					dni->oldDn = odnt;
9687c478bd9Sstevel@tonic-gate 				} else {
9697c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9707c478bd9Sstevel@tonic-gate 					"%s: Skipping update for dn=\"%s\"",
9717c478bd9Sstevel@tonic-gate 						myself, dnt);
9727c478bd9Sstevel@tonic-gate 					sfree(dnt);
9737c478bd9Sstevel@tonic-gate 					dnt = 0;
9747c478bd9Sstevel@tonic-gate 				}
9757c478bd9Sstevel@tonic-gate 				if (dnt != 0) {
9767c478bd9Sstevel@tonic-gate 					dn[idx+n] = dnt;
9777c478bd9Sstevel@tonic-gate 					odn[idx+n] = odnt;
9787c478bd9Sstevel@tonic-gate 					rv[idx+n] = rvt;
9797c478bd9Sstevel@tonic-gate 					rnq++;
9807c478bd9Sstevel@tonic-gate 				} else {
9817c478bd9Sstevel@tonic-gate 					freeRuleValue(rvt, 1);
9827c478bd9Sstevel@tonic-gate 					rvt = 0;
9837c478bd9Sstevel@tonic-gate 				}
9847c478bd9Sstevel@tonic-gate 			} else if (dnt != 0) {
9857c478bd9Sstevel@tonic-gate 				sfree(dnt);
9867c478bd9Sstevel@tonic-gate 				sfree(odnt);
9877c478bd9Sstevel@tonic-gate 				freeRuleValue(rvt, 1);
9887c478bd9Sstevel@tonic-gate 			}
9897c478bd9Sstevel@tonic-gate 		}
9907c478bd9Sstevel@tonic-gate 		sfree(tp);
9917c478bd9Sstevel@tonic-gate 	}
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
9947c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
9957c478bd9Sstevel@tonic-gate 		LOG_WARNING,
9967c478bd9Sstevel@tonic-gate #else
9977c478bd9Sstevel@tonic-gate 		LOG_INFO,
9987c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
9997c478bd9Sstevel@tonic-gate 		"%s: %s: %d update%s requested",
10007c478bd9Sstevel@tonic-gate 		myself, NIL(tm->objName), rnq, rnq != 1 ? "s" : "");
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 	/* Perform the updates */
10037c478bd9Sstevel@tonic-gate 	for (i = rnq = 0; i < (firstOnly ? maxMatches : nq*maxMatches); i++) {
10047c478bd9Sstevel@tonic-gate 		int	delPerDbId;
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 		if (dn[i] == 0)
10077c478bd9Sstevel@tonic-gate 			continue;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
10107c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_INFO,
10117c478bd9Sstevel@tonic-gate 			"%s: %s %s:dn=%s",
10127c478bd9Sstevel@tonic-gate 			myself,
10137c478bd9Sstevel@tonic-gate 			(new != 0 && new[i/maxMatches] != 0) ?
10147c478bd9Sstevel@tonic-gate 				"modify" : "delete",
10157c478bd9Sstevel@tonic-gate 			NIL(tpa[i]->dbId), dn[i]);
10167c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate 		delPerDbId = (tpa[i]->objectDN->delDisp == dd_perDbId);
10197c478bd9Sstevel@tonic-gate 		if ((new != 0 && new[i/maxMatches] != 0) || delPerDbId) {
10207c478bd9Sstevel@tonic-gate 			/*
10217c478bd9Sstevel@tonic-gate 			 * Try to modify/create the specified DN. First,
10227c478bd9Sstevel@tonic-gate 			 * however, if the update changes the DN, make
10237c478bd9Sstevel@tonic-gate 			 * that change.
10247c478bd9Sstevel@tonic-gate 			 */
10257c478bd9Sstevel@tonic-gate 			if (odn[i] == 0 || (r = ldapChangeDN(odn[i], dn[i])) ==
10267c478bd9Sstevel@tonic-gate 					LDAP_SUCCESS) {
10277c478bd9Sstevel@tonic-gate 				int	addFirst;
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 				addFirst = (new != 0 &&
10307c478bd9Sstevel@tonic-gate 						new[i/maxMatches] != 0 &&
10317c478bd9Sstevel@tonic-gate 						!delPerDbId);
10327c478bd9Sstevel@tonic-gate 				r = ldapModify(dn[i], rv[i],
10337c478bd9Sstevel@tonic-gate 					tpa[i]->objectDN->write.attrs,
10347c478bd9Sstevel@tonic-gate 						addFirst);
10357c478bd9Sstevel@tonic-gate 			}
10367c478bd9Sstevel@tonic-gate 		} else {
10377c478bd9Sstevel@tonic-gate 			/* Try to delete the specified DN */
10387c478bd9Sstevel@tonic-gate 			r = ldapModify(dn[i], 0,
10397c478bd9Sstevel@tonic-gate 					tpa[i]->objectDN->write.attrs, 0);
10407c478bd9Sstevel@tonic-gate 		}
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 		if (r == LDAP_SUCCESS) {
10437c478bd9Sstevel@tonic-gate 			rnq++;
10447c478bd9Sstevel@tonic-gate 		} else {
10457c478bd9Sstevel@tonic-gate 			if (ret == LDAP_SUCCESS)
10467c478bd9Sstevel@tonic-gate 				ret = r;
10477c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
10487c478bd9Sstevel@tonic-gate 				"%s: LDAP %s request error %d for %s:dn=%s",
10497c478bd9Sstevel@tonic-gate 				myself,
10507c478bd9Sstevel@tonic-gate 				(new != 0 && new[i/maxMatches] != 0) ?
10517c478bd9Sstevel@tonic-gate 					"modify" : "delete",
10527c478bd9Sstevel@tonic-gate 				r, NIL(tpa[i]->dbId), dn[i]);
10537c478bd9Sstevel@tonic-gate 		}
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 		sfree(dn[i]);
10567c478bd9Sstevel@tonic-gate 		dn[i] = 0;
10577c478bd9Sstevel@tonic-gate 		freeRuleValue(rv[i], 1);
10587c478bd9Sstevel@tonic-gate 		rv[i] = 0;
10597c478bd9Sstevel@tonic-gate 	}
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 	sfree(dn);
10627c478bd9Sstevel@tonic-gate 	sfree(odn);
10637c478bd9Sstevel@tonic-gate 	sfree(rv);
10647c478bd9Sstevel@tonic-gate 	sfree(tpa);
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
10677c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
10687c478bd9Sstevel@tonic-gate 		LOG_WARNING,
10697c478bd9Sstevel@tonic-gate #else
10707c478bd9Sstevel@tonic-gate 		LOG_INFO,
10717c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
10727c478bd9Sstevel@tonic-gate 		"%s: %s: %d update%s performed",
10737c478bd9Sstevel@tonic-gate 		myself, NIL(tm->objName), rnq, rnq != 1 ? "s" : "");
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 	return (ret);
10767c478bd9Sstevel@tonic-gate }
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate /*
10797c478bd9Sstevel@tonic-gate  * In nis+2ldap, check if the query 'q' matches the selector index 'x->index'.
10807c478bd9Sstevel@tonic-gate  *
10817c478bd9Sstevel@tonic-gate  * In nis2ldap, if 'name' is provided then check if its value in 'val'
10827c478bd9Sstevel@tonic-gate  * matches the selector index. If 'name' is NULL, then check if rule-value 'rv'
10837c478bd9Sstevel@tonic-gate  * matches the index.
10847c478bd9Sstevel@tonic-gate  * To match the selector index, all fieldspecs in the indexlist should match
10857c478bd9Sstevel@tonic-gate  * (AND). In nis2ldap, an exception is, if there are multiple fieldspecs with
10867c478bd9Sstevel@tonic-gate  * the same fieldname then only one of them needs to match (OR).
10877c478bd9Sstevel@tonic-gate  * Example:
10887c478bd9Sstevel@tonic-gate  *	Indexlist = [host="H*", host="I*", user="U*", domain="D*"]
10897c478bd9Sstevel@tonic-gate  * Then,
10907c478bd9Sstevel@tonic-gate  *	host = "H1", user="U1", domain="D1" ==> pass
10917c478bd9Sstevel@tonic-gate  *	host = "I1", user="U1", domain="D1" ==> pass
10927c478bd9Sstevel@tonic-gate  *	host = "X1", user="U1", domain="D1" ==> fail
10937c478bd9Sstevel@tonic-gate  *	host = "H1", user="X1", domain="D1" ==> fail
10947c478bd9Sstevel@tonic-gate  *	host = "H1", user="U1" ==> fail
10957c478bd9Sstevel@tonic-gate  *
10967c478bd9Sstevel@tonic-gate  * Return 1 in case of a match, 0 otherwise.
10977c478bd9Sstevel@tonic-gate  */
10987c478bd9Sstevel@tonic-gate int
verifyIndexMatch(__nis_table_mapping_t * x,db_query * q,__nis_rule_value_t * rv,char * name,char * val)10997c478bd9Sstevel@tonic-gate verifyIndexMatch(__nis_table_mapping_t *x, db_query *q,
11007c478bd9Sstevel@tonic-gate 		__nis_rule_value_t *rv, char *name, char *val) {
11017c478bd9Sstevel@tonic-gate 	int	i, j, k, match = 1;
11027c478bd9Sstevel@tonic-gate 	char	*myself = "verifyIndexMatch";
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	/*
11057c478bd9Sstevel@tonic-gate 	 * The pass and fail arrays are used by N2L to keep track of
11067c478bd9Sstevel@tonic-gate 	 * index matches. This saves us from having matches in a
11077c478bd9Sstevel@tonic-gate 	 * nested loop to decide OR or AND.
11087c478bd9Sstevel@tonic-gate 	 */
11097c478bd9Sstevel@tonic-gate 	int	ppos, fpos;
11107c478bd9Sstevel@tonic-gate 	char	**pass, **fail;
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 	if (x == 0)
11137c478bd9Sstevel@tonic-gate 		return (0);
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 	/* Trivial match */
11167c478bd9Sstevel@tonic-gate 	if (x->index.numIndexes <= 0 || (!yp2ldap && q == 0))
11177c478bd9Sstevel@tonic-gate 		return (1);
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	if (yp2ldap) {
11207c478bd9Sstevel@tonic-gate 		if (!(pass = am(myself, x->index.numIndexes * sizeof (char *))))
11217c478bd9Sstevel@tonic-gate 			return (0);
11227c478bd9Sstevel@tonic-gate 		if (!(fail = am(myself,
11237c478bd9Sstevel@tonic-gate 				x->index.numIndexes * sizeof (char *)))) {
11247c478bd9Sstevel@tonic-gate 			sfree(pass);
11257c478bd9Sstevel@tonic-gate 			return (0);
11267c478bd9Sstevel@tonic-gate 		}
11277c478bd9Sstevel@tonic-gate 		ppos = fpos = 0;
11287c478bd9Sstevel@tonic-gate 	}
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 	/* Check each index */
11317c478bd9Sstevel@tonic-gate 	for (i = 0; i < x->index.numIndexes; i++) {
11327c478bd9Sstevel@tonic-gate 		int	len = 0;
11337c478bd9Sstevel@tonic-gate 		char	*value = 0;
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 		/* Skip NULL index names */
11367c478bd9Sstevel@tonic-gate 		if (x->index.name[i] == 0)
11377c478bd9Sstevel@tonic-gate 			continue;
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 		/* Check N2L values */
11407c478bd9Sstevel@tonic-gate 		if (yp2ldap) {
11417c478bd9Sstevel@tonic-gate 			if (name) {
11427c478bd9Sstevel@tonic-gate 				if (strcasecmp(x->index.name[i], name) == 0)
11437c478bd9Sstevel@tonic-gate 					value = val;
11447c478bd9Sstevel@tonic-gate 				else
11457c478bd9Sstevel@tonic-gate 					continue;
11467c478bd9Sstevel@tonic-gate 			} else if (rv) {
11477c478bd9Sstevel@tonic-gate 				if (strcasecmp(x->index.name[i], N2LKEY) == 0 ||
11487c478bd9Sstevel@tonic-gate 					strcasecmp(x->index.name[i], N2LIPKEY)
11497c478bd9Sstevel@tonic-gate 							== 0)
11507c478bd9Sstevel@tonic-gate 					continue;
11517c478bd9Sstevel@tonic-gate 				value = findVal(x->index.name[i], rv,
11527c478bd9Sstevel@tonic-gate 							mit_nisplus);
11537c478bd9Sstevel@tonic-gate 			}
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 			if (value && verifyMappingMatch(x->index.value[i],
11567c478bd9Sstevel@tonic-gate 									value))
11577c478bd9Sstevel@tonic-gate 				pass[ppos++] = x->index.name[i];
11587c478bd9Sstevel@tonic-gate 			else
11597c478bd9Sstevel@tonic-gate 				fail[fpos++] = x->index.name[i];
11607c478bd9Sstevel@tonic-gate 			continue;
11617c478bd9Sstevel@tonic-gate 		}
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 		/* If here, means nis+2ldap */
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 		/* Is the index name a known column ? */
11667c478bd9Sstevel@tonic-gate 		for (j = 0; j < x->numColumns; j++) {
11677c478bd9Sstevel@tonic-gate 			if (strcmp(x->index.name[i], x->column[j]) == 0) {
11687c478bd9Sstevel@tonic-gate 				/*
11697c478bd9Sstevel@tonic-gate 				 * Do we have a value for the column ?
11707c478bd9Sstevel@tonic-gate 				 */
11717c478bd9Sstevel@tonic-gate 				for (k = 0; k < q->components.components_len;
11727c478bd9Sstevel@tonic-gate 						k++) {
11737c478bd9Sstevel@tonic-gate 					if (q->components.components_val[k].
11747c478bd9Sstevel@tonic-gate 							which_index == j) {
11757c478bd9Sstevel@tonic-gate 						value = q->components.
11767c478bd9Sstevel@tonic-gate 							components_val[k].
11777c478bd9Sstevel@tonic-gate 							index_value->
11787c478bd9Sstevel@tonic-gate 							itemvalue.
11797c478bd9Sstevel@tonic-gate 							itemvalue_val;
11807c478bd9Sstevel@tonic-gate 						len = q->components.
11817c478bd9Sstevel@tonic-gate 							components_val[k].
11827c478bd9Sstevel@tonic-gate 							index_value->
11837c478bd9Sstevel@tonic-gate 							itemvalue.
11847c478bd9Sstevel@tonic-gate 							itemvalue_len;
11857c478bd9Sstevel@tonic-gate 						break;
11867c478bd9Sstevel@tonic-gate 					}
11877c478bd9Sstevel@tonic-gate 				}
11887c478bd9Sstevel@tonic-gate 				if (value != 0)
11897c478bd9Sstevel@tonic-gate 					break;
11907c478bd9Sstevel@tonic-gate 			}
11917c478bd9Sstevel@tonic-gate 		}
11927c478bd9Sstevel@tonic-gate 
11937c478bd9Sstevel@tonic-gate 		/*
11947c478bd9Sstevel@tonic-gate 		 * If we found a value, check if it matches the
11957c478bd9Sstevel@tonic-gate 		 * format. If no value found or no match, this
11967c478bd9Sstevel@tonic-gate 		 * mapping is _not_ an alternative. Otherwise,
11977c478bd9Sstevel@tonic-gate 		 * we continue checking any other indexes.
11987c478bd9Sstevel@tonic-gate 		 */
11997c478bd9Sstevel@tonic-gate 		if (value == 0 ||
12007c478bd9Sstevel@tonic-gate 			!verifyMappingMatch(x->index.value[i],
12017c478bd9Sstevel@tonic-gate 				value)) {
12027c478bd9Sstevel@tonic-gate 			match = 0;
12037c478bd9Sstevel@tonic-gate 			break;
12047c478bd9Sstevel@tonic-gate 		}
12057c478bd9Sstevel@tonic-gate 	}
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	if (yp2ldap) {
12087c478bd9Sstevel@tonic-gate 		for (--fpos; fpos >= 0; fpos--) {
12097c478bd9Sstevel@tonic-gate 			for (i = 0; i < ppos; i++) {
12107c478bd9Sstevel@tonic-gate 				if (strcmp(pass[i], fail[fpos]) == 0)
12117c478bd9Sstevel@tonic-gate 					break;
12127c478bd9Sstevel@tonic-gate 			}
12137c478bd9Sstevel@tonic-gate 			if (i == ppos) {
12147c478bd9Sstevel@tonic-gate 				match = 0;
12157c478bd9Sstevel@tonic-gate 				break;
12167c478bd9Sstevel@tonic-gate 			}
12177c478bd9Sstevel@tonic-gate 		}
12187c478bd9Sstevel@tonic-gate 		sfree(pass);
12197c478bd9Sstevel@tonic-gate 		sfree(fail);
12207c478bd9Sstevel@tonic-gate 	}
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate 	return (match);
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate /*
12267c478bd9Sstevel@tonic-gate  * Return all table mappings that match the column values in 'q'.
12277c478bd9Sstevel@tonic-gate  * If there's no match, return those alternative mappings that don't
12287c478bd9Sstevel@tonic-gate  * have an index; if no such mapping exists, return NULL.
12297c478bd9Sstevel@tonic-gate  *
12307c478bd9Sstevel@tonic-gate  * If 'wantWrite' is set, we want mappings for writing (i.e., data
12317c478bd9Sstevel@tonic-gate  * to LDAP); otherwise, we want mappings for reading.
12327c478bd9Sstevel@tonic-gate  *
12337c478bd9Sstevel@tonic-gate  * If 'wantObj' is set, we want object mappings only (i.e., _not_
12347c478bd9Sstevel@tonic-gate  * those used to map entries in tables).
12357c478bd9Sstevel@tonic-gate  *
12367c478bd9Sstevel@tonic-gate  * If 'dbId' is non-NULL, we select mappings with a matching dbId field.
12377c478bd9Sstevel@tonic-gate  */
12387c478bd9Sstevel@tonic-gate __nis_table_mapping_t **
selectTableMapping(__nis_table_mapping_t * t,db_query * q,int wantWrite,int wantObj,char * dbId,int * numMatches)12397c478bd9Sstevel@tonic-gate selectTableMapping(__nis_table_mapping_t *t, db_query *q,
12407c478bd9Sstevel@tonic-gate 			int wantWrite, int wantObj, char *dbId,
12417c478bd9Sstevel@tonic-gate 			int *numMatches) {
12427c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*r, *x, **tp;
12437c478bd9Sstevel@tonic-gate 	int			i, j, k, nm, numap;
12447c478bd9Sstevel@tonic-gate 	char			*myself = "selectTableMapping";
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 	if (numMatches == 0)
12477c478bd9Sstevel@tonic-gate 		numMatches = &nm;
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	/*
12507c478bd9Sstevel@tonic-gate 	 * Count the number of possible mappings, so that we can
12517c478bd9Sstevel@tonic-gate 	 * allocate the 'tp' array up front.
12527c478bd9Sstevel@tonic-gate 	 */
12537c478bd9Sstevel@tonic-gate 	for (numap = 0, x = t; x != 0; numap++, x = x->next);
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	if (numap == 0) {
12567c478bd9Sstevel@tonic-gate 		*numMatches = 0;
12577c478bd9Sstevel@tonic-gate 		return (0);
12587c478bd9Sstevel@tonic-gate 	}
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 	tp = am(myself, numap * sizeof (tp[0]));
12617c478bd9Sstevel@tonic-gate 	if (tp == 0) {
12627c478bd9Sstevel@tonic-gate 		*numMatches = -1;
12637c478bd9Sstevel@tonic-gate 		return (0);
12647c478bd9Sstevel@tonic-gate 	}
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate 	/*
12677c478bd9Sstevel@tonic-gate 	 * Special cases:
12687c478bd9Sstevel@tonic-gate 	 *
12697c478bd9Sstevel@tonic-gate 	 *	q == 0 trivially matches any 't' of the correct object type
12707c478bd9Sstevel@tonic-gate 	 *
12717c478bd9Sstevel@tonic-gate 	 *	wantObj != 0 means we ignore 'q'
12727c478bd9Sstevel@tonic-gate 	 */
12737c478bd9Sstevel@tonic-gate 	if (q == 0 || wantObj) {
12747c478bd9Sstevel@tonic-gate 		for (i = 0, x = t, nm = 0; i < numap; i++, x = x->next) {
12757c478bd9Sstevel@tonic-gate 			if (x->objectDN == 0)
12767c478bd9Sstevel@tonic-gate 				continue;
12777c478bd9Sstevel@tonic-gate 			if (wantWrite) {
12787c478bd9Sstevel@tonic-gate 				if (x->objectDN->write.scope ==
12797c478bd9Sstevel@tonic-gate 						LDAP_SCOPE_UNKNOWN)
12807c478bd9Sstevel@tonic-gate 					continue;
12817c478bd9Sstevel@tonic-gate 			} else {
12827c478bd9Sstevel@tonic-gate 				if (x->objectDN->read.scope ==
12837c478bd9Sstevel@tonic-gate 						LDAP_SCOPE_UNKNOWN)
12847c478bd9Sstevel@tonic-gate 					continue;
12857c478bd9Sstevel@tonic-gate 			}
12867c478bd9Sstevel@tonic-gate 			if (wantObj) {
12877c478bd9Sstevel@tonic-gate 				if (x->numColumns > 0)
12887c478bd9Sstevel@tonic-gate 					continue;
12897c478bd9Sstevel@tonic-gate 			} else {
12907c478bd9Sstevel@tonic-gate 				if (x->numColumns <= 0)
12917c478bd9Sstevel@tonic-gate 					continue;
12927c478bd9Sstevel@tonic-gate 			}
12937c478bd9Sstevel@tonic-gate 			if (dbId != 0 && x->dbId != 0 &&
12947c478bd9Sstevel@tonic-gate 					strcmp(dbId, x->dbId) != 0)
12957c478bd9Sstevel@tonic-gate 				continue;
12967c478bd9Sstevel@tonic-gate 			tp[nm] = x;
12977c478bd9Sstevel@tonic-gate 			nm++;
12987c478bd9Sstevel@tonic-gate 		}
12997c478bd9Sstevel@tonic-gate 		*numMatches = nm;
13007c478bd9Sstevel@tonic-gate 		if (nm == 0) {
13017c478bd9Sstevel@tonic-gate 			sfree(tp);
13027c478bd9Sstevel@tonic-gate 			tp = 0;
13037c478bd9Sstevel@tonic-gate 		}
13047c478bd9Sstevel@tonic-gate 		return (tp);
13057c478bd9Sstevel@tonic-gate 	}
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate 	/* Scan all mappings, and collect candidates */
13087c478bd9Sstevel@tonic-gate 	for (nm = 0, r = 0, x = t; x != 0; x = x->next) {
13097c478bd9Sstevel@tonic-gate 		if (x->objectDN == 0)
13107c478bd9Sstevel@tonic-gate 			continue;
13117c478bd9Sstevel@tonic-gate 		if (wantWrite) {
13127c478bd9Sstevel@tonic-gate 			if (x->objectDN->write.scope == LDAP_SCOPE_UNKNOWN)
13137c478bd9Sstevel@tonic-gate 				continue;
13147c478bd9Sstevel@tonic-gate 		} else {
13157c478bd9Sstevel@tonic-gate 			if (x->objectDN->read.scope == LDAP_SCOPE_UNKNOWN)
13167c478bd9Sstevel@tonic-gate 				continue;
13177c478bd9Sstevel@tonic-gate 		}
13187c478bd9Sstevel@tonic-gate 		/* Only want table/entry mappings */
13197c478bd9Sstevel@tonic-gate 		if (x->numColumns <= 0)
13207c478bd9Sstevel@tonic-gate 			continue;
13217c478bd9Sstevel@tonic-gate 		if (dbId != 0 && x->dbId != 0 &&
13227c478bd9Sstevel@tonic-gate 				strcmp(dbId, x->dbId) != 0)
13237c478bd9Sstevel@tonic-gate 			continue;
13247c478bd9Sstevel@tonic-gate 		/*
13257c478bd9Sstevel@tonic-gate 		 * It's a match if: there are no indexes, or we actually
13267c478bd9Sstevel@tonic-gate 		 * match the query with the indexes.
13277c478bd9Sstevel@tonic-gate 		 */
13287c478bd9Sstevel@tonic-gate 		if (x->index.numIndexes <= 0 ||
13297c478bd9Sstevel@tonic-gate 					verifyIndexMatch(x, q, 0, 0, 0)) {
13307c478bd9Sstevel@tonic-gate 			tp[nm] = x;
13317c478bd9Sstevel@tonic-gate 			nm++;
13327c478bd9Sstevel@tonic-gate 		}
13337c478bd9Sstevel@tonic-gate 	}
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 	if (nm == 0) {
13367c478bd9Sstevel@tonic-gate 		free(tp);
13377c478bd9Sstevel@tonic-gate 		tp = 0;
13387c478bd9Sstevel@tonic-gate 	}
13397c478bd9Sstevel@tonic-gate 
13407c478bd9Sstevel@tonic-gate 	*numMatches = nm;
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 	return (tp);
13437c478bd9Sstevel@tonic-gate }
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate /*
13467c478bd9Sstevel@tonic-gate  * Return 1 if there's an indexed mapping, 0 otherwise.
13477c478bd9Sstevel@tonic-gate  */
13487c478bd9Sstevel@tonic-gate int
haveIndexedMapping(__nis_table_mapping_t * t)13497c478bd9Sstevel@tonic-gate haveIndexedMapping(__nis_table_mapping_t *t) {
13507c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*x;
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	for (x = t; x != 0; x = x->next) {
13537c478bd9Sstevel@tonic-gate 		if (x->index.numIndexes > 0)
13547c478bd9Sstevel@tonic-gate 			return (1);
13557c478bd9Sstevel@tonic-gate 	}
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 	return (0);
13587c478bd9Sstevel@tonic-gate }
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate /*
13617c478bd9Sstevel@tonic-gate  * Given an input string 'attrs' of the form "attr1=val1,attr2=val2,...",
13627c478bd9Sstevel@tonic-gate  * or a filter, return the value associated with the attribute 'attrName'.
13637c478bd9Sstevel@tonic-gate  * If no instance of 'attrName' is found, return 'default'. In all cases,
13647c478bd9Sstevel@tonic-gate  * the return value is a copy, and must be freed by the caller.
13657c478bd9Sstevel@tonic-gate  *
13667c478bd9Sstevel@tonic-gate  * Of course, return NULL in case of failure.
13677c478bd9Sstevel@tonic-gate  */
13687c478bd9Sstevel@tonic-gate static char *
attrVal(char * msg,char * attrName,char * def,char * attrs)13697c478bd9Sstevel@tonic-gate attrVal(char *msg, char *attrName, char *def, char *attrs) {
13707c478bd9Sstevel@tonic-gate 	char	*val, *filter, **fc = 0;
13717c478bd9Sstevel@tonic-gate 	int	i, nfc;
13727c478bd9Sstevel@tonic-gate 	char	*myself = "attrVal";
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 	if (attrName == 0 || attrs == 0)
13757c478bd9Sstevel@tonic-gate 		return (0);
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate 	if (msg == 0)
13787c478bd9Sstevel@tonic-gate 		msg = myself;
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate 	val = def;
13817c478bd9Sstevel@tonic-gate 
13827c478bd9Sstevel@tonic-gate 	filter = makeFilter(attrs);
13837c478bd9Sstevel@tonic-gate 	if (filter != 0 && (fc = makeFilterComp(filter, &nfc)) != 0 &&
13847c478bd9Sstevel@tonic-gate 			nfc > 0) {
13857c478bd9Sstevel@tonic-gate 		for (i = 0; i < nfc; i++) {
13867c478bd9Sstevel@tonic-gate 			char	*name, *value;
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 			name = fc[i];
13897c478bd9Sstevel@tonic-gate 			/* Skip if not of attr=value form */
13907c478bd9Sstevel@tonic-gate 			if ((value = strchr(name, '=')) == 0)
13917c478bd9Sstevel@tonic-gate 				continue;
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate 			*value = '\0';
13947c478bd9Sstevel@tonic-gate 			value++;
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 			if (strcasecmp(attrName, name) == 0) {
13977c478bd9Sstevel@tonic-gate 				val = value;
13987c478bd9Sstevel@tonic-gate 				break;
13997c478bd9Sstevel@tonic-gate 			}
14007c478bd9Sstevel@tonic-gate 		}
14017c478bd9Sstevel@tonic-gate 	}
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	if (val != 0)
14047c478bd9Sstevel@tonic-gate 		val = sdup(msg, T, val);
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 	sfree(filter);
14077c478bd9Sstevel@tonic-gate 	freeFilterComp(fc, nfc);
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 	return (val);
14107c478bd9Sstevel@tonic-gate }
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate extern bool_t	xdr_nis_object(register XDR *xdrs, nis_object *objp);
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate /*
14157c478bd9Sstevel@tonic-gate  * Copy an XDR:ed version of the NIS+ object 'o' (or the one indicated
14167c478bd9Sstevel@tonic-gate  * by 't->objName' if 'o' is NULL) to the place indicated by
14177c478bd9Sstevel@tonic-gate  * 't->objectDN->write'. Return an appropriate LDAP status code.
14187c478bd9Sstevel@tonic-gate  */
14197c478bd9Sstevel@tonic-gate int
objToLDAP(__nis_table_mapping_t * t,nis_object * o,entry_obj ** ea,int numEa)14207c478bd9Sstevel@tonic-gate objToLDAP(__nis_table_mapping_t *t, nis_object *o, entry_obj **ea, int numEa) {
14217c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	**tp;
14227c478bd9Sstevel@tonic-gate 	XDR			xdr;
14237c478bd9Sstevel@tonic-gate 	char			*objName;
14247c478bd9Sstevel@tonic-gate 	int			stat, osize, n, numMatches = 0;
14257c478bd9Sstevel@tonic-gate 	void			*buf;
14267c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
14277c478bd9Sstevel@tonic-gate 	__nis_value_t		*val;
14287c478bd9Sstevel@tonic-gate 	__nis_single_value_t	*sv;
14297c478bd9Sstevel@tonic-gate 	char			**attrName, *dn;
14307c478bd9Sstevel@tonic-gate 	char			*myself = "objToLDAP";
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 	if (t == 0)
14337c478bd9Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
14367c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
14377c478bd9Sstevel@tonic-gate 		LOG_WARNING,
14387c478bd9Sstevel@tonic-gate #else
14397c478bd9Sstevel@tonic-gate 		LOG_INFO,
14407c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
14417c478bd9Sstevel@tonic-gate 		"%s: %s", myself, NIL(t->objName));
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	tp = selectTableMapping(t, 0, 1, 1, 0, &numMatches);
14447c478bd9Sstevel@tonic-gate 	if (tp == 0 || numMatches <= 0) {
14457c478bd9Sstevel@tonic-gate 		sfree(tp);
14467c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK,
14477c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
14487c478bd9Sstevel@tonic-gate 			LOG_WARNING,
14497c478bd9Sstevel@tonic-gate #else
14507c478bd9Sstevel@tonic-gate 			LOG_INFO,
14517c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
14527c478bd9Sstevel@tonic-gate 			"%s: %s (no mapping)", myself, NIL(t->objName));
14537c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
14547c478bd9Sstevel@tonic-gate 	}
14557c478bd9Sstevel@tonic-gate 
14567c478bd9Sstevel@tonic-gate 	for (n = 0; n < numMatches; n++) {
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 		t = tp[n];
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate 		if (o == 0) {
14617c478bd9Sstevel@tonic-gate 			sfree(tp);
14627c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
14637c478bd9Sstevel@tonic-gate 		}
14647c478bd9Sstevel@tonic-gate 
14657c478bd9Sstevel@tonic-gate 		buf = (char *)xdrNisObject(o, ea, numEa, &osize);
14667c478bd9Sstevel@tonic-gate 		if (buf == 0) {
14677c478bd9Sstevel@tonic-gate 			sfree(tp);
14687c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
14697c478bd9Sstevel@tonic-gate 		}
14707c478bd9Sstevel@tonic-gate 
14717c478bd9Sstevel@tonic-gate 		/*
14727c478bd9Sstevel@tonic-gate 		 * Prepare to build a rule-value containing the XDR:ed
14737c478bd9Sstevel@tonic-gate 		 * object
14747c478bd9Sstevel@tonic-gate 		 */
14757c478bd9Sstevel@tonic-gate 		rv = am(myself, sizeof (*rv));
14767c478bd9Sstevel@tonic-gate 		sv = am(myself, sizeof (*sv));
14777c478bd9Sstevel@tonic-gate 		val = am(myself, sizeof (*val));
14787c478bd9Sstevel@tonic-gate 		attrName = am(myself, sizeof (attrName[0]));
14797c478bd9Sstevel@tonic-gate 		if (attrName != 0)
14807c478bd9Sstevel@tonic-gate 			attrName[0] = attrVal(myself, "nisplusObject",
14817c478bd9Sstevel@tonic-gate 						"nisplusObject",
14827c478bd9Sstevel@tonic-gate 						t->objectDN->write.attrs);
14837c478bd9Sstevel@tonic-gate 		if (rv == 0 || sv == 0 || val == 0 || attrName == 0 ||
14847c478bd9Sstevel@tonic-gate 				attrName[0] == 0) {
14857c478bd9Sstevel@tonic-gate 			sfree(tp);
14867c478bd9Sstevel@tonic-gate 			sfree(buf);
14877c478bd9Sstevel@tonic-gate 			sfree(rv);
14887c478bd9Sstevel@tonic-gate 			sfree(sv);
14897c478bd9Sstevel@tonic-gate 			sfree(val);
14907c478bd9Sstevel@tonic-gate 			sfree(attrName);
14917c478bd9Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
14927c478bd9Sstevel@tonic-gate 		}
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 		sv->length = osize;
14957c478bd9Sstevel@tonic-gate 		sv->value = buf;
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate 		/* 'vt_ber' just means "not a NUL-terminated string" */
14987c478bd9Sstevel@tonic-gate 		val->type = vt_ber;
14997c478bd9Sstevel@tonic-gate 		val->repeat = 0;
15007c478bd9Sstevel@tonic-gate 		val->numVals = 1;
15017c478bd9Sstevel@tonic-gate 		val->val = sv;
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 		rv->numAttrs = 1;
15047c478bd9Sstevel@tonic-gate 		rv->attrName = attrName;
15057c478bd9Sstevel@tonic-gate 		rv->attrVal = val;
15067c478bd9Sstevel@tonic-gate 
15077c478bd9Sstevel@tonic-gate 		/*
15087c478bd9Sstevel@tonic-gate 		 * The 'write.base' is the actual DN of the entry (and the
15097c478bd9Sstevel@tonic-gate 		 * scope had better be 'base', but we don't check that).
15107c478bd9Sstevel@tonic-gate 		 */
15117c478bd9Sstevel@tonic-gate 		dn = t->objectDN->write.base;
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 		stat = ldapModify(dn, rv, t->objectDN->write.attrs, 1);
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, 1);
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
15187c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
15197c478bd9Sstevel@tonic-gate 		LOG_WARNING,
15207c478bd9Sstevel@tonic-gate #else
15217c478bd9Sstevel@tonic-gate 		LOG_INFO,
15227c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
15237c478bd9Sstevel@tonic-gate 		"%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate 		if (stat != LDAP_SUCCESS)
15267c478bd9Sstevel@tonic-gate 			break;
15277c478bd9Sstevel@tonic-gate 
15287c478bd9Sstevel@tonic-gate 	}
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 	sfree(tp);
15317c478bd9Sstevel@tonic-gate 
15327c478bd9Sstevel@tonic-gate 	return (stat);
15337c478bd9Sstevel@tonic-gate }
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate /*
15367c478bd9Sstevel@tonic-gate  * Retrieve a copy of the 't->objName' object from LDAP, where it's
15377c478bd9Sstevel@tonic-gate  * stored in XDR:ed form in the place indicated by 't->objectDN->read'.
15387c478bd9Sstevel@tonic-gate  * Un-XDR the object, and return a pointer to it in '*obj'; it's the
15397c478bd9Sstevel@tonic-gate  * responsibility of the caller to free the object when it's no
15407c478bd9Sstevel@tonic-gate  * longer needed.
15417c478bd9Sstevel@tonic-gate  *
15427c478bd9Sstevel@tonic-gate  * Returns an appropriate LDAP status.
15437c478bd9Sstevel@tonic-gate  */
15447c478bd9Sstevel@tonic-gate int
objFromLDAP(__nis_table_mapping_t * t,nis_object ** obj,entry_obj *** eaP,int * numEaP)15457c478bd9Sstevel@tonic-gate objFromLDAP(__nis_table_mapping_t *t, nis_object **obj,
15467c478bd9Sstevel@tonic-gate 		entry_obj ***eaP, int *numEaP) {
15477c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	**tp;
15487c478bd9Sstevel@tonic-gate 	XDR			xdr;
15497c478bd9Sstevel@tonic-gate 	nis_object		*o;
15507c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
15517c478bd9Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
15527c478bd9Sstevel@tonic-gate 	char			*attrs[2], *filter, **fc = 0;
15537c478bd9Sstevel@tonic-gate 	void			*buf;
15547c478bd9Sstevel@tonic-gate 	int			i, j, nfc, nrv, blen, stat = LDAP_SUCCESS;
15557c478bd9Sstevel@tonic-gate 	int			n, numMatches;
15567c478bd9Sstevel@tonic-gate 	char			*myself = "objFromLDAP";
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 	if (t == 0)
15597c478bd9Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
15607c478bd9Sstevel@tonic-gate 
15617c478bd9Sstevel@tonic-gate 	/*
15627c478bd9Sstevel@tonic-gate 	 * If there's nowhere to store the result, we might as
15637c478bd9Sstevel@tonic-gate 	 * well pretend all went well, and return right away.
15647c478bd9Sstevel@tonic-gate 	 */
15657c478bd9Sstevel@tonic-gate 	if (obj == 0)
15667c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate 	/* Prepare for the worst */
15697c478bd9Sstevel@tonic-gate 	*obj = 0;
15707c478bd9Sstevel@tonic-gate 
15717c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
15727c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
15737c478bd9Sstevel@tonic-gate 		LOG_WARNING,
15747c478bd9Sstevel@tonic-gate #else
15757c478bd9Sstevel@tonic-gate 		LOG_INFO,
15767c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
15777c478bd9Sstevel@tonic-gate 		"%s: %s", myself, NIL(t->objName));
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate 	tp = selectTableMapping(t, 0, 0, 1, 0, &numMatches);
15807c478bd9Sstevel@tonic-gate 	if (tp == 0 || numMatches <= 0) {
15817c478bd9Sstevel@tonic-gate 		sfree(tp);
15827c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK,
15837c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
15847c478bd9Sstevel@tonic-gate 			LOG_WARNING,
15857c478bd9Sstevel@tonic-gate #else
15867c478bd9Sstevel@tonic-gate 			LOG_INFO,
15877c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
15887c478bd9Sstevel@tonic-gate 			"%s: %s (no mapping)", myself, NIL(t->objName));
15897c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
15907c478bd9Sstevel@tonic-gate 	}
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 	for (n = 0; n < numMatches; n++) {
15937c478bd9Sstevel@tonic-gate 
15947c478bd9Sstevel@tonic-gate 		t = tp[n];
15957c478bd9Sstevel@tonic-gate 
15967c478bd9Sstevel@tonic-gate 		filter = makeFilter(t->objectDN->read.attrs);
15977c478bd9Sstevel@tonic-gate 		if (filter == 0 || (fc = makeFilterComp(filter, &nfc)) == 0 ||
15987c478bd9Sstevel@tonic-gate 				nfc <= 0) {
15997c478bd9Sstevel@tonic-gate 			sfree(tp);
16007c478bd9Sstevel@tonic-gate 			sfree(filter);
16017c478bd9Sstevel@tonic-gate 			freeFilterComp(fc, nfc);
16027c478bd9Sstevel@tonic-gate 			return ((t->objectDN->read.attrs != 0) ?
16037c478bd9Sstevel@tonic-gate 				LDAP_NO_MEMORY : LDAP_PARAM_ERROR);
16047c478bd9Sstevel@tonic-gate 		}
16057c478bd9Sstevel@tonic-gate 		/* Don't need the filter, just the components */
16067c478bd9Sstevel@tonic-gate 		sfree(filter);
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate 		/*
16097c478bd9Sstevel@tonic-gate 		 * Look for a "nisplusObject" attribute, and (if found) copy
16107c478bd9Sstevel@tonic-gate 		 * the value to attrs[0]. Also remove the "nisplusObject"
16117c478bd9Sstevel@tonic-gate 		 * attribute and value from the filter components.
16127c478bd9Sstevel@tonic-gate 		 */
16137c478bd9Sstevel@tonic-gate 		attrs[0] = sdup(myself, T, "nisplusObject");
16147c478bd9Sstevel@tonic-gate 		if (attrs[0] == 0) {
16157c478bd9Sstevel@tonic-gate 			sfree(tp);
16167c478bd9Sstevel@tonic-gate 			freeFilterComp(fc, nfc);
16177c478bd9Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
16187c478bd9Sstevel@tonic-gate 		}
16197c478bd9Sstevel@tonic-gate 		attrs[1] = 0;
16207c478bd9Sstevel@tonic-gate 		for (i = 0; i < nfc; i++) {
16217c478bd9Sstevel@tonic-gate 			char	*name, *value;
16227c478bd9Sstevel@tonic-gate 			int	compare;
16237c478bd9Sstevel@tonic-gate 
16247c478bd9Sstevel@tonic-gate 			name = fc[i];
16257c478bd9Sstevel@tonic-gate 			/* Skip if not of attr=value form */
16267c478bd9Sstevel@tonic-gate 			if ((value = strchr(name, '=')) == 0)
16277c478bd9Sstevel@tonic-gate 				continue;
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 			/* Temporarily overWrite the '=' with a '\0' */
16307c478bd9Sstevel@tonic-gate 			*value = '\0';
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate 			/* Compare with our target attribute name */
16337c478bd9Sstevel@tonic-gate 			compare = strcasecmp("nisplusObject", name);
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 			/* Put back the '=' */
16367c478bd9Sstevel@tonic-gate 			*value = '=';
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate 			/* Is it the name we're looking for ? */
16397c478bd9Sstevel@tonic-gate 			if (compare == 0) {
16407c478bd9Sstevel@tonic-gate 				sfree(attrs[0]);
16417c478bd9Sstevel@tonic-gate 				attrs[0] = sdup(myself, T, value+1);
16427c478bd9Sstevel@tonic-gate 				if (attrs[0] == 0) {
16437c478bd9Sstevel@tonic-gate 					sfree(tp);
16447c478bd9Sstevel@tonic-gate 					freeFilterComp(fc, nfc);
16457c478bd9Sstevel@tonic-gate 					return (LDAP_NO_MEMORY);
16467c478bd9Sstevel@tonic-gate 				}
16477c478bd9Sstevel@tonic-gate 				sfree(fc[i]);
16487c478bd9Sstevel@tonic-gate 				if (i < nfc-1)
16497c478bd9Sstevel@tonic-gate 					(void) memmove(&fc[i], &fc[i+1],
16507c478bd9Sstevel@tonic-gate 						(nfc-1-i) * sizeof (fc[i]));
16517c478bd9Sstevel@tonic-gate 				nfc--;
16527c478bd9Sstevel@tonic-gate 				break;
16537c478bd9Sstevel@tonic-gate 			}
16547c478bd9Sstevel@tonic-gate 		}
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 		ls = buildLdapSearch(t->objectDN->read.base,
16577c478bd9Sstevel@tonic-gate 					t->objectDN->read.scope,
16587c478bd9Sstevel@tonic-gate 					nfc, fc, 0, attrs, 0, 1);
16597c478bd9Sstevel@tonic-gate 		sfree(attrs[0]);
16607c478bd9Sstevel@tonic-gate 		freeFilterComp(fc, nfc);
16617c478bd9Sstevel@tonic-gate 		if (ls == 0) {
16627c478bd9Sstevel@tonic-gate 			sfree(tp);
16637c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
16647c478bd9Sstevel@tonic-gate 		}
16657c478bd9Sstevel@tonic-gate 
16667c478bd9Sstevel@tonic-gate 		nrv = 0;
16677c478bd9Sstevel@tonic-gate 		rv = ldapSearch(ls, &nrv, 0, &stat);
16687c478bd9Sstevel@tonic-gate 		if (rv == 0) {
16697c478bd9Sstevel@tonic-gate 			sfree(tp);
16707c478bd9Sstevel@tonic-gate 			freeLdapSearch(ls);
16717c478bd9Sstevel@tonic-gate 			return (stat);
16727c478bd9Sstevel@tonic-gate 		}
16737c478bd9Sstevel@tonic-gate 
16747c478bd9Sstevel@tonic-gate 		for (i = 0, buf = 0; i < nrv && buf == 0; i++) {
16757c478bd9Sstevel@tonic-gate 			for (j = 0; j < rv[i].numAttrs; j++) {
16767c478bd9Sstevel@tonic-gate 				if (strcasecmp(ls->attrs[0],
16777c478bd9Sstevel@tonic-gate 					rv[i].attrName[j]) == 0) {
16787c478bd9Sstevel@tonic-gate 					if (rv[i].attrVal[j].numVals <= 0)
16797c478bd9Sstevel@tonic-gate 						continue;
16807c478bd9Sstevel@tonic-gate 					buf = rv[i].attrVal[j].val[0].value;
16817c478bd9Sstevel@tonic-gate 					blen = rv[i].attrVal[j].val[0].length;
16827c478bd9Sstevel@tonic-gate 					break;
16837c478bd9Sstevel@tonic-gate 				}
16847c478bd9Sstevel@tonic-gate 			}
16857c478bd9Sstevel@tonic-gate 		}
16867c478bd9Sstevel@tonic-gate 
16877c478bd9Sstevel@tonic-gate 		if (buf != 0) {
16887c478bd9Sstevel@tonic-gate 			o = unXdrNisObject(buf, blen, eaP, numEaP);
16897c478bd9Sstevel@tonic-gate 			if (o == 0) {
16907c478bd9Sstevel@tonic-gate 				sfree(tp);
16917c478bd9Sstevel@tonic-gate 				freeLdapSearch(ls);
16927c478bd9Sstevel@tonic-gate 				freeRuleValue(rv, nrv);
16937c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
16947c478bd9Sstevel@tonic-gate 			}
16957c478bd9Sstevel@tonic-gate 			stat = LDAP_SUCCESS;
16967c478bd9Sstevel@tonic-gate 			*obj = o;
16977c478bd9Sstevel@tonic-gate 		} else {
16987c478bd9Sstevel@tonic-gate 			stat = LDAP_NO_SUCH_OBJECT;
16997c478bd9Sstevel@tonic-gate 		}
17007c478bd9Sstevel@tonic-gate 
17017c478bd9Sstevel@tonic-gate 		freeLdapSearch(ls);
17027c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, nrv);
17037c478bd9Sstevel@tonic-gate 
17047c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
17057c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
17067c478bd9Sstevel@tonic-gate 		LOG_WARNING,
17077c478bd9Sstevel@tonic-gate #else
17087c478bd9Sstevel@tonic-gate 		LOG_INFO,
17097c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
17107c478bd9Sstevel@tonic-gate 		"%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
17117c478bd9Sstevel@tonic-gate 
17127c478bd9Sstevel@tonic-gate 		if (stat != LDAP_SUCCESS)
17137c478bd9Sstevel@tonic-gate 			break;
17147c478bd9Sstevel@tonic-gate 
17157c478bd9Sstevel@tonic-gate 	}
17167c478bd9Sstevel@tonic-gate 
17177c478bd9Sstevel@tonic-gate 	sfree(tp);
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 	return (stat);
17207c478bd9Sstevel@tonic-gate }
17217c478bd9Sstevel@tonic-gate 
17227c478bd9Sstevel@tonic-gate int
deleteLDAPobj(__nis_table_mapping_t * t)17237c478bd9Sstevel@tonic-gate deleteLDAPobj(__nis_table_mapping_t *t) {
17247c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	**tp;
17257c478bd9Sstevel@tonic-gate 	int		n, stat, numMatches = 0;
17267c478bd9Sstevel@tonic-gate 	char		*myself = "deleteLDAPobj";
17277c478bd9Sstevel@tonic-gate 
17287c478bd9Sstevel@tonic-gate 	if (t == 0)
17297c478bd9Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
17307c478bd9Sstevel@tonic-gate 
17317c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
17327c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
17337c478bd9Sstevel@tonic-gate 		LOG_WARNING,
17347c478bd9Sstevel@tonic-gate #else
17357c478bd9Sstevel@tonic-gate 		LOG_INFO,
17367c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
17377c478bd9Sstevel@tonic-gate 		"%s: %s", myself, NIL(t->objName));
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 	tp = selectTableMapping(t, 0, 1, 1, 0, &numMatches);
17407c478bd9Sstevel@tonic-gate 	if (tp == 0 || numMatches <= 0) {
17417c478bd9Sstevel@tonic-gate 		sfree(tp);
17427c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK,
17437c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
17447c478bd9Sstevel@tonic-gate 			LOG_WARNING,
17457c478bd9Sstevel@tonic-gate #else
17467c478bd9Sstevel@tonic-gate 			LOG_INFO,
17477c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
17487c478bd9Sstevel@tonic-gate 			"%s: %s (no mapping)", myself, NIL(t->objName));
17497c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
17507c478bd9Sstevel@tonic-gate 	}
17517c478bd9Sstevel@tonic-gate 
17527c478bd9Sstevel@tonic-gate 	for (n = 0; n < numMatches; n++) {
17537c478bd9Sstevel@tonic-gate 
17547c478bd9Sstevel@tonic-gate 		t = tp[n];
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 		if (t->objectDN->delDisp == dd_always) {
17577c478bd9Sstevel@tonic-gate 			/* Delete entire entry */
17587c478bd9Sstevel@tonic-gate 			stat = ldapModify(t->objectDN->write.base, 0,
17597c478bd9Sstevel@tonic-gate 					t->objectDN->write.attrs, 1);
17607c478bd9Sstevel@tonic-gate 		} else if (t->objectDN->delDisp == dd_perDbId) {
17617c478bd9Sstevel@tonic-gate 			/*
17627c478bd9Sstevel@tonic-gate 			 * Delete the attribute holding the object.
17637c478bd9Sstevel@tonic-gate 			 * First, determine what that attribute is called.
17647c478bd9Sstevel@tonic-gate 			 */
17657c478bd9Sstevel@tonic-gate 			char			*attrName =
17667c478bd9Sstevel@tonic-gate 						attrVal(myself,
17677c478bd9Sstevel@tonic-gate 							"nisplusObject",
17687c478bd9Sstevel@tonic-gate 							"nisplusObject",
17697c478bd9Sstevel@tonic-gate 						t->objectDN->write.attrs);
17707c478bd9Sstevel@tonic-gate 			__nis_rule_value_t	rv;
17717c478bd9Sstevel@tonic-gate 			__nis_value_t		val;
17727c478bd9Sstevel@tonic-gate 
17737c478bd9Sstevel@tonic-gate 			if (attrName == 0) {
17747c478bd9Sstevel@tonic-gate 				sfree(tp);
17757c478bd9Sstevel@tonic-gate 				return (LDAP_NO_MEMORY);
17767c478bd9Sstevel@tonic-gate 			}
17777c478bd9Sstevel@tonic-gate 
17787c478bd9Sstevel@tonic-gate 			/*
17797c478bd9Sstevel@tonic-gate 			 * Build a __nis_value_t with 'numVals' < 0 to
17807c478bd9Sstevel@tonic-gate 			 * indicate deletion.
17817c478bd9Sstevel@tonic-gate 			 */
17827c478bd9Sstevel@tonic-gate 			val.type = vt_ber;
17837c478bd9Sstevel@tonic-gate 			val.numVals = -1;
17847c478bd9Sstevel@tonic-gate 			val.val = 0;
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate 			/*
17877c478bd9Sstevel@tonic-gate 			 * Build a rule-value with the name we determined
17887c478bd9Sstevel@tonic-gate 			 * above, and the deletion value.
17897c478bd9Sstevel@tonic-gate 			 */
17907c478bd9Sstevel@tonic-gate 			(void) memset(&rv, 0, sizeof (rv));
17917c478bd9Sstevel@tonic-gate 			rv.numAttrs = 1;
17927c478bd9Sstevel@tonic-gate 			rv.attrName = &attrName;
17937c478bd9Sstevel@tonic-gate 			rv.attrVal = &val;
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 			stat = ldapModify(t->objectDN->write.base, &rv,
17967c478bd9Sstevel@tonic-gate 						t->objectDN->write.attrs, 0);
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 			sfree(attrName);
17997c478bd9Sstevel@tonic-gate 		} else if (t->objectDN->delDisp == dd_never) {
18007c478bd9Sstevel@tonic-gate 			/* Nothing to do, so we're trivially successful */
18017c478bd9Sstevel@tonic-gate 			stat = LDAP_SUCCESS;
18027c478bd9Sstevel@tonic-gate 		} else {
18037c478bd9Sstevel@tonic-gate 			stat = LDAP_PARAM_ERROR;
18047c478bd9Sstevel@tonic-gate 		}
18057c478bd9Sstevel@tonic-gate 
18067c478bd9Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
18077c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
18087c478bd9Sstevel@tonic-gate 		LOG_WARNING,
18097c478bd9Sstevel@tonic-gate #else
18107c478bd9Sstevel@tonic-gate 		LOG_INFO,
18117c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
18127c478bd9Sstevel@tonic-gate 		"%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate 		/* If there were no such object, we've trivially succeeded */
18157c478bd9Sstevel@tonic-gate 		if (stat == LDAP_NO_SUCH_OBJECT)
18167c478bd9Sstevel@tonic-gate 			stat = LDAP_SUCCESS;
18177c478bd9Sstevel@tonic-gate 
18187c478bd9Sstevel@tonic-gate 		if (stat != LDAP_SUCCESS)
18197c478bd9Sstevel@tonic-gate 			break;
18207c478bd9Sstevel@tonic-gate 
18217c478bd9Sstevel@tonic-gate 	}
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate 	sfree(tp);
18247c478bd9Sstevel@tonic-gate 
18257c478bd9Sstevel@tonic-gate 	return (stat);
18267c478bd9Sstevel@tonic-gate }
1827