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 536e852a1SRaja Andra * Common Development and Distribution License (the "License"). 636e852a1SRaja Andra * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*a87701e9SGary Mills * Copyright 2015 Gary Mills 2336e852a1SRaja Andra * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <lber.h> 297c478bd9Sstevel@tonic-gate #include <ldap.h> 307c478bd9Sstevel@tonic-gate #include <strings.h> 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include "nisdb_mt.h" 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include "ldap_util.h" 357c478bd9Sstevel@tonic-gate #include "ldap_val.h" 367c478bd9Sstevel@tonic-gate #include "ldap_attr.h" 377c478bd9Sstevel@tonic-gate #include "ldap_ldap.h" 387c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * Free an array of 'count' rule-value elements. 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate void 457c478bd9Sstevel@tonic-gate freeRuleValue(__nis_rule_value_t *rv, int count) { 467c478bd9Sstevel@tonic-gate int n, i, j; 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate if (rv == 0) 497c478bd9Sstevel@tonic-gate return; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate for (n = 0; n < count; n++) { 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate if (rv[n].colName != 0) { 547c478bd9Sstevel@tonic-gate for (i = 0; i < rv[n].numColumns; i++) { 557c478bd9Sstevel@tonic-gate sfree(rv[n].colName[i]); 567c478bd9Sstevel@tonic-gate } 577c478bd9Sstevel@tonic-gate free(rv[n].colName); 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate if (rv[n].colVal != 0) { 607c478bd9Sstevel@tonic-gate for (i = 0; i < rv[n].numColumns; i++) { 617c478bd9Sstevel@tonic-gate for (j = 0; j < rv[n].colVal[i].numVals; j++) { 627c478bd9Sstevel@tonic-gate sfree(rv[n].colVal[i].val[j].value); 637c478bd9Sstevel@tonic-gate } 647c478bd9Sstevel@tonic-gate if (rv[n].colVal[i].numVals > 0) 657c478bd9Sstevel@tonic-gate sfree(rv[n].colVal[i].val); 667c478bd9Sstevel@tonic-gate } 677c478bd9Sstevel@tonic-gate free(rv[n].colVal); 687c478bd9Sstevel@tonic-gate } 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate if (rv[n].attrName != 0) { 717c478bd9Sstevel@tonic-gate for (i = 0; i < rv[n].numAttrs; i++) { 727c478bd9Sstevel@tonic-gate sfree(rv[n].attrName[i]); 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate free(rv[n].attrName); 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate if (rv[n].attrVal != 0) { 777c478bd9Sstevel@tonic-gate for (i = 0; i < rv[n].numAttrs; i++) { 787c478bd9Sstevel@tonic-gate for (j = 0; j < rv[n].attrVal[i].numVals; 797c478bd9Sstevel@tonic-gate j++) { 807c478bd9Sstevel@tonic-gate sfree(rv[n].attrVal[i].val[j].value); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate if (rv[n].attrVal[i].numVals > 0) 837c478bd9Sstevel@tonic-gate sfree(rv[n].attrVal[i].val); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate free(rv[n].attrVal); 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate sfree(rv); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * Return an array of 'count' __nis_rule_value_t elements, initialized 947c478bd9Sstevel@tonic-gate * to be copies of 'rvIn' if supplied; empty otherwise. 957c478bd9Sstevel@tonic-gate */ 967c478bd9Sstevel@tonic-gate __nis_rule_value_t * 977c478bd9Sstevel@tonic-gate initRuleValue(int count, __nis_rule_value_t *rvIn) { 987c478bd9Sstevel@tonic-gate return (growRuleValue(0, count, 0, rvIn)); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate static const __nis_rule_value_t rvZero = {0}; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * Grow 'old' from 'oldCount' to 'newCount' elements, initialize the 1057c478bd9Sstevel@tonic-gate * new portion to 'rvIn' (empty if not supplied), and return a pointer 1067c478bd9Sstevel@tonic-gate * to the result. Following a call to this function, the caller must 1077c478bd9Sstevel@tonic-gate * refer only to the returned array, not to 'old'. 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate __nis_rule_value_t * 1107c478bd9Sstevel@tonic-gate growRuleValue(int oldCount, int newCount, __nis_rule_value_t *old, 1117c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvIn) { 1127c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv; 113*a87701e9SGary Mills int i; 1147c478bd9Sstevel@tonic-gate char *myself = "growRuleValue"; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate if (newCount <= 0 || newCount <= oldCount) 1177c478bd9Sstevel@tonic-gate return (old); 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate if (oldCount <= 0) { 1207c478bd9Sstevel@tonic-gate oldCount = 0; 1217c478bd9Sstevel@tonic-gate old = 0; 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate if (rvIn == 0) 1257c478bd9Sstevel@tonic-gate rvIn = (__nis_rule_value_t *)&rvZero; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate rv = realloc(old, newCount * sizeof (rv[0])); 1287c478bd9Sstevel@tonic-gate if (rv == 0) { 1297c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 1307c478bd9Sstevel@tonic-gate "%s: realloc(%d ((%d+%d)*%d)) => 0", 1317c478bd9Sstevel@tonic-gate myself, (oldCount+newCount) * sizeof (rv[0]), 1327c478bd9Sstevel@tonic-gate oldCount, newCount, sizeof (rv[0])); 1337c478bd9Sstevel@tonic-gate freeRuleValue(old, oldCount); 1347c478bd9Sstevel@tonic-gate return (0); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate (void) memset(&rv[oldCount], 0, (newCount-oldCount)*sizeof (rv[0])); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate for (i = oldCount; i < newCount; i++) { 1407c478bd9Sstevel@tonic-gate rv[i].numColumns = rvIn->numColumns; 1417c478bd9Sstevel@tonic-gate if (rv[i].numColumns > 0) { 1427c478bd9Sstevel@tonic-gate rv[i].colName = cloneName(rvIn->colName, 1437c478bd9Sstevel@tonic-gate rv[i].numColumns); 1447c478bd9Sstevel@tonic-gate rv[i].colVal = cloneValue(rvIn->colVal, 1457c478bd9Sstevel@tonic-gate rv[i].numColumns); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate if (rv[i].numColumns > 0 && 1487c478bd9Sstevel@tonic-gate (rv[i].colName == 0 || rv[i].colVal == 0)) { 1497c478bd9Sstevel@tonic-gate freeRuleValue(rv, i); 1507c478bd9Sstevel@tonic-gate return (0); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate rv[i].numAttrs = rvIn->numAttrs; 1537c478bd9Sstevel@tonic-gate rv[i].attrName = cloneName(rvIn->attrName, rv[i].numAttrs); 1547c478bd9Sstevel@tonic-gate rv[i].attrVal = cloneValue(rvIn->attrVal, rv[i].numAttrs); 1557c478bd9Sstevel@tonic-gate if (rv[i].numAttrs > 0 && 1567c478bd9Sstevel@tonic-gate (rv[i].attrName == 0 || rv[i].attrVal == 0)) { 1577c478bd9Sstevel@tonic-gate freeRuleValue(rv, i); 1587c478bd9Sstevel@tonic-gate return (0); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate return (rv); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * Merge the source rule-value 's' into the target rule-value 't'. 1677c478bd9Sstevel@tonic-gate * If successful, unless 's' is a sub-set of 't', 't' will be changed 1687c478bd9Sstevel@tonic-gate * on exit, and will contain the values from 's' as well. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate int 1717c478bd9Sstevel@tonic-gate mergeRuleValue(__nis_rule_value_t *t, __nis_rule_value_t *s) { 1727c478bd9Sstevel@tonic-gate int i, j; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if (s == 0) 1757c478bd9Sstevel@tonic-gate return (0); 1767c478bd9Sstevel@tonic-gate else if (t == 0) 1777c478bd9Sstevel@tonic-gate return (-1); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate for (i = 0; i < s->numColumns; i++) { 1807c478bd9Sstevel@tonic-gate for (j = 0; j < s->colVal[i].numVals; j++) { 1817c478bd9Sstevel@tonic-gate if (addCol2RuleValue(s->colVal[i].type, s->colName[i], 1827c478bd9Sstevel@tonic-gate s->colVal[i].val[j].value, 1837c478bd9Sstevel@tonic-gate s->colVal[i].val[j].length, 1847c478bd9Sstevel@tonic-gate t)) 1857c478bd9Sstevel@tonic-gate return (-1); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate for (i = 0; i < s->numAttrs; i++) { 1907c478bd9Sstevel@tonic-gate for (j = 0; j < s->attrVal[i].numVals; j++) { 1917c478bd9Sstevel@tonic-gate if (addAttr2RuleValue(s->attrVal[i].type, 1927c478bd9Sstevel@tonic-gate s->attrName[i], 1937c478bd9Sstevel@tonic-gate s->attrVal[i].val[j].value, 1947c478bd9Sstevel@tonic-gate s->attrVal[i].val[j].length, 1957c478bd9Sstevel@tonic-gate t)) 1967c478bd9Sstevel@tonic-gate return (-1); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate return (0); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate static int 2047c478bd9Sstevel@tonic-gate addVal2RuleValue(char *msg, int caseSens, int snipNul, __nis_value_type_t type, 2057c478bd9Sstevel@tonic-gate char *name, void *value, int valueLen, 2067c478bd9Sstevel@tonic-gate int *numP, char ***inNameP, __nis_value_t **inValP) { 2077c478bd9Sstevel@tonic-gate int i, j, copyLen = valueLen; 2087c478bd9Sstevel@tonic-gate __nis_single_value_t *v; 2097c478bd9Sstevel@tonic-gate char **inName = *inNameP; 2107c478bd9Sstevel@tonic-gate __nis_value_t *inVal = *inValP; 2117c478bd9Sstevel@tonic-gate int num = *numP; 2127c478bd9Sstevel@tonic-gate int (*comp)(const char *s1, const char *s2); 2137c478bd9Sstevel@tonic-gate char *myself = "addVal2RuleValue"; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* Internal function, so assume arguments OK */ 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (msg == 0) 2187c478bd9Sstevel@tonic-gate msg = myself; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* Should we match the 'inName' value case sensitive or not ? */ 2217c478bd9Sstevel@tonic-gate if (caseSens) 2227c478bd9Sstevel@tonic-gate comp = strcmp; 2237c478bd9Sstevel@tonic-gate else 2247c478bd9Sstevel@tonic-gate comp = strcasecmp; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * String-valued NIS+ entries count the concluding NUL in the 2287c478bd9Sstevel@tonic-gate * length, while LDAP entries don't. In order to support this, 2297c478bd9Sstevel@tonic-gate * we implement the following for vt_string value types: 2307c478bd9Sstevel@tonic-gate * 2317c478bd9Sstevel@tonic-gate * If the last byte of the value isn't a NUL, add one to the 2327c478bd9Sstevel@tonic-gate * allocated length, so that there always is a NUL after the 2337c478bd9Sstevel@tonic-gate * value, making it safe to pass to strcmp() etc. 2347c478bd9Sstevel@tonic-gate * 2357c478bd9Sstevel@tonic-gate * If 'snipNul' is set (presumably meaning we're inserting a 2367c478bd9Sstevel@tonic-gate * value derived from a NIS+ entry), and the last byte of the 2377c478bd9Sstevel@tonic-gate * value already is a NUL, decrement the length to be copied by 2387c478bd9Sstevel@tonic-gate * one. This (a) doesn't count the NUL in the value length, but 2397c478bd9Sstevel@tonic-gate * (b) still leaves a NUL following the value. 2407c478bd9Sstevel@tonic-gate * 2417c478bd9Sstevel@tonic-gate * In N2L, for all cases we set 'copyLen' to the number of non-0 2427c478bd9Sstevel@tonic-gate * characters in 'value'. 2437c478bd9Sstevel@tonic-gate */ 2447c478bd9Sstevel@tonic-gate if (type == vt_string && valueLen > 0) { 2457c478bd9Sstevel@tonic-gate char *charval = value; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate if (charval[valueLen-1] != '\0') 2487c478bd9Sstevel@tonic-gate valueLen += 1; 2497c478bd9Sstevel@tonic-gate else if (yp2ldap || snipNul) 2507c478bd9Sstevel@tonic-gate copyLen -= 1; 2517c478bd9Sstevel@tonic-gate } else if (valueLen == 0) { 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * If the 'value' pointer is non-NULL, we create a zero- 2547c478bd9Sstevel@tonic-gate * length value with one byte allocated. This takes care 2557c478bd9Sstevel@tonic-gate * of empty strings. 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate valueLen += 1; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* If we already have values for this attribute, add another one */ 2617c478bd9Sstevel@tonic-gate for (i = 0; i < num; i++) { 2627c478bd9Sstevel@tonic-gate if ((*comp)(inName[i], name) == 0) { 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate /* 2657c478bd9Sstevel@tonic-gate * Our caller often doesn't know the type of the 2667c478bd9Sstevel@tonic-gate * value; this happens because the type (vt_string 2677c478bd9Sstevel@tonic-gate * or vt_ber) is determined by the format in the 2687c478bd9Sstevel@tonic-gate * rule sets, and we may be invoked as a preparation 2697c478bd9Sstevel@tonic-gate * for evaluating the rules. Hence, we only use the 2707c478bd9Sstevel@tonic-gate * supplied 'type' if we need to create a value. 2717c478bd9Sstevel@tonic-gate * Otherwise, we accept mixed types. 2727c478bd9Sstevel@tonic-gate * 2737c478bd9Sstevel@tonic-gate * Strings are OK in any case, since we always make 2747c478bd9Sstevel@tonic-gate * sure to have a zero byte at the end of any value, 2757c478bd9Sstevel@tonic-gate * whatever the type. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate if (inVal[i].numVals < 0) { 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * Used to indicate deletion of attribute, 2817c478bd9Sstevel@tonic-gate * so we honor that and don't add a value. 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate return (0); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * If 'value' is NULL, we should delete, so 2887c478bd9Sstevel@tonic-gate * remove any existing values, and set the 2897c478bd9Sstevel@tonic-gate * 'numVals' field to -1. 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate if (value == 0) { 2927c478bd9Sstevel@tonic-gate for (j = 0; j < inVal[i].numVals; j++) { 2937c478bd9Sstevel@tonic-gate sfree(inVal[i].val[j].value); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate sfree(inVal[i].val); 2967c478bd9Sstevel@tonic-gate inVal[i].val = 0; 2977c478bd9Sstevel@tonic-gate inVal[i].numVals = -1; 2987c478bd9Sstevel@tonic-gate return (0); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* Is the value a duplicate ? */ 3027c478bd9Sstevel@tonic-gate for (j = 0; j < inVal[i].numVals; j++) { 3037c478bd9Sstevel@tonic-gate if (copyLen == inVal[i].val[j].length && 3047c478bd9Sstevel@tonic-gate memcmp(value, inVal[i].val[j].value, 3057c478bd9Sstevel@tonic-gate copyLen) == 0) { 3067c478bd9Sstevel@tonic-gate break; 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate if (j < inVal[i].numVals) 3107c478bd9Sstevel@tonic-gate return (0); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* Not a duplicate, so add the name/value pair */ 3137c478bd9Sstevel@tonic-gate v = realloc(inVal[i].val, 3147c478bd9Sstevel@tonic-gate (inVal[i].numVals+1) * 3157c478bd9Sstevel@tonic-gate sizeof (inVal[i].val[0])); 3167c478bd9Sstevel@tonic-gate if (v == 0) 3177c478bd9Sstevel@tonic-gate return (-1); 3187c478bd9Sstevel@tonic-gate inVal[i].val = v; 3197c478bd9Sstevel@tonic-gate v[inVal[i].numVals].length = copyLen; 3207c478bd9Sstevel@tonic-gate v[inVal[i].numVals].value = am(msg, valueLen); 3217c478bd9Sstevel@tonic-gate if (v[inVal[i].numVals].value == 0 && 3227c478bd9Sstevel@tonic-gate value != 0) { 3237c478bd9Sstevel@tonic-gate sfree(v); 3247c478bd9Sstevel@tonic-gate return (-1); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate memcpy(v[inVal[i].numVals].value, value, copyLen); 3277c478bd9Sstevel@tonic-gate inVal[i].numVals++; 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate return (0); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /* No previous value for this attribute */ 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * value == 0 means deletion, in which case we create a 3377c478bd9Sstevel@tonic-gate * __nis_value_t with the numVals field set to -1. 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate if (value != 0) { 3407c478bd9Sstevel@tonic-gate if ((v = am(msg, sizeof (*v))) == 0) 3417c478bd9Sstevel@tonic-gate return (-1); 3427c478bd9Sstevel@tonic-gate v->length = copyLen; 3437c478bd9Sstevel@tonic-gate v->value = am(msg, valueLen); 3447c478bd9Sstevel@tonic-gate if (v->value == 0 && value != 0) { 3457c478bd9Sstevel@tonic-gate sfree(v); 3467c478bd9Sstevel@tonic-gate return (-1); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate memcpy(v->value, value, copyLen); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate inVal = realloc(inVal, (num+1)*sizeof (inVal[0])); 3527c478bd9Sstevel@tonic-gate if (inVal == 0) { 3537c478bd9Sstevel@tonic-gate if (value != 0) { 3547c478bd9Sstevel@tonic-gate sfree(v->value); 3557c478bd9Sstevel@tonic-gate sfree(v); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate return (-1); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate *inValP = inVal; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate inName = realloc(inName, 3627c478bd9Sstevel@tonic-gate (num+1)*sizeof (inName[0])); 3637c478bd9Sstevel@tonic-gate if (inName == 0 || (inName[num] = 3647c478bd9Sstevel@tonic-gate sdup(msg, T, name)) == 0) { 3657c478bd9Sstevel@tonic-gate sfree(v->value); 3667c478bd9Sstevel@tonic-gate sfree(v); 3677c478bd9Sstevel@tonic-gate return (-1); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate *inNameP = inName; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate inVal[num].type = type; 3727c478bd9Sstevel@tonic-gate inVal[num].repeat = 0; 3737c478bd9Sstevel@tonic-gate if (value != 0) { 3747c478bd9Sstevel@tonic-gate inVal[num].numVals = 1; 3757c478bd9Sstevel@tonic-gate inVal[num].val = v; 3767c478bd9Sstevel@tonic-gate } else { 3777c478bd9Sstevel@tonic-gate inVal[num].numVals = -1; 3787c478bd9Sstevel@tonic-gate inVal[num].val = 0; 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate *numP += 1; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate return (0); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate int 3877c478bd9Sstevel@tonic-gate addAttr2RuleValue(__nis_value_type_t type, char *name, void *value, 3887c478bd9Sstevel@tonic-gate int valueLen, __nis_rule_value_t *rv) { 3897c478bd9Sstevel@tonic-gate char *myself = "addAttr2RuleValue"; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate if (name == 0 || rv == 0) 3927c478bd9Sstevel@tonic-gate return (-1); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate return (addVal2RuleValue(myself, 0, 0, type, name, value, valueLen, 3957c478bd9Sstevel@tonic-gate &rv->numAttrs, &rv->attrName, &rv->attrVal)); 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate int 3997c478bd9Sstevel@tonic-gate addSAttr2RuleValue(char *name, char *value, __nis_rule_value_t *rv) { 4007c478bd9Sstevel@tonic-gate return (addAttr2RuleValue(vt_string, name, value, slen(value), rv)); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate int 4047c478bd9Sstevel@tonic-gate addCol2RuleValue(__nis_value_type_t type, char *name, void *value, 4057c478bd9Sstevel@tonic-gate int valueLen, __nis_rule_value_t *rv) { 4067c478bd9Sstevel@tonic-gate char *myself = "addCol2RuleValue"; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate if (name == 0 || rv == 0) 4097c478bd9Sstevel@tonic-gate return (-1); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate return (addVal2RuleValue(myself, 1, 1, type, name, value, valueLen, 4127c478bd9Sstevel@tonic-gate &rv->numColumns, &rv->colName, &rv->colVal)); 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate int 4167c478bd9Sstevel@tonic-gate addSCol2RuleValue(char *name, char *value, __nis_rule_value_t *rv) { 4177c478bd9Sstevel@tonic-gate return (addCol2RuleValue(vt_string, name, value, slen(value), rv)); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * Given a table mapping, a NIS+ DB query, and (optionally) an existing 4227c478bd9Sstevel@tonic-gate * and compatible __nis_rule_value_t, return a new __nis_rule_value_t 4237c478bd9Sstevel@tonic-gate * with the values from the query added. 4247c478bd9Sstevel@tonic-gate */ 4257c478bd9Sstevel@tonic-gate __nis_rule_value_t * 4267c478bd9Sstevel@tonic-gate buildNisPlusRuleValue(__nis_table_mapping_t *t, db_query *q, 4277c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv) { 4287c478bd9Sstevel@tonic-gate int i; 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate if (t == 0 || q == 0) 4317c478bd9Sstevel@tonic-gate return (0); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate rv = initRuleValue(1, rv); 4347c478bd9Sstevel@tonic-gate if (rv == 0) 4357c478bd9Sstevel@tonic-gate return (0); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate /* Ignore out-of-range column index */ 4407c478bd9Sstevel@tonic-gate if (q->components.components_val[i].which_index >= 4417c478bd9Sstevel@tonic-gate t->numColumns) 4427c478bd9Sstevel@tonic-gate continue; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * Add the query value. A NULL value indicates deletion, 4467c478bd9Sstevel@tonic-gate * but addCol2RuleValue() takes care of that for us. 4477c478bd9Sstevel@tonic-gate */ 4487c478bd9Sstevel@tonic-gate if (addCol2RuleValue(vt_string, 4497c478bd9Sstevel@tonic-gate t->column[q->components.components_val[i]. 4507c478bd9Sstevel@tonic-gate which_index], 4517c478bd9Sstevel@tonic-gate q->components.components_val[i].index_value-> 4527c478bd9Sstevel@tonic-gate itemvalue.itemvalue_val, 4537c478bd9Sstevel@tonic-gate q->components.components_val[i].index_value-> 4547c478bd9Sstevel@tonic-gate itemvalue.itemvalue_len, rv) != 0) { 4557c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 4567c478bd9Sstevel@tonic-gate rv = 0; 4577c478bd9Sstevel@tonic-gate break; 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate return (rv); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* 4667c478bd9Sstevel@tonic-gate * Given a LHS rule 'rl', return an array containing the item names, 4677c478bd9Sstevel@tonic-gate * and the number of elements in the array in '*numItems'. 4687c478bd9Sstevel@tonic-gate * 4697c478bd9Sstevel@tonic-gate * If there are 'me_match' __nis_mapping_element_t's, we use the 4707c478bd9Sstevel@tonic-gate * supplied '*rval' (if any) to derive values for the items in 4717c478bd9Sstevel@tonic-gate * the 'me_match', and add the values thus derived to '*rval' (in 4727c478bd9Sstevel@tonic-gate * which case the '*rval' pointer will change; the old '*rval' 4737c478bd9Sstevel@tonic-gate * is deleted). 4747c478bd9Sstevel@tonic-gate */ 4757c478bd9Sstevel@tonic-gate __nis_mapping_item_t * 4767c478bd9Sstevel@tonic-gate buildLvalue(__nis_mapping_rlhs_t *rl, __nis_value_t **rval, int *numItems) { 4777c478bd9Sstevel@tonic-gate __nis_value_t *val, *r; 4787c478bd9Sstevel@tonic-gate __nis_mapping_item_t *item = 0; 4797c478bd9Sstevel@tonic-gate int i, n, ni = 0, nv = 0; 4807c478bd9Sstevel@tonic-gate int repeat = 0; 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate if (rl == 0) 4837c478bd9Sstevel@tonic-gate return (0); 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate if (rval != 0) { 4867c478bd9Sstevel@tonic-gate r = *rval; 4877c478bd9Sstevel@tonic-gate repeat = r->repeat; 4887c478bd9Sstevel@tonic-gate } else 4897c478bd9Sstevel@tonic-gate r = 0; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* If there is more than one element, we concatenate the items */ 4927c478bd9Sstevel@tonic-gate for (i = 0; i < rl->numElements; i++) { 4937c478bd9Sstevel@tonic-gate __nis_mapping_element_t *e = &rl->element[i]; 4947c478bd9Sstevel@tonic-gate __nis_mapping_item_t *olditem, *tmpitem = 0; 4957c478bd9Sstevel@tonic-gate __nis_value_t **tmp; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate switch (e->type) { 4987c478bd9Sstevel@tonic-gate case me_item: 4997c478bd9Sstevel@tonic-gate tmpitem = cloneItem(&e->element.item); 5007c478bd9Sstevel@tonic-gate break; 5017c478bd9Sstevel@tonic-gate case me_match: 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * Obtain values for the items in the 'me_match' 5047c478bd9Sstevel@tonic-gate * element. 5057c478bd9Sstevel@tonic-gate */ 5067c478bd9Sstevel@tonic-gate tmp = matchMappingItem(e->element.match.fmt, r, &nv, 5077c478bd9Sstevel@tonic-gate 0, 0); 5087c478bd9Sstevel@tonic-gate if (tmp != 0) { 5097c478bd9Sstevel@tonic-gate freeValue(r, 1); 5107c478bd9Sstevel@tonic-gate val = 0; 5117c478bd9Sstevel@tonic-gate for (n = 0; n < nv; n++) { 5127c478bd9Sstevel@tonic-gate r = concatenateValues(val, tmp[n]); 5137c478bd9Sstevel@tonic-gate freeValue(val, 1); 5147c478bd9Sstevel@tonic-gate freeValue(tmp[n], 1); 5157c478bd9Sstevel@tonic-gate val = r; 5167c478bd9Sstevel@tonic-gate if (val == 0) { 5177c478bd9Sstevel@tonic-gate for (n++; n < nv; n++) { 5187c478bd9Sstevel@tonic-gate freeValue(tmp[n], 1); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate break; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate free(tmp); 5247c478bd9Sstevel@tonic-gate if (rval != 0) { 5257c478bd9Sstevel@tonic-gate if (repeat && val != 0) 5267c478bd9Sstevel@tonic-gate val->repeat = repeat; 5277c478bd9Sstevel@tonic-gate *rval = val; 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate for (n = 0; n < e->element.match.numItems; 5307c478bd9Sstevel@tonic-gate n++) { 5317c478bd9Sstevel@tonic-gate olditem = item; 5327c478bd9Sstevel@tonic-gate item = concatenateMappingItem(item, ni, 5337c478bd9Sstevel@tonic-gate &e->element.match.item[n]); 5347c478bd9Sstevel@tonic-gate freeMappingItem(olditem, ni); 5357c478bd9Sstevel@tonic-gate if (item == 0) { 5367c478bd9Sstevel@tonic-gate ni = 0; 5377c478bd9Sstevel@tonic-gate break; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate ni++; 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate break; 5437c478bd9Sstevel@tonic-gate case me_print: 5447c478bd9Sstevel@tonic-gate case me_split: 5457c478bd9Sstevel@tonic-gate case me_extract: 5467c478bd9Sstevel@tonic-gate default: 5477c478bd9Sstevel@tonic-gate /* These shouldn't show up on the LHS; ignore */ 5487c478bd9Sstevel@tonic-gate break; 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if (tmpitem != 0) { 5527c478bd9Sstevel@tonic-gate olditem = item; 5537c478bd9Sstevel@tonic-gate item = concatenateMappingItem(item, ni, tmpitem); 5547c478bd9Sstevel@tonic-gate freeMappingItem(olditem, ni); 5557c478bd9Sstevel@tonic-gate freeMappingItem(tmpitem, 1); 5567c478bd9Sstevel@tonic-gate ni++; 5577c478bd9Sstevel@tonic-gate if (item == 0) { 5587c478bd9Sstevel@tonic-gate ni = 0; 5597c478bd9Sstevel@tonic-gate break; 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate if (numItems != 0) 5657c478bd9Sstevel@tonic-gate *numItems = ni; 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate return (item); 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate __nis_value_t * 5717c478bd9Sstevel@tonic-gate buildRvalue(__nis_mapping_rlhs_t *rl, __nis_mapping_item_type_t native, 5727c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv, int *stat) { 5737c478bd9Sstevel@tonic-gate __nis_value_t *val, *vold = 0, *vnew; 5747c478bd9Sstevel@tonic-gate int i; 5757c478bd9Sstevel@tonic-gate char *myself = "buildRvalue"; 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if (rl == 0 || rl->numElements <= 0) { 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * No RHS indicates deletion, as does a __nis_value_t 5807c478bd9Sstevel@tonic-gate * with numVals == -1, so we return such a creature. 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate val = am(myself, sizeof (*val)); 5837c478bd9Sstevel@tonic-gate if (val != 0) { 5847c478bd9Sstevel@tonic-gate val->type = vt_string; 5857c478bd9Sstevel@tonic-gate val->numVals = -1; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate return (val); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* If there is more than one element, we concatenate the values */ 5917c478bd9Sstevel@tonic-gate for (i = 0; i < rl->numElements; i++) { 5927c478bd9Sstevel@tonic-gate vnew = getMappingElement(&rl->element[i], native, rv, stat); 5937c478bd9Sstevel@tonic-gate val = concatenateValues(vold, vnew); 5947c478bd9Sstevel@tonic-gate freeValue(vnew, 1); 5957c478bd9Sstevel@tonic-gate freeValue(vold, 1); 5967c478bd9Sstevel@tonic-gate vold = val; 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate return (val); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate /* 6027c478bd9Sstevel@tonic-gate * Derive values for the LDAP attributes specified by the rule 'r', 6037c478bd9Sstevel@tonic-gate * and add them to the rule-value 'rv'. 6047c478bd9Sstevel@tonic-gate * 6057c478bd9Sstevel@tonic-gate * If 'doAssign' is set, out-of-context assignments are performed, 6067c478bd9Sstevel@tonic-gate * otherwise not. 6077c478bd9Sstevel@tonic-gate */ 6087c478bd9Sstevel@tonic-gate __nis_rule_value_t * 6097c478bd9Sstevel@tonic-gate addLdapRuleValue(__nis_table_mapping_t *t, 6107c478bd9Sstevel@tonic-gate __nis_mapping_rule_t *r, 6117c478bd9Sstevel@tonic-gate __nis_mapping_item_type_t lnative, 6127c478bd9Sstevel@tonic-gate __nis_mapping_item_type_t rnative, 6137c478bd9Sstevel@tonic-gate __nis_rule_value_t *rv, 6147c478bd9Sstevel@tonic-gate int doAssign, int *stat) { 6157c478bd9Sstevel@tonic-gate int i, j; 6167c478bd9Sstevel@tonic-gate __nis_value_t *rval, *lval; 6177c478bd9Sstevel@tonic-gate __nis_mapping_item_t *litem; 6187c478bd9Sstevel@tonic-gate int numItems; 6197c478bd9Sstevel@tonic-gate char **dn = 0; 6207c478bd9Sstevel@tonic-gate int numDN = 0; 6217c478bd9Sstevel@tonic-gate char *myself = "addLdapRuleValue"; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* Do we have the required values ? */ 6257c478bd9Sstevel@tonic-gate if (rv == 0) 6267c478bd9Sstevel@tonic-gate return (0); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * Establish appropriate search base. For rnative == mit_nisplus, 6307c478bd9Sstevel@tonic-gate * we're deriving LDAP attribute values from NIS+ columns; in other 6317c478bd9Sstevel@tonic-gate * words, we're writing to LDAP, and should use the write.base value. 6327c478bd9Sstevel@tonic-gate */ 6337c478bd9Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = (rnative == mit_nisplus) ? 6347c478bd9Sstevel@tonic-gate t->objectDN->write.base : t->objectDN->read.base; 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate /* Set escapeFlag if LHS is "dn" to escape special chars */ 6377c478bd9Sstevel@tonic-gate if (yp2ldap && r->lhs.numElements == 1 && 6387c478bd9Sstevel@tonic-gate r->lhs.element->type == me_item && 6397c478bd9Sstevel@tonic-gate r->lhs.element->element.item.type == mit_ldap && 6407c478bd9Sstevel@tonic-gate strcasecmp(r->lhs.element->element.item.name, "dn") == 0) { 6417c478bd9Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '1'; 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* Build the RHS value */ 6457c478bd9Sstevel@tonic-gate rval = buildRvalue(&r->rhs, rnative, rv, stat); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate /* Reset escapeFlag */ 6487c478bd9Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '\0'; 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate if (rval == 0) 6517c478bd9Sstevel@tonic-gate return (rv); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* 6547c478bd9Sstevel@tonic-gate * Special case: If we got no value for the RHS (presumably because 6557c478bd9Sstevel@tonic-gate * we're missing one or more item values), we don't produce an lval. 6567c478bd9Sstevel@tonic-gate * Note that this isn't the same thing as an empty value, which we 6577c478bd9Sstevel@tonic-gate * faithfully try to transmit to LDAP. 6587c478bd9Sstevel@tonic-gate */ 6597c478bd9Sstevel@tonic-gate if (rval->numVals == 1 && rval->val[0].value == 0) { 6607c478bd9Sstevel@tonic-gate freeValue(rval, 1); 6617c478bd9Sstevel@tonic-gate return (rv); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate /* Obtain the LHS item names */ 6657c478bd9Sstevel@tonic-gate litem = buildLvalue(&r->lhs, &rval, &numItems); 6667c478bd9Sstevel@tonic-gate if (litem == 0) { 6677c478bd9Sstevel@tonic-gate freeValue(rval, 1); 6687c478bd9Sstevel@tonic-gate return (rv); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* Get string representations of the LHS item names */ 6727c478bd9Sstevel@tonic-gate lval = 0; 6737c478bd9Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 6747c478bd9Sstevel@tonic-gate __nis_value_t *tmpval, *old; 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate tmpval = getMappingItem(&litem[i], lnative, 0, 0, NULL); 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate /* 6797c478bd9Sstevel@tonic-gate * If the LHS item is out-of-context, we do the 6807c478bd9Sstevel@tonic-gate * assignment right here. 6817c478bd9Sstevel@tonic-gate */ 68236e852a1SRaja Andra if (doAssign && litem[i].type == mit_ldap && 6837c478bd9Sstevel@tonic-gate litem[i].searchSpec.triple.scope != 6847c478bd9Sstevel@tonic-gate LDAP_SCOPE_UNKNOWN && 6857c478bd9Sstevel@tonic-gate slen(litem[i].searchSpec.triple.base) > 0 && 6867c478bd9Sstevel@tonic-gate (slen(litem[i].searchSpec.triple.attrs) > 0 || 6877c478bd9Sstevel@tonic-gate litem[i].searchSpec.triple.element != 0)) { 6887c478bd9Sstevel@tonic-gate int stat; 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate if (dn == 0) 6917c478bd9Sstevel@tonic-gate dn = findDNs(myself, rv, 1, 6927c478bd9Sstevel@tonic-gate t->objectDN->write.base, 6937c478bd9Sstevel@tonic-gate &numDN); 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate stat = storeLDAP(&litem[i], i, numItems, rval, 6967c478bd9Sstevel@tonic-gate t->objectDN, dn, numDN); 6977c478bd9Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 6987c478bd9Sstevel@tonic-gate char *iname = "<unknown>"; 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate if (tmpval != 0 && 7017c478bd9Sstevel@tonic-gate tmpval->numVals == 1) 7027c478bd9Sstevel@tonic-gate iname = tmpval->val[0].value; 7037c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 7047c478bd9Sstevel@tonic-gate "%s: LDAP store \"%s\": %s", 7057c478bd9Sstevel@tonic-gate myself, iname, 7067c478bd9Sstevel@tonic-gate ldap_err2string(stat)); 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate freeValue(tmpval, 1); 7107c478bd9Sstevel@tonic-gate continue; 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate old = lval; 7147c478bd9Sstevel@tonic-gate lval = concatenateValues(old, tmpval); 7157c478bd9Sstevel@tonic-gate freeValue(tmpval, 1); 7167c478bd9Sstevel@tonic-gate freeValue(old, 1); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* Don't need the LHS items themselves anymore */ 7207c478bd9Sstevel@tonic-gate freeMappingItem(litem, numItems); 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * If we don't have an 'lval' (probably because all litem[i]:s 7247c478bd9Sstevel@tonic-gate * were out-of-context assignments), we're done. 7257c478bd9Sstevel@tonic-gate */ 7267c478bd9Sstevel@tonic-gate if (lval == 0 || lval->numVals <= 0) { 7277c478bd9Sstevel@tonic-gate freeValue(lval, 1); 7287c478bd9Sstevel@tonic-gate freeValue(rval, 1); 7297c478bd9Sstevel@tonic-gate return (rv); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < lval->numVals; i++) { 7337c478bd9Sstevel@tonic-gate /* Special case: rval->numVals < 0 means deletion */ 7347c478bd9Sstevel@tonic-gate if (rval->numVals < 0) { 7357c478bd9Sstevel@tonic-gate (void) addAttr2RuleValue(rval->type, 7367c478bd9Sstevel@tonic-gate lval->val[i].value, 0, 0, rv); 7377c478bd9Sstevel@tonic-gate continue; 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate /* If we're out of values, repeat the last one */ 7407c478bd9Sstevel@tonic-gate if (j >= rval->numVals) 7417c478bd9Sstevel@tonic-gate j = (rval->numVals > 0) ? rval->numVals-1 : 0; 742*a87701e9SGary Mills for (; j < rval->numVals; j++) { 7437c478bd9Sstevel@tonic-gate /* 7447c478bd9Sstevel@tonic-gate * If this is the 'dn', and the value ends in a 7457c478bd9Sstevel@tonic-gate * comma, append the appropriate search base. 7467c478bd9Sstevel@tonic-gate */ 7477c478bd9Sstevel@tonic-gate if (strcasecmp("dn", lval->val[i].value) == 0 && 7487c478bd9Sstevel@tonic-gate lastChar(&rval->val[j]) == ',' && 7497c478bd9Sstevel@tonic-gate t->objectDN->write.scope != 7507c478bd9Sstevel@tonic-gate LDAP_SCOPE_UNKNOWN) { 7517c478bd9Sstevel@tonic-gate void *nval; 7527c478bd9Sstevel@tonic-gate int nlen = -1; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate nval = appendString2SingleVal( 7557c478bd9Sstevel@tonic-gate t->objectDN->write.base, &rval->val[j], 7567c478bd9Sstevel@tonic-gate &nlen); 7577c478bd9Sstevel@tonic-gate if (nval != 0 && nlen >= 0) { 7587c478bd9Sstevel@tonic-gate sfree(rval->val[j].value); 7597c478bd9Sstevel@tonic-gate rval->val[j].value = nval; 7607c478bd9Sstevel@tonic-gate rval->val[j].length = nlen; 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate (void) addAttr2RuleValue(rval->type, 7647c478bd9Sstevel@tonic-gate lval->val[i].value, rval->val[j].value, 7657c478bd9Sstevel@tonic-gate rval->val[j].length, rv); 7667c478bd9Sstevel@tonic-gate /* 7677c478bd9Sstevel@tonic-gate * If the lval is multi-valued, go on to the 7687c478bd9Sstevel@tonic-gate * other values; otherwise, quit (but increment 7697c478bd9Sstevel@tonic-gate * the 'rval' value index). 7707c478bd9Sstevel@tonic-gate */ 7717c478bd9Sstevel@tonic-gate if (!lval->repeat) { 7727c478bd9Sstevel@tonic-gate j++; 7737c478bd9Sstevel@tonic-gate break; 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate /* Clean up */ 7797c478bd9Sstevel@tonic-gate freeValue(lval, 1); 7807c478bd9Sstevel@tonic-gate freeValue(rval, 1); 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate return (rv); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate /* 7867c478bd9Sstevel@tonic-gate * Remove the indicated attribute, and any values for it, from the 7877c478bd9Sstevel@tonic-gate * rule-value. 7887c478bd9Sstevel@tonic-gate */ 7897c478bd9Sstevel@tonic-gate void 7907c478bd9Sstevel@tonic-gate delAttrFromRuleValue(__nis_rule_value_t *rv, char *attrName) { 7917c478bd9Sstevel@tonic-gate int i; 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate if (rv == 0 || attrName == 0) 7947c478bd9Sstevel@tonic-gate return; 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate for (i = 0; i < rv->numAttrs; i++) { 7977c478bd9Sstevel@tonic-gate if (strcasecmp(attrName, rv->attrName[i]) == 0) { 7987c478bd9Sstevel@tonic-gate int j; 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate for (j = 0; j < rv->attrVal[i].numVals; j++) 8017c478bd9Sstevel@tonic-gate sfree(rv->attrVal[i].val[j].value); 8027c478bd9Sstevel@tonic-gate if (rv->attrVal[i].numVals > 0) 8037c478bd9Sstevel@tonic-gate sfree(rv->attrVal[i].val); 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate sfree(rv->attrName[i]); 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate /* Move up the rest of the attribute names/values */ 8087c478bd9Sstevel@tonic-gate for (j = i+1; j < rv->numAttrs; j++) { 8097c478bd9Sstevel@tonic-gate rv->attrName[j-1] = rv->attrName[j]; 8107c478bd9Sstevel@tonic-gate rv->attrVal[j-1] = rv->attrVal[j]; 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate rv->numAttrs -= 1; 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate break; 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate /* 8217c478bd9Sstevel@tonic-gate * Remove the indicated column, and any values for it, from the 8227c478bd9Sstevel@tonic-gate * rule-value. 8237c478bd9Sstevel@tonic-gate */ 8247c478bd9Sstevel@tonic-gate void 8257c478bd9Sstevel@tonic-gate delColFromRuleValue(__nis_rule_value_t *rv, char *colName) { 8267c478bd9Sstevel@tonic-gate int i; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate if (rv == 0 || colName == 0) 8297c478bd9Sstevel@tonic-gate return; 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 8327c478bd9Sstevel@tonic-gate if (strcmp(colName, rv->colName[i]) == 0) { 8337c478bd9Sstevel@tonic-gate int j; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate for (j = 0; j < rv->colVal[i].numVals; j++) 8367c478bd9Sstevel@tonic-gate sfree(rv->colVal[i].val[j].value); 8377c478bd9Sstevel@tonic-gate if (rv->colVal[i].numVals > 0) 8387c478bd9Sstevel@tonic-gate sfree(rv->colVal[i].val); 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate sfree(rv->colName[i]); 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate /* Move up the rest of the column names/values */ 8437c478bd9Sstevel@tonic-gate for (j = i+1; j < rv->numColumns; j++) { 8447c478bd9Sstevel@tonic-gate rv->colName[j-1] = rv->colName[j]; 8457c478bd9Sstevel@tonic-gate rv->colVal[j-1] = rv->colVal[j]; 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate rv->numColumns -= 1; 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate break; 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate /* 8567c478bd9Sstevel@tonic-gate * Add the write-mode object classes specified by 'objClassAttrs' to the 8577c478bd9Sstevel@tonic-gate * rule-value 'rv'. 8587c478bd9Sstevel@tonic-gate * If there's an error, 'rv' is deleted, and NULL returned. 8597c478bd9Sstevel@tonic-gate */ 8607c478bd9Sstevel@tonic-gate __nis_rule_value_t * 8617c478bd9Sstevel@tonic-gate addObjectClasses(__nis_rule_value_t *rv, char *objClassAttrs) { 8627c478bd9Sstevel@tonic-gate char *filter = 0, **fc = 0; 8637c478bd9Sstevel@tonic-gate int i, nfc = 0; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate /* 8667c478bd9Sstevel@tonic-gate * Expect to only use this for existing rule-values, so rv == 0 is 8677c478bd9Sstevel@tonic-gate * an error. 8687c478bd9Sstevel@tonic-gate */ 8697c478bd9Sstevel@tonic-gate if (rv == 0) 8707c478bd9Sstevel@tonic-gate return (0); 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate /* 8737c478bd9Sstevel@tonic-gate * If 'objClassAttrs' is NULL, we trivially have nothing to do. 8747c478bd9Sstevel@tonic-gate * Assume the caller knows what it's doing, and return success. 8757c478bd9Sstevel@tonic-gate */ 8767c478bd9Sstevel@tonic-gate if (objClassAttrs == 0) 8777c478bd9Sstevel@tonic-gate return (rv); 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate /* 8807c478bd9Sstevel@tonic-gate * Make an AND-filter of the object classes, and split into 8817c478bd9Sstevel@tonic-gate * components. (Yes, this is a bit round-about, but leverages 8827c478bd9Sstevel@tonic-gate * existing functions.) 8837c478bd9Sstevel@tonic-gate */ 8847c478bd9Sstevel@tonic-gate filter = makeFilter(objClassAttrs); 8857c478bd9Sstevel@tonic-gate if (filter == 0) { 8867c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 8877c478bd9Sstevel@tonic-gate return (0); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate fc = makeFilterComp(filter, &nfc); 8917c478bd9Sstevel@tonic-gate if (fc == 0 || nfc <= 0) { 8927c478bd9Sstevel@tonic-gate free(filter); 8937c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 8947c478bd9Sstevel@tonic-gate return (0); 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate /* Add the objectClass attributes to the rule-value */ 8987c478bd9Sstevel@tonic-gate for (i = 0; i < nfc; i++) { 8997c478bd9Sstevel@tonic-gate char *name, *value; 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate name = fc[i]; 9027c478bd9Sstevel@tonic-gate /* Skip if not of the "name=value" form */ 9037c478bd9Sstevel@tonic-gate if ((value = strchr(name, '=')) == 0) 9047c478bd9Sstevel@tonic-gate continue; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate *value = '\0'; 9077c478bd9Sstevel@tonic-gate value++; 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate /* Skip if the attribute name isn't "objectClass" */ 9107c478bd9Sstevel@tonic-gate if (strcasecmp("objectClass", name) != 0) 9117c478bd9Sstevel@tonic-gate continue; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate if (addSAttr2RuleValue(name, value, rv) != 0) { 9147c478bd9Sstevel@tonic-gate free(filter); 9157c478bd9Sstevel@tonic-gate freeFilterComp(fc, nfc); 9167c478bd9Sstevel@tonic-gate freeRuleValue(rv, 1); 9177c478bd9Sstevel@tonic-gate return (0); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate free(filter); 9227c478bd9Sstevel@tonic-gate freeFilterComp(fc, nfc); 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate return (rv); 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate static char * 9297c478bd9Sstevel@tonic-gate valString(__nis_value_t *val) { 9307c478bd9Sstevel@tonic-gate int i; 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate if (val == 0 || val->type != vt_string) 9337c478bd9Sstevel@tonic-gate return (0); 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 9367c478bd9Sstevel@tonic-gate /* Look for a non-NULL, non-zero length value */ 9377c478bd9Sstevel@tonic-gate if (val->val[i].value != 0 && val->val[i].length > 0) { 9387c478bd9Sstevel@tonic-gate char *v = val->val[i].value; 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate /* 9417c478bd9Sstevel@tonic-gate * Check that there's a NUL at the end. True, 9427c478bd9Sstevel@tonic-gate * if there isn't, we may be looking beyond 9437c478bd9Sstevel@tonic-gate * allocated memory. However, we would have done 9447c478bd9Sstevel@tonic-gate * so in any case when the supposed string was 9457c478bd9Sstevel@tonic-gate * traversed (printed, etc.), very possibly by 9467c478bd9Sstevel@tonic-gate * a lot more than one byte. So, it's better to 9477c478bd9Sstevel@tonic-gate * take a small risk here than a large one later. 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate if (v[val->val[i].length-1] == '\0' || 9507c478bd9Sstevel@tonic-gate v[val->val[i].length] == '\0') 9517c478bd9Sstevel@tonic-gate return (v); 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate return (0); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate char * 9597c478bd9Sstevel@tonic-gate findVal(char *name, __nis_rule_value_t *rv, __nis_mapping_item_type_t type) { 9607c478bd9Sstevel@tonic-gate int i; 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate if (type == mit_nisplus) { 9637c478bd9Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 9647c478bd9Sstevel@tonic-gate if (rv->colName[i] == 0) 9657c478bd9Sstevel@tonic-gate continue; 9667c478bd9Sstevel@tonic-gate if (strcmp(name, rv->colName[i]) == 0) { 9677c478bd9Sstevel@tonic-gate return (valString(&rv->colVal[i])); 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate } else if (type == mit_ldap) { 9717c478bd9Sstevel@tonic-gate for (i = 0; i < rv->numAttrs; i++) { 9727c478bd9Sstevel@tonic-gate if (rv->attrName[i] == 0) 9737c478bd9Sstevel@tonic-gate continue; 9747c478bd9Sstevel@tonic-gate if (strcasecmp(name, rv->attrName[i]) == 0) { 9757c478bd9Sstevel@tonic-gate return (valString(&rv->attrVal[i])); 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate return (0); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate static char *norv = "<NIL>"; 9847c478bd9Sstevel@tonic-gate static char *unknown = "<unknown>"; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate /* 9877c478bd9Sstevel@tonic-gate * Attempt to derive a string identifying the rule-value 'rv'. The 9887c478bd9Sstevel@tonic-gate * returned string is a pointer, either into 'rv', or to static 9897c478bd9Sstevel@tonic-gate * storage, and must not be freed. 9907c478bd9Sstevel@tonic-gate */ 9917c478bd9Sstevel@tonic-gate char * 9927c478bd9Sstevel@tonic-gate rvId(__nis_rule_value_t *rv, __nis_mapping_item_type_t type) { 9937c478bd9Sstevel@tonic-gate char *v; 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate if (rv == 0) 9967c478bd9Sstevel@tonic-gate return (norv); 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate if (rv->numColumns > 0 && type == mit_nisplus) { 9997c478bd9Sstevel@tonic-gate /* 10007c478bd9Sstevel@tonic-gate * Look for a column called "cname" or "name". 10017c478bd9Sstevel@tonic-gate * If that fails, try "key" or "alias". 10027c478bd9Sstevel@tonic-gate */ 10037c478bd9Sstevel@tonic-gate if ((v = findVal("cname", rv, type)) != 0) 10047c478bd9Sstevel@tonic-gate return (v); 10057c478bd9Sstevel@tonic-gate else if ((v = findVal("name", rv, type)) != 0) 10067c478bd9Sstevel@tonic-gate return (v); 10077c478bd9Sstevel@tonic-gate else if ((v = findVal("key", rv, type)) != 0) 10087c478bd9Sstevel@tonic-gate return (v); 10097c478bd9Sstevel@tonic-gate else if ((v = findVal("alias", rv, type)) != 0) 10107c478bd9Sstevel@tonic-gate return (v); 10117c478bd9Sstevel@tonic-gate } else if (rv->numAttrs > 0 && type == mit_ldap) { 10127c478bd9Sstevel@tonic-gate /* 10137c478bd9Sstevel@tonic-gate * Look for "dn", or "cn". 10147c478bd9Sstevel@tonic-gate */ 10157c478bd9Sstevel@tonic-gate if ((v = findVal("dn", rv, type)) != 0) 10167c478bd9Sstevel@tonic-gate return (v); 10177c478bd9Sstevel@tonic-gate else if ((v = findVal("cn", rv, type)) != 0) 10187c478bd9Sstevel@tonic-gate return (v); 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate return (unknown); 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate /* 10257c478bd9Sstevel@tonic-gate * Merge the rule-values with the same DN into one. Each rule-value 10267c478bd9Sstevel@tonic-gate * in the returned array will have unique 'dn'. On entry, *numVals 10277c478bd9Sstevel@tonic-gate * contains the number of rule-values in 'rv'. On exit, it contains 10287c478bd9Sstevel@tonic-gate * the number of rule-values in the returned array or -1 on error. 10297c478bd9Sstevel@tonic-gate */ 10307c478bd9Sstevel@tonic-gate __nis_rule_value_t * 10317c478bd9Sstevel@tonic-gate mergeRuleValueWithSameDN(__nis_rule_value_t *rv, int *numVals) { 10327c478bd9Sstevel@tonic-gate __nis_rule_value_t *rvq = 0; 10337c478bd9Sstevel@tonic-gate char *dn, *odn; 10347c478bd9Sstevel@tonic-gate int count = 0; 10357c478bd9Sstevel@tonic-gate int i, j; 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate if (numVals == 0) 10387c478bd9Sstevel@tonic-gate return (0); 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate for (i = 0; i < *numVals; i++) { 10417c478bd9Sstevel@tonic-gate if ((dn = findVal("dn", &rv[i], mit_ldap)) != 0) { 10427c478bd9Sstevel@tonic-gate for (j = 0; j < count; j++) { 10437c478bd9Sstevel@tonic-gate if ((odn = findVal("dn", &rvq[j], 10447c478bd9Sstevel@tonic-gate mit_ldap)) != 0) { 10457c478bd9Sstevel@tonic-gate /* case sensitive compare */ 10467c478bd9Sstevel@tonic-gate if (strcmp(dn, odn) != 0) 10477c478bd9Sstevel@tonic-gate continue; 10487c478bd9Sstevel@tonic-gate if (mergeRuleValue(&rvq[j], 10497c478bd9Sstevel@tonic-gate &rv[i]) == -1) { 10507c478bd9Sstevel@tonic-gate freeRuleValue(rvq, count); 10517c478bd9Sstevel@tonic-gate *numVals = -1; 10527c478bd9Sstevel@tonic-gate return (0); 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate break; 10557c478bd9Sstevel@tonic-gate } else { 10567c478bd9Sstevel@tonic-gate freeRuleValue(rvq, count); 10577c478bd9Sstevel@tonic-gate *numVals = -1; 10587c478bd9Sstevel@tonic-gate return (0); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate /* if no match, then add it to the rulevalue array */ 10627c478bd9Sstevel@tonic-gate if (j == count) { 10637c478bd9Sstevel@tonic-gate rvq = growRuleValue(count, count + 1, rvq, 10647c478bd9Sstevel@tonic-gate &rv[i]); 10657c478bd9Sstevel@tonic-gate if (rvq == 0) { 10667c478bd9Sstevel@tonic-gate *numVals = -1; 10677c478bd9Sstevel@tonic-gate return (0); 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate count++; 10707c478bd9Sstevel@tonic-gate } 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate *numVals = count; 10757c478bd9Sstevel@tonic-gate return (rvq); 10767c478bd9Sstevel@tonic-gate } 1077