10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*11262SRajagopal.Andra@Sun.COM * Common Development and Distribution License (the "License"). 6*11262SRajagopal.Andra@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*11262SRajagopal.Andra@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <lber.h> 280Sstevel@tonic-gate #include <ldap.h> 290Sstevel@tonic-gate #include <strings.h> 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include "nisdb_mt.h" 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include "ldap_util.h" 340Sstevel@tonic-gate #include "ldap_val.h" 350Sstevel@tonic-gate #include "ldap_attr.h" 360Sstevel@tonic-gate #include "ldap_ldap.h" 370Sstevel@tonic-gate #include "ldap_ruleval.h" 380Sstevel@tonic-gate 390Sstevel@tonic-gate 400Sstevel@tonic-gate /* 410Sstevel@tonic-gate * Free an array of 'count' rule-value elements. 420Sstevel@tonic-gate */ 430Sstevel@tonic-gate void 440Sstevel@tonic-gate freeRuleValue(__nis_rule_value_t *rv, int count) { 450Sstevel@tonic-gate int n, i, j; 460Sstevel@tonic-gate 470Sstevel@tonic-gate if (rv == 0) 480Sstevel@tonic-gate return; 490Sstevel@tonic-gate 500Sstevel@tonic-gate for (n = 0; n < count; n++) { 510Sstevel@tonic-gate 520Sstevel@tonic-gate if (rv[n].colName != 0) { 530Sstevel@tonic-gate for (i = 0; i < rv[n].numColumns; i++) { 540Sstevel@tonic-gate sfree(rv[n].colName[i]); 550Sstevel@tonic-gate } 560Sstevel@tonic-gate free(rv[n].colName); 570Sstevel@tonic-gate } 580Sstevel@tonic-gate if (rv[n].colVal != 0) { 590Sstevel@tonic-gate for (i = 0; i < rv[n].numColumns; i++) { 600Sstevel@tonic-gate for (j = 0; j < rv[n].colVal[i].numVals; j++) { 610Sstevel@tonic-gate sfree(rv[n].colVal[i].val[j].value); 620Sstevel@tonic-gate } 630Sstevel@tonic-gate if (rv[n].colVal[i].numVals > 0) 640Sstevel@tonic-gate sfree(rv[n].colVal[i].val); 650Sstevel@tonic-gate } 660Sstevel@tonic-gate free(rv[n].colVal); 670Sstevel@tonic-gate } 680Sstevel@tonic-gate 690Sstevel@tonic-gate if (rv[n].attrName != 0) { 700Sstevel@tonic-gate for (i = 0; i < rv[n].numAttrs; i++) { 710Sstevel@tonic-gate sfree(rv[n].attrName[i]); 720Sstevel@tonic-gate } 730Sstevel@tonic-gate free(rv[n].attrName); 740Sstevel@tonic-gate } 750Sstevel@tonic-gate if (rv[n].attrVal != 0) { 760Sstevel@tonic-gate for (i = 0; i < rv[n].numAttrs; i++) { 770Sstevel@tonic-gate for (j = 0; j < rv[n].attrVal[i].numVals; 780Sstevel@tonic-gate j++) { 790Sstevel@tonic-gate sfree(rv[n].attrVal[i].val[j].value); 800Sstevel@tonic-gate } 810Sstevel@tonic-gate if (rv[n].attrVal[i].numVals > 0) 820Sstevel@tonic-gate sfree(rv[n].attrVal[i].val); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate free(rv[n].attrVal); 850Sstevel@tonic-gate } 860Sstevel@tonic-gate 870Sstevel@tonic-gate } 880Sstevel@tonic-gate sfree(rv); 890Sstevel@tonic-gate } 900Sstevel@tonic-gate 910Sstevel@tonic-gate /* 920Sstevel@tonic-gate * Return an array of 'count' __nis_rule_value_t elements, initialized 930Sstevel@tonic-gate * to be copies of 'rvIn' if supplied; empty otherwise. 940Sstevel@tonic-gate */ 950Sstevel@tonic-gate __nis_rule_value_t * 960Sstevel@tonic-gate initRuleValue(int count, __nis_rule_value_t *rvIn) { 970Sstevel@tonic-gate return (growRuleValue(0, count, 0, rvIn)); 980Sstevel@tonic-gate } 990Sstevel@tonic-gate 1000Sstevel@tonic-gate static const __nis_rule_value_t rvZero = {0}; 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* 1030Sstevel@tonic-gate * Grow 'old' from 'oldCount' to 'newCount' elements, initialize the 1040Sstevel@tonic-gate * new portion to 'rvIn' (empty if not supplied), and return a pointer 1050Sstevel@tonic-gate * to the result. Following a call to this function, the caller must 1060Sstevel@tonic-gate * refer only to the returned array, not to 'old'. 1070Sstevel@tonic-gate */ 1080Sstevel@tonic-gate __nis_rule_value_t * 1090Sstevel@tonic-gate growRuleValue(int oldCount, int newCount, __nis_rule_value_t *old, 1100Sstevel@tonic-gate __nis_rule_value_t *rvIn) { 1110Sstevel@tonic-gate __nis_rule_value_t *rv; 1120Sstevel@tonic-gate int i, j; 1130Sstevel@tonic-gate char *myself = "growRuleValue"; 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate if (newCount <= 0 || newCount <= oldCount) 1160Sstevel@tonic-gate return (old); 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate if (oldCount <= 0) { 1190Sstevel@tonic-gate oldCount = 0; 1200Sstevel@tonic-gate old = 0; 1210Sstevel@tonic-gate } 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (rvIn == 0) 1240Sstevel@tonic-gate rvIn = (__nis_rule_value_t *)&rvZero; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate rv = realloc(old, newCount * sizeof (rv[0])); 1270Sstevel@tonic-gate if (rv == 0) { 1280Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 1290Sstevel@tonic-gate "%s: realloc(%d ((%d+%d)*%d)) => 0", 1300Sstevel@tonic-gate myself, (oldCount+newCount) * sizeof (rv[0]), 1310Sstevel@tonic-gate oldCount, newCount, sizeof (rv[0])); 1320Sstevel@tonic-gate freeRuleValue(old, oldCount); 1330Sstevel@tonic-gate return (0); 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate (void) memset(&rv[oldCount], 0, (newCount-oldCount)*sizeof (rv[0])); 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate for (i = oldCount; i < newCount; i++) { 1390Sstevel@tonic-gate rv[i].numColumns = rvIn->numColumns; 1400Sstevel@tonic-gate if (rv[i].numColumns > 0) { 1410Sstevel@tonic-gate rv[i].colName = cloneName(rvIn->colName, 1420Sstevel@tonic-gate rv[i].numColumns); 1430Sstevel@tonic-gate rv[i].colVal = cloneValue(rvIn->colVal, 1440Sstevel@tonic-gate rv[i].numColumns); 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate if (rv[i].numColumns > 0 && 1470Sstevel@tonic-gate (rv[i].colName == 0 || rv[i].colVal == 0)) { 1480Sstevel@tonic-gate freeRuleValue(rv, i); 1490Sstevel@tonic-gate return (0); 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate rv[i].numAttrs = rvIn->numAttrs; 1520Sstevel@tonic-gate rv[i].attrName = cloneName(rvIn->attrName, rv[i].numAttrs); 1530Sstevel@tonic-gate rv[i].attrVal = cloneValue(rvIn->attrVal, rv[i].numAttrs); 1540Sstevel@tonic-gate if (rv[i].numAttrs > 0 && 1550Sstevel@tonic-gate (rv[i].attrName == 0 || rv[i].attrVal == 0)) { 1560Sstevel@tonic-gate freeRuleValue(rv, i); 1570Sstevel@tonic-gate return (0); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate return (rv); 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate /* 1650Sstevel@tonic-gate * Merge the source rule-value 's' into the target rule-value 't'. 1660Sstevel@tonic-gate * If successful, unless 's' is a sub-set of 't', 't' will be changed 1670Sstevel@tonic-gate * on exit, and will contain the values from 's' as well. 1680Sstevel@tonic-gate */ 1690Sstevel@tonic-gate int 1700Sstevel@tonic-gate mergeRuleValue(__nis_rule_value_t *t, __nis_rule_value_t *s) { 1710Sstevel@tonic-gate int i, j; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate if (s == 0) 1740Sstevel@tonic-gate return (0); 1750Sstevel@tonic-gate else if (t == 0) 1760Sstevel@tonic-gate return (-1); 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate for (i = 0; i < s->numColumns; i++) { 1790Sstevel@tonic-gate for (j = 0; j < s->colVal[i].numVals; j++) { 1800Sstevel@tonic-gate if (addCol2RuleValue(s->colVal[i].type, s->colName[i], 1810Sstevel@tonic-gate s->colVal[i].val[j].value, 1820Sstevel@tonic-gate s->colVal[i].val[j].length, 1830Sstevel@tonic-gate t)) 1840Sstevel@tonic-gate return (-1); 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate for (i = 0; i < s->numAttrs; i++) { 1890Sstevel@tonic-gate for (j = 0; j < s->attrVal[i].numVals; j++) { 1900Sstevel@tonic-gate if (addAttr2RuleValue(s->attrVal[i].type, 1910Sstevel@tonic-gate s->attrName[i], 1920Sstevel@tonic-gate s->attrVal[i].val[j].value, 1930Sstevel@tonic-gate s->attrVal[i].val[j].length, 1940Sstevel@tonic-gate t)) 1950Sstevel@tonic-gate return (-1); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate return (0); 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate static int 2030Sstevel@tonic-gate addVal2RuleValue(char *msg, int caseSens, int snipNul, __nis_value_type_t type, 2040Sstevel@tonic-gate char *name, void *value, int valueLen, 2050Sstevel@tonic-gate int *numP, char ***inNameP, __nis_value_t **inValP) { 2060Sstevel@tonic-gate int i, j, copyLen = valueLen; 2070Sstevel@tonic-gate __nis_single_value_t *v; 2080Sstevel@tonic-gate char **inName = *inNameP; 2090Sstevel@tonic-gate __nis_value_t *inVal = *inValP; 2100Sstevel@tonic-gate int num = *numP; 2110Sstevel@tonic-gate int (*comp)(const char *s1, const char *s2); 2120Sstevel@tonic-gate char *myself = "addVal2RuleValue"; 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* Internal function, so assume arguments OK */ 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate if (msg == 0) 2170Sstevel@tonic-gate msg = myself; 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate /* Should we match the 'inName' value case sensitive or not ? */ 2200Sstevel@tonic-gate if (caseSens) 2210Sstevel@tonic-gate comp = strcmp; 2220Sstevel@tonic-gate else 2230Sstevel@tonic-gate comp = strcasecmp; 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate /* 2260Sstevel@tonic-gate * String-valued NIS+ entries count the concluding NUL in the 2270Sstevel@tonic-gate * length, while LDAP entries don't. In order to support this, 2280Sstevel@tonic-gate * we implement the following for vt_string value types: 2290Sstevel@tonic-gate * 2300Sstevel@tonic-gate * If the last byte of the value isn't a NUL, add one to the 2310Sstevel@tonic-gate * allocated length, so that there always is a NUL after the 2320Sstevel@tonic-gate * value, making it safe to pass to strcmp() etc. 2330Sstevel@tonic-gate * 2340Sstevel@tonic-gate * If 'snipNul' is set (presumably meaning we're inserting a 2350Sstevel@tonic-gate * value derived from a NIS+ entry), and the last byte of the 2360Sstevel@tonic-gate * value already is a NUL, decrement the length to be copied by 2370Sstevel@tonic-gate * one. This (a) doesn't count the NUL in the value length, but 2380Sstevel@tonic-gate * (b) still leaves a NUL following the value. 2390Sstevel@tonic-gate * 2400Sstevel@tonic-gate * In N2L, for all cases we set 'copyLen' to the number of non-0 2410Sstevel@tonic-gate * characters in 'value'. 2420Sstevel@tonic-gate */ 2430Sstevel@tonic-gate if (type == vt_string && valueLen > 0) { 2440Sstevel@tonic-gate char *charval = value; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate if (charval[valueLen-1] != '\0') 2470Sstevel@tonic-gate valueLen += 1; 2480Sstevel@tonic-gate else if (yp2ldap || snipNul) 2490Sstevel@tonic-gate copyLen -= 1; 2500Sstevel@tonic-gate } else if (valueLen == 0) { 2510Sstevel@tonic-gate /* 2520Sstevel@tonic-gate * If the 'value' pointer is non-NULL, we create a zero- 2530Sstevel@tonic-gate * length value with one byte allocated. This takes care 2540Sstevel@tonic-gate * of empty strings. 2550Sstevel@tonic-gate */ 2560Sstevel@tonic-gate valueLen += 1; 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate /* If we already have values for this attribute, add another one */ 2600Sstevel@tonic-gate for (i = 0; i < num; i++) { 2610Sstevel@tonic-gate if ((*comp)(inName[i], name) == 0) { 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate /* 2640Sstevel@tonic-gate * Our caller often doesn't know the type of the 2650Sstevel@tonic-gate * value; this happens because the type (vt_string 2660Sstevel@tonic-gate * or vt_ber) is determined by the format in the 2670Sstevel@tonic-gate * rule sets, and we may be invoked as a preparation 2680Sstevel@tonic-gate * for evaluating the rules. Hence, we only use the 2690Sstevel@tonic-gate * supplied 'type' if we need to create a value. 2700Sstevel@tonic-gate * Otherwise, we accept mixed types. 2710Sstevel@tonic-gate * 2720Sstevel@tonic-gate * Strings are OK in any case, since we always make 2730Sstevel@tonic-gate * sure to have a zero byte at the end of any value, 2740Sstevel@tonic-gate * whatever the type. 2750Sstevel@tonic-gate */ 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate if (inVal[i].numVals < 0) { 2780Sstevel@tonic-gate /* 2790Sstevel@tonic-gate * Used to indicate deletion of attribute, 2800Sstevel@tonic-gate * so we honor that and don't add a value. 2810Sstevel@tonic-gate */ 2820Sstevel@tonic-gate return (0); 2830Sstevel@tonic-gate } 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate /* 2860Sstevel@tonic-gate * If 'value' is NULL, we should delete, so 2870Sstevel@tonic-gate * remove any existing values, and set the 2880Sstevel@tonic-gate * 'numVals' field to -1. 2890Sstevel@tonic-gate */ 2900Sstevel@tonic-gate if (value == 0) { 2910Sstevel@tonic-gate for (j = 0; j < inVal[i].numVals; j++) { 2920Sstevel@tonic-gate sfree(inVal[i].val[j].value); 2930Sstevel@tonic-gate } 2940Sstevel@tonic-gate sfree(inVal[i].val); 2950Sstevel@tonic-gate inVal[i].val = 0; 2960Sstevel@tonic-gate inVal[i].numVals = -1; 2970Sstevel@tonic-gate return (0); 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* Is the value a duplicate ? */ 3010Sstevel@tonic-gate for (j = 0; j < inVal[i].numVals; j++) { 3020Sstevel@tonic-gate if (copyLen == inVal[i].val[j].length && 3030Sstevel@tonic-gate memcmp(value, inVal[i].val[j].value, 3040Sstevel@tonic-gate copyLen) == 0) { 3050Sstevel@tonic-gate break; 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate } 3080Sstevel@tonic-gate if (j < inVal[i].numVals) 3090Sstevel@tonic-gate return (0); 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate /* Not a duplicate, so add the name/value pair */ 3120Sstevel@tonic-gate v = realloc(inVal[i].val, 3130Sstevel@tonic-gate (inVal[i].numVals+1) * 3140Sstevel@tonic-gate sizeof (inVal[i].val[0])); 3150Sstevel@tonic-gate if (v == 0) 3160Sstevel@tonic-gate return (-1); 3170Sstevel@tonic-gate inVal[i].val = v; 3180Sstevel@tonic-gate v[inVal[i].numVals].length = copyLen; 3190Sstevel@tonic-gate v[inVal[i].numVals].value = am(msg, valueLen); 3200Sstevel@tonic-gate if (v[inVal[i].numVals].value == 0 && 3210Sstevel@tonic-gate value != 0) { 3220Sstevel@tonic-gate sfree(v); 3230Sstevel@tonic-gate return (-1); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate memcpy(v[inVal[i].numVals].value, value, copyLen); 3260Sstevel@tonic-gate inVal[i].numVals++; 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate return (0); 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate /* No previous value for this attribute */ 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* 3350Sstevel@tonic-gate * value == 0 means deletion, in which case we create a 3360Sstevel@tonic-gate * __nis_value_t with the numVals field set to -1. 3370Sstevel@tonic-gate */ 3380Sstevel@tonic-gate if (value != 0) { 3390Sstevel@tonic-gate if ((v = am(msg, sizeof (*v))) == 0) 3400Sstevel@tonic-gate return (-1); 3410Sstevel@tonic-gate v->length = copyLen; 3420Sstevel@tonic-gate v->value = am(msg, valueLen); 3430Sstevel@tonic-gate if (v->value == 0 && value != 0) { 3440Sstevel@tonic-gate sfree(v); 3450Sstevel@tonic-gate return (-1); 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate memcpy(v->value, value, copyLen); 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate 3500Sstevel@tonic-gate inVal = realloc(inVal, (num+1)*sizeof (inVal[0])); 3510Sstevel@tonic-gate if (inVal == 0) { 3520Sstevel@tonic-gate if (value != 0) { 3530Sstevel@tonic-gate sfree(v->value); 3540Sstevel@tonic-gate sfree(v); 3550Sstevel@tonic-gate } 3560Sstevel@tonic-gate return (-1); 3570Sstevel@tonic-gate } 3580Sstevel@tonic-gate *inValP = inVal; 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate inName = realloc(inName, 3610Sstevel@tonic-gate (num+1)*sizeof (inName[0])); 3620Sstevel@tonic-gate if (inName == 0 || (inName[num] = 3630Sstevel@tonic-gate sdup(msg, T, name)) == 0) { 3640Sstevel@tonic-gate sfree(v->value); 3650Sstevel@tonic-gate sfree(v); 3660Sstevel@tonic-gate return (-1); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate *inNameP = inName; 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate inVal[num].type = type; 3710Sstevel@tonic-gate inVal[num].repeat = 0; 3720Sstevel@tonic-gate if (value != 0) { 3730Sstevel@tonic-gate inVal[num].numVals = 1; 3740Sstevel@tonic-gate inVal[num].val = v; 3750Sstevel@tonic-gate } else { 3760Sstevel@tonic-gate inVal[num].numVals = -1; 3770Sstevel@tonic-gate inVal[num].val = 0; 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate *numP += 1; 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate return (0); 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate int 3860Sstevel@tonic-gate addAttr2RuleValue(__nis_value_type_t type, char *name, void *value, 3870Sstevel@tonic-gate int valueLen, __nis_rule_value_t *rv) { 3880Sstevel@tonic-gate char *myself = "addAttr2RuleValue"; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate if (name == 0 || rv == 0) 3910Sstevel@tonic-gate return (-1); 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate return (addVal2RuleValue(myself, 0, 0, type, name, value, valueLen, 3940Sstevel@tonic-gate &rv->numAttrs, &rv->attrName, &rv->attrVal)); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate int 3980Sstevel@tonic-gate addSAttr2RuleValue(char *name, char *value, __nis_rule_value_t *rv) { 3990Sstevel@tonic-gate return (addAttr2RuleValue(vt_string, name, value, slen(value), rv)); 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate int 4030Sstevel@tonic-gate addCol2RuleValue(__nis_value_type_t type, char *name, void *value, 4040Sstevel@tonic-gate int valueLen, __nis_rule_value_t *rv) { 4050Sstevel@tonic-gate char *myself = "addCol2RuleValue"; 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate if (name == 0 || rv == 0) 4080Sstevel@tonic-gate return (-1); 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate return (addVal2RuleValue(myself, 1, 1, type, name, value, valueLen, 4110Sstevel@tonic-gate &rv->numColumns, &rv->colName, &rv->colVal)); 4120Sstevel@tonic-gate } 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate int 4150Sstevel@tonic-gate addSCol2RuleValue(char *name, char *value, __nis_rule_value_t *rv) { 4160Sstevel@tonic-gate return (addCol2RuleValue(vt_string, name, value, slen(value), rv)); 4170Sstevel@tonic-gate } 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate /* 4200Sstevel@tonic-gate * Given a table mapping, a NIS+ DB query, and (optionally) an existing 4210Sstevel@tonic-gate * and compatible __nis_rule_value_t, return a new __nis_rule_value_t 4220Sstevel@tonic-gate * with the values from the query added. 4230Sstevel@tonic-gate */ 4240Sstevel@tonic-gate __nis_rule_value_t * 4250Sstevel@tonic-gate buildNisPlusRuleValue(__nis_table_mapping_t *t, db_query *q, 4260Sstevel@tonic-gate __nis_rule_value_t *rv) { 4270Sstevel@tonic-gate int i; 4280Sstevel@tonic-gate __nis_single_value_t *sv; 4290Sstevel@tonic-gate char *myself = "buildNisPlusRuleValue"; 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate if (t == 0 || q == 0) 4320Sstevel@tonic-gate return (0); 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate rv = initRuleValue(1, rv); 4350Sstevel@tonic-gate if (rv == 0) 4360Sstevel@tonic-gate return (0); 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 4390Sstevel@tonic-gate int ic; 4400Sstevel@tonic-gate int iv, v, dup; 4410Sstevel@tonic-gate int len; 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate /* Ignore out-of-range column index */ 4440Sstevel@tonic-gate if (q->components.components_val[i].which_index >= 4450Sstevel@tonic-gate t->numColumns) 4460Sstevel@tonic-gate continue; 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate /* 4490Sstevel@tonic-gate * Add the query value. A NULL value indicates deletion, 4500Sstevel@tonic-gate * but addCol2RuleValue() takes care of that for us. 4510Sstevel@tonic-gate */ 4520Sstevel@tonic-gate if (addCol2RuleValue(vt_string, 4530Sstevel@tonic-gate t->column[q->components.components_val[i]. 4540Sstevel@tonic-gate which_index], 4550Sstevel@tonic-gate q->components.components_val[i].index_value-> 4560Sstevel@tonic-gate itemvalue.itemvalue_val, 4570Sstevel@tonic-gate q->components.components_val[i].index_value-> 4580Sstevel@tonic-gate itemvalue.itemvalue_len, rv) != 0) { 4590Sstevel@tonic-gate freeRuleValue(rv, 1); 4600Sstevel@tonic-gate rv = 0; 4610Sstevel@tonic-gate break; 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate return (rv); 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate /* 4700Sstevel@tonic-gate * Given a LHS rule 'rl', return an array containing the item names, 4710Sstevel@tonic-gate * and the number of elements in the array in '*numItems'. 4720Sstevel@tonic-gate * 4730Sstevel@tonic-gate * If there are 'me_match' __nis_mapping_element_t's, we use the 4740Sstevel@tonic-gate * supplied '*rval' (if any) to derive values for the items in 4750Sstevel@tonic-gate * the 'me_match', and add the values thus derived to '*rval' (in 4760Sstevel@tonic-gate * which case the '*rval' pointer will change; the old '*rval' 4770Sstevel@tonic-gate * is deleted). 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate __nis_mapping_item_t * 4800Sstevel@tonic-gate buildLvalue(__nis_mapping_rlhs_t *rl, __nis_value_t **rval, int *numItems) { 4810Sstevel@tonic-gate __nis_value_t *val, *r; 4820Sstevel@tonic-gate __nis_mapping_item_t *item = 0; 4830Sstevel@tonic-gate int i, n, ni = 0, nv = 0; 4840Sstevel@tonic-gate int repeat = 0; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate if (rl == 0) 4870Sstevel@tonic-gate return (0); 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate if (rval != 0) { 4900Sstevel@tonic-gate r = *rval; 4910Sstevel@tonic-gate repeat = r->repeat; 4920Sstevel@tonic-gate } else 4930Sstevel@tonic-gate r = 0; 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate /* If there is more than one element, we concatenate the items */ 4960Sstevel@tonic-gate for (i = 0; i < rl->numElements; i++) { 4970Sstevel@tonic-gate __nis_mapping_element_t *e = &rl->element[i]; 4980Sstevel@tonic-gate __nis_mapping_item_t *olditem, *tmpitem = 0; 4990Sstevel@tonic-gate __nis_value_t **tmp; 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate switch (e->type) { 5020Sstevel@tonic-gate case me_item: 5030Sstevel@tonic-gate tmpitem = cloneItem(&e->element.item); 5040Sstevel@tonic-gate break; 5050Sstevel@tonic-gate case me_match: 5060Sstevel@tonic-gate /* 5070Sstevel@tonic-gate * Obtain values for the items in the 'me_match' 5080Sstevel@tonic-gate * element. 5090Sstevel@tonic-gate */ 5100Sstevel@tonic-gate tmp = matchMappingItem(e->element.match.fmt, r, &nv, 5110Sstevel@tonic-gate 0, 0); 5120Sstevel@tonic-gate if (tmp != 0) { 5130Sstevel@tonic-gate freeValue(r, 1); 5140Sstevel@tonic-gate val = 0; 5150Sstevel@tonic-gate for (n = 0; n < nv; n++) { 5160Sstevel@tonic-gate r = concatenateValues(val, tmp[n]); 5170Sstevel@tonic-gate freeValue(val, 1); 5180Sstevel@tonic-gate freeValue(tmp[n], 1); 5190Sstevel@tonic-gate val = r; 5200Sstevel@tonic-gate if (val == 0) { 5210Sstevel@tonic-gate for (n++; n < nv; n++) { 5220Sstevel@tonic-gate freeValue(tmp[n], 1); 5230Sstevel@tonic-gate } 5240Sstevel@tonic-gate break; 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate free(tmp); 5280Sstevel@tonic-gate if (rval != 0) { 5290Sstevel@tonic-gate if (repeat && val != 0) 5300Sstevel@tonic-gate val->repeat = repeat; 5310Sstevel@tonic-gate *rval = val; 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate for (n = 0; n < e->element.match.numItems; 5340Sstevel@tonic-gate n++) { 5350Sstevel@tonic-gate olditem = item; 5360Sstevel@tonic-gate item = concatenateMappingItem(item, ni, 5370Sstevel@tonic-gate &e->element.match.item[n]); 5380Sstevel@tonic-gate freeMappingItem(olditem, ni); 5390Sstevel@tonic-gate if (item == 0) { 5400Sstevel@tonic-gate ni = 0; 5410Sstevel@tonic-gate break; 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate ni++; 5440Sstevel@tonic-gate } 5450Sstevel@tonic-gate } 5460Sstevel@tonic-gate break; 5470Sstevel@tonic-gate case me_print: 5480Sstevel@tonic-gate case me_split: 5490Sstevel@tonic-gate case me_extract: 5500Sstevel@tonic-gate default: 5510Sstevel@tonic-gate /* These shouldn't show up on the LHS; ignore */ 5520Sstevel@tonic-gate break; 5530Sstevel@tonic-gate } 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate if (tmpitem != 0) { 5560Sstevel@tonic-gate olditem = item; 5570Sstevel@tonic-gate item = concatenateMappingItem(item, ni, tmpitem); 5580Sstevel@tonic-gate freeMappingItem(olditem, ni); 5590Sstevel@tonic-gate freeMappingItem(tmpitem, 1); 5600Sstevel@tonic-gate ni++; 5610Sstevel@tonic-gate if (item == 0) { 5620Sstevel@tonic-gate ni = 0; 5630Sstevel@tonic-gate break; 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate } 5660Sstevel@tonic-gate } 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate if (numItems != 0) 5690Sstevel@tonic-gate *numItems = ni; 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate return (item); 5720Sstevel@tonic-gate } 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate __nis_value_t * 5750Sstevel@tonic-gate buildRvalue(__nis_mapping_rlhs_t *rl, __nis_mapping_item_type_t native, 5760Sstevel@tonic-gate __nis_rule_value_t *rv, int *stat) { 5770Sstevel@tonic-gate __nis_value_t *val, *vold = 0, *vnew; 5780Sstevel@tonic-gate int i; 5790Sstevel@tonic-gate char *myself = "buildRvalue"; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate if (rl == 0 || rl->numElements <= 0) { 5820Sstevel@tonic-gate /* 5830Sstevel@tonic-gate * No RHS indicates deletion, as does a __nis_value_t 5840Sstevel@tonic-gate * with numVals == -1, so we return such a creature. 5850Sstevel@tonic-gate */ 5860Sstevel@tonic-gate val = am(myself, sizeof (*val)); 5870Sstevel@tonic-gate if (val != 0) { 5880Sstevel@tonic-gate val->type = vt_string; 5890Sstevel@tonic-gate val->numVals = -1; 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate return (val); 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate /* If there is more than one element, we concatenate the values */ 5950Sstevel@tonic-gate for (i = 0; i < rl->numElements; i++) { 5960Sstevel@tonic-gate vnew = getMappingElement(&rl->element[i], native, rv, stat); 5970Sstevel@tonic-gate val = concatenateValues(vold, vnew); 5980Sstevel@tonic-gate freeValue(vnew, 1); 5990Sstevel@tonic-gate freeValue(vold, 1); 6000Sstevel@tonic-gate vold = val; 6010Sstevel@tonic-gate } 6020Sstevel@tonic-gate return (val); 6030Sstevel@tonic-gate } 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate /* 6060Sstevel@tonic-gate * Derive values for the LDAP attributes specified by the rule 'r', 6070Sstevel@tonic-gate * and add them to the rule-value 'rv'. 6080Sstevel@tonic-gate * 6090Sstevel@tonic-gate * If 'doAssign' is set, out-of-context assignments are performed, 6100Sstevel@tonic-gate * otherwise not. 6110Sstevel@tonic-gate */ 6120Sstevel@tonic-gate __nis_rule_value_t * 6130Sstevel@tonic-gate addLdapRuleValue(__nis_table_mapping_t *t, 6140Sstevel@tonic-gate __nis_mapping_rule_t *r, 6150Sstevel@tonic-gate __nis_mapping_item_type_t lnative, 6160Sstevel@tonic-gate __nis_mapping_item_type_t rnative, 6170Sstevel@tonic-gate __nis_rule_value_t *rv, 6180Sstevel@tonic-gate int doAssign, int *stat) { 6190Sstevel@tonic-gate int i, j; 6200Sstevel@tonic-gate char **new; 6210Sstevel@tonic-gate __nis_value_t *rval, *lval; 6220Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 6230Sstevel@tonic-gate __nis_mapping_item_t *litem; 6240Sstevel@tonic-gate int numItems; 6250Sstevel@tonic-gate char **dn = 0; 6260Sstevel@tonic-gate int numDN = 0; 6270Sstevel@tonic-gate char *myself = "addLdapRuleValue"; 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate /* Do we have the required values ? */ 6310Sstevel@tonic-gate if (rv == 0) 6320Sstevel@tonic-gate return (0); 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate /* 6350Sstevel@tonic-gate * Establish appropriate search base. For rnative == mit_nisplus, 6360Sstevel@tonic-gate * we're deriving LDAP attribute values from NIS+ columns; in other 6370Sstevel@tonic-gate * words, we're writing to LDAP, and should use the write.base value. 6380Sstevel@tonic-gate */ 6390Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = (rnative == mit_nisplus) ? 6400Sstevel@tonic-gate t->objectDN->write.base : t->objectDN->read.base; 6410Sstevel@tonic-gate 6420Sstevel@tonic-gate /* Set escapeFlag if LHS is "dn" to escape special chars */ 6430Sstevel@tonic-gate if (yp2ldap && r->lhs.numElements == 1 && 6440Sstevel@tonic-gate r->lhs.element->type == me_item && 6450Sstevel@tonic-gate r->lhs.element->element.item.type == mit_ldap && 6460Sstevel@tonic-gate strcasecmp(r->lhs.element->element.item.name, "dn") == 0) { 6470Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '1'; 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate /* Build the RHS value */ 6510Sstevel@tonic-gate rval = buildRvalue(&r->rhs, rnative, rv, stat); 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate /* Reset escapeFlag */ 6540Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '\0'; 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate if (rval == 0) 6570Sstevel@tonic-gate return (rv); 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate /* 6600Sstevel@tonic-gate * Special case: If we got no value for the RHS (presumably because 6610Sstevel@tonic-gate * we're missing one or more item values), we don't produce an lval. 6620Sstevel@tonic-gate * Note that this isn't the same thing as an empty value, which we 6630Sstevel@tonic-gate * faithfully try to transmit to LDAP. 6640Sstevel@tonic-gate */ 6650Sstevel@tonic-gate if (rval->numVals == 1 && rval->val[0].value == 0) { 6660Sstevel@tonic-gate freeValue(rval, 1); 6670Sstevel@tonic-gate return (rv); 6680Sstevel@tonic-gate } 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate /* Obtain the LHS item names */ 6710Sstevel@tonic-gate litem = buildLvalue(&r->lhs, &rval, &numItems); 6720Sstevel@tonic-gate if (litem == 0) { 6730Sstevel@tonic-gate freeValue(rval, 1); 6740Sstevel@tonic-gate return (rv); 6750Sstevel@tonic-gate } 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate /* Get string representations of the LHS item names */ 6780Sstevel@tonic-gate lval = 0; 6790Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 6800Sstevel@tonic-gate __nis_value_t *tmpval, *old; 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate tmpval = getMappingItem(&litem[i], lnative, 0, 0, NULL); 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate /* 6850Sstevel@tonic-gate * If the LHS item is out-of-context, we do the 6860Sstevel@tonic-gate * assignment right here. 6870Sstevel@tonic-gate */ 688*11262SRajagopal.Andra@Sun.COM if (doAssign && litem[i].type == mit_ldap && 6890Sstevel@tonic-gate litem[i].searchSpec.triple.scope != 6900Sstevel@tonic-gate LDAP_SCOPE_UNKNOWN && 6910Sstevel@tonic-gate slen(litem[i].searchSpec.triple.base) > 0 && 6920Sstevel@tonic-gate (slen(litem[i].searchSpec.triple.attrs) > 0 || 6930Sstevel@tonic-gate litem[i].searchSpec.triple.element != 0)) { 6940Sstevel@tonic-gate int stat; 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate if (dn == 0) 6970Sstevel@tonic-gate dn = findDNs(myself, rv, 1, 6980Sstevel@tonic-gate t->objectDN->write.base, 6990Sstevel@tonic-gate &numDN); 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate stat = storeLDAP(&litem[i], i, numItems, rval, 7020Sstevel@tonic-gate t->objectDN, dn, numDN); 7030Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 7040Sstevel@tonic-gate char *iname = "<unknown>"; 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate if (tmpval != 0 && 7070Sstevel@tonic-gate tmpval->numVals == 1) 7080Sstevel@tonic-gate iname = tmpval->val[0].value; 7090Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 7100Sstevel@tonic-gate "%s: LDAP store \"%s\": %s", 7110Sstevel@tonic-gate myself, iname, 7120Sstevel@tonic-gate ldap_err2string(stat)); 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate freeValue(tmpval, 1); 7160Sstevel@tonic-gate continue; 7170Sstevel@tonic-gate } 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate old = lval; 7200Sstevel@tonic-gate lval = concatenateValues(old, tmpval); 7210Sstevel@tonic-gate freeValue(tmpval, 1); 7220Sstevel@tonic-gate freeValue(old, 1); 7230Sstevel@tonic-gate } 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate /* Don't need the LHS items themselves anymore */ 7260Sstevel@tonic-gate freeMappingItem(litem, numItems); 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate /* 7290Sstevel@tonic-gate * If we don't have an 'lval' (probably because all litem[i]:s 7300Sstevel@tonic-gate * were out-of-context assignments), we're done. 7310Sstevel@tonic-gate */ 7320Sstevel@tonic-gate if (lval == 0 || lval->numVals <= 0) { 7330Sstevel@tonic-gate freeValue(lval, 1); 7340Sstevel@tonic-gate freeValue(rval, 1); 7350Sstevel@tonic-gate return (rv); 7360Sstevel@tonic-gate } 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate for (i = 0, j = 0; i < lval->numVals; i++) { 7390Sstevel@tonic-gate /* Special case: rval->numVals < 0 means deletion */ 7400Sstevel@tonic-gate if (rval->numVals < 0) { 7410Sstevel@tonic-gate (void) addAttr2RuleValue(rval->type, 7420Sstevel@tonic-gate lval->val[i].value, 0, 0, rv); 7430Sstevel@tonic-gate continue; 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate /* If we're out of values, repeat the last one */ 7460Sstevel@tonic-gate if (j >= rval->numVals) 7470Sstevel@tonic-gate j = (rval->numVals > 0) ? rval->numVals-1 : 0; 7480Sstevel@tonic-gate for (0; j < rval->numVals; j++) { 7490Sstevel@tonic-gate /* 7500Sstevel@tonic-gate * If this is the 'dn', and the value ends in a 7510Sstevel@tonic-gate * comma, append the appropriate search base. 7520Sstevel@tonic-gate */ 7530Sstevel@tonic-gate if (strcasecmp("dn", lval->val[i].value) == 0 && 7540Sstevel@tonic-gate lastChar(&rval->val[j]) == ',' && 7550Sstevel@tonic-gate t->objectDN->write.scope != 7560Sstevel@tonic-gate LDAP_SCOPE_UNKNOWN) { 7570Sstevel@tonic-gate void *nval; 7580Sstevel@tonic-gate int nlen = -1; 7590Sstevel@tonic-gate 7600Sstevel@tonic-gate nval = appendString2SingleVal( 7610Sstevel@tonic-gate t->objectDN->write.base, &rval->val[j], 7620Sstevel@tonic-gate &nlen); 7630Sstevel@tonic-gate if (nval != 0 && nlen >= 0) { 7640Sstevel@tonic-gate sfree(rval->val[j].value); 7650Sstevel@tonic-gate rval->val[j].value = nval; 7660Sstevel@tonic-gate rval->val[j].length = nlen; 7670Sstevel@tonic-gate } 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate (void) addAttr2RuleValue(rval->type, 7700Sstevel@tonic-gate lval->val[i].value, rval->val[j].value, 7710Sstevel@tonic-gate rval->val[j].length, rv); 7720Sstevel@tonic-gate /* 7730Sstevel@tonic-gate * If the lval is multi-valued, go on to the 7740Sstevel@tonic-gate * other values; otherwise, quit (but increment 7750Sstevel@tonic-gate * the 'rval' value index). 7760Sstevel@tonic-gate */ 7770Sstevel@tonic-gate if (!lval->repeat) { 7780Sstevel@tonic-gate j++; 7790Sstevel@tonic-gate break; 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate } 7820Sstevel@tonic-gate } 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate /* Clean up */ 7850Sstevel@tonic-gate freeValue(lval, 1); 7860Sstevel@tonic-gate freeValue(rval, 1); 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate return (rv); 7890Sstevel@tonic-gate } 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate /* 7920Sstevel@tonic-gate * Remove the indicated attribute, and any values for it, from the 7930Sstevel@tonic-gate * rule-value. 7940Sstevel@tonic-gate */ 7950Sstevel@tonic-gate void 7960Sstevel@tonic-gate delAttrFromRuleValue(__nis_rule_value_t *rv, char *attrName) { 7970Sstevel@tonic-gate int i; 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate if (rv == 0 || attrName == 0) 8000Sstevel@tonic-gate return; 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate for (i = 0; i < rv->numAttrs; i++) { 8030Sstevel@tonic-gate if (strcasecmp(attrName, rv->attrName[i]) == 0) { 8040Sstevel@tonic-gate int j; 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate for (j = 0; j < rv->attrVal[i].numVals; j++) 8070Sstevel@tonic-gate sfree(rv->attrVal[i].val[j].value); 8080Sstevel@tonic-gate if (rv->attrVal[i].numVals > 0) 8090Sstevel@tonic-gate sfree(rv->attrVal[i].val); 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate sfree(rv->attrName[i]); 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate /* Move up the rest of the attribute names/values */ 8140Sstevel@tonic-gate for (j = i+1; j < rv->numAttrs; j++) { 8150Sstevel@tonic-gate rv->attrName[j-1] = rv->attrName[j]; 8160Sstevel@tonic-gate rv->attrVal[j-1] = rv->attrVal[j]; 8170Sstevel@tonic-gate } 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate rv->numAttrs -= 1; 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate break; 8220Sstevel@tonic-gate } 8230Sstevel@tonic-gate } 8240Sstevel@tonic-gate } 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate /* 8270Sstevel@tonic-gate * Remove the indicated column, and any values for it, from the 8280Sstevel@tonic-gate * rule-value. 8290Sstevel@tonic-gate */ 8300Sstevel@tonic-gate void 8310Sstevel@tonic-gate delColFromRuleValue(__nis_rule_value_t *rv, char *colName) { 8320Sstevel@tonic-gate int i; 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate if (rv == 0 || colName == 0) 8350Sstevel@tonic-gate return; 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 8380Sstevel@tonic-gate if (strcmp(colName, rv->colName[i]) == 0) { 8390Sstevel@tonic-gate int j; 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate for (j = 0; j < rv->colVal[i].numVals; j++) 8420Sstevel@tonic-gate sfree(rv->colVal[i].val[j].value); 8430Sstevel@tonic-gate if (rv->colVal[i].numVals > 0) 8440Sstevel@tonic-gate sfree(rv->colVal[i].val); 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate sfree(rv->colName[i]); 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate /* Move up the rest of the column names/values */ 8490Sstevel@tonic-gate for (j = i+1; j < rv->numColumns; j++) { 8500Sstevel@tonic-gate rv->colName[j-1] = rv->colName[j]; 8510Sstevel@tonic-gate rv->colVal[j-1] = rv->colVal[j]; 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate rv->numColumns -= 1; 8550Sstevel@tonic-gate 8560Sstevel@tonic-gate break; 8570Sstevel@tonic-gate } 8580Sstevel@tonic-gate } 8590Sstevel@tonic-gate } 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate /* 8620Sstevel@tonic-gate * Add the write-mode object classes specified by 'objClassAttrs' to the 8630Sstevel@tonic-gate * rule-value 'rv'. 8640Sstevel@tonic-gate * If there's an error, 'rv' is deleted, and NULL returned. 8650Sstevel@tonic-gate */ 8660Sstevel@tonic-gate __nis_rule_value_t * 8670Sstevel@tonic-gate addObjectClasses(__nis_rule_value_t *rv, char *objClassAttrs) { 8680Sstevel@tonic-gate char *filter = 0, **fc = 0; 8690Sstevel@tonic-gate int i, nfc = 0; 8700Sstevel@tonic-gate 8710Sstevel@tonic-gate /* 8720Sstevel@tonic-gate * Expect to only use this for existing rule-values, so rv == 0 is 8730Sstevel@tonic-gate * an error. 8740Sstevel@tonic-gate */ 8750Sstevel@tonic-gate if (rv == 0) 8760Sstevel@tonic-gate return (0); 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate /* 8790Sstevel@tonic-gate * If 'objClassAttrs' is NULL, we trivially have nothing to do. 8800Sstevel@tonic-gate * Assume the caller knows what it's doing, and return success. 8810Sstevel@tonic-gate */ 8820Sstevel@tonic-gate if (objClassAttrs == 0) 8830Sstevel@tonic-gate return (rv); 8840Sstevel@tonic-gate 8850Sstevel@tonic-gate /* 8860Sstevel@tonic-gate * Make an AND-filter of the object classes, and split into 8870Sstevel@tonic-gate * components. (Yes, this is a bit round-about, but leverages 8880Sstevel@tonic-gate * existing functions.) 8890Sstevel@tonic-gate */ 8900Sstevel@tonic-gate filter = makeFilter(objClassAttrs); 8910Sstevel@tonic-gate if (filter == 0) { 8920Sstevel@tonic-gate freeRuleValue(rv, 1); 8930Sstevel@tonic-gate return (0); 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate 8960Sstevel@tonic-gate fc = makeFilterComp(filter, &nfc); 8970Sstevel@tonic-gate if (fc == 0 || nfc <= 0) { 8980Sstevel@tonic-gate free(filter); 8990Sstevel@tonic-gate freeRuleValue(rv, 1); 9000Sstevel@tonic-gate return (0); 9010Sstevel@tonic-gate } 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate /* Add the objectClass attributes to the rule-value */ 9040Sstevel@tonic-gate for (i = 0; i < nfc; i++) { 9050Sstevel@tonic-gate char *name, *value; 9060Sstevel@tonic-gate 9070Sstevel@tonic-gate name = fc[i]; 9080Sstevel@tonic-gate /* Skip if not of the "name=value" form */ 9090Sstevel@tonic-gate if ((value = strchr(name, '=')) == 0) 9100Sstevel@tonic-gate continue; 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate *value = '\0'; 9130Sstevel@tonic-gate value++; 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate /* Skip if the attribute name isn't "objectClass" */ 9160Sstevel@tonic-gate if (strcasecmp("objectClass", name) != 0) 9170Sstevel@tonic-gate continue; 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate if (addSAttr2RuleValue(name, value, rv) != 0) { 9200Sstevel@tonic-gate free(filter); 9210Sstevel@tonic-gate freeFilterComp(fc, nfc); 9220Sstevel@tonic-gate freeRuleValue(rv, 1); 9230Sstevel@tonic-gate return (0); 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate } 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate free(filter); 9280Sstevel@tonic-gate freeFilterComp(fc, nfc); 9290Sstevel@tonic-gate 9300Sstevel@tonic-gate return (rv); 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate 9340Sstevel@tonic-gate static char * 9350Sstevel@tonic-gate valString(__nis_value_t *val) { 9360Sstevel@tonic-gate int i; 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate if (val == 0 || val->type != vt_string) 9390Sstevel@tonic-gate return (0); 9400Sstevel@tonic-gate 9410Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 9420Sstevel@tonic-gate /* Look for a non-NULL, non-zero length value */ 9430Sstevel@tonic-gate if (val->val[i].value != 0 && val->val[i].length > 0) { 9440Sstevel@tonic-gate char *v = val->val[i].value; 9450Sstevel@tonic-gate 9460Sstevel@tonic-gate /* 9470Sstevel@tonic-gate * Check that there's a NUL at the end. True, 9480Sstevel@tonic-gate * if there isn't, we may be looking beyond 9490Sstevel@tonic-gate * allocated memory. However, we would have done 9500Sstevel@tonic-gate * so in any case when the supposed string was 9510Sstevel@tonic-gate * traversed (printed, etc.), very possibly by 9520Sstevel@tonic-gate * a lot more than one byte. So, it's better to 9530Sstevel@tonic-gate * take a small risk here than a large one later. 9540Sstevel@tonic-gate */ 9550Sstevel@tonic-gate if (v[val->val[i].length-1] == '\0' || 9560Sstevel@tonic-gate v[val->val[i].length] == '\0') 9570Sstevel@tonic-gate return (v); 9580Sstevel@tonic-gate } 9590Sstevel@tonic-gate } 9600Sstevel@tonic-gate 9610Sstevel@tonic-gate return (0); 9620Sstevel@tonic-gate } 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate char * 9650Sstevel@tonic-gate findVal(char *name, __nis_rule_value_t *rv, __nis_mapping_item_type_t type) { 9660Sstevel@tonic-gate int i; 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate if (type == mit_nisplus) { 9690Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 9700Sstevel@tonic-gate if (rv->colName[i] == 0) 9710Sstevel@tonic-gate continue; 9720Sstevel@tonic-gate if (strcmp(name, rv->colName[i]) == 0) { 9730Sstevel@tonic-gate return (valString(&rv->colVal[i])); 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate } 9760Sstevel@tonic-gate } else if (type == mit_ldap) { 9770Sstevel@tonic-gate for (i = 0; i < rv->numAttrs; i++) { 9780Sstevel@tonic-gate if (rv->attrName[i] == 0) 9790Sstevel@tonic-gate continue; 9800Sstevel@tonic-gate if (strcasecmp(name, rv->attrName[i]) == 0) { 9810Sstevel@tonic-gate return (valString(&rv->attrVal[i])); 9820Sstevel@tonic-gate } 9830Sstevel@tonic-gate } 9840Sstevel@tonic-gate } 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate return (0); 9870Sstevel@tonic-gate } 9880Sstevel@tonic-gate 9890Sstevel@tonic-gate static char *norv = "<NIL>"; 9900Sstevel@tonic-gate static char *unknown = "<unknown>"; 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate /* 9930Sstevel@tonic-gate * Attempt to derive a string identifying the rule-value 'rv'. The 9940Sstevel@tonic-gate * returned string is a pointer, either into 'rv', or to static 9950Sstevel@tonic-gate * storage, and must not be freed. 9960Sstevel@tonic-gate */ 9970Sstevel@tonic-gate char * 9980Sstevel@tonic-gate rvId(__nis_rule_value_t *rv, __nis_mapping_item_type_t type) { 9990Sstevel@tonic-gate char *v; 10000Sstevel@tonic-gate 10010Sstevel@tonic-gate if (rv == 0) 10020Sstevel@tonic-gate return (norv); 10030Sstevel@tonic-gate 10040Sstevel@tonic-gate if (rv->numColumns > 0 && type == mit_nisplus) { 10050Sstevel@tonic-gate /* 10060Sstevel@tonic-gate * Look for a column called "cname" or "name". 10070Sstevel@tonic-gate * If that fails, try "key" or "alias". 10080Sstevel@tonic-gate */ 10090Sstevel@tonic-gate if ((v = findVal("cname", rv, type)) != 0) 10100Sstevel@tonic-gate return (v); 10110Sstevel@tonic-gate else if ((v = findVal("name", rv, type)) != 0) 10120Sstevel@tonic-gate return (v); 10130Sstevel@tonic-gate else if ((v = findVal("key", rv, type)) != 0) 10140Sstevel@tonic-gate return (v); 10150Sstevel@tonic-gate else if ((v = findVal("alias", rv, type)) != 0) 10160Sstevel@tonic-gate return (v); 10170Sstevel@tonic-gate } else if (rv->numAttrs > 0 && type == mit_ldap) { 10180Sstevel@tonic-gate /* 10190Sstevel@tonic-gate * Look for "dn", or "cn". 10200Sstevel@tonic-gate */ 10210Sstevel@tonic-gate if ((v = findVal("dn", rv, type)) != 0) 10220Sstevel@tonic-gate return (v); 10230Sstevel@tonic-gate else if ((v = findVal("cn", rv, type)) != 0) 10240Sstevel@tonic-gate return (v); 10250Sstevel@tonic-gate } 10260Sstevel@tonic-gate 10270Sstevel@tonic-gate return (unknown); 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate /* 10310Sstevel@tonic-gate * Merge the rule-values with the same DN into one. Each rule-value 10320Sstevel@tonic-gate * in the returned array will have unique 'dn'. On entry, *numVals 10330Sstevel@tonic-gate * contains the number of rule-values in 'rv'. On exit, it contains 10340Sstevel@tonic-gate * the number of rule-values in the returned array or -1 on error. 10350Sstevel@tonic-gate */ 10360Sstevel@tonic-gate __nis_rule_value_t * 10370Sstevel@tonic-gate mergeRuleValueWithSameDN(__nis_rule_value_t *rv, int *numVals) { 10380Sstevel@tonic-gate __nis_rule_value_t *rvq = 0; 10390Sstevel@tonic-gate char *dn, *odn; 10400Sstevel@tonic-gate int count = 0; 10410Sstevel@tonic-gate int i, j; 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate if (numVals == 0) 10440Sstevel@tonic-gate return (0); 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate for (i = 0; i < *numVals; i++) { 10470Sstevel@tonic-gate if ((dn = findVal("dn", &rv[i], mit_ldap)) != 0) { 10480Sstevel@tonic-gate for (j = 0; j < count; j++) { 10490Sstevel@tonic-gate if ((odn = findVal("dn", &rvq[j], 10500Sstevel@tonic-gate mit_ldap)) != 0) { 10510Sstevel@tonic-gate /* case sensitive compare */ 10520Sstevel@tonic-gate if (strcmp(dn, odn) != 0) 10530Sstevel@tonic-gate continue; 10540Sstevel@tonic-gate if (mergeRuleValue(&rvq[j], 10550Sstevel@tonic-gate &rv[i]) == -1) { 10560Sstevel@tonic-gate freeRuleValue(rvq, count); 10570Sstevel@tonic-gate *numVals = -1; 10580Sstevel@tonic-gate return (0); 10590Sstevel@tonic-gate } 10600Sstevel@tonic-gate break; 10610Sstevel@tonic-gate } else { 10620Sstevel@tonic-gate freeRuleValue(rvq, count); 10630Sstevel@tonic-gate *numVals = -1; 10640Sstevel@tonic-gate return (0); 10650Sstevel@tonic-gate } 10660Sstevel@tonic-gate } 10670Sstevel@tonic-gate /* if no match, then add it to the rulevalue array */ 10680Sstevel@tonic-gate if (j == count) { 10690Sstevel@tonic-gate rvq = growRuleValue(count, count + 1, rvq, 10700Sstevel@tonic-gate &rv[i]); 10710Sstevel@tonic-gate if (rvq == 0) { 10720Sstevel@tonic-gate *numVals = -1; 10730Sstevel@tonic-gate return (0); 10740Sstevel@tonic-gate } 10750Sstevel@tonic-gate count++; 10760Sstevel@tonic-gate } 10770Sstevel@tonic-gate } 10780Sstevel@tonic-gate } 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate *numVals = count; 10810Sstevel@tonic-gate return (rvq); 10820Sstevel@tonic-gate } 1083