xref: /onnv-gate/usr/src/lib/libnisdb/ldap_map.c (revision 11262:b7ebfbf2359e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*11262SRajagopal.Andra@Sun.COM  * Common Development and Distribution License (the "License").
6*11262SRajagopal.Andra@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11262SRajagopal.Andra@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <strings.h>
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <sys/stat.h>
290Sstevel@tonic-gate #include <errno.h>
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <rpcsvc/nis.h>
320Sstevel@tonic-gate #include <rpc/xdr.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include "ldap_util.h"
350Sstevel@tonic-gate #include "ldap_attr.h"
360Sstevel@tonic-gate #include "ldap_ruleval.h"
370Sstevel@tonic-gate #include "ldap_op.h"
380Sstevel@tonic-gate #include "ldap_map.h"
390Sstevel@tonic-gate #include "ldap_glob.h"
400Sstevel@tonic-gate #include "ldap_xdr.h"
410Sstevel@tonic-gate #include "ldap_val.h"
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /* From yptol/dit_access_utils.h */
440Sstevel@tonic-gate #define	N2LKEY		"rf_key"
450Sstevel@tonic-gate #define	N2LIPKEY	"rf_ipkey"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate __nis_hash_table_mt	ldapMappingList = NIS_HASH_TABLE_MT_INIT;
480Sstevel@tonic-gate extern	int yp2ldap;
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 
510Sstevel@tonic-gate int
setColumnNames(__nis_table_mapping_t * t)520Sstevel@tonic-gate setColumnNames(__nis_table_mapping_t *t) {
53*11262SRajagopal.Andra@Sun.COM 	int	i, j, nic, noc;
540Sstevel@tonic-gate 	char	**col;
550Sstevel@tonic-gate 	zotypes	type;
560Sstevel@tonic-gate 	char	*myself = "setColumnNames";
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	if (t == 0)
590Sstevel@tonic-gate 		return (0);
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	type = t->objType;
620Sstevel@tonic-gate 	col = t->column;
630Sstevel@tonic-gate 	nic = (col != 0) ? t->numColumns : -1;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 	t->objType = NIS_BOGUS_OBJ;
660Sstevel@tonic-gate 	t->obj = 0;
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	/*
690Sstevel@tonic-gate 	 * If it's a table object, but there are no translation rules,
700Sstevel@tonic-gate 	 * this mapping is for the table object itself. In that case,
710Sstevel@tonic-gate 	 * we throw away the column names (if any).
720Sstevel@tonic-gate 	 */
730Sstevel@tonic-gate 	if (t->objType == NIS_TABLE_OBJ && t->numRulesFromLDAP == 0 &&
740Sstevel@tonic-gate 			t->numRulesToLDAP == 0) {
750Sstevel@tonic-gate 		for (i = 0; i < t->numColumns; i++)
760Sstevel@tonic-gate 			sfree(t->column[i]);
770Sstevel@tonic-gate 		sfree(t->column);
780Sstevel@tonic-gate 		t->column = 0;
790Sstevel@tonic-gate 		t->numColumns = 0;
800Sstevel@tonic-gate 		noc = 0;
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 	/*
840Sstevel@tonic-gate 	 * Verify that all column names found by the parser
850Sstevel@tonic-gate 	 * are present in the actual column list.
860Sstevel@tonic-gate 	 */
870Sstevel@tonic-gate 	if (verbose) {
880Sstevel@tonic-gate 		for (i = 0, noc = 0; i < nic; i++) {
890Sstevel@tonic-gate 			int	found = 0;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 			if (col[i] == 0)
920Sstevel@tonic-gate 				continue;
930Sstevel@tonic-gate 			/* Skip the 'zo_*' special column names */
940Sstevel@tonic-gate 			if (isObjAttrString(col[i]))
950Sstevel@tonic-gate 				continue;
960Sstevel@tonic-gate 			for (j = 0; j < t->numColumns; j++) {
970Sstevel@tonic-gate 				if (strcmp(col[i], t->column[j]) == 0) {
980Sstevel@tonic-gate 					noc++;
990Sstevel@tonic-gate 					found = 1;
1000Sstevel@tonic-gate 					break;
1010Sstevel@tonic-gate 				}
1020Sstevel@tonic-gate 			}
1030Sstevel@tonic-gate 			if (!found) {
1040Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1050Sstevel@tonic-gate 					"%s: No column \"%s\" in \"%s\"",
1060Sstevel@tonic-gate 					myself, NIL(col[i]), NIL(t->objName));
1070Sstevel@tonic-gate 			}
1080Sstevel@tonic-gate 		}
1090Sstevel@tonic-gate 	}
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	/* Remove any setup by the parser */
1120Sstevel@tonic-gate 	for (i = 0; i < nic; i++) {
1130Sstevel@tonic-gate 		sfree(col[i]);
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 	sfree(col);
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	return (0);
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate void
freeSingleObjAttr(__nis_obj_attr_t * attr)1210Sstevel@tonic-gate freeSingleObjAttr(__nis_obj_attr_t *attr) {
1220Sstevel@tonic-gate 	if (attr == 0)
1230Sstevel@tonic-gate 		return;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	sfree(attr->zo_owner);
1260Sstevel@tonic-gate 	sfree(attr->zo_group);
1270Sstevel@tonic-gate 	sfree(attr->zo_domain);
1280Sstevel@tonic-gate 	sfree(attr);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate void
freeObjAttr(__nis_obj_attr_t ** attr,int numAttr)1320Sstevel@tonic-gate freeObjAttr(__nis_obj_attr_t **attr, int numAttr) {
1330Sstevel@tonic-gate 	int	i;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	if (attr == 0)
1360Sstevel@tonic-gate 		return;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	for (i = 0; i < numAttr; i++) {
1390Sstevel@tonic-gate 		freeSingleObjAttr(attr[i]);
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	sfree(attr);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate __nis_obj_attr_t *
cloneObjAttr(__nis_obj_attr_t * old)1460Sstevel@tonic-gate cloneObjAttr(__nis_obj_attr_t *old) {
1470Sstevel@tonic-gate 	__nis_obj_attr_t	*new;
1480Sstevel@tonic-gate 	char			*myself = "cloneObjAttr";
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	if (old == 0)
1510Sstevel@tonic-gate 		return (0);
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	new = am(myself, sizeof (*new));
1540Sstevel@tonic-gate 	if (new == 0)
1550Sstevel@tonic-gate 		return (0);
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	new->zo_owner = sdup(myself, T, old->zo_owner);
1580Sstevel@tonic-gate 	if (new->zo_owner == 0 && old->zo_owner != 0)
1590Sstevel@tonic-gate 		goto cleanup;
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	new->zo_group = sdup(myself, T, old->zo_group);
1620Sstevel@tonic-gate 	if (new->zo_group == 0 && old->zo_group != 0)
1630Sstevel@tonic-gate 		goto cleanup;
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	new->zo_domain = sdup(myself, T, old->zo_domain);
1660Sstevel@tonic-gate 	if (new->zo_domain == 0 && old->zo_domain != 0)
1670Sstevel@tonic-gate 		goto cleanup;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	new->zo_access = old->zo_access;
1700Sstevel@tonic-gate 	new->zo_ttl = old->zo_ttl;
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	return (new);
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate cleanup:
1750Sstevel@tonic-gate 	freeSingleObjAttr(new);
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	return (0);
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate /*
1820Sstevel@tonic-gate  * Obtain NIS+ entries (in the form of db_query's) from the supplied table
1830Sstevel@tonic-gate  * mapping and db_query.
1840Sstevel@tonic-gate  *
1850Sstevel@tonic-gate  * If 'qin' is NULL, enumeration is desired.
1860Sstevel@tonic-gate  *
1870Sstevel@tonic-gate  * On exit, '*numQueries' contains the number of (db_query *)'s in the
1880Sstevel@tonic-gate  * return array, '*ldapStat' the LDAP operation status, and '*objAttr'
1890Sstevel@tonic-gate  * a pointer to an array (of '*numQueries elements) of object attributes
1900Sstevel@tonic-gate  * (zo_owner, etc.). If no object attributes were retrieved, '*objAttr'
1910Sstevel@tonic-gate  * is NULL; any and all of the (*objAttr)[i]'s may be NULL.
1920Sstevel@tonic-gate  */
1930Sstevel@tonic-gate db_query **
mapFromLDAP(__nis_table_mapping_t * t,db_query * qin,int * numQueries,char * dbId,int * ldapStat,__nis_obj_attr_t *** objAttr)1940Sstevel@tonic-gate mapFromLDAP(__nis_table_mapping_t *t, db_query *qin, int *numQueries,
1950Sstevel@tonic-gate 		char *dbId, int *ldapStat, __nis_obj_attr_t ***objAttr) {
1960Sstevel@tonic-gate 	__nis_table_mapping_t	**tp;
1970Sstevel@tonic-gate 	db_query		**q;
1980Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
1990Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
2000Sstevel@tonic-gate 	int			n, numVals, numMatches = 0;
2010Sstevel@tonic-gate 	int			stat;
2020Sstevel@tonic-gate 	__nis_obj_attr_t	**attr;
2030Sstevel@tonic-gate 	char			*myself = "mapFromLDAP";
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if (ldapStat == 0)
2060Sstevel@tonic-gate 		ldapStat = &stat;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	if (t == 0 || numQueries == 0) {
2090Sstevel@tonic-gate 		*ldapStat = LDAP_PARAM_ERROR;
2100Sstevel@tonic-gate 		return (0);
2110Sstevel@tonic-gate 	}
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	/* Select the correct table mapping(s) */
2140Sstevel@tonic-gate 	tp = selectTableMapping(t, qin, 0, 0, dbId, &numMatches);
2150Sstevel@tonic-gate 	if (tp == 0 || numMatches <= 0) {
2160Sstevel@tonic-gate 		/*
2170Sstevel@tonic-gate 		 * Not really an error; just no matching mapping
2180Sstevel@tonic-gate 		 * for the query.
2190Sstevel@tonic-gate 		 */
2200Sstevel@tonic-gate 		*ldapStat = LDAP_SUCCESS;
2210Sstevel@tonic-gate 		return (0);
2220Sstevel@tonic-gate 	}
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	q = 0;
2250Sstevel@tonic-gate 	attr = 0;
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	/* For each mapping */
2280Sstevel@tonic-gate 	for (numVals = 0, n = 0; n < numMatches; n++) {
2290Sstevel@tonic-gate 		db_query		**qt;
2300Sstevel@tonic-gate 		int			i, nqt = 0, filterOnQin, res = 0;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 		t = tp[n];
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 		if (qin != 0) {
2350Sstevel@tonic-gate 			rv = buildNisPlusRuleValue(t, qin, 0);
2360Sstevel@tonic-gate 			if (rv != 0) {
2370Sstevel@tonic-gate 				/*
2380Sstevel@tonic-gate 				 * Depending on the value of res, we shall
2390Sstevel@tonic-gate 				 * proceed to next table mapping.
2400Sstevel@tonic-gate 				 */
2410Sstevel@tonic-gate 				ls = createLdapRequest(t, rv, 0, 1, &res, NULL);
2420Sstevel@tonic-gate 			}
2430Sstevel@tonic-gate 			else
2440Sstevel@tonic-gate 				ls = 0;
2450Sstevel@tonic-gate 		} else {
2460Sstevel@tonic-gate 			/* Build enumeration request */
2470Sstevel@tonic-gate 			rv = 0;
2480Sstevel@tonic-gate 			ls = createLdapRequest(t, 0, 0, 1, NULL, NULL);
2490Sstevel@tonic-gate 		}
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 		freeRuleValue(rv, 1);
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 		if (ls == 0) {
2540Sstevel@tonic-gate 			/*
2550Sstevel@tonic-gate 			 * if the res is NP_LDAP_RULES_NO_VALUE, that means we
2560Sstevel@tonic-gate 			 * have enough NIS+ columns for the rules to produce
2570Sstevel@tonic-gate 			 * values, but none of them did, so continue to the
2580Sstevel@tonic-gate 			 * next table mapping. Otherwise do cleanup and return
2590Sstevel@tonic-gate 			 * error.
2600Sstevel@tonic-gate 			 */
2610Sstevel@tonic-gate 			if (res == NP_LDAP_RULES_NO_VALUE)
2620Sstevel@tonic-gate 				continue;
2630Sstevel@tonic-gate 			for (i = 0; i < numVals; i++)
2640Sstevel@tonic-gate 				freeQuery(q[i]);
2650Sstevel@tonic-gate 			sfree(q);
2660Sstevel@tonic-gate 			free(tp);
2670Sstevel@tonic-gate 			*ldapStat = LDAP_OPERATIONS_ERROR;
2680Sstevel@tonic-gate 			return (0);
2690Sstevel@tonic-gate 		}
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 		/* Query LDAP */
2720Sstevel@tonic-gate 		nqt = (ls->isDN || qin != 0) ? 0 : -1;
2730Sstevel@tonic-gate 		rv = ldapSearch(ls, &nqt, 0, ldapStat);
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 		/*
2760Sstevel@tonic-gate 		 * If qin != 0, then we need to make sure that the
2770Sstevel@tonic-gate 		 * LDAP search is filtered so that only entries that
2780Sstevel@tonic-gate 		 * are compatible with 'qin' are retained. This will
2790Sstevel@tonic-gate 		 * happen automatically if we do a DN search (in which
2800Sstevel@tonic-gate 		 * case, no need to filter on 'qin').
2810Sstevel@tonic-gate 		 */
2820Sstevel@tonic-gate 		if (ls->isDN || qin == 0)
2830Sstevel@tonic-gate 			filterOnQin = 0;
2840Sstevel@tonic-gate 		else
2850Sstevel@tonic-gate 			filterOnQin = 1;
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 		freeLdapSearch(ls);
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 		/* Convert rule-values to db_query's */
2900Sstevel@tonic-gate 		if (rv != 0 && nqt > 0) {
2910Sstevel@tonic-gate 			int			nrv = nqt;
2920Sstevel@tonic-gate 			__nis_obj_attr_t	**at = 0;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 			qt = ruleValue2Query(t, rv,
2950Sstevel@tonic-gate 				(filterOnQin) ? qin : 0, &at, &nqt);
2960Sstevel@tonic-gate 			freeRuleValue(rv, nrv);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 			if (qt != 0 && q == 0) {
2990Sstevel@tonic-gate 				q = qt;
3000Sstevel@tonic-gate 				attr = at;
3010Sstevel@tonic-gate 				numVals = nqt;
3020Sstevel@tonic-gate 			} else if (qt != 0) {
3030Sstevel@tonic-gate 				db_query		**tmp;
3040Sstevel@tonic-gate 				__nis_obj_attr_t	**atmp;
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 				/* Extend the 'q' array */
3070Sstevel@tonic-gate 				tmp = realloc(q,
3080Sstevel@tonic-gate 					(numVals+nqt) * sizeof (q[0]));
3090Sstevel@tonic-gate 				/* ... and the 'attr' array */
3100Sstevel@tonic-gate 				atmp = realloc(attr,
3110Sstevel@tonic-gate 					(numVals+nqt) * sizeof (attr[0]));
3120Sstevel@tonic-gate 				if (tmp == 0 || atmp == 0) {
3130Sstevel@tonic-gate 					logmsg(MSG_NOMEM, LOG_ERR,
3140Sstevel@tonic-gate 						"%s: realloc(%d) => NULL",
3150Sstevel@tonic-gate 						myself,
3160Sstevel@tonic-gate 						(numVals+nqt) * sizeof (q[0]));
3170Sstevel@tonic-gate 					for (i = 0; i < numVals; i++)
3180Sstevel@tonic-gate 						freeQuery(q[i]);
3190Sstevel@tonic-gate 					for (i = 0; i < nqt; i++)
3200Sstevel@tonic-gate 						freeQuery(qt[i]);
3210Sstevel@tonic-gate 					sfree(tmp);
3220Sstevel@tonic-gate 					sfree(atmp);
3230Sstevel@tonic-gate 					sfree(q);
3240Sstevel@tonic-gate 					sfree(qt);
3250Sstevel@tonic-gate 					sfree(tp);
3260Sstevel@tonic-gate 					freeObjAttr(at, nqt);
3270Sstevel@tonic-gate 					freeObjAttr(attr, numVals);
3280Sstevel@tonic-gate 					*ldapStat = LDAP_NO_MEMORY;
3290Sstevel@tonic-gate 					return (0);
3300Sstevel@tonic-gate 				}
3310Sstevel@tonic-gate 				q = tmp;
3320Sstevel@tonic-gate 				attr = atmp;
3330Sstevel@tonic-gate 				/* Add the results for this 't' */
3340Sstevel@tonic-gate 				(void) memcpy(&q[numVals], qt,
3350Sstevel@tonic-gate 						nqt * sizeof (qt[0]));
3360Sstevel@tonic-gate 				(void) memcpy(&attr[numVals], at,
3370Sstevel@tonic-gate 						nqt * sizeof (at[0]));
3380Sstevel@tonic-gate 				numVals += nqt;
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 				sfree(qt);
3410Sstevel@tonic-gate 				sfree(at);
3420Sstevel@tonic-gate 			}
3430Sstevel@tonic-gate 		}
3440Sstevel@tonic-gate 	}
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	*numQueries = numVals;
3470Sstevel@tonic-gate 	if (objAttr != 0)
3480Sstevel@tonic-gate 		*objAttr = attr;
3490Sstevel@tonic-gate 	else
3500Sstevel@tonic-gate 		freeObjAttr(attr, numVals);
3510Sstevel@tonic-gate 	sfree(tp);
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	return (q);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate /*
3570Sstevel@tonic-gate  * Add the object attributes (zo_owner, etc.) to the rule-value 'rv'.
3580Sstevel@tonic-gate  * Returns a pointer to the (possibly newly allocated) rule-value,
3590Sstevel@tonic-gate  * or NULL in case of failure. If not returning 'rvIn', the latter
3600Sstevel@tonic-gate  * will have been freed.
3610Sstevel@tonic-gate  */
3620Sstevel@tonic-gate __nis_rule_value_t *
addObjAttr2RuleValue(nis_object * obj,__nis_rule_value_t * rvIn)3630Sstevel@tonic-gate addObjAttr2RuleValue(nis_object *obj, __nis_rule_value_t *rvIn) {
3640Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
3650Sstevel@tonic-gate 	char			abuf[2 * sizeof (obj->zo_access) + 1];
3660Sstevel@tonic-gate 	char			tbuf[2 * sizeof (obj->zo_ttl) + 1];
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	if (obj == 0)
3690Sstevel@tonic-gate 		return (0);
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	if (rvIn != 0) {
3720Sstevel@tonic-gate 		rv = rvIn;
3730Sstevel@tonic-gate 	} else {
3740Sstevel@tonic-gate 		rv = initRuleValue(1, 0);
3750Sstevel@tonic-gate 		if (rv == 0)
3760Sstevel@tonic-gate 			return (0);
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	if (obj->zo_owner != 0) {
3800Sstevel@tonic-gate 		if (addSCol2RuleValue("zo_owner", obj->zo_owner, rv) != 0) {
3810Sstevel@tonic-gate 			freeRuleValue(rv, 1);
3820Sstevel@tonic-gate 			return (0);
3830Sstevel@tonic-gate 		}
3840Sstevel@tonic-gate 	}
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	if (obj->zo_group != 0) {
3870Sstevel@tonic-gate 		if (addSCol2RuleValue("zo_group", obj->zo_group, rv) != 0) {
3880Sstevel@tonic-gate 			freeRuleValue(rv, 1);
3890Sstevel@tonic-gate 			return (0);
3900Sstevel@tonic-gate 		}
3910Sstevel@tonic-gate 	}
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	if (obj->zo_domain != 0) {
3940Sstevel@tonic-gate 		if (addSCol2RuleValue("zo_domain", obj->zo_domain, rv) != 0) {
3950Sstevel@tonic-gate 			freeRuleValue(rv, 1);
3960Sstevel@tonic-gate 			return (0);
3970Sstevel@tonic-gate 		}
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	(void) memset(abuf, 0, sizeof (abuf));
4010Sstevel@tonic-gate 	(void) memset(tbuf, 0, sizeof (tbuf));
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	sprintf(abuf, "%x", obj->zo_access);
4040Sstevel@tonic-gate 	sprintf(tbuf, "%x", obj->zo_ttl);
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	if (addSCol2RuleValue("zo_access", abuf, rv) != 0) {
4070Sstevel@tonic-gate 		freeRuleValue(rv, 1);
4080Sstevel@tonic-gate 		return (0);
4090Sstevel@tonic-gate 	}
4100Sstevel@tonic-gate 	if (addSCol2RuleValue("zo_ttl", tbuf, rv) != 0) {
4110Sstevel@tonic-gate 		freeRuleValue(rv, 1);
4120Sstevel@tonic-gate 		return (0);
4130Sstevel@tonic-gate 	}
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	return (rv);
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate /*
4190Sstevel@tonic-gate  * Returns a pointer to (NOT a copy of) the value for the specified
4200Sstevel@tonic-gate  * column 'col' in the rule-value 'rv'.
4210Sstevel@tonic-gate  */
4220Sstevel@tonic-gate __nis_value_t *
findColValue(char * col,__nis_rule_value_t * rv)4230Sstevel@tonic-gate findColValue(char *col, __nis_rule_value_t *rv) {
4240Sstevel@tonic-gate 	int		i;
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	if (col == 0 || rv == 0 || rv->numColumns <= 0)
4270Sstevel@tonic-gate 		return (0);
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	for (i = 0; i < rv->numColumns; i++) {
4300Sstevel@tonic-gate 		if (strcmp(col, rv->colName[i]) == 0)
4310Sstevel@tonic-gate 			return (&rv->colVal[i]);
4320Sstevel@tonic-gate 	}
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	return (0);
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate  * Return the NIS+ object attributes (if any) in the rule-value 'rv'.
4390Sstevel@tonic-gate  */
4400Sstevel@tonic-gate __nis_obj_attr_t *
ruleValue2ObjAttr(__nis_rule_value_t * rv)4410Sstevel@tonic-gate ruleValue2ObjAttr(__nis_rule_value_t *rv) {
4420Sstevel@tonic-gate 	__nis_obj_attr_t	*attr;
4430Sstevel@tonic-gate 	__nis_value_t		*val;
4440Sstevel@tonic-gate 	char			*myself = "ruleValue2ObjAttr";
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	if (rv == 0 || rv->numColumns <= 0)
4470Sstevel@tonic-gate 		return (0);
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	attr = am(myself, sizeof (*attr));
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	if ((val = findColValue("zo_owner", rv)) != 0 &&
4520Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4530Sstevel@tonic-gate 			val->val[0].value != 0) {
4540Sstevel@tonic-gate 		attr->zo_owner = sdup(myself, T, val->val[0].value);
4550Sstevel@tonic-gate 		if (attr->zo_owner == 0) {
4560Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4570Sstevel@tonic-gate 			return (0);
4580Sstevel@tonic-gate 		}
4590Sstevel@tonic-gate 	}
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	if ((val = findColValue("zo_group", rv)) != 0 &&
4620Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4630Sstevel@tonic-gate 			val->val[0].value != 0) {
4640Sstevel@tonic-gate 		attr->zo_group = sdup(myself, T, val->val[0].value);
4650Sstevel@tonic-gate 		if (attr->zo_group == 0) {
4660Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4670Sstevel@tonic-gate 			return (0);
4680Sstevel@tonic-gate 		}
4690Sstevel@tonic-gate 	}
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	if ((val = findColValue("zo_domain", rv)) != 0 &&
4720Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4730Sstevel@tonic-gate 			val->val[0].value != 0) {
4740Sstevel@tonic-gate 		attr->zo_domain = sdup(myself, T, val->val[0].value);
4750Sstevel@tonic-gate 		if (attr->zo_domain == 0) {
4760Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4770Sstevel@tonic-gate 			return (0);
4780Sstevel@tonic-gate 		}
4790Sstevel@tonic-gate 	}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	if ((val = findColValue("zo_access", rv)) != 0 &&
4820Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4830Sstevel@tonic-gate 			val->val[0].value != 0) {
4840Sstevel@tonic-gate 		if (sscanf(val->val[0].value, "%x", &attr->zo_access) != 1) {
4850Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4860Sstevel@tonic-gate 			return (0);
4870Sstevel@tonic-gate 		}
4880Sstevel@tonic-gate 	}
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	if ((val = findColValue("zo_ttl", rv)) != 0 &&
4910Sstevel@tonic-gate 			val->type == vt_string && val->numVals == 1 &&
4920Sstevel@tonic-gate 			val->val[0].value != 0) {
4930Sstevel@tonic-gate 		if (sscanf(val->val[0].value, "%x", &attr->zo_ttl) != 1) {
4940Sstevel@tonic-gate 			freeSingleObjAttr(attr);
4950Sstevel@tonic-gate 			return (0);
4960Sstevel@tonic-gate 		}
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	return (attr);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate /*
5030Sstevel@tonic-gate  * If the supplied string is one of the object attributes, return one.
5040Sstevel@tonic-gate  * Otherwise, return zero.
5050Sstevel@tonic-gate  */
5060Sstevel@tonic-gate int
isObjAttrString(char * str)5070Sstevel@tonic-gate isObjAttrString(char *str) {
5080Sstevel@tonic-gate 	if (str == 0)
5090Sstevel@tonic-gate 		return (0);
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	if (strcmp("zo_owner", str) == 0 ||
5120Sstevel@tonic-gate 		strcmp("zo_group", str) == 0 ||
5130Sstevel@tonic-gate 		strcmp("zo_domain", str) == 0 ||
5140Sstevel@tonic-gate 		strcmp("zo_access", str) == 0 ||
5150Sstevel@tonic-gate 		strcmp("zo_ttl", str) == 0)
5160Sstevel@tonic-gate 		return (1);
5170Sstevel@tonic-gate 	else
5180Sstevel@tonic-gate 		return (0);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate /*
5230Sstevel@tonic-gate  * If the supplied value is one of the object attribute strings, return
5240Sstevel@tonic-gate  * a pointer to the string. Otherwise, return NULL.
5250Sstevel@tonic-gate  */
5260Sstevel@tonic-gate char *
isObjAttr(__nis_single_value_t * val)5270Sstevel@tonic-gate isObjAttr(__nis_single_value_t *val) {
5280Sstevel@tonic-gate 	if (val == 0 || val->length <= 0 || val->value == 0)
5290Sstevel@tonic-gate 		return (0);
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	if (isObjAttrString(val->value))
5320Sstevel@tonic-gate 		return (val->value);
5330Sstevel@tonic-gate 	else
5340Sstevel@tonic-gate 		return (0);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate int
setObjAttrField(char * attrName,__nis_single_value_t * val,__nis_obj_attr_t ** objAttr)5380Sstevel@tonic-gate setObjAttrField(char *attrName, __nis_single_value_t *val,
5390Sstevel@tonic-gate 		__nis_obj_attr_t **objAttr) {
5400Sstevel@tonic-gate 	__nis_obj_attr_t	*attr;
5410Sstevel@tonic-gate 	char			*myself = "setObjAttrField";
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	if (attrName == 0 || val == 0 || objAttr == 0 ||
5440Sstevel@tonic-gate 			val->value == 0 || val->length <= 0)
5450Sstevel@tonic-gate 		return (-1);
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	if (*objAttr != 0) {
5480Sstevel@tonic-gate 		attr = *objAttr;
5490Sstevel@tonic-gate 	} else {
5500Sstevel@tonic-gate 		attr = am(myself, sizeof (*attr));
5510Sstevel@tonic-gate 		if (attr == 0)
5520Sstevel@tonic-gate 			return (-2);
5530Sstevel@tonic-gate 		*objAttr = attr;
5540Sstevel@tonic-gate 	}
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	if (strcmp("zo_owner", attrName) == 0) {
5570Sstevel@tonic-gate 		if (attr->zo_owner == 0) {
5580Sstevel@tonic-gate 			attr->zo_owner = sdup(myself, T, val->value);
5590Sstevel@tonic-gate 			if (attr->zo_owner == 0)
5600Sstevel@tonic-gate 				return (-11);
5610Sstevel@tonic-gate 		}
5620Sstevel@tonic-gate 	} else if (strcmp("zo_group", attrName) == 0) {
5630Sstevel@tonic-gate 		if (attr->zo_group == 0) {
5640Sstevel@tonic-gate 			attr->zo_group = sdup(myself, T, val->value);
5650Sstevel@tonic-gate 			if (attr->zo_group == 0)
5660Sstevel@tonic-gate 				return (-12);
5670Sstevel@tonic-gate 		}
5680Sstevel@tonic-gate 	} else if (strcmp("zo_domain", attrName) == 0) {
5690Sstevel@tonic-gate 		if (attr->zo_domain == 0) {
5700Sstevel@tonic-gate 			attr->zo_domain = sdup(myself, T, val->value);
5710Sstevel@tonic-gate 			if (attr->zo_domain == 0)
5720Sstevel@tonic-gate 				return (-13);
5730Sstevel@tonic-gate 		}
5740Sstevel@tonic-gate 	} else if (strcmp("zo_access", attrName) == 0) {
5750Sstevel@tonic-gate 		if (attr->zo_access == 0) {
5760Sstevel@tonic-gate 			if (sscanf(val->value, "%x", &attr->zo_access) != 1)
5770Sstevel@tonic-gate 				return (-14);
5780Sstevel@tonic-gate 		}
5790Sstevel@tonic-gate 	} else if (strcmp("zo_ttl", attrName) == 0) {
5800Sstevel@tonic-gate 		if (attr->zo_ttl == 0) {
5810Sstevel@tonic-gate 			if (sscanf(val->value, "%x", &attr->zo_ttl) != 1)
5820Sstevel@tonic-gate 				return (-15);
5830Sstevel@tonic-gate 		}
5840Sstevel@tonic-gate 	}
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	return (0);
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate /*
5900Sstevel@tonic-gate  * Return a DN and rule-value for the supplied mapping, db_query's, and
5910Sstevel@tonic-gate  * input rule-value. This function only works on a single mapping. See
5920Sstevel@tonic-gate  * mapToLDAP() below for a description of the action depending on the
5930Sstevel@tonic-gate  * values of 'old' and 'new'.
5940Sstevel@tonic-gate  *
5950Sstevel@tonic-gate  * If both 'old' and 'new' are supplied, and the modify would result
5960Sstevel@tonic-gate  * in a change to the DN, '*oldDN' will contain the old DN. Otherwise
5970Sstevel@tonic-gate  * (and normally), '*oldDN' will be NULL.
5980Sstevel@tonic-gate  */
5990Sstevel@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)6000Sstevel@tonic-gate map1qToLDAP(__nis_table_mapping_t *t, db_query *old, db_query *new,
6010Sstevel@tonic-gate 		__nis_rule_value_t *rvIn, __nis_rule_value_t **rvOutP,
6020Sstevel@tonic-gate 		char **oldDnP) {
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	__nis_rule_value_t	*rv, *rvt;
6050Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
6060Sstevel@tonic-gate 	char			*dn = 0, *oldDn = 0;
6070Sstevel@tonic-gate 	__nis_table_mapping_t	del;
6080Sstevel@tonic-gate 	char			*myself = "map1qToLDAP";
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	if (t == 0 || (old == 0 && new == 0) || rvOutP == 0)
6110Sstevel@tonic-gate 		return (0);
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	/*
6140Sstevel@tonic-gate 	 * If entry should be deleted, we look at the delete
6150Sstevel@tonic-gate 	 * policy in the table mapping. Should it specify a
6160Sstevel@tonic-gate 	 * rule set, we use that rule set to build a rule-
6170Sstevel@tonic-gate 	 * value, and the delete actually becomes a modify
6180Sstevel@tonic-gate 	 * operation.
6190Sstevel@tonic-gate 	 */
6200Sstevel@tonic-gate 	if (old != 0 && new == 0) {
6210Sstevel@tonic-gate 		if (t->objectDN->delDisp == dd_perDbId) {
6220Sstevel@tonic-gate 			/*
6230Sstevel@tonic-gate 			 * The functions that build a rule-value from a
6240Sstevel@tonic-gate 			 * rule set expect a __nis_table_mapping_t, but the
6250Sstevel@tonic-gate 			 * rule set in the __nis_object_dn_t isn't of that
6260Sstevel@tonic-gate 			 * form. So, build a pseudo-__nis_table_mapping_t that
6270Sstevel@tonic-gate 			 * borrows heavily from 't'.
6280Sstevel@tonic-gate 			 */
6290Sstevel@tonic-gate 			del = *t;
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 			del.numRulesToLDAP = del.objectDN->numDbIds;
6320Sstevel@tonic-gate 			del.ruleToLDAP = del.objectDN->dbId;
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 			/*
6350Sstevel@tonic-gate 			 * Do a modify with the pseudo-table
6360Sstevel@tonic-gate 			 * mapping, and the 'old' db_query
6370Sstevel@tonic-gate 			 * supplying input to the delete rule
6380Sstevel@tonic-gate 			 * set.
6390Sstevel@tonic-gate 			 */
6400Sstevel@tonic-gate 			t = &del;
6410Sstevel@tonic-gate 			new = old;
6420Sstevel@tonic-gate 		} else if (t->objectDN->delDisp == dd_always) {
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 			/* Nothing to do here; all handled below */
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 		} else if (t->objectDN->delDisp == dd_never) {
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 			return (0);
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 		} else {
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 			logmsg(MSG_INVALIDDELDISP, LOG_WARNING,
6530Sstevel@tonic-gate 				"%s: Invalid delete disposition %d for \"%s\"",
6540Sstevel@tonic-gate 				myself, t->objectDN->delDisp,
6550Sstevel@tonic-gate 				NIL(t->dbId));
6560Sstevel@tonic-gate 			return (0);
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 		}
6590Sstevel@tonic-gate 	}
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	/* Make a copy of the input rule-value */
6620Sstevel@tonic-gate 	if (rvIn != 0) {
6630Sstevel@tonic-gate 		rv = initRuleValue(1, rvIn);
6640Sstevel@tonic-gate 		if (rv == 0)
6650Sstevel@tonic-gate 			return (0);
6660Sstevel@tonic-gate 	} else {
6670Sstevel@tonic-gate 		rv = 0;
6680Sstevel@tonic-gate 	}
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 	/* First get a rule-value from the supplied NIS+ entry. */
6710Sstevel@tonic-gate 	rvt = rv;
6720Sstevel@tonic-gate 	rv = buildNisPlusRuleValue(t, ((old != 0) ? old : new), rvt);
6730Sstevel@tonic-gate 	freeRuleValue(rvt, 1);
6740Sstevel@tonic-gate 	if (rv == 0) {
6750Sstevel@tonic-gate 		logmsg(MSG_NORULEVALUE, LOG_WARNING,
6760Sstevel@tonic-gate 			"%s: No in-query rule-value derived for \"%s\"",
6770Sstevel@tonic-gate 			myself, NIL(t->dbId));
6780Sstevel@tonic-gate 		return (0);
6790Sstevel@tonic-gate 	}
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	/*
6820Sstevel@tonic-gate 	 * Create a request (really only care about the DN) from the
6830Sstevel@tonic-gate 	 * supplied NIS+ entry data.
6840Sstevel@tonic-gate 	 */
6850Sstevel@tonic-gate 	ls = createLdapRequest(t, rv, &dn, 0, NULL, NULL);
6860Sstevel@tonic-gate 	if (ls == 0 || dn == 0) {
6870Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
6880Sstevel@tonic-gate 			"%s: Unable to create LDAP request for %s: %s",
6890Sstevel@tonic-gate 			myself, NIL(t->dbId),
6900Sstevel@tonic-gate 			(dn != 0) ? dn : rvId(rv, mit_nisplus));
6910Sstevel@tonic-gate 		sfree(dn);
6920Sstevel@tonic-gate 		freeLdapSearch(ls);
6930Sstevel@tonic-gate 		freeRuleValue(rv, 1);
6940Sstevel@tonic-gate 		return (0);
6950Sstevel@tonic-gate 	}
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 	freeLdapSearch(ls);
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	if (new != 0) {
7000Sstevel@tonic-gate 		/*
7010Sstevel@tonic-gate 		 * Create a rule-value from the new NIS+ entry.
7020Sstevel@tonic-gate 		 * Don't want to mix in the rule-value derived
7030Sstevel@tonic-gate 		 * from 'old', so delete it. However, we still
7040Sstevel@tonic-gate 		 * want the owner, group, etc., from 'rvIn'.
7050Sstevel@tonic-gate 		 */
7060Sstevel@tonic-gate 		if (old != 0) {
7070Sstevel@tonic-gate 			freeRuleValue(rv, 1);
7080Sstevel@tonic-gate 			if (rvIn != 0) {
7090Sstevel@tonic-gate 				rv = initRuleValue(1, rvIn);
7100Sstevel@tonic-gate 				if (rv == 0) {
7110Sstevel@tonic-gate 					sfree(dn);
7120Sstevel@tonic-gate 					return (0);
7130Sstevel@tonic-gate 				}
7140Sstevel@tonic-gate 			} else {
7150Sstevel@tonic-gate 				rv = 0;
7160Sstevel@tonic-gate 			}
7170Sstevel@tonic-gate 		}
7180Sstevel@tonic-gate 		rvt = rv;
7190Sstevel@tonic-gate 		rv = buildNisPlusRuleValue(t, new, rvt);
7200Sstevel@tonic-gate 		freeRuleValue(rvt, 1);
7210Sstevel@tonic-gate 		if (rv == 0) {
7220Sstevel@tonic-gate 			logmsg(MSG_NORULEVALUE, LOG_WARNING,
7230Sstevel@tonic-gate 				"%s: No new rule-value derived for \"%s: %s\"",
7240Sstevel@tonic-gate 				myself, NIL(t->dbId), dn);
7250Sstevel@tonic-gate 			sfree(dn);
7260Sstevel@tonic-gate 			return (0);
7270Sstevel@tonic-gate 		}
7280Sstevel@tonic-gate 		/*
7290Sstevel@tonic-gate 		 * Check if the proposed modification would result in a
7300Sstevel@tonic-gate 		 * a change to the DN.
7310Sstevel@tonic-gate 		 */
7320Sstevel@tonic-gate 		if (old != 0) {
7330Sstevel@tonic-gate 			oldDn = dn;
7340Sstevel@tonic-gate 			dn = 0;
7350Sstevel@tonic-gate 			ls = createLdapRequest(t, rv, &dn, 0, NULL, NULL);
7360Sstevel@tonic-gate 			if (ls == 0 || dn == 0) {
7370Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
7380Sstevel@tonic-gate 				"%s: Unable to create new DN for \"%s: %s\"",
7390Sstevel@tonic-gate 					myself, NIL(t->dbId), oldDn);
7400Sstevel@tonic-gate 				sfree(oldDn);
7410Sstevel@tonic-gate 				freeLdapSearch(ls);
7420Sstevel@tonic-gate 				freeRuleValue(rv, 1);
7430Sstevel@tonic-gate 				return (0);
7440Sstevel@tonic-gate 			}
7450Sstevel@tonic-gate 			freeLdapSearch(ls);
7460Sstevel@tonic-gate 			if (strcasecmp(oldDn, dn) == 0) {
7470Sstevel@tonic-gate 				sfree(oldDn);
7480Sstevel@tonic-gate 				oldDn = 0;
7490Sstevel@tonic-gate 			}
7500Sstevel@tonic-gate 		}
7510Sstevel@tonic-gate 	}
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	*rvOutP = rv;
7550Sstevel@tonic-gate 	if (oldDnP != 0)
7560Sstevel@tonic-gate 		*oldDnP = oldDn;
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	return (dn);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate /*
7620Sstevel@tonic-gate  * Since the DN hash list is an automatic variable, there's no need for
7630Sstevel@tonic-gate  * locking, and we remove the locking overhead by using the libnsl
7640Sstevel@tonic-gate  * hash functions.
7650Sstevel@tonic-gate  */
766*11262SRajagopal.Andra@Sun.COM #undef  NIS_HASH_ITEM
767*11262SRajagopal.Andra@Sun.COM #undef  NIS_HASH_TABLE
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate typedef struct {
7700Sstevel@tonic-gate 	NIS_HASH_ITEM	item;
7710Sstevel@tonic-gate 	int		index;
7720Sstevel@tonic-gate 	char		*oldDn;
7730Sstevel@tonic-gate } __dn_item_t;
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate /*
7760Sstevel@tonic-gate  * Update LDAP per the supplied table mapping and db_query's.
7770Sstevel@tonic-gate  *
7780Sstevel@tonic-gate  * 'nq' is the number of elements in the 'old', 'new', and 'rvIn'
7790Sstevel@tonic-gate  * arrays. mapToLDAP() generally performs one update for each
7800Sstevel@tonic-gate  * element; however, if one or more of the individual queries
7810Sstevel@tonic-gate  * produce the same DN, they're merged into a single update.
7820Sstevel@tonic-gate  *
7830Sstevel@tonic-gate  * There are four cases, depending on the values of 'old[iq]' and
7840Sstevel@tonic-gate  * 'new[iq]':
7850Sstevel@tonic-gate  *
7860Sstevel@tonic-gate  * (1)	old[iq] == 0 && new[iq] == 0
7870Sstevel@tonic-gate  *	No action; skip to next query
7880Sstevel@tonic-gate  *
7890Sstevel@tonic-gate  * (2)	old[iq] == 0 && new[iq] != 0
7900Sstevel@tonic-gate  *	Attempt to use the 'new' db_query to get a DN, and try to create
7910Sstevel@tonic-gate  *	the corresponding LDAP entry.
7920Sstevel@tonic-gate  *
7930Sstevel@tonic-gate  * (3)	old[iq] != 0 && new[iq] == 0
7940Sstevel@tonic-gate  *	Use the 'old' db_query to get a DN, and try to delete the LDAP
7950Sstevel@tonic-gate  *	entry per the table mapping.
7960Sstevel@tonic-gate  *
7970Sstevel@tonic-gate  * (4)	old[iq] != 0 && new[iq] != 0
7980Sstevel@tonic-gate  *	Use the 'old' db_query to get a DN, and update (possibly create)
7990Sstevel@tonic-gate  *	the corresponding LDAP entry per the 'new' db_query.
8000Sstevel@tonic-gate  *
8010Sstevel@tonic-gate  * If 'rvIn' is non-NULL, it is expected to contain the object attributes
8020Sstevel@tonic-gate  * (zo_owner, etc.) to be written to LDAP. 'rvIn' is an array with 'nq'
8030Sstevel@tonic-gate  * elements.
8040Sstevel@tonic-gate  *
8050Sstevel@tonic-gate  * If 'firstOnly' is set, only the first old[iq]/new[iq] pair is used
8060Sstevel@tonic-gate  * to perform the actual update. Any additional queries specified will
8070Sstevel@tonic-gate  * have their values folded in, but are not used to derive update targets.
8080Sstevel@tonic-gate  * This mode is inteded to support the case where multiple NIS+ entries
8090Sstevel@tonic-gate  * map to one and the same LDAP entry. Note that 'rvIn' must still be
8100Sstevel@tonic-gate  * an array of 'nq' elements, though if 'firstOnly' is set, it should be
8110Sstevel@tonic-gate  * OK to leave all but 'rvIn[0]' empty.
8120Sstevel@tonic-gate  *
8130Sstevel@tonic-gate  * 'dbId' is used to further narow down the selection of mapping candidates
8140Sstevel@tonic-gate  * to those matching the 'dbId' value.
8150Sstevel@tonic-gate  */
8160Sstevel@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)8170Sstevel@tonic-gate mapToLDAP(__nis_table_mapping_t *tm, int nq, db_query **old, db_query **new,
8180Sstevel@tonic-gate 		__nis_rule_value_t *rvIn, int firstOnly, char *dbId) {
8190Sstevel@tonic-gate 	__nis_table_mapping_t	**tp, **tpa;
8200Sstevel@tonic-gate 	int			i, n, rnq, iq, r, ret = LDAP_SUCCESS;
8210Sstevel@tonic-gate 	int			maxMatches, numMatches = 0;
8220Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
8230Sstevel@tonic-gate 	char			**dn = 0, **odn = 0;
8240Sstevel@tonic-gate 	__nis_rule_value_t	**rv;
8250Sstevel@tonic-gate 	__dn_item_t		*dni;
8260Sstevel@tonic-gate 	char			*myself = "mapToLDAP";
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	if (tm == 0 || (old == 0 && new == 0) || nq <= 0)
8300Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate 	/* Determine maximum number of table mapping matches */
8330Sstevel@tonic-gate 	if (nq == 1) {
8340Sstevel@tonic-gate 		tp = selectTableMapping(tm,
8350Sstevel@tonic-gate 			(old != 0 && old[0] != 0) ? old[0] : new[0], 1, 0,
8360Sstevel@tonic-gate 				dbId, &maxMatches);
8370Sstevel@tonic-gate 		numMatches = maxMatches;
8380Sstevel@tonic-gate 	} else {
8390Sstevel@tonic-gate 		tp = selectTableMapping(tm, 0, 1, 0, dbId, &maxMatches);
8400Sstevel@tonic-gate 	}
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 	/*
8430Sstevel@tonic-gate 	 * If no matching mapping, we're not mapping to LDAP in this
8440Sstevel@tonic-gate 	 * particular case.
8450Sstevel@tonic-gate 	 */
8460Sstevel@tonic-gate 	if (tp == 0 || maxMatches == 0) {
8470Sstevel@tonic-gate 		sfree(tp);
8480Sstevel@tonic-gate 		return (LDAP_SUCCESS);
8490Sstevel@tonic-gate 	}
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate 	/*
8520Sstevel@tonic-gate 	 * Allocate the 'rv', 'dn', and 'tpa' arrays. Worst case is that
8530Sstevel@tonic-gate 	 * we need nq * maxMatches elements in each array. However, if
8540Sstevel@tonic-gate 	 * 'firstOnly' is set, we only need one element per matching
8550Sstevel@tonic-gate 	 * mapping in each.
8560Sstevel@tonic-gate 	 */
8570Sstevel@tonic-gate 	dn = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (dn[0]));
8580Sstevel@tonic-gate 	odn = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (odn[0]));
8590Sstevel@tonic-gate 	rv = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (rv[0]));
8600Sstevel@tonic-gate 	tpa = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (tpa[0]));
8610Sstevel@tonic-gate 	if (dn == 0 || odn == 0 || rv == 0 || tpa == 0) {
8620Sstevel@tonic-gate 		sfree(tp);
8630Sstevel@tonic-gate 		sfree(dn);
8640Sstevel@tonic-gate 		sfree(odn);
8650Sstevel@tonic-gate 		sfree(rv);
8660Sstevel@tonic-gate 		sfree(tpa);
8670Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
8680Sstevel@tonic-gate 	}
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	/* Unless nq == 1, we don't need the 'tp' value */
8710Sstevel@tonic-gate 	if (nq != 1)
8720Sstevel@tonic-gate 		sfree(tp);
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
8750Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
8760Sstevel@tonic-gate 		LOG_WARNING,
8770Sstevel@tonic-gate #else
8780Sstevel@tonic-gate 		LOG_INFO,
8790Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
8800Sstevel@tonic-gate 		"%s: %s: %d * %d potential updates",
8810Sstevel@tonic-gate 		myself, NIL(tm->objName), nq, maxMatches);
8820Sstevel@tonic-gate 
8830Sstevel@tonic-gate 	/*
8840Sstevel@tonic-gate 	 * Create DNs, column and attribute values, and merge duplicate DNs.
8850Sstevel@tonic-gate 	 */
8860Sstevel@tonic-gate 	for (iq = 0, rnq = 0; iq < nq; iq++) {
8870Sstevel@tonic-gate 		int	idx;
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 		if ((old == 0 || old[iq] == 0) &&
8900Sstevel@tonic-gate 				(new == 0 || new[iq] == 0))
8910Sstevel@tonic-gate 			continue;
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 		/*
8940Sstevel@tonic-gate 		 * Select matching table mappings; if nq == 1, we've already
8950Sstevel@tonic-gate 		 * got the 'tp' array from above. We expect this to be the
8960Sstevel@tonic-gate 		 * most common case, so it's worth special treatment.
8970Sstevel@tonic-gate 		 */
8980Sstevel@tonic-gate 		if (nq != 1)
8990Sstevel@tonic-gate 			tp = selectTableMapping(tm,
9000Sstevel@tonic-gate 			(old != 0 && old[iq] != 0) ? old[iq] : new[iq], 1, 0,
9010Sstevel@tonic-gate 					dbId, &numMatches);
9020Sstevel@tonic-gate 		if (tp == 0)
9030Sstevel@tonic-gate 			continue;
9040Sstevel@tonic-gate 		else if (numMatches <= 0) {
9050Sstevel@tonic-gate 			sfree(tp);
9060Sstevel@tonic-gate 			continue;
9070Sstevel@tonic-gate 		}
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 		idx = iq * maxMatches;
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 		if (idx == 0 || !firstOnly)
9120Sstevel@tonic-gate 			(void) memcpy(&tpa[idx], tp,
9130Sstevel@tonic-gate 					numMatches * sizeof (tpa[idx]));
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 		for (n = 0; n < numMatches; n++) {
9160Sstevel@tonic-gate 			char			*dnt, *odnt;
9170Sstevel@tonic-gate 			__nis_rule_value_t	*rvt = 0;
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 			if (tp[n] == 0)
9200Sstevel@tonic-gate 				continue;
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 			dnt = map1qToLDAP(tp[n],
9230Sstevel@tonic-gate 					(old != 0) ? old[iq] : 0,
9240Sstevel@tonic-gate 					(new != 0) ? new[iq] : 0,
9250Sstevel@tonic-gate 					(rvIn != 0) ? &rvIn[iq] : 0,
9260Sstevel@tonic-gate 					&rvt, &odnt);
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 			if (dnt == 0)
9290Sstevel@tonic-gate 				continue;
9300Sstevel@tonic-gate 			if (rvt == 0) {
9310Sstevel@tonic-gate #ifdef  NISDB_LDAP_DEBUG
9320Sstevel@tonic-gate 				abort();
9330Sstevel@tonic-gate #else
9340Sstevel@tonic-gate 				sfree(dnt);
9350Sstevel@tonic-gate 				sfree(odnt);
9360Sstevel@tonic-gate 				continue;
9370Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
9380Sstevel@tonic-gate 			}
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 			/*
9410Sstevel@tonic-gate 			 * Create a request to get a rule-value with
9420Sstevel@tonic-gate 			 * NIS+ data translated to LDAP equivalents.
9430Sstevel@tonic-gate 			 */
9440Sstevel@tonic-gate 			ls = createLdapRequest(tp[n], rvt, 0, 0, NULL, NULL);
9450Sstevel@tonic-gate 			if (ls == 0) {
9460Sstevel@tonic-gate 				if (ret == LDAP_SUCCESS)
9470Sstevel@tonic-gate 					ret = LDAP_OPERATIONS_ERROR;
9480Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9490Sstevel@tonic-gate 				"%s: Unable to map to LDAP attrs for %s:dn=%s",
9500Sstevel@tonic-gate 				myself, NIL(tp[n]->dbId), dnt);
9510Sstevel@tonic-gate 				sfree(dnt);
9520Sstevel@tonic-gate 				freeRuleValue(rvt, 1);
9530Sstevel@tonic-gate 				continue;
9540Sstevel@tonic-gate 			}
9550Sstevel@tonic-gate 			freeLdapSearch(ls);
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 			/*
9580Sstevel@tonic-gate 			 * If the DN is the same as one we already know
9590Sstevel@tonic-gate 			 * about, merge the rule-values.
9600Sstevel@tonic-gate 			 */
9610Sstevel@tonic-gate 
962*11262SRajagopal.Andra@Sun.COM 			if ((iq == 0 || !firstOnly) && dnt != 0) {
9630Sstevel@tonic-gate 				dni = am(myself, sizeof (*dni));
9640Sstevel@tonic-gate 				if (dni != 0) {
9650Sstevel@tonic-gate 					dni->item.name = dnt;
9660Sstevel@tonic-gate 					dni->index = idx + n;
9670Sstevel@tonic-gate 					dni->oldDn = odnt;
9680Sstevel@tonic-gate 				} else {
9690Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9700Sstevel@tonic-gate 					"%s: Skipping update for dn=\"%s\"",
9710Sstevel@tonic-gate 						myself, dnt);
9720Sstevel@tonic-gate 					sfree(dnt);
9730Sstevel@tonic-gate 					dnt = 0;
9740Sstevel@tonic-gate 				}
9750Sstevel@tonic-gate 				if (dnt != 0) {
9760Sstevel@tonic-gate 					dn[idx+n] = dnt;
9770Sstevel@tonic-gate 					odn[idx+n] = odnt;
9780Sstevel@tonic-gate 					rv[idx+n] = rvt;
9790Sstevel@tonic-gate 					rnq++;
9800Sstevel@tonic-gate 				} else {
9810Sstevel@tonic-gate 					freeRuleValue(rvt, 1);
9820Sstevel@tonic-gate 					rvt = 0;
9830Sstevel@tonic-gate 				}
9840Sstevel@tonic-gate 			} else if (dnt != 0) {
9850Sstevel@tonic-gate 				sfree(dnt);
9860Sstevel@tonic-gate 				sfree(odnt);
9870Sstevel@tonic-gate 				freeRuleValue(rvt, 1);
9880Sstevel@tonic-gate 			}
9890Sstevel@tonic-gate 		}
9900Sstevel@tonic-gate 		sfree(tp);
9910Sstevel@tonic-gate 	}
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
9940Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
9950Sstevel@tonic-gate 		LOG_WARNING,
9960Sstevel@tonic-gate #else
9970Sstevel@tonic-gate 		LOG_INFO,
9980Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
9990Sstevel@tonic-gate 		"%s: %s: %d update%s requested",
10000Sstevel@tonic-gate 		myself, NIL(tm->objName), rnq, rnq != 1 ? "s" : "");
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate 	/* Perform the updates */
10030Sstevel@tonic-gate 	for (i = rnq = 0; i < (firstOnly ? maxMatches : nq*maxMatches); i++) {
10040Sstevel@tonic-gate 		int	delPerDbId;
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 		if (dn[i] == 0)
10070Sstevel@tonic-gate 			continue;
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
10100Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_INFO,
10110Sstevel@tonic-gate 			"%s: %s %s:dn=%s",
10120Sstevel@tonic-gate 			myself,
10130Sstevel@tonic-gate 			(new != 0 && new[i/maxMatches] != 0) ?
10140Sstevel@tonic-gate 				"modify" : "delete",
10150Sstevel@tonic-gate 			NIL(tpa[i]->dbId), dn[i]);
10160Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate 		delPerDbId = (tpa[i]->objectDN->delDisp == dd_perDbId);
10190Sstevel@tonic-gate 		if ((new != 0 && new[i/maxMatches] != 0) || delPerDbId) {
10200Sstevel@tonic-gate 			/*
10210Sstevel@tonic-gate 			 * Try to modify/create the specified DN. First,
10220Sstevel@tonic-gate 			 * however, if the update changes the DN, make
10230Sstevel@tonic-gate 			 * that change.
10240Sstevel@tonic-gate 			 */
10250Sstevel@tonic-gate 			if (odn[i] == 0 || (r = ldapChangeDN(odn[i], dn[i])) ==
10260Sstevel@tonic-gate 					LDAP_SUCCESS) {
10270Sstevel@tonic-gate 				int	addFirst;
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 				addFirst = (new != 0 &&
10300Sstevel@tonic-gate 						new[i/maxMatches] != 0 &&
10310Sstevel@tonic-gate 						!delPerDbId);
10320Sstevel@tonic-gate 				r = ldapModify(dn[i], rv[i],
10330Sstevel@tonic-gate 					tpa[i]->objectDN->write.attrs,
10340Sstevel@tonic-gate 						addFirst);
10350Sstevel@tonic-gate 			}
10360Sstevel@tonic-gate 		} else {
10370Sstevel@tonic-gate 			/* Try to delete the specified DN */
10380Sstevel@tonic-gate 			r = ldapModify(dn[i], 0,
10390Sstevel@tonic-gate 					tpa[i]->objectDN->write.attrs, 0);
10400Sstevel@tonic-gate 		}
10410Sstevel@tonic-gate 
10420Sstevel@tonic-gate 		if (r == LDAP_SUCCESS) {
10430Sstevel@tonic-gate 			rnq++;
10440Sstevel@tonic-gate 		} else {
10450Sstevel@tonic-gate 			if (ret == LDAP_SUCCESS)
10460Sstevel@tonic-gate 				ret = r;
10470Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
10480Sstevel@tonic-gate 				"%s: LDAP %s request error %d for %s:dn=%s",
10490Sstevel@tonic-gate 				myself,
10500Sstevel@tonic-gate 				(new != 0 && new[i/maxMatches] != 0) ?
10510Sstevel@tonic-gate 					"modify" : "delete",
10520Sstevel@tonic-gate 				r, NIL(tpa[i]->dbId), dn[i]);
10530Sstevel@tonic-gate 		}
10540Sstevel@tonic-gate 
10550Sstevel@tonic-gate 		sfree(dn[i]);
10560Sstevel@tonic-gate 		dn[i] = 0;
10570Sstevel@tonic-gate 		freeRuleValue(rv[i], 1);
10580Sstevel@tonic-gate 		rv[i] = 0;
10590Sstevel@tonic-gate 	}
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	sfree(dn);
10620Sstevel@tonic-gate 	sfree(odn);
10630Sstevel@tonic-gate 	sfree(rv);
10640Sstevel@tonic-gate 	sfree(tpa);
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
10670Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
10680Sstevel@tonic-gate 		LOG_WARNING,
10690Sstevel@tonic-gate #else
10700Sstevel@tonic-gate 		LOG_INFO,
10710Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
10720Sstevel@tonic-gate 		"%s: %s: %d update%s performed",
10730Sstevel@tonic-gate 		myself, NIL(tm->objName), rnq, rnq != 1 ? "s" : "");
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	return (ret);
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate /*
10790Sstevel@tonic-gate  * In nis+2ldap, check if the query 'q' matches the selector index 'x->index'.
10800Sstevel@tonic-gate  *
10810Sstevel@tonic-gate  * In nis2ldap, if 'name' is provided then check if its value in 'val'
10820Sstevel@tonic-gate  * matches the selector index. If 'name' is NULL, then check if rule-value 'rv'
10830Sstevel@tonic-gate  * matches the index.
10840Sstevel@tonic-gate  * To match the selector index, all fieldspecs in the indexlist should match
10850Sstevel@tonic-gate  * (AND). In nis2ldap, an exception is, if there are multiple fieldspecs with
10860Sstevel@tonic-gate  * the same fieldname then only one of them needs to match (OR).
10870Sstevel@tonic-gate  * Example:
10880Sstevel@tonic-gate  *	Indexlist = [host="H*", host="I*", user="U*", domain="D*"]
10890Sstevel@tonic-gate  * Then,
10900Sstevel@tonic-gate  *	host = "H1", user="U1", domain="D1" ==> pass
10910Sstevel@tonic-gate  *	host = "I1", user="U1", domain="D1" ==> pass
10920Sstevel@tonic-gate  *	host = "X1", user="U1", domain="D1" ==> fail
10930Sstevel@tonic-gate  *	host = "H1", user="X1", domain="D1" ==> fail
10940Sstevel@tonic-gate  *	host = "H1", user="U1" ==> fail
10950Sstevel@tonic-gate  *
10960Sstevel@tonic-gate  * Return 1 in case of a match, 0 otherwise.
10970Sstevel@tonic-gate  */
10980Sstevel@tonic-gate int
verifyIndexMatch(__nis_table_mapping_t * x,db_query * q,__nis_rule_value_t * rv,char * name,char * val)10990Sstevel@tonic-gate verifyIndexMatch(__nis_table_mapping_t *x, db_query *q,
11000Sstevel@tonic-gate 		__nis_rule_value_t *rv, char *name, char *val) {
11010Sstevel@tonic-gate 	int	i, j, k, match = 1;
11020Sstevel@tonic-gate 	char	*myself = "verifyIndexMatch";
11030Sstevel@tonic-gate 
11040Sstevel@tonic-gate 	/*
11050Sstevel@tonic-gate 	 * The pass and fail arrays are used by N2L to keep track of
11060Sstevel@tonic-gate 	 * index matches. This saves us from having matches in a
11070Sstevel@tonic-gate 	 * nested loop to decide OR or AND.
11080Sstevel@tonic-gate 	 */
11090Sstevel@tonic-gate 	int	ppos, fpos;
11100Sstevel@tonic-gate 	char	**pass, **fail;
11110Sstevel@tonic-gate 
11120Sstevel@tonic-gate 	if (x == 0)
11130Sstevel@tonic-gate 		return (0);
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 	/* Trivial match */
11160Sstevel@tonic-gate 	if (x->index.numIndexes <= 0 || (!yp2ldap && q == 0))
11170Sstevel@tonic-gate 		return (1);
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	if (yp2ldap) {
11200Sstevel@tonic-gate 		if (!(pass = am(myself, x->index.numIndexes * sizeof (char *))))
11210Sstevel@tonic-gate 			return (0);
11220Sstevel@tonic-gate 		if (!(fail = am(myself,
11230Sstevel@tonic-gate 				x->index.numIndexes * sizeof (char *)))) {
11240Sstevel@tonic-gate 			sfree(pass);
11250Sstevel@tonic-gate 			return (0);
11260Sstevel@tonic-gate 		}
11270Sstevel@tonic-gate 		ppos = fpos = 0;
11280Sstevel@tonic-gate 	}
11290Sstevel@tonic-gate 
11300Sstevel@tonic-gate 	/* Check each index */
11310Sstevel@tonic-gate 	for (i = 0; i < x->index.numIndexes; i++) {
11320Sstevel@tonic-gate 		int	len = 0;
11330Sstevel@tonic-gate 		char	*value = 0;
11340Sstevel@tonic-gate 
11350Sstevel@tonic-gate 		/* Skip NULL index names */
11360Sstevel@tonic-gate 		if (x->index.name[i] == 0)
11370Sstevel@tonic-gate 			continue;
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate 		/* Check N2L values */
11400Sstevel@tonic-gate 		if (yp2ldap) {
11410Sstevel@tonic-gate 			if (name) {
11420Sstevel@tonic-gate 				if (strcasecmp(x->index.name[i], name) == 0)
11430Sstevel@tonic-gate 					value = val;
11440Sstevel@tonic-gate 				else
11450Sstevel@tonic-gate 					continue;
11460Sstevel@tonic-gate 			} else if (rv) {
11470Sstevel@tonic-gate 				if (strcasecmp(x->index.name[i], N2LKEY) == 0 ||
11480Sstevel@tonic-gate 					strcasecmp(x->index.name[i], N2LIPKEY)
11490Sstevel@tonic-gate 							== 0)
11500Sstevel@tonic-gate 					continue;
11510Sstevel@tonic-gate 				value = findVal(x->index.name[i], rv,
11520Sstevel@tonic-gate 							mit_nisplus);
11530Sstevel@tonic-gate 			}
11540Sstevel@tonic-gate 
11550Sstevel@tonic-gate 			if (value && verifyMappingMatch(x->index.value[i],
11560Sstevel@tonic-gate 									value))
11570Sstevel@tonic-gate 				pass[ppos++] = x->index.name[i];
11580Sstevel@tonic-gate 			else
11590Sstevel@tonic-gate 				fail[fpos++] = x->index.name[i];
11600Sstevel@tonic-gate 			continue;
11610Sstevel@tonic-gate 		}
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 		/* If here, means nis+2ldap */
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 		/* Is the index name a known column ? */
11660Sstevel@tonic-gate 		for (j = 0; j < x->numColumns; j++) {
11670Sstevel@tonic-gate 			if (strcmp(x->index.name[i], x->column[j]) == 0) {
11680Sstevel@tonic-gate 				/*
11690Sstevel@tonic-gate 				 * Do we have a value for the column ?
11700Sstevel@tonic-gate 				 */
11710Sstevel@tonic-gate 				for (k = 0; k < q->components.components_len;
11720Sstevel@tonic-gate 						k++) {
11730Sstevel@tonic-gate 					if (q->components.components_val[k].
11740Sstevel@tonic-gate 							which_index == j) {
11750Sstevel@tonic-gate 						value = q->components.
11760Sstevel@tonic-gate 							components_val[k].
11770Sstevel@tonic-gate 							index_value->
11780Sstevel@tonic-gate 							itemvalue.
11790Sstevel@tonic-gate 							itemvalue_val;
11800Sstevel@tonic-gate 						len = q->components.
11810Sstevel@tonic-gate 							components_val[k].
11820Sstevel@tonic-gate 							index_value->
11830Sstevel@tonic-gate 							itemvalue.
11840Sstevel@tonic-gate 							itemvalue_len;
11850Sstevel@tonic-gate 						break;
11860Sstevel@tonic-gate 					}
11870Sstevel@tonic-gate 				}
11880Sstevel@tonic-gate 				if (value != 0)
11890Sstevel@tonic-gate 					break;
11900Sstevel@tonic-gate 			}
11910Sstevel@tonic-gate 		}
11920Sstevel@tonic-gate 
11930Sstevel@tonic-gate 		/*
11940Sstevel@tonic-gate 		 * If we found a value, check if it matches the
11950Sstevel@tonic-gate 		 * format. If no value found or no match, this
11960Sstevel@tonic-gate 		 * mapping is _not_ an alternative. Otherwise,
11970Sstevel@tonic-gate 		 * we continue checking any other indexes.
11980Sstevel@tonic-gate 		 */
11990Sstevel@tonic-gate 		if (value == 0 ||
12000Sstevel@tonic-gate 			!verifyMappingMatch(x->index.value[i],
12010Sstevel@tonic-gate 				value)) {
12020Sstevel@tonic-gate 			match = 0;
12030Sstevel@tonic-gate 			break;
12040Sstevel@tonic-gate 		}
12050Sstevel@tonic-gate 	}
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	if (yp2ldap) {
12080Sstevel@tonic-gate 		for (--fpos; fpos >= 0; fpos--) {
12090Sstevel@tonic-gate 			for (i = 0; i < ppos; i++) {
12100Sstevel@tonic-gate 				if (strcmp(pass[i], fail[fpos]) == 0)
12110Sstevel@tonic-gate 					break;
12120Sstevel@tonic-gate 			}
12130Sstevel@tonic-gate 			if (i == ppos) {
12140Sstevel@tonic-gate 				match = 0;
12150Sstevel@tonic-gate 				break;
12160Sstevel@tonic-gate 			}
12170Sstevel@tonic-gate 		}
12180Sstevel@tonic-gate 		sfree(pass);
12190Sstevel@tonic-gate 		sfree(fail);
12200Sstevel@tonic-gate 	}
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate 	return (match);
12230Sstevel@tonic-gate }
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate /*
12260Sstevel@tonic-gate  * Return all table mappings that match the column values in 'q'.
12270Sstevel@tonic-gate  * If there's no match, return those alternative mappings that don't
12280Sstevel@tonic-gate  * have an index; if no such mapping exists, return NULL.
12290Sstevel@tonic-gate  *
12300Sstevel@tonic-gate  * If 'wantWrite' is set, we want mappings for writing (i.e., data
12310Sstevel@tonic-gate  * to LDAP); otherwise, we want mappings for reading.
12320Sstevel@tonic-gate  *
12330Sstevel@tonic-gate  * If 'wantObj' is set, we want object mappings only (i.e., _not_
12340Sstevel@tonic-gate  * those used to map entries in tables).
12350Sstevel@tonic-gate  *
12360Sstevel@tonic-gate  * If 'dbId' is non-NULL, we select mappings with a matching dbId field.
12370Sstevel@tonic-gate  */
12380Sstevel@tonic-gate __nis_table_mapping_t **
selectTableMapping(__nis_table_mapping_t * t,db_query * q,int wantWrite,int wantObj,char * dbId,int * numMatches)12390Sstevel@tonic-gate selectTableMapping(__nis_table_mapping_t *t, db_query *q,
12400Sstevel@tonic-gate 			int wantWrite, int wantObj, char *dbId,
12410Sstevel@tonic-gate 			int *numMatches) {
12420Sstevel@tonic-gate 	__nis_table_mapping_t	*r, *x, **tp;
12430Sstevel@tonic-gate 	int			i, j, k, nm, numap;
12440Sstevel@tonic-gate 	char			*myself = "selectTableMapping";
12450Sstevel@tonic-gate 
12460Sstevel@tonic-gate 	if (numMatches == 0)
12470Sstevel@tonic-gate 		numMatches = &nm;
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate 	/*
12500Sstevel@tonic-gate 	 * Count the number of possible mappings, so that we can
12510Sstevel@tonic-gate 	 * allocate the 'tp' array up front.
12520Sstevel@tonic-gate 	 */
12530Sstevel@tonic-gate 	for (numap = 0, x = t; x != 0; numap++, x = x->next);
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate 	if (numap == 0) {
12560Sstevel@tonic-gate 		*numMatches = 0;
12570Sstevel@tonic-gate 		return (0);
12580Sstevel@tonic-gate 	}
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 	tp = am(myself, numap * sizeof (tp[0]));
12610Sstevel@tonic-gate 	if (tp == 0) {
12620Sstevel@tonic-gate 		*numMatches = -1;
12630Sstevel@tonic-gate 		return (0);
12640Sstevel@tonic-gate 	}
12650Sstevel@tonic-gate 
12660Sstevel@tonic-gate 	/*
12670Sstevel@tonic-gate 	 * Special cases:
12680Sstevel@tonic-gate 	 *
12690Sstevel@tonic-gate 	 *	q == 0 trivially matches any 't' of the correct object type
12700Sstevel@tonic-gate 	 *
12710Sstevel@tonic-gate 	 *	wantObj != 0 means we ignore 'q'
12720Sstevel@tonic-gate 	 */
12730Sstevel@tonic-gate 	if (q == 0 || wantObj) {
12740Sstevel@tonic-gate 		for (i = 0, x = t, nm = 0; i < numap; i++, x = x->next) {
12750Sstevel@tonic-gate 			if (x->objectDN == 0)
12760Sstevel@tonic-gate 				continue;
12770Sstevel@tonic-gate 			if (wantWrite) {
12780Sstevel@tonic-gate 				if (x->objectDN->write.scope ==
12790Sstevel@tonic-gate 						LDAP_SCOPE_UNKNOWN)
12800Sstevel@tonic-gate 					continue;
12810Sstevel@tonic-gate 			} else {
12820Sstevel@tonic-gate 				if (x->objectDN->read.scope ==
12830Sstevel@tonic-gate 						LDAP_SCOPE_UNKNOWN)
12840Sstevel@tonic-gate 					continue;
12850Sstevel@tonic-gate 			}
12860Sstevel@tonic-gate 			if (wantObj) {
12870Sstevel@tonic-gate 				if (x->numColumns > 0)
12880Sstevel@tonic-gate 					continue;
12890Sstevel@tonic-gate 			} else {
12900Sstevel@tonic-gate 				if (x->numColumns <= 0)
12910Sstevel@tonic-gate 					continue;
12920Sstevel@tonic-gate 			}
12930Sstevel@tonic-gate 			if (dbId != 0 && x->dbId != 0 &&
12940Sstevel@tonic-gate 					strcmp(dbId, x->dbId) != 0)
12950Sstevel@tonic-gate 				continue;
12960Sstevel@tonic-gate 			tp[nm] = x;
12970Sstevel@tonic-gate 			nm++;
12980Sstevel@tonic-gate 		}
12990Sstevel@tonic-gate 		*numMatches = nm;
13000Sstevel@tonic-gate 		if (nm == 0) {
13010Sstevel@tonic-gate 			sfree(tp);
13020Sstevel@tonic-gate 			tp = 0;
13030Sstevel@tonic-gate 		}
13040Sstevel@tonic-gate 		return (tp);
13050Sstevel@tonic-gate 	}
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate 	/* Scan all mappings, and collect candidates */
13080Sstevel@tonic-gate 	for (nm = 0, r = 0, x = t; x != 0; x = x->next) {
13090Sstevel@tonic-gate 		if (x->objectDN == 0)
13100Sstevel@tonic-gate 			continue;
13110Sstevel@tonic-gate 		if (wantWrite) {
13120Sstevel@tonic-gate 			if (x->objectDN->write.scope == LDAP_SCOPE_UNKNOWN)
13130Sstevel@tonic-gate 				continue;
13140Sstevel@tonic-gate 		} else {
13150Sstevel@tonic-gate 			if (x->objectDN->read.scope == LDAP_SCOPE_UNKNOWN)
13160Sstevel@tonic-gate 				continue;
13170Sstevel@tonic-gate 		}
13180Sstevel@tonic-gate 		/* Only want table/entry mappings */
13190Sstevel@tonic-gate 		if (x->numColumns <= 0)
13200Sstevel@tonic-gate 			continue;
13210Sstevel@tonic-gate 		if (dbId != 0 && x->dbId != 0 &&
13220Sstevel@tonic-gate 				strcmp(dbId, x->dbId) != 0)
13230Sstevel@tonic-gate 			continue;
13240Sstevel@tonic-gate 		/*
13250Sstevel@tonic-gate 		 * It's a match if: there are no indexes, or we actually
13260Sstevel@tonic-gate 		 * match the query with the indexes.
13270Sstevel@tonic-gate 		 */
13280Sstevel@tonic-gate 		if (x->index.numIndexes <= 0 ||
13290Sstevel@tonic-gate 					verifyIndexMatch(x, q, 0, 0, 0)) {
13300Sstevel@tonic-gate 			tp[nm] = x;
13310Sstevel@tonic-gate 			nm++;
13320Sstevel@tonic-gate 		}
13330Sstevel@tonic-gate 	}
13340Sstevel@tonic-gate 
13350Sstevel@tonic-gate 	if (nm == 0) {
13360Sstevel@tonic-gate 		free(tp);
13370Sstevel@tonic-gate 		tp = 0;
13380Sstevel@tonic-gate 	}
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 	*numMatches = nm;
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate 	return (tp);
13430Sstevel@tonic-gate }
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate /*
13460Sstevel@tonic-gate  * Return 1 if there's an indexed mapping, 0 otherwise.
13470Sstevel@tonic-gate  */
13480Sstevel@tonic-gate int
haveIndexedMapping(__nis_table_mapping_t * t)13490Sstevel@tonic-gate haveIndexedMapping(__nis_table_mapping_t *t) {
13500Sstevel@tonic-gate 	__nis_table_mapping_t	*x;
13510Sstevel@tonic-gate 
13520Sstevel@tonic-gate 	for (x = t; x != 0; x = x->next) {
13530Sstevel@tonic-gate 		if (x->index.numIndexes > 0)
13540Sstevel@tonic-gate 			return (1);
13550Sstevel@tonic-gate 	}
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate 	return (0);
13580Sstevel@tonic-gate }
13590Sstevel@tonic-gate 
13600Sstevel@tonic-gate /*
13610Sstevel@tonic-gate  * Given an input string 'attrs' of the form "attr1=val1,attr2=val2,...",
13620Sstevel@tonic-gate  * or a filter, return the value associated with the attribute 'attrName'.
13630Sstevel@tonic-gate  * If no instance of 'attrName' is found, return 'default'. In all cases,
13640Sstevel@tonic-gate  * the return value is a copy, and must be freed by the caller.
13650Sstevel@tonic-gate  *
13660Sstevel@tonic-gate  * Of course, return NULL in case of failure.
13670Sstevel@tonic-gate  */
13680Sstevel@tonic-gate static char *
attrVal(char * msg,char * attrName,char * def,char * attrs)13690Sstevel@tonic-gate attrVal(char *msg, char *attrName, char *def, char *attrs) {
13700Sstevel@tonic-gate 	char	*val, *filter, **fc = 0;
13710Sstevel@tonic-gate 	int	i, nfc;
13720Sstevel@tonic-gate 	char	*myself = "attrVal";
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 	if (attrName == 0 || attrs == 0)
13750Sstevel@tonic-gate 		return (0);
13760Sstevel@tonic-gate 
13770Sstevel@tonic-gate 	if (msg == 0)
13780Sstevel@tonic-gate 		msg = myself;
13790Sstevel@tonic-gate 
13800Sstevel@tonic-gate 	val = def;
13810Sstevel@tonic-gate 
13820Sstevel@tonic-gate 	filter = makeFilter(attrs);
13830Sstevel@tonic-gate 	if (filter != 0 && (fc = makeFilterComp(filter, &nfc)) != 0 &&
13840Sstevel@tonic-gate 			nfc > 0) {
13850Sstevel@tonic-gate 		for (i = 0; i < nfc; i++) {
13860Sstevel@tonic-gate 			char	*name, *value;
13870Sstevel@tonic-gate 
13880Sstevel@tonic-gate 			name = fc[i];
13890Sstevel@tonic-gate 			/* Skip if not of attr=value form */
13900Sstevel@tonic-gate 			if ((value = strchr(name, '=')) == 0)
13910Sstevel@tonic-gate 				continue;
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate 			*value = '\0';
13940Sstevel@tonic-gate 			value++;
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 			if (strcasecmp(attrName, name) == 0) {
13970Sstevel@tonic-gate 				val = value;
13980Sstevel@tonic-gate 				break;
13990Sstevel@tonic-gate 			}
14000Sstevel@tonic-gate 		}
14010Sstevel@tonic-gate 	}
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate 	if (val != 0)
14040Sstevel@tonic-gate 		val = sdup(msg, T, val);
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 	sfree(filter);
14070Sstevel@tonic-gate 	freeFilterComp(fc, nfc);
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 	return (val);
14100Sstevel@tonic-gate }
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate extern bool_t	xdr_nis_object(register XDR *xdrs, nis_object *objp);
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate /*
14150Sstevel@tonic-gate  * Copy an XDR:ed version of the NIS+ object 'o' (or the one indicated
14160Sstevel@tonic-gate  * by 't->objName' if 'o' is NULL) to the place indicated by
14170Sstevel@tonic-gate  * 't->objectDN->write'. Return an appropriate LDAP status code.
14180Sstevel@tonic-gate  */
14190Sstevel@tonic-gate int
objToLDAP(__nis_table_mapping_t * t,nis_object * o,entry_obj ** ea,int numEa)14200Sstevel@tonic-gate objToLDAP(__nis_table_mapping_t *t, nis_object *o, entry_obj **ea, int numEa) {
14210Sstevel@tonic-gate 	__nis_table_mapping_t	**tp;
14220Sstevel@tonic-gate 	XDR			xdr;
14230Sstevel@tonic-gate 	char			*objName;
14240Sstevel@tonic-gate 	int			stat, osize, n, numMatches = 0;
14250Sstevel@tonic-gate 	void			*buf;
14260Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
14270Sstevel@tonic-gate 	__nis_value_t		*val;
14280Sstevel@tonic-gate 	__nis_single_value_t	*sv;
14290Sstevel@tonic-gate 	char			**attrName, *dn;
14300Sstevel@tonic-gate 	char			*myself = "objToLDAP";
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate 	if (t == 0)
14330Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
14360Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
14370Sstevel@tonic-gate 		LOG_WARNING,
14380Sstevel@tonic-gate #else
14390Sstevel@tonic-gate 		LOG_INFO,
14400Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
14410Sstevel@tonic-gate 		"%s: %s", myself, NIL(t->objName));
14420Sstevel@tonic-gate 
14430Sstevel@tonic-gate 	tp = selectTableMapping(t, 0, 1, 1, 0, &numMatches);
14440Sstevel@tonic-gate 	if (tp == 0 || numMatches <= 0) {
14450Sstevel@tonic-gate 		sfree(tp);
14460Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK,
14470Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
14480Sstevel@tonic-gate 			LOG_WARNING,
14490Sstevel@tonic-gate #else
14500Sstevel@tonic-gate 			LOG_INFO,
14510Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
14520Sstevel@tonic-gate 			"%s: %s (no mapping)", myself, NIL(t->objName));
14530Sstevel@tonic-gate 		return (LDAP_SUCCESS);
14540Sstevel@tonic-gate 	}
14550Sstevel@tonic-gate 
14560Sstevel@tonic-gate 	for (n = 0; n < numMatches; n++) {
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate 		t = tp[n];
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 		if (o == 0) {
1461*11262SRajagopal.Andra@Sun.COM 			sfree(tp);
1462*11262SRajagopal.Andra@Sun.COM 			return (LDAP_OPERATIONS_ERROR);
14630Sstevel@tonic-gate 		}
14640Sstevel@tonic-gate 
14650Sstevel@tonic-gate 		buf = (char *)xdrNisObject(o, ea, numEa, &osize);
14660Sstevel@tonic-gate 		if (buf == 0) {
14670Sstevel@tonic-gate 			sfree(tp);
14680Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
14690Sstevel@tonic-gate 		}
14700Sstevel@tonic-gate 
14710Sstevel@tonic-gate 		/*
14720Sstevel@tonic-gate 		 * Prepare to build a rule-value containing the XDR:ed
14730Sstevel@tonic-gate 		 * object
14740Sstevel@tonic-gate 		 */
14750Sstevel@tonic-gate 		rv = am(myself, sizeof (*rv));
14760Sstevel@tonic-gate 		sv = am(myself, sizeof (*sv));
14770Sstevel@tonic-gate 		val = am(myself, sizeof (*val));
14780Sstevel@tonic-gate 		attrName = am(myself, sizeof (attrName[0]));
14790Sstevel@tonic-gate 		if (attrName != 0)
14800Sstevel@tonic-gate 			attrName[0] = attrVal(myself, "nisplusObject",
14810Sstevel@tonic-gate 						"nisplusObject",
14820Sstevel@tonic-gate 						t->objectDN->write.attrs);
14830Sstevel@tonic-gate 		if (rv == 0 || sv == 0 || val == 0 || attrName == 0 ||
14840Sstevel@tonic-gate 				attrName[0] == 0) {
14850Sstevel@tonic-gate 			sfree(tp);
14860Sstevel@tonic-gate 			sfree(buf);
14870Sstevel@tonic-gate 			sfree(rv);
14880Sstevel@tonic-gate 			sfree(sv);
14890Sstevel@tonic-gate 			sfree(val);
14900Sstevel@tonic-gate 			sfree(attrName);
14910Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
14920Sstevel@tonic-gate 		}
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate 		sv->length = osize;
14950Sstevel@tonic-gate 		sv->value = buf;
14960Sstevel@tonic-gate 
14970Sstevel@tonic-gate 		/* 'vt_ber' just means "not a NUL-terminated string" */
14980Sstevel@tonic-gate 		val->type = vt_ber;
14990Sstevel@tonic-gate 		val->repeat = 0;
15000Sstevel@tonic-gate 		val->numVals = 1;
15010Sstevel@tonic-gate 		val->val = sv;
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate 		rv->numAttrs = 1;
15040Sstevel@tonic-gate 		rv->attrName = attrName;
15050Sstevel@tonic-gate 		rv->attrVal = val;
15060Sstevel@tonic-gate 
15070Sstevel@tonic-gate 		/*
15080Sstevel@tonic-gate 		 * The 'write.base' is the actual DN of the entry (and the
15090Sstevel@tonic-gate 		 * scope had better be 'base', but we don't check that).
15100Sstevel@tonic-gate 		 */
15110Sstevel@tonic-gate 		dn = t->objectDN->write.base;
15120Sstevel@tonic-gate 
15130Sstevel@tonic-gate 		stat = ldapModify(dn, rv, t->objectDN->write.attrs, 1);
15140Sstevel@tonic-gate 
15150Sstevel@tonic-gate 		freeRuleValue(rv, 1);
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
15180Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
15190Sstevel@tonic-gate 		LOG_WARNING,
15200Sstevel@tonic-gate #else
15210Sstevel@tonic-gate 		LOG_INFO,
15220Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
15230Sstevel@tonic-gate 		"%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
15240Sstevel@tonic-gate 
15250Sstevel@tonic-gate 		if (stat != LDAP_SUCCESS)
15260Sstevel@tonic-gate 			break;
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate 	}
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 	sfree(tp);
15310Sstevel@tonic-gate 
15320Sstevel@tonic-gate 	return (stat);
15330Sstevel@tonic-gate }
15340Sstevel@tonic-gate 
15350Sstevel@tonic-gate /*
15360Sstevel@tonic-gate  * Retrieve a copy of the 't->objName' object from LDAP, where it's
15370Sstevel@tonic-gate  * stored in XDR:ed form in the place indicated by 't->objectDN->read'.
15380Sstevel@tonic-gate  * Un-XDR the object, and return a pointer to it in '*obj'; it's the
15390Sstevel@tonic-gate  * responsibility of the caller to free the object when it's no
15400Sstevel@tonic-gate  * longer needed.
15410Sstevel@tonic-gate  *
15420Sstevel@tonic-gate  * Returns an appropriate LDAP status.
15430Sstevel@tonic-gate  */
15440Sstevel@tonic-gate int
objFromLDAP(__nis_table_mapping_t * t,nis_object ** obj,entry_obj *** eaP,int * numEaP)15450Sstevel@tonic-gate objFromLDAP(__nis_table_mapping_t *t, nis_object **obj,
15460Sstevel@tonic-gate 		entry_obj ***eaP, int *numEaP) {
15470Sstevel@tonic-gate 	__nis_table_mapping_t	**tp;
15480Sstevel@tonic-gate 	XDR			xdr;
15490Sstevel@tonic-gate 	nis_object		*o;
15500Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
15510Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
15520Sstevel@tonic-gate 	char			*attrs[2], *filter, **fc = 0;
15530Sstevel@tonic-gate 	void			*buf;
15540Sstevel@tonic-gate 	int			i, j, nfc, nrv, blen, stat = LDAP_SUCCESS;
15550Sstevel@tonic-gate 	int			n, numMatches;
15560Sstevel@tonic-gate 	char			*myself = "objFromLDAP";
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate 	if (t == 0)
15590Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate 	/*
15620Sstevel@tonic-gate 	 * If there's nowhere to store the result, we might as
15630Sstevel@tonic-gate 	 * well pretend all went well, and return right away.
15640Sstevel@tonic-gate 	 */
15650Sstevel@tonic-gate 	if (obj == 0)
15660Sstevel@tonic-gate 		return (LDAP_SUCCESS);
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate 	/* Prepare for the worst */
15690Sstevel@tonic-gate 	*obj = 0;
15700Sstevel@tonic-gate 
15710Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
15720Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
15730Sstevel@tonic-gate 		LOG_WARNING,
15740Sstevel@tonic-gate #else
15750Sstevel@tonic-gate 		LOG_INFO,
15760Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
15770Sstevel@tonic-gate 		"%s: %s", myself, NIL(t->objName));
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 	tp = selectTableMapping(t, 0, 0, 1, 0, &numMatches);
15800Sstevel@tonic-gate 	if (tp == 0 || numMatches <= 0) {
15810Sstevel@tonic-gate 		sfree(tp);
15820Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK,
15830Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
15840Sstevel@tonic-gate 			LOG_WARNING,
15850Sstevel@tonic-gate #else
15860Sstevel@tonic-gate 			LOG_INFO,
15870Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
15880Sstevel@tonic-gate 			"%s: %s (no mapping)", myself, NIL(t->objName));
15890Sstevel@tonic-gate 		return (LDAP_SUCCESS);
15900Sstevel@tonic-gate 	}
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate 	for (n = 0; n < numMatches; n++) {
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 		t = tp[n];
15950Sstevel@tonic-gate 
15960Sstevel@tonic-gate 		filter = makeFilter(t->objectDN->read.attrs);
15970Sstevel@tonic-gate 		if (filter == 0 || (fc = makeFilterComp(filter, &nfc)) == 0 ||
15980Sstevel@tonic-gate 				nfc <= 0) {
15990Sstevel@tonic-gate 			sfree(tp);
16000Sstevel@tonic-gate 			sfree(filter);
16010Sstevel@tonic-gate 			freeFilterComp(fc, nfc);
16020Sstevel@tonic-gate 			return ((t->objectDN->read.attrs != 0) ?
16030Sstevel@tonic-gate 				LDAP_NO_MEMORY : LDAP_PARAM_ERROR);
16040Sstevel@tonic-gate 		}
16050Sstevel@tonic-gate 		/* Don't need the filter, just the components */
16060Sstevel@tonic-gate 		sfree(filter);
16070Sstevel@tonic-gate 
16080Sstevel@tonic-gate 		/*
16090Sstevel@tonic-gate 		 * Look for a "nisplusObject" attribute, and (if found) copy
16100Sstevel@tonic-gate 		 * the value to attrs[0]. Also remove the "nisplusObject"
16110Sstevel@tonic-gate 		 * attribute and value from the filter components.
16120Sstevel@tonic-gate 		 */
16130Sstevel@tonic-gate 		attrs[0] = sdup(myself, T, "nisplusObject");
16140Sstevel@tonic-gate 		if (attrs[0] == 0) {
16150Sstevel@tonic-gate 			sfree(tp);
16160Sstevel@tonic-gate 			freeFilterComp(fc, nfc);
16170Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
16180Sstevel@tonic-gate 		}
16190Sstevel@tonic-gate 		attrs[1] = 0;
16200Sstevel@tonic-gate 		for (i = 0; i < nfc; i++) {
16210Sstevel@tonic-gate 			char	*name, *value;
16220Sstevel@tonic-gate 			int	compare;
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate 			name = fc[i];
16250Sstevel@tonic-gate 			/* Skip if not of attr=value form */
16260Sstevel@tonic-gate 			if ((value = strchr(name, '=')) == 0)
16270Sstevel@tonic-gate 				continue;
16280Sstevel@tonic-gate 
16290Sstevel@tonic-gate 			/* Temporarily overWrite the '=' with a '\0' */
16300Sstevel@tonic-gate 			*value = '\0';
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate 			/* Compare with our target attribute name */
16330Sstevel@tonic-gate 			compare = strcasecmp("nisplusObject", name);
16340Sstevel@tonic-gate 
16350Sstevel@tonic-gate 			/* Put back the '=' */
16360Sstevel@tonic-gate 			*value = '=';
16370Sstevel@tonic-gate 
16380Sstevel@tonic-gate 			/* Is it the name we're looking for ? */
16390Sstevel@tonic-gate 			if (compare == 0) {
16400Sstevel@tonic-gate 				sfree(attrs[0]);
16410Sstevel@tonic-gate 				attrs[0] = sdup(myself, T, value+1);
16420Sstevel@tonic-gate 				if (attrs[0] == 0) {
16430Sstevel@tonic-gate 					sfree(tp);
16440Sstevel@tonic-gate 					freeFilterComp(fc, nfc);
16450Sstevel@tonic-gate 					return (LDAP_NO_MEMORY);
16460Sstevel@tonic-gate 				}
16470Sstevel@tonic-gate 				sfree(fc[i]);
16480Sstevel@tonic-gate 				if (i < nfc-1)
16490Sstevel@tonic-gate 					(void) memmove(&fc[i], &fc[i+1],
16500Sstevel@tonic-gate 						(nfc-1-i) * sizeof (fc[i]));
16510Sstevel@tonic-gate 				nfc--;
16520Sstevel@tonic-gate 				break;
16530Sstevel@tonic-gate 			}
16540Sstevel@tonic-gate 		}
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 		ls = buildLdapSearch(t->objectDN->read.base,
16570Sstevel@tonic-gate 					t->objectDN->read.scope,
16580Sstevel@tonic-gate 					nfc, fc, 0, attrs, 0, 1);
16590Sstevel@tonic-gate 		sfree(attrs[0]);
16600Sstevel@tonic-gate 		freeFilterComp(fc, nfc);
16610Sstevel@tonic-gate 		if (ls == 0) {
16620Sstevel@tonic-gate 			sfree(tp);
16630Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
16640Sstevel@tonic-gate 		}
16650Sstevel@tonic-gate 
16660Sstevel@tonic-gate 		nrv = 0;
16670Sstevel@tonic-gate 		rv = ldapSearch(ls, &nrv, 0, &stat);
16680Sstevel@tonic-gate 		if (rv == 0) {
16690Sstevel@tonic-gate 			sfree(tp);
16700Sstevel@tonic-gate 			freeLdapSearch(ls);
16710Sstevel@tonic-gate 			return (stat);
16720Sstevel@tonic-gate 		}
16730Sstevel@tonic-gate 
16740Sstevel@tonic-gate 		for (i = 0, buf = 0; i < nrv && buf == 0; i++) {
16750Sstevel@tonic-gate 			for (j = 0; j < rv[i].numAttrs; j++) {
16760Sstevel@tonic-gate 				if (strcasecmp(ls->attrs[0],
16770Sstevel@tonic-gate 					rv[i].attrName[j]) == 0) {
16780Sstevel@tonic-gate 					if (rv[i].attrVal[j].numVals <= 0)
16790Sstevel@tonic-gate 						continue;
16800Sstevel@tonic-gate 					buf = rv[i].attrVal[j].val[0].value;
16810Sstevel@tonic-gate 					blen = rv[i].attrVal[j].val[0].length;
16820Sstevel@tonic-gate 					break;
16830Sstevel@tonic-gate 				}
16840Sstevel@tonic-gate 			}
16850Sstevel@tonic-gate 		}
16860Sstevel@tonic-gate 
16870Sstevel@tonic-gate 		if (buf != 0) {
16880Sstevel@tonic-gate 			o = unXdrNisObject(buf, blen, eaP, numEaP);
16890Sstevel@tonic-gate 			if (o == 0) {
16900Sstevel@tonic-gate 				sfree(tp);
16910Sstevel@tonic-gate 				freeLdapSearch(ls);
16920Sstevel@tonic-gate 				freeRuleValue(rv, nrv);
16930Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
16940Sstevel@tonic-gate 			}
16950Sstevel@tonic-gate 			stat = LDAP_SUCCESS;
16960Sstevel@tonic-gate 			*obj = o;
16970Sstevel@tonic-gate 		} else {
16980Sstevel@tonic-gate 			stat = LDAP_NO_SUCH_OBJECT;
16990Sstevel@tonic-gate 		}
17000Sstevel@tonic-gate 
17010Sstevel@tonic-gate 		freeLdapSearch(ls);
17020Sstevel@tonic-gate 		freeRuleValue(rv, nrv);
17030Sstevel@tonic-gate 
17040Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
17050Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
17060Sstevel@tonic-gate 		LOG_WARNING,
17070Sstevel@tonic-gate #else
17080Sstevel@tonic-gate 		LOG_INFO,
17090Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
17100Sstevel@tonic-gate 		"%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
17110Sstevel@tonic-gate 
17120Sstevel@tonic-gate 		if (stat != LDAP_SUCCESS)
17130Sstevel@tonic-gate 			break;
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate 	}
17160Sstevel@tonic-gate 
17170Sstevel@tonic-gate 	sfree(tp);
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate 	return (stat);
17200Sstevel@tonic-gate }
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate int
deleteLDAPobj(__nis_table_mapping_t * t)17230Sstevel@tonic-gate deleteLDAPobj(__nis_table_mapping_t *t) {
17240Sstevel@tonic-gate 	__nis_table_mapping_t	**tp;
17250Sstevel@tonic-gate 	int		n, stat, numMatches = 0;
17260Sstevel@tonic-gate 	char		*myself = "deleteLDAPobj";
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 	if (t == 0)
17290Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
17320Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
17330Sstevel@tonic-gate 		LOG_WARNING,
17340Sstevel@tonic-gate #else
17350Sstevel@tonic-gate 		LOG_INFO,
17360Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
17370Sstevel@tonic-gate 		"%s: %s", myself, NIL(t->objName));
17380Sstevel@tonic-gate 
17390Sstevel@tonic-gate 	tp = selectTableMapping(t, 0, 1, 1, 0, &numMatches);
17400Sstevel@tonic-gate 	if (tp == 0 || numMatches <= 0) {
17410Sstevel@tonic-gate 		sfree(tp);
17420Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK,
17430Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
17440Sstevel@tonic-gate 			LOG_WARNING,
17450Sstevel@tonic-gate #else
17460Sstevel@tonic-gate 			LOG_INFO,
17470Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
17480Sstevel@tonic-gate 			"%s: %s (no mapping)", myself, NIL(t->objName));
17490Sstevel@tonic-gate 		return (LDAP_SUCCESS);
17500Sstevel@tonic-gate 	}
17510Sstevel@tonic-gate 
17520Sstevel@tonic-gate 	for (n = 0; n < numMatches; n++) {
17530Sstevel@tonic-gate 
17540Sstevel@tonic-gate 		t = tp[n];
17550Sstevel@tonic-gate 
17560Sstevel@tonic-gate 		if (t->objectDN->delDisp == dd_always) {
17570Sstevel@tonic-gate 			/* Delete entire entry */
17580Sstevel@tonic-gate 			stat = ldapModify(t->objectDN->write.base, 0,
17590Sstevel@tonic-gate 					t->objectDN->write.attrs, 1);
17600Sstevel@tonic-gate 		} else if (t->objectDN->delDisp == dd_perDbId) {
17610Sstevel@tonic-gate 			/*
17620Sstevel@tonic-gate 			 * Delete the attribute holding the object.
17630Sstevel@tonic-gate 			 * First, determine what that attribute is called.
17640Sstevel@tonic-gate 			 */
17650Sstevel@tonic-gate 			char			*attrName =
17660Sstevel@tonic-gate 						attrVal(myself,
17670Sstevel@tonic-gate 							"nisplusObject",
17680Sstevel@tonic-gate 							"nisplusObject",
17690Sstevel@tonic-gate 						t->objectDN->write.attrs);
17700Sstevel@tonic-gate 			__nis_rule_value_t	rv;
17710Sstevel@tonic-gate 			__nis_value_t		val;
17720Sstevel@tonic-gate 
17730Sstevel@tonic-gate 			if (attrName == 0) {
17740Sstevel@tonic-gate 				sfree(tp);
17750Sstevel@tonic-gate 				return (LDAP_NO_MEMORY);
17760Sstevel@tonic-gate 			}
17770Sstevel@tonic-gate 
17780Sstevel@tonic-gate 			/*
17790Sstevel@tonic-gate 			 * Build a __nis_value_t with 'numVals' < 0 to
17800Sstevel@tonic-gate 			 * indicate deletion.
17810Sstevel@tonic-gate 			 */
17820Sstevel@tonic-gate 			val.type = vt_ber;
17830Sstevel@tonic-gate 			val.numVals = -1;
17840Sstevel@tonic-gate 			val.val = 0;
17850Sstevel@tonic-gate 
17860Sstevel@tonic-gate 			/*
17870Sstevel@tonic-gate 			 * Build a rule-value with the name we determined
17880Sstevel@tonic-gate 			 * above, and the deletion value.
17890Sstevel@tonic-gate 			 */
17900Sstevel@tonic-gate 			(void) memset(&rv, 0, sizeof (rv));
17910Sstevel@tonic-gate 			rv.numAttrs = 1;
17920Sstevel@tonic-gate 			rv.attrName = &attrName;
17930Sstevel@tonic-gate 			rv.attrVal = &val;
17940Sstevel@tonic-gate 
17950Sstevel@tonic-gate 			stat = ldapModify(t->objectDN->write.base, &rv,
17960Sstevel@tonic-gate 						t->objectDN->write.attrs, 0);
17970Sstevel@tonic-gate 
17980Sstevel@tonic-gate 			sfree(attrName);
17990Sstevel@tonic-gate 		} else if (t->objectDN->delDisp == dd_never) {
18000Sstevel@tonic-gate 			/* Nothing to do, so we're trivially successful */
18010Sstevel@tonic-gate 			stat = LDAP_SUCCESS;
18020Sstevel@tonic-gate 		} else {
18030Sstevel@tonic-gate 			stat = LDAP_PARAM_ERROR;
18040Sstevel@tonic-gate 		}
18050Sstevel@tonic-gate 
18060Sstevel@tonic-gate 	logmsg(MSG_NOTIMECHECK,
18070Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
18080Sstevel@tonic-gate 		LOG_WARNING,
18090Sstevel@tonic-gate #else
18100Sstevel@tonic-gate 		LOG_INFO,
18110Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
18120Sstevel@tonic-gate 		"%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
18130Sstevel@tonic-gate 
18140Sstevel@tonic-gate 		/* If there were no such object, we've trivially succeeded */
18150Sstevel@tonic-gate 		if (stat == LDAP_NO_SUCH_OBJECT)
18160Sstevel@tonic-gate 			stat = LDAP_SUCCESS;
18170Sstevel@tonic-gate 
18180Sstevel@tonic-gate 		if (stat != LDAP_SUCCESS)
18190Sstevel@tonic-gate 			break;
18200Sstevel@tonic-gate 
18210Sstevel@tonic-gate 	}
18220Sstevel@tonic-gate 
18230Sstevel@tonic-gate 	sfree(tp);
18240Sstevel@tonic-gate 
18250Sstevel@tonic-gate 	return (stat);
18260Sstevel@tonic-gate }
1827