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
5ea10ff14SBen Chang  * Common Development and Distribution License (the "License").
6ea10ff14SBen Chang  * 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*a87701e9SGary Mills  * Copyright 2015 Gary Mills
23ea10ff14SBen Chang  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * DESCRIPTION:	Contains dit_access interface support functions.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/stat.h>
347c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
357c478bd9Sstevel@tonic-gate #include <unistd.h>
367c478bd9Sstevel@tonic-gate #include <stdlib.h>
377c478bd9Sstevel@tonic-gate #include <syslog.h>
387c478bd9Sstevel@tonic-gate #include <ndbm.h>
397c478bd9Sstevel@tonic-gate #include <strings.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
41*a87701e9SGary Mills #include <ctype.h>
427c478bd9Sstevel@tonic-gate #include "../ldap_util.h"
437c478bd9Sstevel@tonic-gate #include "../ldap_map.h"
447c478bd9Sstevel@tonic-gate #include "../ldap_parse.h"
457c478bd9Sstevel@tonic-gate #include "../ldap_structs.h"
467c478bd9Sstevel@tonic-gate #include "../ldap_val.h"
477c478bd9Sstevel@tonic-gate #include "../ldap_ruleval.h"
487c478bd9Sstevel@tonic-gate #include "../ldap_op.h"
497c478bd9Sstevel@tonic-gate #include "../ldap_attr.h"
507c478bd9Sstevel@tonic-gate #include "../ldap_nisdbquery.h"
517c478bd9Sstevel@tonic-gate #include "../nisdb_mt.h"
527c478bd9Sstevel@tonic-gate #include "shim.h"
537c478bd9Sstevel@tonic-gate #include "yptol.h"
547c478bd9Sstevel@tonic-gate #include "dit_access_utils.h"
557c478bd9Sstevel@tonic-gate 
56ea10ff14SBen Chang #define	YPMULTI		"YP_MULTI_"
57ea10ff14SBen Chang #define	YPMULTISZ	9		/* == strlen(YPMULTI) */
58ea10ff14SBen Chang 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * Returns 'map,domain.'
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate char *
getFullMapName(char * map,char * domain)637c478bd9Sstevel@tonic-gate getFullMapName(char *map, char *domain) {
647c478bd9Sstevel@tonic-gate 	char	*myself = "getFullMapName";
657c478bd9Sstevel@tonic-gate 	char	*objPath;
667c478bd9Sstevel@tonic-gate 	if (map == 0 || domain == 0) {
677c478bd9Sstevel@tonic-gate 		return (0);
687c478bd9Sstevel@tonic-gate 	}
697c478bd9Sstevel@tonic-gate 	objPath =  scat(myself, T, scat(myself, F, map, ","),
707c478bd9Sstevel@tonic-gate 		scat(myself, F, domain, "."));
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	return (objPath);
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * Convert string to __nis_value_t
777c478bd9Sstevel@tonic-gate  */
stringToValue(char * dptr,int dsize)787c478bd9Sstevel@tonic-gate __nis_value_t *stringToValue(char *dptr, int dsize) {
797c478bd9Sstevel@tonic-gate 	char		*myself = "stringToValue";
807c478bd9Sstevel@tonic-gate 	char		*emptystr = "";
817c478bd9Sstevel@tonic-gate 	__nis_value_t	*val;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	if ((val = am(myself, sizeof (*val))) == 0) {
847c478bd9Sstevel@tonic-gate 		return (0);
857c478bd9Sstevel@tonic-gate 	}
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	val->type = vt_string;
887c478bd9Sstevel@tonic-gate 	val->repeat = 0;
897c478bd9Sstevel@tonic-gate 	val->numVals = 1;
907c478bd9Sstevel@tonic-gate 	if ((val->val = am(myself, sizeof (val->val[0]))) == 0) {
917c478bd9Sstevel@tonic-gate 		sfree(val);
927c478bd9Sstevel@tonic-gate 		return (0);
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	/*
967c478bd9Sstevel@tonic-gate 	 * Null strings or strings with length 0 are treated
977c478bd9Sstevel@tonic-gate 	 * as empty strings with length 1
987c478bd9Sstevel@tonic-gate 	 */
997c478bd9Sstevel@tonic-gate 	if (dptr == 0 || dsize <= 0) {
1007c478bd9Sstevel@tonic-gate 		dptr = emptystr;
1017c478bd9Sstevel@tonic-gate 		dsize = 1;
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	val->val->length = dsize;
1057c478bd9Sstevel@tonic-gate 	if (dptr[dsize - 1] != '\0') {
1067c478bd9Sstevel@tonic-gate 		val->val->length = dsize + 1;
1077c478bd9Sstevel@tonic-gate 	}
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	val->val->value = am(myself, val->val->length);
1107c478bd9Sstevel@tonic-gate 	if (val->val->value == 0) {
1117c478bd9Sstevel@tonic-gate 		freeValue(val, 1);
1127c478bd9Sstevel@tonic-gate 		return (0);
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 	(void) memcpy(val->val->value, dptr, dsize);
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	return (val);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate  * Returns an array of rule-values corresponding to the
1217c478bd9Sstevel@tonic-gate  * splitfields.
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate __nis_rule_value_t *
processSplitField(__nis_table_mapping_t * sf,__nis_value_t * inVal,int * nv,int * statP)1247c478bd9Sstevel@tonic-gate processSplitField(__nis_table_mapping_t *sf, __nis_value_t *inVal,
1257c478bd9Sstevel@tonic-gate 			int *nv, int *statP) {
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	char			*sepset;
1287c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rvq;
1297c478bd9Sstevel@tonic-gate 	__nis_value_t		**valA, *tempVal;
1307c478bd9Sstevel@tonic-gate 	int			i, j, res, numVals, oldlen, count;
1317c478bd9Sstevel@tonic-gate 	char			*str, *oldstr;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	/* sf will be non NULL */
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	if (inVal == 0 || inVal->type != vt_string) {
1367c478bd9Sstevel@tonic-gate 		*statP =  MAP_PARAM_ERROR;
1377c478bd9Sstevel@tonic-gate 		return (0);
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	/* Get the separator list */
1417c478bd9Sstevel@tonic-gate 	sepset = sf->separatorStr;
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/* Initialize rule-value */
1447c478bd9Sstevel@tonic-gate 	rvq = 0;
1457c478bd9Sstevel@tonic-gate 	count = 0;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	if ((tempVal = stringToValue(inVal->val->value,
1487c478bd9Sstevel@tonic-gate 			inVal->val->length)) == 0) {
1497c478bd9Sstevel@tonic-gate 		*statP = MAP_NO_MEMORY;
1507c478bd9Sstevel@tonic-gate 		return (0);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	str = oldstr = tempVal->val->value;
1547c478bd9Sstevel@tonic-gate 	oldlen = tempVal->val->length;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	while (str) {
1577c478bd9Sstevel@tonic-gate 		tempVal->val->value = str;
1587c478bd9Sstevel@tonic-gate 		tempVal->val->length = strlen(str) + 1;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 		/* Loop to check which format matches str */
1617c478bd9Sstevel@tonic-gate 		for (i = 0; i <= sf->numSplits; i++) {
1627c478bd9Sstevel@tonic-gate 			valA = matchMappingItem(sf->e[i].element.match.fmt,
1637c478bd9Sstevel@tonic-gate 				tempVal, &numVals, sepset, &str);
1647c478bd9Sstevel@tonic-gate 			if (valA == 0) {
1657c478bd9Sstevel@tonic-gate 				/* The format didn't match. Try the next one */
1667c478bd9Sstevel@tonic-gate 				continue;
1677c478bd9Sstevel@tonic-gate 			}
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 			/*
1707c478bd9Sstevel@tonic-gate 			 * If we are here means we had a match.
1717c478bd9Sstevel@tonic-gate 			 * Each new set of values obtained from the match is
1727c478bd9Sstevel@tonic-gate 			 * added to a new rule-value. This is to preserve the
1737c478bd9Sstevel@tonic-gate 			 * the distinction between each set.
1747c478bd9Sstevel@tonic-gate 			 */
1757c478bd9Sstevel@tonic-gate 			rvq = growRuleValue(count, count + 1, rvq, 0);
1767c478bd9Sstevel@tonic-gate 			if (rvq == 0) {
1777c478bd9Sstevel@tonic-gate 				*statP = MAP_INTERNAL_ERROR;
1787c478bd9Sstevel@tonic-gate 				for (j = 0; j < numVals; j++)
1797c478bd9Sstevel@tonic-gate 					freeValue(valA[j], 1);
1807c478bd9Sstevel@tonic-gate 				sfree(valA);
1817c478bd9Sstevel@tonic-gate 				tempVal->val->value = oldstr;
1827c478bd9Sstevel@tonic-gate 				tempVal->val->length = oldlen;
1837c478bd9Sstevel@tonic-gate 				freeValue(tempVal, 1);
1847c478bd9Sstevel@tonic-gate 				return (0);
1857c478bd9Sstevel@tonic-gate 			}
1867c478bd9Sstevel@tonic-gate 			count++;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 			for (j = 0; j < numVals; j++) {
1897c478bd9Sstevel@tonic-gate 				res = addCol2RuleValue(vt_string,
1907c478bd9Sstevel@tonic-gate 					sf->e[i].element.match.item[j].name,
1917c478bd9Sstevel@tonic-gate 					valA[j]->val->value,
1927c478bd9Sstevel@tonic-gate 					valA[j]->val->length,
1937c478bd9Sstevel@tonic-gate 					&rvq[count - 1]);
1947c478bd9Sstevel@tonic-gate 				if (res == -1) {
1957c478bd9Sstevel@tonic-gate 					*statP = MAP_INTERNAL_ERROR;
1967c478bd9Sstevel@tonic-gate 					for (; j < numVals; j++)
1977c478bd9Sstevel@tonic-gate 						freeValue(valA[j], 1);
1987c478bd9Sstevel@tonic-gate 					sfree(valA);
1997c478bd9Sstevel@tonic-gate 					tempVal->val->value = oldstr;
2007c478bd9Sstevel@tonic-gate 					tempVal->val->length = oldlen;
2017c478bd9Sstevel@tonic-gate 					freeValue(tempVal, 1);
2027c478bd9Sstevel@tonic-gate 					freeRuleValue(rvq, count);
2037c478bd9Sstevel@tonic-gate 					return (0);
2047c478bd9Sstevel@tonic-gate 				}
2057c478bd9Sstevel@tonic-gate 				freeValue(valA[j], 1);
2067c478bd9Sstevel@tonic-gate 			}
2077c478bd9Sstevel@tonic-gate 			sfree(valA);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 			/*
2107c478bd9Sstevel@tonic-gate 			 * Since we had a match, break out of this loop
2117c478bd9Sstevel@tonic-gate 			 * to parse remainder of str
2127c478bd9Sstevel@tonic-gate 			 */
2137c478bd9Sstevel@tonic-gate 			break;
2147c478bd9Sstevel@tonic-gate 		}
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 		/* Didn't find any match, so get out of the loop */
2177c478bd9Sstevel@tonic-gate 		if (i > sf->numSplits) {
2187c478bd9Sstevel@tonic-gate 			str = 0;
2197c478bd9Sstevel@tonic-gate 			break;
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 		/* Skip the separators before looping back */
2237c478bd9Sstevel@tonic-gate 		if (str) {
2247c478bd9Sstevel@tonic-gate 			str = str + strspn(str, sepset);
2257c478bd9Sstevel@tonic-gate 			if (*str == '\0')
2267c478bd9Sstevel@tonic-gate 				break;
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	tempVal->val->value = oldstr;
2317c478bd9Sstevel@tonic-gate 	tempVal->val->length = oldlen;
2327c478bd9Sstevel@tonic-gate 	freeValue(tempVal, 1);
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	if (str == 0) {
2357c478bd9Sstevel@tonic-gate 		freeRuleValue(rvq, count);
2367c478bd9Sstevel@tonic-gate 		return (0);
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	if (nv != 0)
2407c478bd9Sstevel@tonic-gate 		*nv = count;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	return (rvq);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate  * Convert the datum to an array of RuleValues
2477c478bd9Sstevel@tonic-gate  */
2487c478bd9Sstevel@tonic-gate __nis_rule_value_t *
datumToRuleValue(datum * key,datum * value,__nis_table_mapping_t * t,int * nv,char * domain,bool_t readonly,int * statP)2497c478bd9Sstevel@tonic-gate datumToRuleValue(datum *key, datum *value, __nis_table_mapping_t *t,
2507c478bd9Sstevel@tonic-gate 			int *nv, char *domain, bool_t readonly, int *statP) {
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rvq, *subrvq, *newrvq;
2537c478bd9Sstevel@tonic-gate 	__nis_value_t		*val;
2547c478bd9Sstevel@tonic-gate 	__nis_value_t		**valA;
2557c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*sf;
2567c478bd9Sstevel@tonic-gate 	int			valueLen, comLen, numVals, nr, count = 1;
257*a87701e9SGary Mills 	int			i, j, k, l;
2587c478bd9Sstevel@tonic-gate 	char			*ipaddr, *ipvalue;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	/*  At this point, 't' is always non NULL */
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	/* Initialize rule-value */
2637c478bd9Sstevel@tonic-gate 	if ((rvq = initRuleValue(1, 0)) == 0) {
2647c478bd9Sstevel@tonic-gate 		*statP = MAP_INTERNAL_ERROR;
2657c478bd9Sstevel@tonic-gate 		return (0);
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/* Add domainname to rule-value */
2697c478bd9Sstevel@tonic-gate 	if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain),
2707c478bd9Sstevel@tonic-gate 						rvq)) {
2717c478bd9Sstevel@tonic-gate 		freeRuleValue(rvq, 1);
2727c478bd9Sstevel@tonic-gate 		*statP = MAP_INTERNAL_ERROR;
2737c478bd9Sstevel@tonic-gate 		return (0);
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	/* Handle key */
2777c478bd9Sstevel@tonic-gate 	if (key != 0) {
2787c478bd9Sstevel@tonic-gate 		/* Add field=value pair for N2LKEY */
2797c478bd9Sstevel@tonic-gate 		i = addCol2RuleValue(vt_string, N2LKEY, key->dptr, key->dsize,
2807c478bd9Sstevel@tonic-gate 						rvq);
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 		/* For readonly, add field=value pair for N2LSEARCHKEY */
2837c478bd9Sstevel@tonic-gate 		if (readonly == TRUE && i == 0) {
2847c478bd9Sstevel@tonic-gate 			i = addCol2RuleValue(vt_string, N2LSEARCHKEY, key->dptr,
2857c478bd9Sstevel@tonic-gate 						key->dsize, rvq);
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 		if (i) {
2887c478bd9Sstevel@tonic-gate 			freeRuleValue(rvq, 1);
2897c478bd9Sstevel@tonic-gate 			*statP = MAP_INTERNAL_ERROR;
2907c478bd9Sstevel@tonic-gate 			return (0);
2917c478bd9Sstevel@tonic-gate 		}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 		/* Add field=value pairs for IP addresses */
2947c478bd9Sstevel@tonic-gate 		if (checkIPaddress(key->dptr, key->dsize, &ipaddr) > 0) {
2957c478bd9Sstevel@tonic-gate 			/* If key is IPaddress, use preferred format */
2967c478bd9Sstevel@tonic-gate 			ipvalue = ipaddr;
2977c478bd9Sstevel@tonic-gate 			valueLen = strlen(ipaddr);
2987c478bd9Sstevel@tonic-gate 			i = addCol2RuleValue(vt_string, N2LIPKEY, ipvalue,
2997c478bd9Sstevel@tonic-gate 						valueLen, rvq);
3007c478bd9Sstevel@tonic-gate 		} else {
3017c478bd9Sstevel@tonic-gate 			/* If not, use original value for N2LSEARCHIPKEY */
3027c478bd9Sstevel@tonic-gate 			ipaddr = 0;
3037c478bd9Sstevel@tonic-gate 			ipvalue = key->dptr;
3047c478bd9Sstevel@tonic-gate 			valueLen = key->dsize;
3057c478bd9Sstevel@tonic-gate 			i = 0;
3067c478bd9Sstevel@tonic-gate 		}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 		if (readonly == TRUE && i == 0) {
3097c478bd9Sstevel@tonic-gate 			i = addCol2RuleValue(vt_string, N2LSEARCHIPKEY, ipvalue,
3107c478bd9Sstevel@tonic-gate 								valueLen, rvq);
3117c478bd9Sstevel@tonic-gate 		}
3127c478bd9Sstevel@tonic-gate 		sfree(ipaddr);
3137c478bd9Sstevel@tonic-gate 		if (i) {
3147c478bd9Sstevel@tonic-gate 			freeRuleValue(rvq, 1);
3157c478bd9Sstevel@tonic-gate 			*statP = MAP_INTERNAL_ERROR;
3167c478bd9Sstevel@tonic-gate 			return (0);
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	/* Handle datum value */
3217c478bd9Sstevel@tonic-gate 	if (value != 0 && t->e) {
3227c478bd9Sstevel@tonic-gate 		valueLen = value->dsize;
3237c478bd9Sstevel@tonic-gate 		/*
3247c478bd9Sstevel@tonic-gate 		 * Extract the comment, if any, and add it to
3257c478bd9Sstevel@tonic-gate 		 * the rule-value.
3267c478bd9Sstevel@tonic-gate 		 */
3277c478bd9Sstevel@tonic-gate 		if (t->commentChar != '\0') {
3287c478bd9Sstevel@tonic-gate 			/*
3297c478bd9Sstevel@tonic-gate 			 * We loop on value->dsize because value->dptr
3307c478bd9Sstevel@tonic-gate 			 * may not be NULL-terminated.
3317c478bd9Sstevel@tonic-gate 			 */
3327c478bd9Sstevel@tonic-gate 			for (i = 0; i < value->dsize; i++) {
3337c478bd9Sstevel@tonic-gate 				if (value->dptr[i] == t->commentChar) {
3347c478bd9Sstevel@tonic-gate 					valueLen = i;
3357c478bd9Sstevel@tonic-gate 					comLen = value->dsize - i - 1;
3367c478bd9Sstevel@tonic-gate 					if (comLen == 0)
3377c478bd9Sstevel@tonic-gate 						break;
3387c478bd9Sstevel@tonic-gate 					if (addCol2RuleValue(vt_string,
3397c478bd9Sstevel@tonic-gate 						N2LCOMMENT, value->dptr + i + 1,
3407c478bd9Sstevel@tonic-gate 						comLen, rvq)) {
3417c478bd9Sstevel@tonic-gate 						freeRuleValue(rvq, 1);
3427c478bd9Sstevel@tonic-gate 						*statP = MAP_INTERNAL_ERROR;
3437c478bd9Sstevel@tonic-gate 						return (0);
3447c478bd9Sstevel@tonic-gate 					}
3457c478bd9Sstevel@tonic-gate 					break;
3467c478bd9Sstevel@tonic-gate 				}
3477c478bd9Sstevel@tonic-gate 			}
3487c478bd9Sstevel@tonic-gate 		}
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 		/* Skip trailing whitespaces */
3517c478bd9Sstevel@tonic-gate 		for (; valueLen > 0 && (value->dptr[valueLen - 1] == ' ' ||
3527c478bd9Sstevel@tonic-gate 			value->dptr[valueLen - 1] == '\t'); valueLen--);
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 		/*
3557c478bd9Sstevel@tonic-gate 		 * At this point valueLen is the effective length of
3567c478bd9Sstevel@tonic-gate 		 * the data. Convert value into __nis_value_t so that
3577c478bd9Sstevel@tonic-gate 		 * we can use the matchMappingItem function to break it
3587c478bd9Sstevel@tonic-gate 		 * into fields.
3597c478bd9Sstevel@tonic-gate 		 */
3607c478bd9Sstevel@tonic-gate 		if ((val = stringToValue(value->dptr, valueLen)) == 0) {
3617c478bd9Sstevel@tonic-gate 			freeRuleValue(rvq, 1);
3627c478bd9Sstevel@tonic-gate 			*statP = MAP_NO_MEMORY;
3637c478bd9Sstevel@tonic-gate 			return (0);
3647c478bd9Sstevel@tonic-gate 		}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 		/* Perform namefield match */
3677c478bd9Sstevel@tonic-gate 		valA = matchMappingItem(t->e->element.match.fmt, val,
3687c478bd9Sstevel@tonic-gate 							&numVals, 0, 0);
3697c478bd9Sstevel@tonic-gate 		if (valA == 0) {
3707c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
3717c478bd9Sstevel@tonic-gate 			freeRuleValue(rvq, 1);
3727c478bd9Sstevel@tonic-gate 			*statP = MAP_NAMEFIELD_MATCH_ERROR;
3737c478bd9Sstevel@tonic-gate 			return (0);
3747c478bd9Sstevel@tonic-gate 		}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 		/* We don't need val anymore, so free it */
3777c478bd9Sstevel@tonic-gate 		freeValue(val, 1);
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 		/*
3807c478bd9Sstevel@tonic-gate 		 * Since matchMappingItem only returns us an array of
3817c478bd9Sstevel@tonic-gate 		 * __nis_value_t's, we need to associate each value
3827c478bd9Sstevel@tonic-gate 		 * in the array with the corresponding item name.
3837c478bd9Sstevel@tonic-gate 		 * This code assumes that numVals will be less than or
3847c478bd9Sstevel@tonic-gate 		 * equal to the number of item names associated with
3857c478bd9Sstevel@tonic-gate 		 * the format.
3867c478bd9Sstevel@tonic-gate 		 * These name=value pairs are added to rvq.
3877c478bd9Sstevel@tonic-gate 		 */
3887c478bd9Sstevel@tonic-gate 		for (i = 0, *statP = SUCCESS; i < numVals; i++) {
3897c478bd9Sstevel@tonic-gate 			for (j = 0; j < count; j++) {
3907c478bd9Sstevel@tonic-gate 				if (addCol2RuleValue(vt_string,
3917c478bd9Sstevel@tonic-gate 					t->e->element.match.item[i].name,
3927c478bd9Sstevel@tonic-gate 					valA[i]->val->value,
3937c478bd9Sstevel@tonic-gate 					valA[i]->val->length, &rvq[j])) {
3947c478bd9Sstevel@tonic-gate 					*statP = MAP_INTERNAL_ERROR;
3957c478bd9Sstevel@tonic-gate 					break;
3967c478bd9Sstevel@tonic-gate 				}
3977c478bd9Sstevel@tonic-gate 			}
3987c478bd9Sstevel@tonic-gate 			if (*statP == MAP_INTERNAL_ERROR)
3997c478bd9Sstevel@tonic-gate 				break;
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 			/*
4027c478bd9Sstevel@tonic-gate 			 * Check if splitField exists for the field.
4037c478bd9Sstevel@tonic-gate 			 * Since splitfields are also stored as mapping
4047c478bd9Sstevel@tonic-gate 			 * structures, we need to get the hash table entry
4057c478bd9Sstevel@tonic-gate 			 * corresponding to the splitfield name
4067c478bd9Sstevel@tonic-gate 			 */
4077c478bd9Sstevel@tonic-gate 			sf = mappingFromMap(t->e->element.match.item[i].name,
4087c478bd9Sstevel@tonic-gate 					domain, statP);
4097c478bd9Sstevel@tonic-gate 			if (*statP == MAP_NO_MEMORY)
4107c478bd9Sstevel@tonic-gate 				break;
4117c478bd9Sstevel@tonic-gate 			*statP = SUCCESS;
4127c478bd9Sstevel@tonic-gate 			if (sf == 0)
4137c478bd9Sstevel@tonic-gate 				continue;
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 			/*
4167c478bd9Sstevel@tonic-gate 			 * Process and add splitFields to rule-value rvq
4177c478bd9Sstevel@tonic-gate 			 */
4187c478bd9Sstevel@tonic-gate 			subrvq = processSplitField(sf, valA[i], &nr, statP);
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 			if (subrvq == 0) {
4217c478bd9Sstevel@tonic-gate 				/* statP would have been set */
4227c478bd9Sstevel@tonic-gate 				break;
4237c478bd9Sstevel@tonic-gate 			}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 			/*
4267c478bd9Sstevel@tonic-gate 			 * We merge 'count' rule-values in rvq with 'nr'
4277c478bd9Sstevel@tonic-gate 			 * rule-values from subrvq to give us a whopping
4287c478bd9Sstevel@tonic-gate 			 * 'count * nr' rule-values
4297c478bd9Sstevel@tonic-gate 			 */
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 			/* Initialize the new rule-value array */
4327c478bd9Sstevel@tonic-gate 			if ((newrvq = initRuleValue(count * nr, 0)) == 0) {
4337c478bd9Sstevel@tonic-gate 				*statP = MAP_INTERNAL_ERROR;
4347c478bd9Sstevel@tonic-gate 				freeRuleValue(subrvq, nr);
4357c478bd9Sstevel@tonic-gate 				break;
4367c478bd9Sstevel@tonic-gate 			}
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 			for (j = 0, l = 0; j < nr; j++) {
4397c478bd9Sstevel@tonic-gate 				for (k = 0; k < count; k++, l++) {
4407c478bd9Sstevel@tonic-gate 					if ((mergeRuleValue(&newrvq[l],
4417c478bd9Sstevel@tonic-gate 							&rvq[k]) == -1) ||
4427c478bd9Sstevel@tonic-gate 							(mergeRuleValue(
4437c478bd9Sstevel@tonic-gate 							&newrvq[l],
4447c478bd9Sstevel@tonic-gate 							&subrvq[j]) == -1)) {
4457c478bd9Sstevel@tonic-gate 						*statP = MAP_INTERNAL_ERROR;
4467c478bd9Sstevel@tonic-gate 						for (i = 0; i < numVals; i++)
4477c478bd9Sstevel@tonic-gate 							freeValue(valA[i], 1);
4487c478bd9Sstevel@tonic-gate 						sfree(valA);
4497c478bd9Sstevel@tonic-gate 						freeRuleValue(rvq, count);
4507c478bd9Sstevel@tonic-gate 						freeRuleValue(newrvq,
4517c478bd9Sstevel@tonic-gate 								count * nr);
4527c478bd9Sstevel@tonic-gate 						freeRuleValue(subrvq, nr);
4537c478bd9Sstevel@tonic-gate 						return (0);
4547c478bd9Sstevel@tonic-gate 					}
4557c478bd9Sstevel@tonic-gate 				}
4567c478bd9Sstevel@tonic-gate 			}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 			freeRuleValue(rvq, count);
4597c478bd9Sstevel@tonic-gate 			rvq = newrvq;
4607c478bd9Sstevel@tonic-gate 			count = l;
4617c478bd9Sstevel@tonic-gate 			freeRuleValue(subrvq, nr);
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 		}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 		/* We don't need valA anymore, so free it */
4667c478bd9Sstevel@tonic-gate 		for (i = 0; i < numVals; i++)
4677c478bd9Sstevel@tonic-gate 			freeValue(valA[i], 1);
4687c478bd9Sstevel@tonic-gate 		sfree(valA);
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 		if (*statP != SUCCESS) {
4717c478bd9Sstevel@tonic-gate 			freeRuleValue(rvq, count);
4727c478bd9Sstevel@tonic-gate 			return (0);
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	} /* if value */
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	if (nv != 0)
4787c478bd9Sstevel@tonic-gate 		*nv = count;
4797c478bd9Sstevel@tonic-gate 	return (rvq);
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate /*
4847c478bd9Sstevel@tonic-gate  * Generate name=values pairs for splitfield names
4857c478bd9Sstevel@tonic-gate  *
4867c478bd9Sstevel@tonic-gate  * Consider Example:
4877c478bd9Sstevel@tonic-gate  *	nisLDAPnameFields club:
4887c478bd9Sstevel@tonic-gate  *			("%s %s %s", name, code, members)
4897c478bd9Sstevel@tonic-gate  *	nisLDAPsplitField members:
4907c478bd9Sstevel@tonic-gate  *			("(%s,%s,%s)", host, user, domain),
4917c478bd9Sstevel@tonic-gate  *			("%s", group)
4927c478bd9Sstevel@tonic-gate  * On entry,
4937c478bd9Sstevel@tonic-gate  * - rv is an array of numVals rule-values each containing
4947c478bd9Sstevel@tonic-gate  * name=value pairs for names occuring in nisLDAPsplitField.
4957c478bd9Sstevel@tonic-gate  * (i.e host, user, domain, group)
4967c478bd9Sstevel@tonic-gate  * - trv contains name=value pairs for names occuring in
4977c478bd9Sstevel@tonic-gate  * nisLDAPnameFields. (i.e name, code but not members)
4987c478bd9Sstevel@tonic-gate  *
4997c478bd9Sstevel@tonic-gate  * For every name in nisLDAPnamefields that is a splitfield,
5007c478bd9Sstevel@tonic-gate  * this function applies the data in rv to the corresponding
5017c478bd9Sstevel@tonic-gate  * splitfield formats (accessed thru t), to generate a single
5027c478bd9Sstevel@tonic-gate  * string value for the corresponding splitfield (members).
5037c478bd9Sstevel@tonic-gate  * This new name=value pair is then added to trv.
5047c478bd9Sstevel@tonic-gate  * Besides, any uninitialized namefield names are set to empty strings.
5057c478bd9Sstevel@tonic-gate  */
5067c478bd9Sstevel@tonic-gate suc_code
addSplitFieldValues(__nis_table_mapping_t * t,__nis_rule_value_t * rv,__nis_rule_value_t * trv,int numVals,char * domain)5077c478bd9Sstevel@tonic-gate addSplitFieldValues(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
5087c478bd9Sstevel@tonic-gate 			__nis_rule_value_t *trv, int numVals, char *domain) {
5097c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*sf;
5107c478bd9Sstevel@tonic-gate 	__nis_value_t		*val;
5117c478bd9Sstevel@tonic-gate 	int			i, j, k, nitems, res, statP;
5127c478bd9Sstevel@tonic-gate 	char			*str, *tempstr;
5137c478bd9Sstevel@tonic-gate 	char			delim[2] = {0, 0};
5147c478bd9Sstevel@tonic-gate 	char			*emptystr = "";
5157c478bd9Sstevel@tonic-gate 	char			*myself = "addSplitFieldValues";
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	if (trv == 0)
5187c478bd9Sstevel@tonic-gate 		return (MAP_INTERNAL_ERROR);
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	if (t->e == 0)
5217c478bd9Sstevel@tonic-gate 		return (SUCCESS);
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	nitems = t->e->element.match.numItems;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	/*
5267c478bd9Sstevel@tonic-gate 	 * Procedure:
5277c478bd9Sstevel@tonic-gate 	 * - Check each name in nisLDAPnamefield
5287c478bd9Sstevel@tonic-gate 	 * - if it's a splifield, construct its value and add it to trv
5297c478bd9Sstevel@tonic-gate 	 * - if not, check if it has a value
5307c478bd9Sstevel@tonic-gate 	 * - if not, add empty string
5317c478bd9Sstevel@tonic-gate 	 */
5327c478bd9Sstevel@tonic-gate 	for (i = 0, sf = 0; i < nitems; i++) {
5337c478bd9Sstevel@tonic-gate 		if (rv) {
5347c478bd9Sstevel@tonic-gate 			/*
5357c478bd9Sstevel@tonic-gate 			 * str will eventually contain the single string
5367c478bd9Sstevel@tonic-gate 			 * value for the corresponding  splitfield.
5377c478bd9Sstevel@tonic-gate 			 * No point initializing str if rv == 0 because
5387c478bd9Sstevel@tonic-gate 			 * splitfield cannot be constructed without rv.
5397c478bd9Sstevel@tonic-gate 			 * So, only initialized here.
5407c478bd9Sstevel@tonic-gate 			 */
5417c478bd9Sstevel@tonic-gate 			str = 0;
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 			/* Check if it's a splitfield name */
5447c478bd9Sstevel@tonic-gate 			sf = mappingFromMap(t->e->element.match.item[i].name,
5457c478bd9Sstevel@tonic-gate 				domain, &statP);
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 			/*
5487c478bd9Sstevel@tonic-gate 			 * Return only incase of memory allocation failure.
5497c478bd9Sstevel@tonic-gate 			 * The other error case (MAP_NO_MAPPING_EXISTS),
5507c478bd9Sstevel@tonic-gate 			 * indicates that the item name is not a splitfieldname
5517c478bd9Sstevel@tonic-gate 			 * i.e it's a namefieldname. This case is handled by
5527c478bd9Sstevel@tonic-gate 			 * the following if (sf == 0)
5537c478bd9Sstevel@tonic-gate 			 */
5547c478bd9Sstevel@tonic-gate 			if (statP == MAP_NO_MEMORY)
5557c478bd9Sstevel@tonic-gate 				return (statP);
5567c478bd9Sstevel@tonic-gate 		}
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 		if (sf == 0) {
5597c478bd9Sstevel@tonic-gate 			/*
5607c478bd9Sstevel@tonic-gate 			 * Not a splitfield name. Verify if it has a value
5617c478bd9Sstevel@tonic-gate 			 */
5627c478bd9Sstevel@tonic-gate 			if (findVal(t->e->element.match.item[i].name,
5637c478bd9Sstevel@tonic-gate 				trv, mit_nisplus) == 0) {
5647c478bd9Sstevel@tonic-gate 				/* if not, use empty string */
5657c478bd9Sstevel@tonic-gate 				res = addCol2RuleValue(vt_string,
5667c478bd9Sstevel@tonic-gate 					t->e->element.match.item[i].name,
5677c478bd9Sstevel@tonic-gate 					emptystr, 0, trv);
5687c478bd9Sstevel@tonic-gate 				if (res == -1) {
5697c478bd9Sstevel@tonic-gate 					return (MAP_INTERNAL_ERROR);
5707c478bd9Sstevel@tonic-gate 				}
5717c478bd9Sstevel@tonic-gate 			}
5727c478bd9Sstevel@tonic-gate 			/*
5737c478bd9Sstevel@tonic-gate 			 * If rv == 0 then sf == 0 so we will continue here
5747c478bd9Sstevel@tonic-gate 			 * i.e. does not matter that str is not yet set up.
5757c478bd9Sstevel@tonic-gate 			 */
5767c478bd9Sstevel@tonic-gate 			continue;
5777c478bd9Sstevel@tonic-gate 		}
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 		/* Code to construct a single value */
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 		/* Use the first separator character as the delimiter */
5827c478bd9Sstevel@tonic-gate 		delim[0] = sf->separatorStr[0];
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 		for (j = 0; j < numVals; j++) {
5857c478bd9Sstevel@tonic-gate 			/* sf->numSplits is zero-based */
5867c478bd9Sstevel@tonic-gate 			for (k = 0; k <= sf->numSplits; k++) {
5877c478bd9Sstevel@tonic-gate 				val = getMappingFormatArray(
5887c478bd9Sstevel@tonic-gate 					sf->e[k].element.match.fmt, &rv[j],
5897c478bd9Sstevel@tonic-gate 					fa_item,
5907c478bd9Sstevel@tonic-gate 					sf->e[k].element.match.numItems,
5917c478bd9Sstevel@tonic-gate 					sf->e[k].element.match.item);
5927c478bd9Sstevel@tonic-gate 				if (val == 0)
5937c478bd9Sstevel@tonic-gate 					continue;
5947c478bd9Sstevel@tonic-gate 				if (val->numVals > 0) {
5957c478bd9Sstevel@tonic-gate 					if (str) {
5967c478bd9Sstevel@tonic-gate 						tempstr = scat(myself,
5977c478bd9Sstevel@tonic-gate 							0, str, delim);
5987c478bd9Sstevel@tonic-gate 						sfree(str);
5997c478bd9Sstevel@tonic-gate 						if (tempstr)
6007c478bd9Sstevel@tonic-gate 							str = tempstr;
6017c478bd9Sstevel@tonic-gate 						else {
6027c478bd9Sstevel@tonic-gate 							freeValue(val, 1);
6037c478bd9Sstevel@tonic-gate 							return (MAP_NO_MEMORY);
6047c478bd9Sstevel@tonic-gate 						}
6057c478bd9Sstevel@tonic-gate 					}
6067c478bd9Sstevel@tonic-gate 					tempstr = scat(myself, 0, str,
6077c478bd9Sstevel@tonic-gate 						val->val->value);
6087c478bd9Sstevel@tonic-gate 					sfree(str);
6097c478bd9Sstevel@tonic-gate 					if (tempstr)
6107c478bd9Sstevel@tonic-gate 						str = tempstr;
6117c478bd9Sstevel@tonic-gate 					else {
6127c478bd9Sstevel@tonic-gate 						freeValue(val, 1);
6137c478bd9Sstevel@tonic-gate 						return (MAP_NO_MEMORY);
6147c478bd9Sstevel@tonic-gate 					}
6157c478bd9Sstevel@tonic-gate 				}
6167c478bd9Sstevel@tonic-gate 				freeValue(val, 1);
6177c478bd9Sstevel@tonic-gate 			}
6187c478bd9Sstevel@tonic-gate 		}
6197c478bd9Sstevel@tonic-gate 		if (str == 0)
6207c478bd9Sstevel@tonic-gate 			str = emptystr;
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 		res = addCol2RuleValue(vt_string,
6237c478bd9Sstevel@tonic-gate 				t->e->element.match.item[i].name,
6247c478bd9Sstevel@tonic-gate 				str, strlen(str), trv);
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		if (str != emptystr)
6277c478bd9Sstevel@tonic-gate 			sfree(str);
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 		if (res == -1) {
6307c478bd9Sstevel@tonic-gate 			return (MAP_INTERNAL_ERROR);
6317c478bd9Sstevel@tonic-gate 		}
6327c478bd9Sstevel@tonic-gate 	}
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	return (SUCCESS);
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate /*
6387c478bd9Sstevel@tonic-gate  * Updates 'rv' with NIS name=value pairs suitable to
6397c478bd9Sstevel@tonic-gate  * construct datum from namefield information.
6407c478bd9Sstevel@tonic-gate  * Some part based on createNisPlusEntry (from ldap_nisdbquery.c)
6417c478bd9Sstevel@tonic-gate  * This code assumes that from a given LDAP entry, applying the
6427c478bd9Sstevel@tonic-gate  * mapping rules, would give us one or more NIS entries, differing
6437c478bd9Sstevel@tonic-gate  * only in key.
6447c478bd9Sstevel@tonic-gate  */
6457c478bd9Sstevel@tonic-gate suc_code
buildNISRuleValue(__nis_table_mapping_t * t,__nis_rule_value_t * rv,char * domain)6467c478bd9Sstevel@tonic-gate buildNISRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
6477c478bd9Sstevel@tonic-gate 					char *domain) {
648*a87701e9SGary Mills 	int			r, i, j, k, l, nrq, res, len;
6497c478bd9Sstevel@tonic-gate 	int			numItems, splitname, count, statP;
6507c478bd9Sstevel@tonic-gate 	__nis_value_t		*rval;
6517c478bd9Sstevel@tonic-gate 	__nis_mapping_item_t	*litem;
6527c478bd9Sstevel@tonic-gate 	__nis_mapping_rule_t	*rl;
6537c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rvq;
6547c478bd9Sstevel@tonic-gate 	char			*value, *emptystr = "";
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	statP = SUCCESS;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	/* Initialize default base */
6597c478bd9Sstevel@tonic-gate 	__nisdb_get_tsd()->searchBase = t->objectDN->read.base;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	/* Initialize rule-value rvq */
6627c478bd9Sstevel@tonic-gate 	rvq = 0;
6637c478bd9Sstevel@tonic-gate 	count = 0;
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	/* Add domainname to rule-value */
6667c478bd9Sstevel@tonic-gate 	if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain),
6677c478bd9Sstevel@tonic-gate 						rv)) {
6687c478bd9Sstevel@tonic-gate 		return (MAP_INTERNAL_ERROR);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	for (r = 0; r < t->numRulesFromLDAP; r++) {
6727c478bd9Sstevel@tonic-gate 		rl = t->ruleFromLDAP[r];
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 		/* Set escapeFlag if RHS is "dn" to remove escape chars */
6757c478bd9Sstevel@tonic-gate 		if (rl->rhs.numElements == 1 &&
6767c478bd9Sstevel@tonic-gate 			rl->rhs.element->type == me_item &&
6777c478bd9Sstevel@tonic-gate 			rl->rhs.element->element.item.type == mit_ldap &&
6787c478bd9Sstevel@tonic-gate 			strcasecmp(rl->rhs.element->element.item.name, "dn")
6797c478bd9Sstevel@tonic-gate 									== 0) {
6807c478bd9Sstevel@tonic-gate 				__nisdb_get_tsd()->escapeFlag = '2';
6817c478bd9Sstevel@tonic-gate 		}
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 		rval = buildRvalue(&rl->rhs, mit_ldap, rv, NULL);
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 		/* Reset escapeFlag */
6867c478bd9Sstevel@tonic-gate 		__nisdb_get_tsd()->escapeFlag = '\0';
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 		if (rval == 0) {
6897c478bd9Sstevel@tonic-gate 			continue;
6907c478bd9Sstevel@tonic-gate 		}
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 		if (rval->numVals <= 0) {
6937c478bd9Sstevel@tonic-gate 			/* Treat as invalid */
6947c478bd9Sstevel@tonic-gate 			freeValue(rval, 1);
6957c478bd9Sstevel@tonic-gate 			continue;
6967c478bd9Sstevel@tonic-gate 		}
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 		litem = buildLvalue(&rl->lhs, &rval, &numItems);
6997c478bd9Sstevel@tonic-gate 		if (litem == 0) {
7007c478bd9Sstevel@tonic-gate 			/* This will take care of numItems == 0 */
7017c478bd9Sstevel@tonic-gate 			freeValue(rval, 1);
7027c478bd9Sstevel@tonic-gate 			continue;
7037c478bd9Sstevel@tonic-gate 		}
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 		if (rval->numVals > 1) {
7067c478bd9Sstevel@tonic-gate 			if (numItems == 1 && litem->repeat)
7077c478bd9Sstevel@tonic-gate 				nrq = rval->numVals;
7087c478bd9Sstevel@tonic-gate 			else if (numItems > 1 && rval->repeat)
7097c478bd9Sstevel@tonic-gate 				nrq = 1 + ((rval->numVals-1)/numItems);
7107c478bd9Sstevel@tonic-gate 			else
7117c478bd9Sstevel@tonic-gate 				nrq = 1;
7127c478bd9Sstevel@tonic-gate 		} else
7137c478bd9Sstevel@tonic-gate 			nrq = 1;
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 		/* Set splitname if splitfield names are specified */
7167c478bd9Sstevel@tonic-gate 		for (i = 0; i < numItems; i++) {
7177c478bd9Sstevel@tonic-gate 			if (strcasecmp(litem[i].name, N2LKEY) == 0 ||
7187c478bd9Sstevel@tonic-gate 				strcasecmp(litem[i].name, N2LIPKEY) == 0 ||
7197c478bd9Sstevel@tonic-gate 				strcasecmp(litem[i].name, N2LCOMMENT) == 0)
7207c478bd9Sstevel@tonic-gate 				continue;
7217c478bd9Sstevel@tonic-gate 			for (j = 0; j < t->numColumns; j++) {
7227c478bd9Sstevel@tonic-gate 				if (strcmp(litem[i].name, t->column[j]) == 0)
7237c478bd9Sstevel@tonic-gate 					break;
7247c478bd9Sstevel@tonic-gate 			}
7257c478bd9Sstevel@tonic-gate 			if (j == t->numColumns)
7267c478bd9Sstevel@tonic-gate 				break;
7277c478bd9Sstevel@tonic-gate 		}
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 		splitname = (i < numItems)?1:0;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 		for (j = 0; j < nrq; j++) {
7327c478bd9Sstevel@tonic-gate 			if (splitname == 1) {
7337c478bd9Sstevel@tonic-gate 				/*
7347c478bd9Sstevel@tonic-gate 				 * Put every value of splitfieldname in a new
7357c478bd9Sstevel@tonic-gate 				 * rule-value. Helps generating splitfields.
7367c478bd9Sstevel@tonic-gate 				 */
7377c478bd9Sstevel@tonic-gate 				rvq = growRuleValue(count, count + 1, rvq, 0);
7387c478bd9Sstevel@tonic-gate 				if (rvq == 0) {
7397c478bd9Sstevel@tonic-gate 					freeRuleValue(rvq, count);
7407c478bd9Sstevel@tonic-gate 					freeValue(rval, 1);
7417c478bd9Sstevel@tonic-gate 					freeMappingItem(litem, numItems);
7427c478bd9Sstevel@tonic-gate 					return (MAP_INTERNAL_ERROR);
7437c478bd9Sstevel@tonic-gate 				}
7447c478bd9Sstevel@tonic-gate 				count++;
7457c478bd9Sstevel@tonic-gate 			}
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 			for (k = j % nrq, l = 0; l < numItems; k += nrq, l++) {
7487c478bd9Sstevel@tonic-gate 				/* If we run out of values, use empty strings */
7497c478bd9Sstevel@tonic-gate 				if (k >= rval->numVals) {
7507c478bd9Sstevel@tonic-gate 					value = emptystr;
7517c478bd9Sstevel@tonic-gate 					len = 0;
7527c478bd9Sstevel@tonic-gate 				} else {
7537c478bd9Sstevel@tonic-gate 					value = rval->val[k].value;
7547c478bd9Sstevel@tonic-gate 					len = rval->val[k].length;
7557c478bd9Sstevel@tonic-gate 				}
7567c478bd9Sstevel@tonic-gate 				res = (splitname == 1)?addCol2RuleValue(
7577c478bd9Sstevel@tonic-gate 					vt_string, litem[l].name, value,
7587c478bd9Sstevel@tonic-gate 					len, &rvq[count - 1]):0;
7597c478bd9Sstevel@tonic-gate 				if (res != -1)
7607c478bd9Sstevel@tonic-gate 					res = addCol2RuleValue(vt_string,
7617c478bd9Sstevel@tonic-gate 						litem[l].name, value, len, rv);
7627c478bd9Sstevel@tonic-gate 				if (res == -1) {
7637c478bd9Sstevel@tonic-gate 					freeRuleValue(rvq, count);
7647c478bd9Sstevel@tonic-gate 					freeValue(rval, 1);
7657c478bd9Sstevel@tonic-gate 					freeMappingItem(litem, numItems);
7667c478bd9Sstevel@tonic-gate 					return (MAP_INTERNAL_ERROR);
7677c478bd9Sstevel@tonic-gate 				}
7687c478bd9Sstevel@tonic-gate 			}
7697c478bd9Sstevel@tonic-gate 		}
7707c478bd9Sstevel@tonic-gate 		freeValue(rval, 1);
7717c478bd9Sstevel@tonic-gate 		rval = 0;
7727c478bd9Sstevel@tonic-gate 		freeMappingItem(litem, numItems);
7737c478bd9Sstevel@tonic-gate 		litem = 0;
7747c478bd9Sstevel@tonic-gate 		numItems = 0;
7757c478bd9Sstevel@tonic-gate 	} /* for r < t->numRulesFromLDAP */
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	statP = addSplitFieldValues(t, rvq, rv, count, domain);
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	if (rvq)
7807c478bd9Sstevel@tonic-gate 		freeRuleValue(rvq, count);
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 	if (verifyIndexMatch(t, 0, rv, 0, 0) == 0)
7837c478bd9Sstevel@tonic-gate 		return (MAP_INDEXLIST_ERROR);
7847c478bd9Sstevel@tonic-gate 	return (statP);
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate } /* end of buildNISRuleValue */
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate /*
7897c478bd9Sstevel@tonic-gate  * Convert rule-value to datum using namefield information
7907c478bd9Sstevel@tonic-gate  */
7917c478bd9Sstevel@tonic-gate datum *
ruleValueToDatum(__nis_table_mapping_t * t,__nis_rule_value_t * rv,int * statP)7927c478bd9Sstevel@tonic-gate ruleValueToDatum(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *statP) {
7937c478bd9Sstevel@tonic-gate 	__nis_value_t	*val;
7947c478bd9Sstevel@tonic-gate 	datum		*value;
7957c478bd9Sstevel@tonic-gate 	char		*str, *cstr, commentSep[3] = {' ', 0, 0};
7967c478bd9Sstevel@tonic-gate 	char		*myself = "ruleValueToDatum";
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 	/* No error yet */
7997c478bd9Sstevel@tonic-gate 	*statP = 0;
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	/* Return empty datum if no namefield information available */
8027c478bd9Sstevel@tonic-gate 	if (t->e == 0) {
8037c478bd9Sstevel@tonic-gate 		if ((value = am(myself, sizeof (*value))) == 0)
8047c478bd9Sstevel@tonic-gate 			*statP = MAP_NO_MEMORY;
8057c478bd9Sstevel@tonic-gate 		return (value);
8067c478bd9Sstevel@tonic-gate 	}
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 	val = getMappingFormatArray(t->e->element.match.fmt, rv,
8097c478bd9Sstevel@tonic-gate 				fa_item, t->e->element.match.numItems,
8107c478bd9Sstevel@tonic-gate 				t->e->element.match.item);
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	if (val && val->val && val->val->value) {
8137c478bd9Sstevel@tonic-gate 		if ((value = am(myself, sizeof (*value))) == 0) {
8147c478bd9Sstevel@tonic-gate 			*statP = MAP_NO_MEMORY;
8157c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
8167c478bd9Sstevel@tonic-gate 			return (0);
8177c478bd9Sstevel@tonic-gate 		}
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 		/* Strip trailing whitespaces */
8207c478bd9Sstevel@tonic-gate 		cstr = (char *)val->val->value + val->val->length;
8217c478bd9Sstevel@tonic-gate 		for (; cstr >= (char *)val->val->value &&
8227c478bd9Sstevel@tonic-gate 			(*cstr == ' ' || *cstr == '\t'); *cstr-- = '\0');
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 		if (t->commentChar != '\0' &&
8257c478bd9Sstevel@tonic-gate 		    (str = findVal(N2LCOMMENT, rv, mit_nisplus)) != 0 &&
8267c478bd9Sstevel@tonic-gate 		    *str != '\0') {
8277c478bd9Sstevel@tonic-gate 			commentSep[1] = t->commentChar;
8287c478bd9Sstevel@tonic-gate 			cstr = scat(myself, F, commentSep, str);
8297c478bd9Sstevel@tonic-gate 			if (cstr) {
8307c478bd9Sstevel@tonic-gate 				value->dptr = scat(myself, F,
8317c478bd9Sstevel@tonic-gate 						val->val->value, cstr);
8327c478bd9Sstevel@tonic-gate 				sfree(cstr);
8337c478bd9Sstevel@tonic-gate 			}
8347c478bd9Sstevel@tonic-gate 		} else {
8357c478bd9Sstevel@tonic-gate 			value->dptr = sdup(myself, T, val->val->value);
8367c478bd9Sstevel@tonic-gate 		}
8377c478bd9Sstevel@tonic-gate 		freeValue(val, 1);
8387c478bd9Sstevel@tonic-gate 		if (value->dptr) {
8397c478bd9Sstevel@tonic-gate 			value->dsize = strlen(value->dptr);
8407c478bd9Sstevel@tonic-gate 			return (value);
8417c478bd9Sstevel@tonic-gate 		} else {
8427c478bd9Sstevel@tonic-gate 			*statP = MAP_NO_MEMORY;
8437c478bd9Sstevel@tonic-gate 			sfree(value);
8447c478bd9Sstevel@tonic-gate 			return (0);
8457c478bd9Sstevel@tonic-gate 		}
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	*statP = MAP_NAMEFIELD_MATCH_ERROR;
8497c478bd9Sstevel@tonic-gate 	return (0);
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate datum *
getKeyFromRuleValue(__nis_table_mapping_t * t,__nis_rule_value_t * rv,int * nv,int * statP,bool_t xlate_to_lcase)8537c478bd9Sstevel@tonic-gate getKeyFromRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *nv,
854ea10ff14SBen Chang     int *statP, bool_t xlate_to_lcase)
855ea10ff14SBen Chang {
856ea10ff14SBen Chang 	int	i, j, k;
8577c478bd9Sstevel@tonic-gate 	datum	*key = 0;
8587c478bd9Sstevel@tonic-gate 	char	*str;
8597c478bd9Sstevel@tonic-gate 	char	*myself = "getKeyFromRuleValue";
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	/* No error yet */
8627c478bd9Sstevel@tonic-gate 	*statP = 0;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	if (rv == 0 || nv == 0)
8657c478bd9Sstevel@tonic-gate 		return (0);
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	for (i = 0; i < rv->numColumns; i++) {
8687c478bd9Sstevel@tonic-gate 		if (rv->colName[i] == 0)
8697c478bd9Sstevel@tonic-gate 			continue;
8707c478bd9Sstevel@tonic-gate 		if (strcasecmp(N2LKEY, rv->colName[i]) == 0 ||
871ea10ff14SBen Chang 		    strcasecmp(N2LIPKEY, rv->colName[i]) == 0) {
8727c478bd9Sstevel@tonic-gate 			if ((*nv = rv->colVal[i].numVals) == 0)
8737c478bd9Sstevel@tonic-gate 				return (0);
8747c478bd9Sstevel@tonic-gate 			if ((key = am(myself, sizeof (key[0]) * *nv)) == 0) {
8757c478bd9Sstevel@tonic-gate 				*statP = MAP_NO_MEMORY;
8767c478bd9Sstevel@tonic-gate 				return (0);
8777c478bd9Sstevel@tonic-gate 			}
8787c478bd9Sstevel@tonic-gate 			for (j = 0; j < *nv; j++) {
8797c478bd9Sstevel@tonic-gate 				if ((str = rv->colVal[i].val[j].value) == 0) {
8807c478bd9Sstevel@tonic-gate 					key[j].dsize = 0;
8817c478bd9Sstevel@tonic-gate 					key[j].dptr = 0;
8827c478bd9Sstevel@tonic-gate 				} else {
8837c478bd9Sstevel@tonic-gate 					if (verifyIndexMatch(t, 0, 0,
884ea10ff14SBen Chang 					    rv->colName[i], str) == 0) {
8857c478bd9Sstevel@tonic-gate 						key[j].dsize = 0;
8867c478bd9Sstevel@tonic-gate 						key[j].dptr = 0;
8877c478bd9Sstevel@tonic-gate 						continue;
8887c478bd9Sstevel@tonic-gate 					}
889ea10ff14SBen Chang 
8907c478bd9Sstevel@tonic-gate 					key[j].dsize = strlen(str);
8917c478bd9Sstevel@tonic-gate 					key[j].dptr = am(myself,
892ea10ff14SBen Chang 					    key[j].dsize + 1);
8937c478bd9Sstevel@tonic-gate 					if (key[j].dptr == 0) {
8947c478bd9Sstevel@tonic-gate 						*statP = MAP_NO_MEMORY;
8957c478bd9Sstevel@tonic-gate 						for (--j; j >= 0; j--)
8967c478bd9Sstevel@tonic-gate 							sfree(key[j].dptr);
8977c478bd9Sstevel@tonic-gate 						sfree(key);
8987c478bd9Sstevel@tonic-gate 						return (0);
8997c478bd9Sstevel@tonic-gate 					}
900ea10ff14SBen Chang 
901ea10ff14SBen Chang 					/* transliterate key to lowercase */
902ea10ff14SBen Chang 					if (xlate_to_lcase == TRUE) {
903ea10ff14SBen Chang 
904ea10ff14SBen Chang 						/*
905ea10ff14SBen Chang 						 * For multi-homed
906ea10ff14SBen Chang 						 * entries, skip over
907ea10ff14SBen Chang 						 * "YP_MULTI_" prefix.
908ea10ff14SBen Chang 						 */
909ea10ff14SBen Chang 						k = 0;
910ea10ff14SBen Chang 						if (strncmp(YPMULTI, str,
911ea10ff14SBen Chang 						    YPMULTISZ) == 0) {
912ea10ff14SBen Chang 							k = YPMULTISZ;
913ea10ff14SBen Chang 							bcopy(str, key[j].dptr,
914ea10ff14SBen Chang 							    YPMULTISZ);
915ea10ff14SBen Chang 						}
916ea10ff14SBen Chang 						while (k < key[j].dsize) {
917ea10ff14SBen Chang 							key[j].dptr[k] =
918ea10ff14SBen Chang 							    (char)tolower(
919ea10ff14SBen Chang 							    (int)(uchar_t)
920ea10ff14SBen Chang 							    str[k]);
921ea10ff14SBen Chang 							k++;
922ea10ff14SBen Chang 						}
923ea10ff14SBen Chang 					} else {
924ea10ff14SBen Chang 						bcopy(str, key[j].dptr,
925ea10ff14SBen Chang 						    key[j].dsize);
926ea10ff14SBen Chang 					}
9277c478bd9Sstevel@tonic-gate 				}
9287c478bd9Sstevel@tonic-gate 			}
9297c478bd9Sstevel@tonic-gate 			return (key);
9307c478bd9Sstevel@tonic-gate 		}
9317c478bd9Sstevel@tonic-gate 	}
9327c478bd9Sstevel@tonic-gate 	return (0);
9337c478bd9Sstevel@tonic-gate }
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate /*
9367c478bd9Sstevel@tonic-gate  * Get the mapping structure corresponding to `map,domain.'
9377c478bd9Sstevel@tonic-gate  */
9387c478bd9Sstevel@tonic-gate __nis_table_mapping_t *
mappingFromMap(char * map,char * domain,int * statP)9397c478bd9Sstevel@tonic-gate mappingFromMap(char *map, char *domain, int *statP) {
9407c478bd9Sstevel@tonic-gate 	char			*mapPath;
9417c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 	/* No error yet */
9447c478bd9Sstevel@tonic-gate 	*statP = 0;
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	/* Construct map,domain. */
9477c478bd9Sstevel@tonic-gate 	if ((mapPath = getFullMapName(map, domain)) == 0) {
9487c478bd9Sstevel@tonic-gate 		*statP = MAP_NO_MEMORY;
9497c478bd9Sstevel@tonic-gate 		return (0);
9507c478bd9Sstevel@tonic-gate 	}
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 	/* Get the hash table entry for the mapPath */
9537c478bd9Sstevel@tonic-gate 	if ((t = __nis_find_item_mt(mapPath, &ldapMappingList, 1, 0))
9547c478bd9Sstevel@tonic-gate 			== 0) {
9557c478bd9Sstevel@tonic-gate 		*statP = MAP_NO_MAPPING_EXISTS;
9567c478bd9Sstevel@tonic-gate 	}
9577c478bd9Sstevel@tonic-gate 	sfree(mapPath);
9587c478bd9Sstevel@tonic-gate 	return (t);
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate /*
9627c478bd9Sstevel@tonic-gate  * Verify at least one key value obtained from DIT matches the search key
9637c478bd9Sstevel@tonic-gate  * RETURNS:	 1	MATCH
9647c478bd9Sstevel@tonic-gate  *		 0	NO MATCH
9657c478bd9Sstevel@tonic-gate  *		-1	NO KEY FOUND
9667c478bd9Sstevel@tonic-gate  */
9677c478bd9Sstevel@tonic-gate static int
verifyKey(char * key,__nis_rule_value_t * rv)9687c478bd9Sstevel@tonic-gate verifyKey(char *key, __nis_rule_value_t *rv) {
9697c478bd9Sstevel@tonic-gate 	int	i, j;
9707c478bd9Sstevel@tonic-gate 	char	*sipkey, *str;
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 	for (i = 0; i < rv->numColumns; i++) {
9737c478bd9Sstevel@tonic-gate 		if (rv->colName[i] == 0)
9747c478bd9Sstevel@tonic-gate 			continue;
9757c478bd9Sstevel@tonic-gate 		if (strcasecmp(N2LKEY, rv->colName[i]) == 0) {
9767c478bd9Sstevel@tonic-gate 			if (rv->colVal[i].val == 0)
9777c478bd9Sstevel@tonic-gate 				return (0);
9787c478bd9Sstevel@tonic-gate 			for (j = 0; j < rv->colVal[i].numVals; j++) {
9797c478bd9Sstevel@tonic-gate 				str = (char *)rv->colVal[i].val[j].value;
9807c478bd9Sstevel@tonic-gate 				if (str && strcmp(str, key) == 0)
9817c478bd9Sstevel@tonic-gate 					return (1);
9827c478bd9Sstevel@tonic-gate 			}
9837c478bd9Sstevel@tonic-gate 			return (0);
9847c478bd9Sstevel@tonic-gate 		} else if (strcasecmp(N2LIPKEY, rv->colName[i]) == 0) {
9857c478bd9Sstevel@tonic-gate 			if (checkIPaddress(key, strlen(key), &sipkey) > 0) {
9867c478bd9Sstevel@tonic-gate 				if (rv->colVal[i].val == 0)
9877c478bd9Sstevel@tonic-gate 					return (0);
9887c478bd9Sstevel@tonic-gate 				for (j = 0; j < rv->colVal[i].numVals; j++) {
9897c478bd9Sstevel@tonic-gate 					str = rv->colVal[i].val[j].value;
9907c478bd9Sstevel@tonic-gate 					if (str && strcmp(str, sipkey) == 0) {
9917c478bd9Sstevel@tonic-gate 						sfree(sipkey);
9927c478bd9Sstevel@tonic-gate 						return (1);
9937c478bd9Sstevel@tonic-gate 					}
9947c478bd9Sstevel@tonic-gate 				}
9957c478bd9Sstevel@tonic-gate 				sfree(sipkey);
9967c478bd9Sstevel@tonic-gate 			}
9977c478bd9Sstevel@tonic-gate 			return (0);
9987c478bd9Sstevel@tonic-gate 		}
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 	return (-1);
10017c478bd9Sstevel@tonic-gate }
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate /*
10047c478bd9Sstevel@tonic-gate  * Read (i.e get and map) a single NIS entry from the LDAP DIT
10057c478bd9Sstevel@tonic-gate  */
10067c478bd9Sstevel@tonic-gate bool_t
singleReadFromDIT(char * map,char * domain,datum * key,datum * value,int * statP)10077c478bd9Sstevel@tonic-gate singleReadFromDIT(char *map, char *domain, datum *key, datum *value,
10087c478bd9Sstevel@tonic-gate 							int *statP) {
10097c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
10107c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv_request = 0, *rv_result = 0;
10117c478bd9Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
10127c478bd9Sstevel@tonic-gate 	__nis_object_dn_t	*objectDN = NULL;
1013*a87701e9SGary Mills 	int			i, rc, nr = 0;
10147c478bd9Sstevel@tonic-gate 	datum			*datval = 0;
1015*a87701e9SGary Mills 	char			*skey, *str;
10167c478bd9Sstevel@tonic-gate 	char			*myself = "singleReadFromDIT";
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate 	*statP = SUCCESS;
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	if (!map || !domain || !key || !value) {
10217c478bd9Sstevel@tonic-gate 		*statP = MAP_PARAM_ERROR;
10227c478bd9Sstevel@tonic-gate 		return (FALSE);
10237c478bd9Sstevel@tonic-gate 	}
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 	/* Get the mapping information for the map */
10277c478bd9Sstevel@tonic-gate 	if ((t = mappingFromMap(map, domain, statP)) == 0) {
10287c478bd9Sstevel@tonic-gate 		/*
10297c478bd9Sstevel@tonic-gate 		 * No problem. We don't handle this map and domain. Maybe it's
10307c478bd9Sstevel@tonic-gate 		 * handled by a service other than NIS.
10317c478bd9Sstevel@tonic-gate 		 */
10327c478bd9Sstevel@tonic-gate 		return (FALSE);
10337c478bd9Sstevel@tonic-gate 	}
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	/* NULL-terminated version of datum key for logging */
10367c478bd9Sstevel@tonic-gate 	if ((skey = am(myself, key->dsize + 1)) == 0) {
10377c478bd9Sstevel@tonic-gate 		*statP = MAP_NO_MEMORY;
10387c478bd9Sstevel@tonic-gate 		return (FALSE);
10397c478bd9Sstevel@tonic-gate 	}
10407c478bd9Sstevel@tonic-gate 	(void) memcpy(skey, key->dptr, key->dsize);
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	if ((str = getFullMapName(map, domain)) == 0) {
10437c478bd9Sstevel@tonic-gate 		*statP = MAP_NO_MEMORY;
10447c478bd9Sstevel@tonic-gate 		return (FALSE);
10457c478bd9Sstevel@tonic-gate 	}
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	/* For each alternate mapping */
10487c478bd9Sstevel@tonic-gate 	for (; t != 0; t = t->next) {
10497c478bd9Sstevel@tonic-gate 		/* Verify objName */
10507c478bd9Sstevel@tonic-gate 		if (strcmp(str, t->objName) != 0) {
10517c478bd9Sstevel@tonic-gate 			continue;
10527c478bd9Sstevel@tonic-gate 		}
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 		/* Verify if key matches the index */
10557c478bd9Sstevel@tonic-gate 		if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 ||
10567c478bd9Sstevel@tonic-gate 			verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0)
10577c478bd9Sstevel@tonic-gate 			continue;
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 		/* Check if rulesFromLDAP are provided */
10607c478bd9Sstevel@tonic-gate 		if (t->numRulesFromLDAP == 0) {
10617c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_INFO,
10627c478bd9Sstevel@tonic-gate 				"%s: No rulesFromLDAP information available "
10637c478bd9Sstevel@tonic-gate 				"for %s (%s)", myself, t->dbId, map);
10647c478bd9Sstevel@tonic-gate 			continue;
10657c478bd9Sstevel@tonic-gate 		}
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 		/* Convert key into rule-value */
10687c478bd9Sstevel@tonic-gate 		if ((rv_request = datumToRuleValue(key, 0, t, 0, domain, TRUE,
10697c478bd9Sstevel@tonic-gate 								statP)) == 0) {
10707c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
10717c478bd9Sstevel@tonic-gate 				"%s: Conversion error %d (NIS to name=value "
10727c478bd9Sstevel@tonic-gate 				"pairs) for NIS key (%s) for %s (%s)",
10737c478bd9Sstevel@tonic-gate 				myself, *statP, skey, t->dbId, map);
10747c478bd9Sstevel@tonic-gate 			continue;
10757c478bd9Sstevel@tonic-gate 		}
10767c478bd9Sstevel@tonic-gate 		/* Convert rule-value into ldap request */
10777c478bd9Sstevel@tonic-gate 		for (objectDN = t->objectDN; objectDN &&
10787c478bd9Sstevel@tonic-gate 				objectDN->read.base;
10797c478bd9Sstevel@tonic-gate 				objectDN = objectDN->next) {
10807c478bd9Sstevel@tonic-gate 			ls = createLdapRequest(t, rv_request, 0, 1, NULL,
10817c478bd9Sstevel@tonic-gate 								objectDN);
10827c478bd9Sstevel@tonic-gate 			if (ls == 0) {
10837c478bd9Sstevel@tonic-gate 				*statP = MAP_CREATE_LDAP_REQUEST_ERROR;
10847c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
10857c478bd9Sstevel@tonic-gate 					"%s: Failed to create ldapSearch "
10867c478bd9Sstevel@tonic-gate 					"request for "
10877c478bd9Sstevel@tonic-gate 					"NIS key (%s) for %s (%s) "
10887c478bd9Sstevel@tonic-gate 					"for base %s",
10897c478bd9Sstevel@tonic-gate 					myself, skey, t->dbId, map,
10907c478bd9Sstevel@tonic-gate 					objectDN->read.base);
10917c478bd9Sstevel@tonic-gate 				continue;
10927c478bd9Sstevel@tonic-gate 			}
10937c478bd9Sstevel@tonic-gate 			ls->timeout.tv_sec = SINGLE_ACCESS_TIMEOUT_SEC;
10947c478bd9Sstevel@tonic-gate 			ls->timeout.tv_usec = SINGLE_ACCESS_TIMEOUT_USEC;
10957c478bd9Sstevel@tonic-gate 			/* Query LDAP */
10967c478bd9Sstevel@tonic-gate 			nr = (ls->isDN)?0:-1;
10977c478bd9Sstevel@tonic-gate 			rv_result = ldapSearch(ls, &nr, 0, statP);
10987c478bd9Sstevel@tonic-gate 			freeLdapSearch(ls);
10997c478bd9Sstevel@tonic-gate 			if (rv_result == 0) {
11007c478bd9Sstevel@tonic-gate 				if (*statP == LDAP_NO_SUCH_OBJECT) {
11017c478bd9Sstevel@tonic-gate 					/* Entry does not exist in */
11027c478bd9Sstevel@tonic-gate 					/* the ldap server */
11037c478bd9Sstevel@tonic-gate 				}
11047c478bd9Sstevel@tonic-gate 				continue;
11057c478bd9Sstevel@tonic-gate 			}
11067c478bd9Sstevel@tonic-gate 			freeRuleValue(rv_request, 1);
11077c478bd9Sstevel@tonic-gate 			rv_request = 0;
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 			/* if result > 1, first match will be returned */
11107c478bd9Sstevel@tonic-gate 			if (nr > 1) {
11117c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_INFO,
11127c478bd9Sstevel@tonic-gate 					"%s: %d ldapSearch results "
11137c478bd9Sstevel@tonic-gate 					"for NIS key (%s) "
11147c478bd9Sstevel@tonic-gate 					"for %s (%s) for base %s. "
11157c478bd9Sstevel@tonic-gate 					"First match will be returned ",
11167c478bd9Sstevel@tonic-gate 					myself, nr, skey, t->dbId, map,
11177c478bd9Sstevel@tonic-gate 					objectDN->read.base);
11187c478bd9Sstevel@tonic-gate 			}
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 			for (i = 0; i < nr; i++) {
11217c478bd9Sstevel@tonic-gate 				/* Convert LDAP data to NIS equivalents */
11227c478bd9Sstevel@tonic-gate 				*statP = buildNISRuleValue(t, &rv_result[i],
11237c478bd9Sstevel@tonic-gate 								domain);
11247c478bd9Sstevel@tonic-gate 				if (*statP == MAP_INDEXLIST_ERROR)
11257c478bd9Sstevel@tonic-gate 					continue;
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 				if (*statP != SUCCESS) {
11287c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
11297c478bd9Sstevel@tonic-gate 					"%s: Conversion error %d (LDAP to "
11307c478bd9Sstevel@tonic-gate 					"name=value pairs) for NIS key (%s) "
11317c478bd9Sstevel@tonic-gate 					"for %s (%s) for base %s", myself,
11327c478bd9Sstevel@tonic-gate 					*statP, skey,
11337c478bd9Sstevel@tonic-gate 					t->dbId, map, objectDN->read.base);
11347c478bd9Sstevel@tonic-gate 					continue;
11357c478bd9Sstevel@tonic-gate 				}
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 			/*
11387c478bd9Sstevel@tonic-gate 			 * Check if 'key' from the ldap result matches the key
11397c478bd9Sstevel@tonic-gate 			 * provided by our caller
11407c478bd9Sstevel@tonic-gate 			 */
11417c478bd9Sstevel@tonic-gate 				if ((rc = verifyKey(skey, &rv_result[i]))
11427c478bd9Sstevel@tonic-gate 						== -1) {
11437c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_INFO,
11447c478bd9Sstevel@tonic-gate 					"%s: Cannot verify key from ldap "
11457c478bd9Sstevel@tonic-gate 					"result for NIS key (%s) for %s (%s) "
11467c478bd9Sstevel@tonic-gate 					"for base %s",
11477c478bd9Sstevel@tonic-gate 					myself, skey, t->dbId, map,
11487c478bd9Sstevel@tonic-gate 					objectDN->read.base);
11497c478bd9Sstevel@tonic-gate 					continue;
11507c478bd9Sstevel@tonic-gate 				}
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 				if (rc == 1) {
11537c478bd9Sstevel@tonic-gate 					datval = ruleValueToDatum(t,
11547c478bd9Sstevel@tonic-gate 							&rv_result[i], statP);
11557c478bd9Sstevel@tonic-gate 					if (datval == 0) {
11567c478bd9Sstevel@tonic-gate 						logmsg(MSG_NOTIMECHECK,
11577c478bd9Sstevel@tonic-gate 						LOG_WARNING,
11587c478bd9Sstevel@tonic-gate 						"%s: Conversion error %d "
11597c478bd9Sstevel@tonic-gate 						"(name=value pairs to NIS) "
11607c478bd9Sstevel@tonic-gate 						"for NIS key (%s) for %s (%s)"
11617c478bd9Sstevel@tonic-gate 						" for base %s",
11627c478bd9Sstevel@tonic-gate 						myself,
11637c478bd9Sstevel@tonic-gate 						*statP, skey, t->dbId, map,
11647c478bd9Sstevel@tonic-gate 						objectDN->read.base);
11657c478bd9Sstevel@tonic-gate 						continue;
11667c478bd9Sstevel@tonic-gate 					}
11677c478bd9Sstevel@tonic-gate 					if (value) {
11687c478bd9Sstevel@tonic-gate 						value->dptr = datval->dptr;
11697c478bd9Sstevel@tonic-gate 						value->dsize = datval->dsize;
11707c478bd9Sstevel@tonic-gate 					}
11717c478bd9Sstevel@tonic-gate 					sfree(datval);
11727c478bd9Sstevel@tonic-gate 					sfree(skey);
11737c478bd9Sstevel@tonic-gate 					freeRuleValue(rv_result, nr);
11747c478bd9Sstevel@tonic-gate 					rv_result = 0;
11757c478bd9Sstevel@tonic-gate 					*statP = SUCCESS;
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate 					/* Free full map name */
11787c478bd9Sstevel@tonic-gate 					sfree(str);
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 					return (TRUE);
11817c478bd9Sstevel@tonic-gate 				}
11827c478bd9Sstevel@tonic-gate 			}
11837c478bd9Sstevel@tonic-gate 			freeRuleValue(rv_result, nr);
11847c478bd9Sstevel@tonic-gate 			rv_result = 0;
11857c478bd9Sstevel@tonic-gate 		}   /* end of for over objectDN */
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 		if (rv_request != 0) {
11887c478bd9Sstevel@tonic-gate 			freeRuleValue(rv_request, 1);
11897c478bd9Sstevel@tonic-gate 			rv_request = 0;
11907c478bd9Sstevel@tonic-gate 		}
11917c478bd9Sstevel@tonic-gate 		if (rv_result != 0) {
11927c478bd9Sstevel@tonic-gate 			freeRuleValue(rv_result, nr);
11937c478bd9Sstevel@tonic-gate 			rv_result = 0;
11947c478bd9Sstevel@tonic-gate 		}
11957c478bd9Sstevel@tonic-gate 	}
11967c478bd9Sstevel@tonic-gate 	sfree(skey);
11977c478bd9Sstevel@tonic-gate 	*statP = MAP_NO_MATCHING_KEY;
11987c478bd9Sstevel@tonic-gate 
11997c478bd9Sstevel@tonic-gate 	/* Free full map name */
12007c478bd9Sstevel@tonic-gate 	sfree(str);
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 	return (FALSE);
12037c478bd9Sstevel@tonic-gate }
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate /*
12077c478bd9Sstevel@tonic-gate  * Maps and writes a single NIS entry to the LDAP DIT
12087c478bd9Sstevel@tonic-gate  */
12097c478bd9Sstevel@tonic-gate int
singleWriteToDIT(char * map,char * domain,datum * key,datum * value,bool_t replace)12107c478bd9Sstevel@tonic-gate singleWriteToDIT(char *map, char *domain, datum *key, datum *value,
12117c478bd9Sstevel@tonic-gate 						bool_t replace) {
12127c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
12137c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv, *frv;
12147c478bd9Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
12157c478bd9Sstevel@tonic-gate 	int			statP = SUCCESS, flag;
12167c478bd9Sstevel@tonic-gate 	int			nv, nr, i, rc, collapse;
12177c478bd9Sstevel@tonic-gate 	char			*dn = 0, *skey, *svalue, *str;
12187c478bd9Sstevel@tonic-gate 	char			*myself = "singleWriteToDIT";
12197c478bd9Sstevel@tonic-gate 
12207c478bd9Sstevel@tonic-gate 	if (!map || !domain || !key || !value) {
12217c478bd9Sstevel@tonic-gate 		return (MAP_PARAM_ERROR);
12227c478bd9Sstevel@tonic-gate 	}
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 	/* Return SUCCESS for empty or whitespace key */
12257c478bd9Sstevel@tonic-gate 	for (i = 0; i < key->dsize && (key->dptr[i] == 0 ||
12267c478bd9Sstevel@tonic-gate 		key->dptr[i] == ' ' || key->dptr[i] == '\t'); i++);
12277c478bd9Sstevel@tonic-gate 	if (i >= key->dsize)
12287c478bd9Sstevel@tonic-gate 		return (SUCCESS);
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 	/* Get the mapping information for the map */
12317c478bd9Sstevel@tonic-gate 	if ((t = mappingFromMap(map, domain, &statP)) == 0) {
12327c478bd9Sstevel@tonic-gate 		/*
12337c478bd9Sstevel@tonic-gate 		 * No problem. We don't handle this map and domain. Maybe it's
12347c478bd9Sstevel@tonic-gate 		 * handled by a service other than NIS.
12357c478bd9Sstevel@tonic-gate 		 */
12367c478bd9Sstevel@tonic-gate 		return (statP);
12377c478bd9Sstevel@tonic-gate 	}
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 	/* NULL-terminated version of key and value for logging */
12407c478bd9Sstevel@tonic-gate 	if ((skey = am(myself, key->dsize + 1)) == 0)
12417c478bd9Sstevel@tonic-gate 		return (MAP_NO_MEMORY);
12427c478bd9Sstevel@tonic-gate 	(void) memcpy(skey, key->dptr, key->dsize);
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 	if ((svalue = am(myself, value->dsize + 1)) == 0) {
12457c478bd9Sstevel@tonic-gate 		sfree(skey);
12467c478bd9Sstevel@tonic-gate 		return (MAP_NO_MEMORY);
12477c478bd9Sstevel@tonic-gate 	}
12487c478bd9Sstevel@tonic-gate 	(void) memcpy(svalue, value->dptr, value->dsize);
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 	if ((str = getFullMapName(map, domain)) == 0) {
12517c478bd9Sstevel@tonic-gate 		sfree(skey);
12527c478bd9Sstevel@tonic-gate 		sfree(svalue);
12537c478bd9Sstevel@tonic-gate 		return (MAP_NO_MEMORY);
12547c478bd9Sstevel@tonic-gate 	}
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 	/* For each alternate mapping */
12577c478bd9Sstevel@tonic-gate 	for (flag = 0; t != 0; t = t->next) {
12587c478bd9Sstevel@tonic-gate 		/* Verify objName */
12597c478bd9Sstevel@tonic-gate 		if (strcmp(str, t->objName) != 0) {
12607c478bd9Sstevel@tonic-gate 			continue;
12617c478bd9Sstevel@tonic-gate 		}
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 		/* Verify if key matches the index */
12647c478bd9Sstevel@tonic-gate 		if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 ||
12657c478bd9Sstevel@tonic-gate 			verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0)
12667c478bd9Sstevel@tonic-gate 			continue;
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 		/* Check the writespecs */
12697c478bd9Sstevel@tonic-gate 		if (t->objectDN->write.base == 0) {
12707c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_INFO,
12717c478bd9Sstevel@tonic-gate 				"%s: No baseDN in writespec. Write disabled "
12727c478bd9Sstevel@tonic-gate 				"for %s (%s)", myself, t->dbId, map);
12737c478bd9Sstevel@tonic-gate 			continue;
12747c478bd9Sstevel@tonic-gate 		}
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 		/* Check if rulesToLDAP are provided */
12777c478bd9Sstevel@tonic-gate 		if (t->numRulesToLDAP == 0) {
12787c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_INFO,
12797c478bd9Sstevel@tonic-gate 				"%s: No rulesToLDAP. Write disabled for "
12807c478bd9Sstevel@tonic-gate 				"%s (%s)", myself, t->dbId, map);
12817c478bd9Sstevel@tonic-gate 			continue;
12827c478bd9Sstevel@tonic-gate 		}
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 		/* Set flag to indicate write is enabled */
12857c478bd9Sstevel@tonic-gate 		flag = 1;
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 		/* Convert key  and value into an array of rule-values */
12887c478bd9Sstevel@tonic-gate 		if ((rv = datumToRuleValue(key, value, t, &nv, domain, FALSE,
12897c478bd9Sstevel@tonic-gate 								&statP)) == 0) {
12907c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
12917c478bd9Sstevel@tonic-gate 				"%s: Conversion error %d (NIS to name=value "
12927c478bd9Sstevel@tonic-gate 				"pairs) for NIS data (key=%s, value=%s) "
12937c478bd9Sstevel@tonic-gate 				"for %s (%s)",
12947c478bd9Sstevel@tonic-gate 				myself, statP, skey, svalue, t->dbId, map);
12957c478bd9Sstevel@tonic-gate 			sfree(skey);
12967c478bd9Sstevel@tonic-gate 			sfree(svalue);
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 			/* Free full map name */
12997c478bd9Sstevel@tonic-gate 			sfree(str);
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 			return (statP);
13027c478bd9Sstevel@tonic-gate 		}
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 		/* Convert NIS data to LDAP equivalents for each rule-value */
13057c478bd9Sstevel@tonic-gate 		for (i = 0; i < nv; i++) {
13067c478bd9Sstevel@tonic-gate 			/* Verify indexlist with name=value pairs */
13077c478bd9Sstevel@tonic-gate 			if (verifyIndexMatch(t, 0, &rv[i], 0, 0) == 0)
13087c478bd9Sstevel@tonic-gate 				break;
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 			/* Create LDAP request and LDAP name=value pairs */
13117c478bd9Sstevel@tonic-gate 			if ((ls = createLdapRequest(t, &rv[i],
13127c478bd9Sstevel@tonic-gate 			    0, 0, NULL, NULL)) == 0) {
13137c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
13147c478bd9Sstevel@tonic-gate 					"%s: Conversion error (name=value pairs"
13157c478bd9Sstevel@tonic-gate 					" to LDAP) for NIS data "
13167c478bd9Sstevel@tonic-gate 					"(key=%s, value=%s) for %s (%s)",
13177c478bd9Sstevel@tonic-gate 					myself, skey, svalue, t->dbId, map);
13187c478bd9Sstevel@tonic-gate 				freeRuleValue(rv, nv);
13197c478bd9Sstevel@tonic-gate 				sfree(skey);
13207c478bd9Sstevel@tonic-gate 				sfree(svalue);
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 				/* Free full map name */
13237c478bd9Sstevel@tonic-gate 				sfree(str);
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 				return (MAP_CREATE_LDAP_REQUEST_ERROR);
13267c478bd9Sstevel@tonic-gate 			}
13277c478bd9Sstevel@tonic-gate 			freeLdapSearch(ls);
13287c478bd9Sstevel@tonic-gate 			/* printRuleValue(&rv[i]); */
13297c478bd9Sstevel@tonic-gate 		}
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate 		/* If i < nv then this alternate mapping isn't the one */
13327c478bd9Sstevel@tonic-gate 		if (i < nv)
13337c478bd9Sstevel@tonic-gate 			continue;
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 		/*
13367c478bd9Sstevel@tonic-gate 		 * Merge rule-values with the same DN so that we have
13377c478bd9Sstevel@tonic-gate 		 * one ldap write request for each DN
13387c478bd9Sstevel@tonic-gate 		 */
13397c478bd9Sstevel@tonic-gate 		nr = nv;
13407c478bd9Sstevel@tonic-gate 		frv = mergeRuleValueWithSameDN(rv, &nr);
13417c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, nv);
13427c478bd9Sstevel@tonic-gate 		if (frv == 0) {
13437c478bd9Sstevel@tonic-gate 			if (nr == -1) {
13447c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
13457c478bd9Sstevel@tonic-gate 					"%s: Unable to merge LDAP write "
13467c478bd9Sstevel@tonic-gate 					"requests to same DN for NIS data "
13477c478bd9Sstevel@tonic-gate 					"(key=%s, value=%s) for %s (%s)",
13487c478bd9Sstevel@tonic-gate 					myself, skey, svalue, t->dbId, map);
13497c478bd9Sstevel@tonic-gate 				statP = MAP_INTERNAL_ERROR;
13507c478bd9Sstevel@tonic-gate 			} else if (nr == 0) {
13517c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
13527c478bd9Sstevel@tonic-gate 					"%s: Cannot generate write DN due to "
13537c478bd9Sstevel@tonic-gate 					"missing information for NIS data "
13547c478bd9Sstevel@tonic-gate 					"(key=%s, value=%s) for %s (%s)",
13557c478bd9Sstevel@tonic-gate 					myself, skey, svalue, t->dbId, map);
13567c478bd9Sstevel@tonic-gate 				statP = MAP_NO_DN;
13577c478bd9Sstevel@tonic-gate 			}
13587c478bd9Sstevel@tonic-gate 			sfree(skey);
13597c478bd9Sstevel@tonic-gate 			sfree(svalue);
13607c478bd9Sstevel@tonic-gate 
13617c478bd9Sstevel@tonic-gate 			/* Free full map name */
13627c478bd9Sstevel@tonic-gate 			sfree(str);
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 			return (statP);
13657c478bd9Sstevel@tonic-gate 		}
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 		/* Write to the LDAP server */
13687c478bd9Sstevel@tonic-gate 		for (collapse = 0, i = 0; i < nr; i++) {
13697c478bd9Sstevel@tonic-gate 			if ((dn = findVal("dn", &frv[i], mit_ldap)) != 0) {
13707c478bd9Sstevel@tonic-gate 				if (replace == FALSE) {
13717c478bd9Sstevel@tonic-gate 					/* ldap add */
13727c478bd9Sstevel@tonic-gate 					rc = ldapAdd(dn, &frv[i],
13737c478bd9Sstevel@tonic-gate 						t->objectDN->write.attrs, 0);
13747c478bd9Sstevel@tonic-gate 				} else {
13757c478bd9Sstevel@tonic-gate 					/* ldap modify with addFirst set */
13767c478bd9Sstevel@tonic-gate 					rc = ldapModify(dn, &frv[i],
13777c478bd9Sstevel@tonic-gate 						t->objectDN->write.attrs, 1);
13787c478bd9Sstevel@tonic-gate 				}
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate 				/* if we get err=20, collapse and try again */
13817c478bd9Sstevel@tonic-gate 				if (!collapse &&
13827c478bd9Sstevel@tonic-gate 					(rc == LDAP_TYPE_OR_VALUE_EXISTS) &&
13837c478bd9Sstevel@tonic-gate 					(collapseRuleValue(&frv[i]) == 1)) {
13847c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
13857c478bd9Sstevel@tonic-gate 						"%s: Ignoring values differing "
13867c478bd9Sstevel@tonic-gate 						"in case from NIS data (key=%s,"
13877c478bd9Sstevel@tonic-gate 						" value=%s) for (dn: %s) for "
13887c478bd9Sstevel@tonic-gate 						"%s (%s)", myself, skey,
13897c478bd9Sstevel@tonic-gate 						svalue, dn, t->dbId, map);
13907c478bd9Sstevel@tonic-gate 					collapse = 1;
13917c478bd9Sstevel@tonic-gate 					i--;
13927c478bd9Sstevel@tonic-gate 					continue;
13937c478bd9Sstevel@tonic-gate 				}
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate 				collapse = 0;
13967c478bd9Sstevel@tonic-gate 				if (rc != LDAP_SUCCESS) {
13977c478bd9Sstevel@tonic-gate 					/* Log error */
13987c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_ERR,
13997c478bd9Sstevel@tonic-gate 						"%s: %s error %d (%s) for "
14007c478bd9Sstevel@tonic-gate 						"(dn: %s) for NIS data "
14017c478bd9Sstevel@tonic-gate 						"(key=%s, value=%s) "
14027c478bd9Sstevel@tonic-gate 						"for %s (%s)",
14037c478bd9Sstevel@tonic-gate 						myself, (replace == TRUE) ?
14047c478bd9Sstevel@tonic-gate 						"ldapModify" : "ldapAdd", rc,
14057c478bd9Sstevel@tonic-gate 						ldap_err2string(rc), dn, skey,
14067c478bd9Sstevel@tonic-gate 						svalue, t->dbId, map);
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 					/* Dumping failed call may be useful */
14097c478bd9Sstevel@tonic-gate 					/* printRuleValue(&frv[i]); */
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 					/*
14127c478bd9Sstevel@tonic-gate 					 * Return the error code and let wrapper
14137c478bd9Sstevel@tonic-gate 					 * sort out if mapping should continue
14147c478bd9Sstevel@tonic-gate 					 * or abort.
14157c478bd9Sstevel@tonic-gate 					 */
14167c478bd9Sstevel@tonic-gate 					statP = rc;
14177c478bd9Sstevel@tonic-gate 					sfree(skey);
14187c478bd9Sstevel@tonic-gate 					sfree(svalue);
14197c478bd9Sstevel@tonic-gate 					freeRuleValue(frv, nr);
14207c478bd9Sstevel@tonic-gate 
14217c478bd9Sstevel@tonic-gate 					/* Free full map name */
14227c478bd9Sstevel@tonic-gate 					sfree(str);
14237c478bd9Sstevel@tonic-gate 
14247c478bd9Sstevel@tonic-gate 					return (statP);
14257c478bd9Sstevel@tonic-gate 				}
14267c478bd9Sstevel@tonic-gate 			}
14277c478bd9Sstevel@tonic-gate 		}
14287c478bd9Sstevel@tonic-gate 
14297c478bd9Sstevel@tonic-gate 		freeRuleValue(frv, nr);
14307c478bd9Sstevel@tonic-gate 	}
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 	sfree(skey);
14337c478bd9Sstevel@tonic-gate 	sfree(svalue);
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 	/* Free full map name */
14367c478bd9Sstevel@tonic-gate 	sfree(str);
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate 	return ((flag)?SUCCESS:MAP_WRITE_DISABLED);
14397c478bd9Sstevel@tonic-gate }
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate suc_code
collapseRuleValue(__nis_rule_value_t * rv)14427c478bd9Sstevel@tonic-gate collapseRuleValue(__nis_rule_value_t *rv) {
14437c478bd9Sstevel@tonic-gate 	int		i, j, k, flag;
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate 	/* Using 'val' to appease cstyle's 80 chars/line limit */
14467c478bd9Sstevel@tonic-gate 	__nis_value_t	*val;
14477c478bd9Sstevel@tonic-gate 
14487c478bd9Sstevel@tonic-gate 	for (i = 0, flag = 0; i < rv->numAttrs; i++) {
14497c478bd9Sstevel@tonic-gate 		val = &rv->attrVal[i];
14507c478bd9Sstevel@tonic-gate 		for (j = 1; j < val->numVals; j++) {
14517c478bd9Sstevel@tonic-gate 			for (k = 0; k < j; k++) {
14527c478bd9Sstevel@tonic-gate 				if (val->val[j].length != val->val[k].length)
14537c478bd9Sstevel@tonic-gate 					continue;
14547c478bd9Sstevel@tonic-gate 				if (val->val[k].length == 0)
14557c478bd9Sstevel@tonic-gate 					continue;
14567c478bd9Sstevel@tonic-gate 				if (strncasecmp(val->val[j].value,
14577c478bd9Sstevel@tonic-gate 						val->val[k].value,
14587c478bd9Sstevel@tonic-gate 						val->val[j].length) != 0)
14597c478bd9Sstevel@tonic-gate 					continue;
14607c478bd9Sstevel@tonic-gate 				flag = 1;
14617c478bd9Sstevel@tonic-gate 				sfree(val->val[j].value);
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate #ifdef	ORDER_NOT_IMPORTANT
14647c478bd9Sstevel@tonic-gate 				val->val[j--] = val->val[--val->numVals];
14657c478bd9Sstevel@tonic-gate #else
14667c478bd9Sstevel@tonic-gate 				/* Order needs to be maintained */
14677c478bd9Sstevel@tonic-gate 				for (k = j + 1; k < val->numVals; k++)
14687c478bd9Sstevel@tonic-gate 					val->val[k - 1] = val->val[k];
14697c478bd9Sstevel@tonic-gate 				j--;
14707c478bd9Sstevel@tonic-gate 				val->numVals--;
14717c478bd9Sstevel@tonic-gate #endif
14727c478bd9Sstevel@tonic-gate 				break;
14737c478bd9Sstevel@tonic-gate 			}
14747c478bd9Sstevel@tonic-gate 		}
14757c478bd9Sstevel@tonic-gate 	}
14767c478bd9Sstevel@tonic-gate 	return (flag);
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate /* ObjectClass lookup table */
14807c478bd9Sstevel@tonic-gate static struct {
14817c478bd9Sstevel@tonic-gate 	const char *attrType;
14827c478bd9Sstevel@tonic-gate 	const char *objectClass;
14837c478bd9Sstevel@tonic-gate } oc_lookup[] = {
14847c478bd9Sstevel@tonic-gate 	{ "o",				"objectclass=organization"},
14857c478bd9Sstevel@tonic-gate 	{ "organizationname",		"objectclass=organization"},
14867c478bd9Sstevel@tonic-gate 	{ "2.5.4.10",			"objectclass=organization"},
14877c478bd9Sstevel@tonic-gate 	{ "ou",				"objectclass=organizationalunit"},
14887c478bd9Sstevel@tonic-gate 	{ "organizationalunitname",	"objectclass=organizationalunit"},
14897c478bd9Sstevel@tonic-gate 	{ "2.5.4.11",			"objectclass=organizationalunit"},
14907c478bd9Sstevel@tonic-gate 	{ "c",				"objectclass=country"},
14917c478bd9Sstevel@tonic-gate 	{ "countryname",		"objectclass=country"},
14927c478bd9Sstevel@tonic-gate 	{ "2.5.4.6",			"objectclass=country"},
14937c478bd9Sstevel@tonic-gate 	{ "dc",				"objectclass=domain"},
14947c478bd9Sstevel@tonic-gate 	{ "domaincomponent",		"objectclass=domain"},
14957c478bd9Sstevel@tonic-gate 	{ "0.9.2342.19200300.100.1.25",	"objectclass=domain"},
14967c478bd9Sstevel@tonic-gate 	{ "nismapname",			"objectclass=nismap"},
14977c478bd9Sstevel@tonic-gate 	{ "1.3.6.1.1.1.1.26",		"objectclass=nismap"},
14987c478bd9Sstevel@tonic-gate 	{ "automountmapname",		"objectclass=automountmap"},
14997c478bd9Sstevel@tonic-gate 	{ "1.3.6.1.1.1.1.31",		"objectclass=automountmap"},
15007c478bd9Sstevel@tonic-gate 	{ 0,				0}
15017c478bd9Sstevel@tonic-gate };
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate /*
15047c478bd9Sstevel@tonic-gate  * Returns the name of the objectclass to which the object
15057c478bd9Sstevel@tonic-gate  * represented by the given 'rdn' will most likely belong to.
15067c478bd9Sstevel@tonic-gate  * The return value is in static memory so it should not be
15077c478bd9Sstevel@tonic-gate  * freed
15087c478bd9Sstevel@tonic-gate  */
15097c478bd9Sstevel@tonic-gate const char *
getObjectClass(char * rdn)15107c478bd9Sstevel@tonic-gate getObjectClass(char *rdn) {
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 	char *attrtype, *p;
15137c478bd9Sstevel@tonic-gate 	int len, i;
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 	/* Skip leading whitespaces */
15167c478bd9Sstevel@tonic-gate 	for (p = rdn; *p == ' ' || *p == '\t'; p++);
15177c478bd9Sstevel@tonic-gate 	if (*p == '\0')
15187c478bd9Sstevel@tonic-gate 		return (0);
15197c478bd9Sstevel@tonic-gate 	attrtype = p;
15207c478bd9Sstevel@tonic-gate 
15217c478bd9Sstevel@tonic-gate 	/* Find '=' */
15227c478bd9Sstevel@tonic-gate 	if ((p = strchr(attrtype, '=')) == 0 || p == attrtype ||
15237c478bd9Sstevel@tonic-gate 						*(p - 1) == '\\')
15247c478bd9Sstevel@tonic-gate 		return (0);
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate 	/*
15277c478bd9Sstevel@tonic-gate 	 * Skip trailing whitespaces in attrtype
15287c478bd9Sstevel@tonic-gate 	 * Don't worry, p won't decrease beyond attrtype
15297c478bd9Sstevel@tonic-gate 	 */
15307c478bd9Sstevel@tonic-gate 	for (--p; *p == ' ' || *p == '\t'; p--);
15317c478bd9Sstevel@tonic-gate 	len = p - attrtype + 1;
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 	for (i = 0; oc_lookup[i].attrType; i++)
15347c478bd9Sstevel@tonic-gate 		if (!strncasecmp(oc_lookup[i].attrType, attrtype, len))
15357c478bd9Sstevel@tonic-gate 			/* Check length is right */
15367c478bd9Sstevel@tonic-gate 			if (len == strlen(oc_lookup[i].attrType))
15377c478bd9Sstevel@tonic-gate 				return (oc_lookup[i].objectClass);
15387c478bd9Sstevel@tonic-gate 
15397c478bd9Sstevel@tonic-gate 	return (0);
15407c478bd9Sstevel@tonic-gate }
15417c478bd9Sstevel@tonic-gate 
15427c478bd9Sstevel@tonic-gate /*
15437c478bd9Sstevel@tonic-gate  * Split 'dn' into rdn and parentdn based on the first
15447c478bd9Sstevel@tonic-gate  * occurrence of unescaped 'comma' or 'semicolon'. rdn
15457c478bd9Sstevel@tonic-gate  * lies on the LHS while parentdn lies on the RHS of the
15467c478bd9Sstevel@tonic-gate  * split. If none found, then an empty string ("") is
15477c478bd9Sstevel@tonic-gate  * assigned to parentdn
15487c478bd9Sstevel@tonic-gate  */
15497c478bd9Sstevel@tonic-gate int
splitDN(char * dn,char ** rdn,char ** parentdn)15507c478bd9Sstevel@tonic-gate splitDN(char *dn, char **rdn, char **parentdn) {
15517c478bd9Sstevel@tonic-gate 	char	*value, *name;
15527c478bd9Sstevel@tonic-gate 	char	*myself = "splitDN";
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate 	if ((name = sdup(myself, T, dn)) == 0)
15557c478bd9Sstevel@tonic-gate 		return (-1);
15567c478bd9Sstevel@tonic-gate 
15577c478bd9Sstevel@tonic-gate 	for (value = name; *value != '\0'; value++) {
15587c478bd9Sstevel@tonic-gate 		if (*value == ',' || *value == ';')
15597c478bd9Sstevel@tonic-gate 			if (value == name || *(value - 1) != '\\')
15607c478bd9Sstevel@tonic-gate 				break;
15617c478bd9Sstevel@tonic-gate 	}
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 	if (*value != '\0') {
15647c478bd9Sstevel@tonic-gate 		*value = '\0';
15657c478bd9Sstevel@tonic-gate 		value++;
15667c478bd9Sstevel@tonic-gate 	} else
15677c478bd9Sstevel@tonic-gate 		value = 0;
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate 	if (parentdn) {
15707c478bd9Sstevel@tonic-gate 		if ((*parentdn = sdup(myself, T, value)) == 0) {
15717c478bd9Sstevel@tonic-gate 			sfree(name);
15727c478bd9Sstevel@tonic-gate 			return (-1);
15737c478bd9Sstevel@tonic-gate 		}
15747c478bd9Sstevel@tonic-gate 	}
15757c478bd9Sstevel@tonic-gate 	if (rdn)
15767c478bd9Sstevel@tonic-gate 		*rdn = name;
15777c478bd9Sstevel@tonic-gate 	else
15787c478bd9Sstevel@tonic-gate 		sfree(name);
15797c478bd9Sstevel@tonic-gate 
15807c478bd9Sstevel@tonic-gate 	return (1);
15817c478bd9Sstevel@tonic-gate }
15827c478bd9Sstevel@tonic-gate 
15837c478bd9Sstevel@tonic-gate /*
15847c478bd9Sstevel@tonic-gate  * FUNCTION :	makeNISObject()
15857c478bd9Sstevel@tonic-gate  *
15867c478bd9Sstevel@tonic-gate  * DESCRIPTION: Sets up a nis Object in the DIT.
15877c478bd9Sstevel@tonic-gate  *
15887c478bd9Sstevel@tonic-gate  * GIVEN :
15897c478bd9Sstevel@tonic-gate  *		Case 1: Both 'domain' and 'dn' are non-NULL
15907c478bd9Sstevel@tonic-gate  *			Create nisDomainObject with the given information
15917c478bd9Sstevel@tonic-gate  *		Case 2: Only 'domain' is  non-NULL
15927c478bd9Sstevel@tonic-gate  *			Obtain the 'dn' from the nisLDAPdomainContext list
15937c478bd9Sstevel@tonic-gate  *			Create nisDomainObject with the above information
15947c478bd9Sstevel@tonic-gate  *		Case 3: Only 'dn' is  non-NULL
15957c478bd9Sstevel@tonic-gate  *			Create an object with the 'dn'
15967c478bd9Sstevel@tonic-gate  *			Here we guess the objectclass attribute, based on
15977c478bd9Sstevel@tonic-gate  *			oc_lookup table
15987c478bd9Sstevel@tonic-gate  *		Case 4: Both 'domain' and 'dn' are NULL
15997c478bd9Sstevel@tonic-gate  *			Error
16007c478bd9Sstevel@tonic-gate  *
16017c478bd9Sstevel@tonic-gate  * RETURNS :	SUCCESS = It worked
16027c478bd9Sstevel@tonic-gate  *		FAILURE = There was a problem.
16037c478bd9Sstevel@tonic-gate  */
16047c478bd9Sstevel@tonic-gate suc_code
makeNISObject(char * domain,char * dn)16057c478bd9Sstevel@tonic-gate makeNISObject(char *domain, char *dn) {
16067c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
16077c478bd9Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
16087c478bd9Sstevel@tonic-gate 	int			i, rc, nr, add_rc;
16097c478bd9Sstevel@tonic-gate 	char			*val;
16107c478bd9Sstevel@tonic-gate 	char			*myself = "makeNISObject";
16117c478bd9Sstevel@tonic-gate 
16127c478bd9Sstevel@tonic-gate 	if (!dn && !domain)
16137c478bd9Sstevel@tonic-gate 		return (FAILURE);
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate 	/*
16167c478bd9Sstevel@tonic-gate 	 * If only 'domain' name is provided, then
16177c478bd9Sstevel@tonic-gate 	 * try to find dn from the nisLDAPdomainContext
16187c478bd9Sstevel@tonic-gate 	 * list generated by the parser
16197c478bd9Sstevel@tonic-gate 	 */
16207c478bd9Sstevel@tonic-gate 	if (!dn) {
16217c478bd9Sstevel@tonic-gate 		for (i = 0; i < ypDomains.numDomains; i++) {
16227c478bd9Sstevel@tonic-gate 			if (ypDomains.domainLabels[i] == 0)
16237c478bd9Sstevel@tonic-gate 				continue;
16247c478bd9Sstevel@tonic-gate 			if (strcasecmp(domain, ypDomains.domainLabels[i])
16257c478bd9Sstevel@tonic-gate 								== 0) {
16267c478bd9Sstevel@tonic-gate 				dn = ypDomains.domains[i];
16277c478bd9Sstevel@tonic-gate 				break;
16287c478bd9Sstevel@tonic-gate 			}
16297c478bd9Sstevel@tonic-gate 		}
16307c478bd9Sstevel@tonic-gate 		if (!dn)
16317c478bd9Sstevel@tonic-gate 			return (FAILURE);
16327c478bd9Sstevel@tonic-gate 	}
16337c478bd9Sstevel@tonic-gate 
16347c478bd9Sstevel@tonic-gate 	/*
16357c478bd9Sstevel@tonic-gate 	 * If only 'dn' is given, then it means that the
16367c478bd9Sstevel@tonic-gate 	 * caller simply wants to a create an entry for
16377c478bd9Sstevel@tonic-gate 	 * that 'dn'.
16387c478bd9Sstevel@tonic-gate 	 *
16397c478bd9Sstevel@tonic-gate 	 * If 'domain' is given, then check if the 'dn'
16407c478bd9Sstevel@tonic-gate 	 * has already been set up as a nis domain object.
16417c478bd9Sstevel@tonic-gate 	 * If not, see if we can make it become one.
16427c478bd9Sstevel@tonic-gate 	 */
16437c478bd9Sstevel@tonic-gate 	if (domain) {
16447c478bd9Sstevel@tonic-gate 		/*
16457c478bd9Sstevel@tonic-gate 		 * Check to see if the nis domain object has
16467c478bd9Sstevel@tonic-gate 		 * already been set up
16477c478bd9Sstevel@tonic-gate 		 */
16487c478bd9Sstevel@tonic-gate 		ls = buildLdapSearch(dn, LDAP_SCOPE_BASE, 0, 0,
16497c478bd9Sstevel@tonic-gate 			"objectclass=*", 0, 0, 0);
16507c478bd9Sstevel@tonic-gate 		if (ls == 0) {
16517c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
16527c478bd9Sstevel@tonic-gate 				"%s: Unable to create ldapSearch "
16537c478bd9Sstevel@tonic-gate 				"request for dn: %s", myself, dn);
16547c478bd9Sstevel@tonic-gate 			return (FAILURE);
16557c478bd9Sstevel@tonic-gate 		}
16567c478bd9Sstevel@tonic-gate 		nr = -1;
16577c478bd9Sstevel@tonic-gate 		rv = ldapSearch(ls, &nr, 0, &rc);
16587c478bd9Sstevel@tonic-gate 		freeLdapSearch(ls);
16597c478bd9Sstevel@tonic-gate 		if (rc == LDAP_SUCCESS) {
16607c478bd9Sstevel@tonic-gate 			val = findVal("nisDomain", rv, mit_ldap);
16617c478bd9Sstevel@tonic-gate 			if (val != NULL) {
16627c478bd9Sstevel@tonic-gate 				/*
16637c478bd9Sstevel@tonic-gate 				 * Yes, nis domain object found. Check
16647c478bd9Sstevel@tonic-gate 				 * to see if the domain names match.
16657c478bd9Sstevel@tonic-gate 				 * If so, we are done. If not, log
16667c478bd9Sstevel@tonic-gate 				 * a warning message, and return SUCCESS.
16677c478bd9Sstevel@tonic-gate 				 */
16687c478bd9Sstevel@tonic-gate 				if (strcasecmp(val, domain) == 0) {
16697c478bd9Sstevel@tonic-gate 					freeRuleValue(rv, nr);
16707c478bd9Sstevel@tonic-gate 					return (SUCCESS);
16717c478bd9Sstevel@tonic-gate 				} else {
16727c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK,
16737c478bd9Sstevel@tonic-gate 						LOG_WARNING,
16747c478bd9Sstevel@tonic-gate 						"%s: Entry (dn: %s) already "
16757c478bd9Sstevel@tonic-gate 						"contains a nis domain name "
16767c478bd9Sstevel@tonic-gate 						"(%s). The domain name (%s) "
16777c478bd9Sstevel@tonic-gate 						"is not added.",
16787c478bd9Sstevel@tonic-gate 						myself, dn, val, domain);
16797c478bd9Sstevel@tonic-gate 					freeRuleValue(rv, nr);
16807c478bd9Sstevel@tonic-gate 					return (SUCCESS);
16817c478bd9Sstevel@tonic-gate 				}
16827c478bd9Sstevel@tonic-gate 			} else {
16837c478bd9Sstevel@tonic-gate 				freeRuleValue(rv, nr);
16847c478bd9Sstevel@tonic-gate 				/*
16857c478bd9Sstevel@tonic-gate 				 * Entry for the 'dn' exists, but it
16867c478bd9Sstevel@tonic-gate 				 * is not a nis domain object yet.
16877c478bd9Sstevel@tonic-gate 				 * Add the nisDoamin attribute and
16887c478bd9Sstevel@tonic-gate 				 * the nisDomainObject objectclass to
16897c478bd9Sstevel@tonic-gate 				 * the entry.
16907c478bd9Sstevel@tonic-gate 				 */
16917c478bd9Sstevel@tonic-gate 				if ((rv = initRuleValue(1, 0)) == 0)
16927c478bd9Sstevel@tonic-gate 					return (FAILURE);
16937c478bd9Sstevel@tonic-gate 
16947c478bd9Sstevel@tonic-gate 				if (addSAttr2RuleValue("nisDomain",
16957c478bd9Sstevel@tonic-gate 						domain, rv) == -1) {
16967c478bd9Sstevel@tonic-gate 					freeRuleValue(rv, 1);
16977c478bd9Sstevel@tonic-gate 					return (FAILURE);
16987c478bd9Sstevel@tonic-gate 				}
16997c478bd9Sstevel@tonic-gate 				rc = ldapModify(dn, rv,
17007c478bd9Sstevel@tonic-gate 					"objectclass=nisDomainObject",
17017c478bd9Sstevel@tonic-gate 					0);
17027c478bd9Sstevel@tonic-gate 				freeRuleValue(rv, 1);
17037c478bd9Sstevel@tonic-gate 				if (rc == LDAP_SUCCESS) {
17047c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK,
17057c478bd9Sstevel@tonic-gate 						LOG_INFO,
17067c478bd9Sstevel@tonic-gate 						"%s: entry (dn: %s) "
17077c478bd9Sstevel@tonic-gate 						"modified to be an "
17087c478bd9Sstevel@tonic-gate 						"nis domain object",
17097c478bd9Sstevel@tonic-gate 						myself, dn);
17107c478bd9Sstevel@tonic-gate 					return (SUCCESS);
17117c478bd9Sstevel@tonic-gate 				} else {
17127c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK,
17137c478bd9Sstevel@tonic-gate 						LOG_ERR,
17147c478bd9Sstevel@tonic-gate 						"%s: unable to modify "
17157c478bd9Sstevel@tonic-gate 						"entry (dn: %s) to be "
17167c478bd9Sstevel@tonic-gate 						"a nis domain object: "
17177c478bd9Sstevel@tonic-gate 						"ldapModify error %d (%s)",
17187c478bd9Sstevel@tonic-gate 						myself, dn, rc,
17197c478bd9Sstevel@tonic-gate 						ldap_err2string(rc));
17207c478bd9Sstevel@tonic-gate 					return (FAILURE);
17217c478bd9Sstevel@tonic-gate 				}
17227c478bd9Sstevel@tonic-gate 			}
17237c478bd9Sstevel@tonic-gate 		} else { /* search for 'dn' failed */
17247c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, nr);
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate 			/*
17277c478bd9Sstevel@tonic-gate 			 * It is OK if no such object, otherwise
17287c478bd9Sstevel@tonic-gate 			 * log an error.
17297c478bd9Sstevel@tonic-gate 			 */
17307c478bd9Sstevel@tonic-gate 			if (rc != LDAP_NO_SUCH_OBJECT) {
17317c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
17327c478bd9Sstevel@tonic-gate 					"%s: unable to retrieve "
17337c478bd9Sstevel@tonic-gate 					"entry (dn: %s): "
17347c478bd9Sstevel@tonic-gate 					"ldapSearch error %d (%s)",
17357c478bd9Sstevel@tonic-gate 					myself, dn, rc,
17367c478bd9Sstevel@tonic-gate 					ldap_err2string(rc));
17377c478bd9Sstevel@tonic-gate 				return (FAILURE);
17387c478bd9Sstevel@tonic-gate 			}
17397c478bd9Sstevel@tonic-gate 		}
17407c478bd9Sstevel@tonic-gate 
17417c478bd9Sstevel@tonic-gate 		/*
17427c478bd9Sstevel@tonic-gate 		 * If the 'dn' is actually the naming context of
17437c478bd9Sstevel@tonic-gate 		 * the DIT, we should be able to make it a nis domain
17447c478bd9Sstevel@tonic-gate 		 * object without worrying about missing parent
17457c478bd9Sstevel@tonic-gate 		 * entries. If unable to add the entry for the 'dn'
17467c478bd9Sstevel@tonic-gate 		 * due to missing parent entries, fall through
17477c478bd9Sstevel@tonic-gate 		 * to create them and then add the nis domain object.
17487c478bd9Sstevel@tonic-gate 		 */
17497c478bd9Sstevel@tonic-gate 		if (addNISObject(domain, dn, &add_rc) == SUCCESS)
17507c478bd9Sstevel@tonic-gate 			return (SUCCESS);
17517c478bd9Sstevel@tonic-gate 		else if (add_rc != LDAP_NO_SUCH_OBJECT)
17527c478bd9Sstevel@tonic-gate 			return (FAILURE);
17537c478bd9Sstevel@tonic-gate 	}
17547c478bd9Sstevel@tonic-gate 
17557c478bd9Sstevel@tonic-gate 	/* Create parent */
17567c478bd9Sstevel@tonic-gate 	if (addParent(dn, NULL) == FAILURE)
17577c478bd9Sstevel@tonic-gate 		return (FAILURE);
17587c478bd9Sstevel@tonic-gate 
17597c478bd9Sstevel@tonic-gate 	if (addNISObject(domain, dn, NULL) == FAILURE)
17607c478bd9Sstevel@tonic-gate 		return (FAILURE);
17617c478bd9Sstevel@tonic-gate 
17627c478bd9Sstevel@tonic-gate 	return (SUCCESS);
17637c478bd9Sstevel@tonic-gate }
17647c478bd9Sstevel@tonic-gate 
17657c478bd9Sstevel@tonic-gate suc_code
addParent(char * dn,char ** attr)17667c478bd9Sstevel@tonic-gate addParent(char *dn, char **attr) {
17677c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
17687c478bd9Sstevel@tonic-gate 	__nis_ldap_search_t	*ls;
17697c478bd9Sstevel@tonic-gate 	int			rc, nr;
17707c478bd9Sstevel@tonic-gate 	char			*parentdn = 0, *rdn = 0;
17717c478bd9Sstevel@tonic-gate 	char			*myself = "addParent";
17727c478bd9Sstevel@tonic-gate 
17737c478bd9Sstevel@tonic-gate 	/* Obtain parentdn */
17747c478bd9Sstevel@tonic-gate 	if (splitDN(dn, &rdn, &parentdn) == -1)
17757c478bd9Sstevel@tonic-gate 		return (FAILURE);
17767c478bd9Sstevel@tonic-gate 	if (!parentdn) {
17777c478bd9Sstevel@tonic-gate 		sfree(rdn);
17787c478bd9Sstevel@tonic-gate 		return (FAILURE);
17797c478bd9Sstevel@tonic-gate 	}
17807c478bd9Sstevel@tonic-gate 
17817c478bd9Sstevel@tonic-gate 	/* Check if parentdn exists */
17827c478bd9Sstevel@tonic-gate 	ls = buildLdapSearch(parentdn, LDAP_SCOPE_BASE, 0, 0,
17837c478bd9Sstevel@tonic-gate 					"objectclass=*", 0, 0, 0);
17847c478bd9Sstevel@tonic-gate 	if (ls == 0) {
17857c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
17867c478bd9Sstevel@tonic-gate 			"%s: Unable to create ldapSearch request for "
17877c478bd9Sstevel@tonic-gate 			"parent (dn: %s) of (dn: %s)",
17887c478bd9Sstevel@tonic-gate 			myself, parentdn, dn);
17897c478bd9Sstevel@tonic-gate 		sfree(parentdn);
17907c478bd9Sstevel@tonic-gate 		sfree(rdn);
17917c478bd9Sstevel@tonic-gate 		return (FAILURE);
17927c478bd9Sstevel@tonic-gate 	}
17937c478bd9Sstevel@tonic-gate 	nr = -1;
17947c478bd9Sstevel@tonic-gate 	rv = ldapSearch(ls, &nr, 0, &rc);
17957c478bd9Sstevel@tonic-gate 	freeLdapSearch(ls);
17967c478bd9Sstevel@tonic-gate 	freeRuleValue(rv, nr);
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 	/* Create parent if it doesn't exists */
17997c478bd9Sstevel@tonic-gate 	if (rc == LDAP_NO_SUCH_OBJECT) {
18007c478bd9Sstevel@tonic-gate 		if (makeNISObject(0, parentdn) == FAILURE) {
18017c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
18027c478bd9Sstevel@tonic-gate 				"%s: Unable to create parent (dn: %s) of "
18037c478bd9Sstevel@tonic-gate 				"(dn: %s) in the DIT", myself, parentdn, dn);
18047c478bd9Sstevel@tonic-gate 			sfree(parentdn);
18057c478bd9Sstevel@tonic-gate 			sfree(rdn);
18067c478bd9Sstevel@tonic-gate 			return (FAILURE);
18077c478bd9Sstevel@tonic-gate 		}
18087c478bd9Sstevel@tonic-gate 	}
18097c478bd9Sstevel@tonic-gate 	sfree(parentdn);
18107c478bd9Sstevel@tonic-gate 
18117c478bd9Sstevel@tonic-gate 	if (attr && rdn)
18127c478bd9Sstevel@tonic-gate 		*attr = (char *)getObjectClass(rdn);
18137c478bd9Sstevel@tonic-gate 	sfree(rdn);
18147c478bd9Sstevel@tonic-gate 
18157c478bd9Sstevel@tonic-gate 	return (SUCCESS);
18167c478bd9Sstevel@tonic-gate }
18177c478bd9Sstevel@tonic-gate 
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 
18207c478bd9Sstevel@tonic-gate /*
18217c478bd9Sstevel@tonic-gate  * FUNCTION :	is_fatal_error()
18227c478bd9Sstevel@tonic-gate  *
18237c478bd9Sstevel@tonic-gate  * DESCRIPTION:	Works out if a failed mapping operation should be retried.
18247c478bd9Sstevel@tonic-gate  *
18257c478bd9Sstevel@tonic-gate  * INPUTS :	Result code from operation
18267c478bd9Sstevel@tonic-gate  *
18277c478bd9Sstevel@tonic-gate  * OUTPUTS :	TRUE = Fatal error, don't retry.
18287c478bd9Sstevel@tonic-gate  *		FALSE = Temporary error, retry.
18297c478bd9Sstevel@tonic-gate  */
18307c478bd9Sstevel@tonic-gate bool_t
is_fatal_error(int res)18317c478bd9Sstevel@tonic-gate is_fatal_error(int res)
18327c478bd9Sstevel@tonic-gate {
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate 	if (0 > res)
18357c478bd9Sstevel@tonic-gate 		/* An internal mapping error. Not going to go away. */
18367c478bd9Sstevel@tonic-gate 		return (TRUE);
18377c478bd9Sstevel@tonic-gate 
18387c478bd9Sstevel@tonic-gate 	switch (res) {
18397c478bd9Sstevel@tonic-gate 		case (LDAP_PROTOCOL_ERROR):
18407c478bd9Sstevel@tonic-gate 		case (LDAP_TIMELIMIT_EXCEEDED):
18417c478bd9Sstevel@tonic-gate 		case (LDAP_PARTIAL_RESULTS):
18427c478bd9Sstevel@tonic-gate 		case (LDAP_BUSY):
18437c478bd9Sstevel@tonic-gate 		case (LDAP_UNAVAILABLE):
18447c478bd9Sstevel@tonic-gate 		case (LDAP_UNWILLING_TO_PERFORM):
18457c478bd9Sstevel@tonic-gate 		case (LDAP_OTHER):
18467c478bd9Sstevel@tonic-gate 		case (LDAP_SERVER_DOWN):
18477c478bd9Sstevel@tonic-gate 		case (LDAP_LOCAL_ERROR):
18487c478bd9Sstevel@tonic-gate 		case (LDAP_TIMEOUT):
18497c478bd9Sstevel@tonic-gate 		case (LDAP_NO_MEMORY):
18507c478bd9Sstevel@tonic-gate 			/* Probably worth a retry */
18517c478bd9Sstevel@tonic-gate 			return (FALSE);
18527c478bd9Sstevel@tonic-gate 
18537c478bd9Sstevel@tonic-gate 		default:
18547c478bd9Sstevel@tonic-gate 			return (TRUE);
18557c478bd9Sstevel@tonic-gate 	}
18567c478bd9Sstevel@tonic-gate }
18577c478bd9Sstevel@tonic-gate 
18587c478bd9Sstevel@tonic-gate /*
18597c478bd9Sstevel@tonic-gate  * FUNCTION :	addNISObject()
18607c478bd9Sstevel@tonic-gate  *
18617c478bd9Sstevel@tonic-gate  * DESCRIPTION: Add a nis Object in the DIT.
18627c478bd9Sstevel@tonic-gate  *
18637c478bd9Sstevel@tonic-gate  * GIVEN :
18647c478bd9Sstevel@tonic-gate  *		Case 1: 'dn' is NULL
18657c478bd9Sstevel@tonic-gate  *			Error
18667c478bd9Sstevel@tonic-gate  *		Case 2: 'domain' is non-NULL
18677c478bd9Sstevel@tonic-gate  *			Create nisDomainObject with the given information
18687c478bd9Sstevel@tonic-gate  *		Case 3: 'domain' is NULL
18697c478bd9Sstevel@tonic-gate  *			Create an object with the 'dn'
18707c478bd9Sstevel@tonic-gate  *			Here we guess the objectclass attribute, based on
18717c478bd9Sstevel@tonic-gate  *			oc_lookup table
18727c478bd9Sstevel@tonic-gate  *
18737c478bd9Sstevel@tonic-gate  * RETURNS :	SUCCESS = It worked
18747c478bd9Sstevel@tonic-gate  *		FAILURE = There was a problem. If the ldap add
18757c478bd9Sstevel@tonic-gate  *                        operation failed, ldap_rc will be set
18767c478bd9Sstevel@tonic-gate  *			  to the ldap error code.
18777c478bd9Sstevel@tonic-gate  */
18787c478bd9Sstevel@tonic-gate suc_code
addNISObject(char * domain,char * dn,int * ldap_rc)18797c478bd9Sstevel@tonic-gate addNISObject(char *domain, char *dn, int *ldap_rc) {
18807c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv;
18817c478bd9Sstevel@tonic-gate 	int			rc;
18827c478bd9Sstevel@tonic-gate 	char			*objClassAttrs = NULL, *attrs;
18837c478bd9Sstevel@tonic-gate 	char			*value, *svalue, *rdn = NULL;
18847c478bd9Sstevel@tonic-gate 	char			*myself = "addNISObject";
18857c478bd9Sstevel@tonic-gate 
18867c478bd9Sstevel@tonic-gate 	if (!dn)
18877c478bd9Sstevel@tonic-gate 		return (FAILURE);
18887c478bd9Sstevel@tonic-gate 
18897c478bd9Sstevel@tonic-gate 	if ((rv = initRuleValue(1, 0)) == 0)
18907c478bd9Sstevel@tonic-gate 		return (FAILURE);
18917c478bd9Sstevel@tonic-gate 
18927c478bd9Sstevel@tonic-gate 	if (ldap_rc)
18937c478bd9Sstevel@tonic-gate 		*ldap_rc = -1;
18947c478bd9Sstevel@tonic-gate 
18957c478bd9Sstevel@tonic-gate 	/*
18967c478bd9Sstevel@tonic-gate 	 * Add name=value pairs from RDN. Although this is not required
18977c478bd9Sstevel@tonic-gate 	 * for SunOne Directory Server, during openldap interoperabilty
18987c478bd9Sstevel@tonic-gate 	 * tests, it was found out that openldap server returned object
18997c478bd9Sstevel@tonic-gate 	 * class violation errors if MUST attributes were not specified
19007c478bd9Sstevel@tonic-gate 	 * explicitly.
19017c478bd9Sstevel@tonic-gate 	 */
19027c478bd9Sstevel@tonic-gate 	if (splitDN(dn, &rdn, 0) == -1)
19037c478bd9Sstevel@tonic-gate 		return (FAILURE);
19047c478bd9Sstevel@tonic-gate 	if (rdn != NULL) {
19057c478bd9Sstevel@tonic-gate 		objClassAttrs = (char *)getObjectClass(rdn);
19067c478bd9Sstevel@tonic-gate 		if (objClassAttrs == NULL) {
19077c478bd9Sstevel@tonic-gate 			sfree(rdn);
19087c478bd9Sstevel@tonic-gate 			return (FAILURE);
19097c478bd9Sstevel@tonic-gate 		}
19107c478bd9Sstevel@tonic-gate 
19117c478bd9Sstevel@tonic-gate 		/*
19127c478bd9Sstevel@tonic-gate 		 * RDN can be composed of multiple name=value pairs
19137c478bd9Sstevel@tonic-gate 		 * concatenated by '+'. Hence, we need to determine each
19147c478bd9Sstevel@tonic-gate 		 * pair and add it to 'rv'
19157c478bd9Sstevel@tonic-gate 		 */
19167c478bd9Sstevel@tonic-gate 		for (value = rdn, svalue = NULL; *value != '\0'; value++) {
19177c478bd9Sstevel@tonic-gate 			if (*value == '+') {
19187c478bd9Sstevel@tonic-gate 				/* Make sure it's not escaped */
19197c478bd9Sstevel@tonic-gate 				if (value == rdn || *(value - 1) != '\\') {
19207c478bd9Sstevel@tonic-gate 					/*
19217c478bd9Sstevel@tonic-gate 					 * We are at the start of the new
19227c478bd9Sstevel@tonic-gate 					 * pair. 'svalue' now contains the
19237c478bd9Sstevel@tonic-gate 					 * value for the previous pair. Add
19247c478bd9Sstevel@tonic-gate 					 * the previous pair to 'rv'
19257c478bd9Sstevel@tonic-gate 					 */
19267c478bd9Sstevel@tonic-gate 					*value = '\0';
19277c478bd9Sstevel@tonic-gate 					if (svalue &&
19287c478bd9Sstevel@tonic-gate 					addSAttr2RuleValue(rdn, svalue, rv)
19297c478bd9Sstevel@tonic-gate 									== -1) {
19307c478bd9Sstevel@tonic-gate 						sfree(rdn);
19317c478bd9Sstevel@tonic-gate 						freeRuleValue(rv, 1);
19327c478bd9Sstevel@tonic-gate 						return (FAILURE);
19337c478bd9Sstevel@tonic-gate 					}
19347c478bd9Sstevel@tonic-gate 					svalue = NULL;
19357c478bd9Sstevel@tonic-gate 					rdn = value + 1;
19367c478bd9Sstevel@tonic-gate 					continue;
19377c478bd9Sstevel@tonic-gate 				}
19387c478bd9Sstevel@tonic-gate 			}
19397c478bd9Sstevel@tonic-gate 
19407c478bd9Sstevel@tonic-gate 			if (*value == '=') {
19417c478bd9Sstevel@tonic-gate 				if (value == rdn || *(value - 1) != '\\') {
19427c478bd9Sstevel@tonic-gate 					/*
19437c478bd9Sstevel@tonic-gate 					 * 'rdn' now contains the name.
19447c478bd9Sstevel@tonic-gate 					 * Whatever follows till the next
19457c478bd9Sstevel@tonic-gate 					 * unescaped '+' or '\0' is the
19467c478bd9Sstevel@tonic-gate 					 * value for this pair.
19477c478bd9Sstevel@tonic-gate 					 */
19487c478bd9Sstevel@tonic-gate 					*value = '\0';
19497c478bd9Sstevel@tonic-gate 					svalue = value + 1;
19507c478bd9Sstevel@tonic-gate 					continue;
19517c478bd9Sstevel@tonic-gate 				}
19527c478bd9Sstevel@tonic-gate 			}
19537c478bd9Sstevel@tonic-gate 		}
19547c478bd9Sstevel@tonic-gate 
19557c478bd9Sstevel@tonic-gate 		/*
19567c478bd9Sstevel@tonic-gate 		 * End of String. Add the previous name=value pair to 'rv'
19577c478bd9Sstevel@tonic-gate 		 */
19587c478bd9Sstevel@tonic-gate 		if (svalue && addSAttr2RuleValue(rdn, svalue, rv) == -1) {
19597c478bd9Sstevel@tonic-gate 			sfree(rdn);
19607c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, 1);
19617c478bd9Sstevel@tonic-gate 			return (FAILURE);
19627c478bd9Sstevel@tonic-gate 		}
19637c478bd9Sstevel@tonic-gate 		sfree(rdn);
19647c478bd9Sstevel@tonic-gate 	} else /* rdn  == NULL */
19657c478bd9Sstevel@tonic-gate 		return (FAILURE);
19667c478bd9Sstevel@tonic-gate 
19677c478bd9Sstevel@tonic-gate 	/* Create the entry */
19687c478bd9Sstevel@tonic-gate 	if (domain) {
19697c478bd9Sstevel@tonic-gate 		if (addSAttr2RuleValue("nisDomain", domain, rv) == -1) {
19707c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, 1);
19717c478bd9Sstevel@tonic-gate 			return (FAILURE);
19727c478bd9Sstevel@tonic-gate 		}
19737c478bd9Sstevel@tonic-gate 		attrs = scat(myself, F, "objectclass=nisdomainobject,",
19747c478bd9Sstevel@tonic-gate 					objClassAttrs);
19757c478bd9Sstevel@tonic-gate 		if (!attrs) {
19767c478bd9Sstevel@tonic-gate 			freeRuleValue(rv, 1);
19777c478bd9Sstevel@tonic-gate 			return (FAILURE);
19787c478bd9Sstevel@tonic-gate 		}
19797c478bd9Sstevel@tonic-gate 		rc = ldapAdd(dn, rv, attrs, 0);
19807c478bd9Sstevel@tonic-gate 		sfree(attrs);
19817c478bd9Sstevel@tonic-gate 	} else {
19827c478bd9Sstevel@tonic-gate 		rc = ldapAdd(dn, rv, objClassAttrs, 0);
19837c478bd9Sstevel@tonic-gate 	}
19847c478bd9Sstevel@tonic-gate 
19857c478bd9Sstevel@tonic-gate 	if (rc == LDAP_SUCCESS)
19867c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_INFO,
19877c478bd9Sstevel@tonic-gate 				"%s: Entry (dn: %s) added to DIT",
19887c478bd9Sstevel@tonic-gate 				myself, dn);
19897c478bd9Sstevel@tonic-gate 	else if (rc == LDAP_ALREADY_EXISTS)
19907c478bd9Sstevel@tonic-gate 		/* Treat this as success */
19917c478bd9Sstevel@tonic-gate 		rc = LDAP_SUCCESS;
19927c478bd9Sstevel@tonic-gate 	else
19937c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
19947c478bd9Sstevel@tonic-gate 				"%s: ldapAdd error %d (%s) for (dn: %s)",
19957c478bd9Sstevel@tonic-gate 				myself, rc, ldap_err2string(rc), dn);
19967c478bd9Sstevel@tonic-gate 
19977c478bd9Sstevel@tonic-gate 	freeRuleValue(rv, 1);
19987c478bd9Sstevel@tonic-gate 	if (ldap_rc)
19997c478bd9Sstevel@tonic-gate 		*ldap_rc = rc;
20007c478bd9Sstevel@tonic-gate 	return ((rc == LDAP_SUCCESS)?SUCCESS:FAILURE);
20017c478bd9Sstevel@tonic-gate }
2002