1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <lber.h> 30*0Sstevel@tonic-gate #include <ldap.h> 31*0Sstevel@tonic-gate #include <strings.h> 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include "nisdb_mt.h" 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #include "ldap_util.h" 36*0Sstevel@tonic-gate #include "ldap_val.h" 37*0Sstevel@tonic-gate #include "ldap_attr.h" 38*0Sstevel@tonic-gate #include "ldap_ldap.h" 39*0Sstevel@tonic-gate #include "ldap_nisplus.h" 40*0Sstevel@tonic-gate #include "ldap_ruleval.h" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate /* 44*0Sstevel@tonic-gate * Free an array of 'count' rule-value elements. 45*0Sstevel@tonic-gate */ 46*0Sstevel@tonic-gate void 47*0Sstevel@tonic-gate freeRuleValue(__nis_rule_value_t *rv, int count) { 48*0Sstevel@tonic-gate int n, i, j; 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate if (rv == 0) 51*0Sstevel@tonic-gate return; 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate for (n = 0; n < count; n++) { 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate if (rv[n].colName != 0) { 56*0Sstevel@tonic-gate for (i = 0; i < rv[n].numColumns; i++) { 57*0Sstevel@tonic-gate sfree(rv[n].colName[i]); 58*0Sstevel@tonic-gate } 59*0Sstevel@tonic-gate free(rv[n].colName); 60*0Sstevel@tonic-gate } 61*0Sstevel@tonic-gate if (rv[n].colVal != 0) { 62*0Sstevel@tonic-gate for (i = 0; i < rv[n].numColumns; i++) { 63*0Sstevel@tonic-gate for (j = 0; j < rv[n].colVal[i].numVals; j++) { 64*0Sstevel@tonic-gate sfree(rv[n].colVal[i].val[j].value); 65*0Sstevel@tonic-gate } 66*0Sstevel@tonic-gate if (rv[n].colVal[i].numVals > 0) 67*0Sstevel@tonic-gate sfree(rv[n].colVal[i].val); 68*0Sstevel@tonic-gate } 69*0Sstevel@tonic-gate free(rv[n].colVal); 70*0Sstevel@tonic-gate } 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate if (rv[n].attrName != 0) { 73*0Sstevel@tonic-gate for (i = 0; i < rv[n].numAttrs; i++) { 74*0Sstevel@tonic-gate sfree(rv[n].attrName[i]); 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate free(rv[n].attrName); 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate if (rv[n].attrVal != 0) { 79*0Sstevel@tonic-gate for (i = 0; i < rv[n].numAttrs; i++) { 80*0Sstevel@tonic-gate for (j = 0; j < rv[n].attrVal[i].numVals; 81*0Sstevel@tonic-gate j++) { 82*0Sstevel@tonic-gate sfree(rv[n].attrVal[i].val[j].value); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate if (rv[n].attrVal[i].numVals > 0) 85*0Sstevel@tonic-gate sfree(rv[n].attrVal[i].val); 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate free(rv[n].attrVal); 88*0Sstevel@tonic-gate } 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate } 91*0Sstevel@tonic-gate sfree(rv); 92*0Sstevel@tonic-gate } 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate /* 95*0Sstevel@tonic-gate * Return an array of 'count' __nis_rule_value_t elements, initialized 96*0Sstevel@tonic-gate * to be copies of 'rvIn' if supplied; empty otherwise. 97*0Sstevel@tonic-gate */ 98*0Sstevel@tonic-gate __nis_rule_value_t * 99*0Sstevel@tonic-gate initRuleValue(int count, __nis_rule_value_t *rvIn) { 100*0Sstevel@tonic-gate return (growRuleValue(0, count, 0, rvIn)); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate static const __nis_rule_value_t rvZero = {0}; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate /* 106*0Sstevel@tonic-gate * Grow 'old' from 'oldCount' to 'newCount' elements, initialize the 107*0Sstevel@tonic-gate * new portion to 'rvIn' (empty if not supplied), and return a pointer 108*0Sstevel@tonic-gate * to the result. Following a call to this function, the caller must 109*0Sstevel@tonic-gate * refer only to the returned array, not to 'old'. 110*0Sstevel@tonic-gate */ 111*0Sstevel@tonic-gate __nis_rule_value_t * 112*0Sstevel@tonic-gate growRuleValue(int oldCount, int newCount, __nis_rule_value_t *old, 113*0Sstevel@tonic-gate __nis_rule_value_t *rvIn) { 114*0Sstevel@tonic-gate __nis_rule_value_t *rv; 115*0Sstevel@tonic-gate int i, j; 116*0Sstevel@tonic-gate char *myself = "growRuleValue"; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate if (newCount <= 0 || newCount <= oldCount) 119*0Sstevel@tonic-gate return (old); 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate if (oldCount <= 0) { 122*0Sstevel@tonic-gate oldCount = 0; 123*0Sstevel@tonic-gate old = 0; 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate if (rvIn == 0) 127*0Sstevel@tonic-gate rvIn = (__nis_rule_value_t *)&rvZero; 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate rv = realloc(old, newCount * sizeof (rv[0])); 130*0Sstevel@tonic-gate if (rv == 0) { 131*0Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 132*0Sstevel@tonic-gate "%s: realloc(%d ((%d+%d)*%d)) => 0", 133*0Sstevel@tonic-gate myself, (oldCount+newCount) * sizeof (rv[0]), 134*0Sstevel@tonic-gate oldCount, newCount, sizeof (rv[0])); 135*0Sstevel@tonic-gate freeRuleValue(old, oldCount); 136*0Sstevel@tonic-gate return (0); 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate (void) memset(&rv[oldCount], 0, (newCount-oldCount)*sizeof (rv[0])); 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate for (i = oldCount; i < newCount; i++) { 142*0Sstevel@tonic-gate rv[i].numColumns = rvIn->numColumns; 143*0Sstevel@tonic-gate if (rv[i].numColumns > 0) { 144*0Sstevel@tonic-gate rv[i].colName = cloneName(rvIn->colName, 145*0Sstevel@tonic-gate rv[i].numColumns); 146*0Sstevel@tonic-gate rv[i].colVal = cloneValue(rvIn->colVal, 147*0Sstevel@tonic-gate rv[i].numColumns); 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate if (rv[i].numColumns > 0 && 150*0Sstevel@tonic-gate (rv[i].colName == 0 || rv[i].colVal == 0)) { 151*0Sstevel@tonic-gate freeRuleValue(rv, i); 152*0Sstevel@tonic-gate return (0); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate rv[i].numAttrs = rvIn->numAttrs; 155*0Sstevel@tonic-gate rv[i].attrName = cloneName(rvIn->attrName, rv[i].numAttrs); 156*0Sstevel@tonic-gate rv[i].attrVal = cloneValue(rvIn->attrVal, rv[i].numAttrs); 157*0Sstevel@tonic-gate if (rv[i].numAttrs > 0 && 158*0Sstevel@tonic-gate (rv[i].attrName == 0 || rv[i].attrVal == 0)) { 159*0Sstevel@tonic-gate freeRuleValue(rv, i); 160*0Sstevel@tonic-gate return (0); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate return (rv); 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate /* 168*0Sstevel@tonic-gate * Merge the source rule-value 's' into the target rule-value 't'. 169*0Sstevel@tonic-gate * If successful, unless 's' is a sub-set of 't', 't' will be changed 170*0Sstevel@tonic-gate * on exit, and will contain the values from 's' as well. 171*0Sstevel@tonic-gate */ 172*0Sstevel@tonic-gate int 173*0Sstevel@tonic-gate mergeRuleValue(__nis_rule_value_t *t, __nis_rule_value_t *s) { 174*0Sstevel@tonic-gate int i, j; 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate if (s == 0) 177*0Sstevel@tonic-gate return (0); 178*0Sstevel@tonic-gate else if (t == 0) 179*0Sstevel@tonic-gate return (-1); 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate for (i = 0; i < s->numColumns; i++) { 182*0Sstevel@tonic-gate for (j = 0; j < s->colVal[i].numVals; j++) { 183*0Sstevel@tonic-gate if (addCol2RuleValue(s->colVal[i].type, s->colName[i], 184*0Sstevel@tonic-gate s->colVal[i].val[j].value, 185*0Sstevel@tonic-gate s->colVal[i].val[j].length, 186*0Sstevel@tonic-gate t)) 187*0Sstevel@tonic-gate return (-1); 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate for (i = 0; i < s->numAttrs; i++) { 192*0Sstevel@tonic-gate for (j = 0; j < s->attrVal[i].numVals; j++) { 193*0Sstevel@tonic-gate if (addAttr2RuleValue(s->attrVal[i].type, 194*0Sstevel@tonic-gate s->attrName[i], 195*0Sstevel@tonic-gate s->attrVal[i].val[j].value, 196*0Sstevel@tonic-gate s->attrVal[i].val[j].length, 197*0Sstevel@tonic-gate t)) 198*0Sstevel@tonic-gate return (-1); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate return (0); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate static int 206*0Sstevel@tonic-gate addVal2RuleValue(char *msg, int caseSens, int snipNul, __nis_value_type_t type, 207*0Sstevel@tonic-gate char *name, void *value, int valueLen, 208*0Sstevel@tonic-gate int *numP, char ***inNameP, __nis_value_t **inValP) { 209*0Sstevel@tonic-gate int i, j, copyLen = valueLen; 210*0Sstevel@tonic-gate __nis_single_value_t *v; 211*0Sstevel@tonic-gate char **inName = *inNameP; 212*0Sstevel@tonic-gate __nis_value_t *inVal = *inValP; 213*0Sstevel@tonic-gate int num = *numP; 214*0Sstevel@tonic-gate int (*comp)(const char *s1, const char *s2); 215*0Sstevel@tonic-gate char *myself = "addVal2RuleValue"; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate /* Internal function, so assume arguments OK */ 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate if (msg == 0) 220*0Sstevel@tonic-gate msg = myself; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate /* Should we match the 'inName' value case sensitive or not ? */ 223*0Sstevel@tonic-gate if (caseSens) 224*0Sstevel@tonic-gate comp = strcmp; 225*0Sstevel@tonic-gate else 226*0Sstevel@tonic-gate comp = strcasecmp; 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate /* 229*0Sstevel@tonic-gate * String-valued NIS+ entries count the concluding NUL in the 230*0Sstevel@tonic-gate * length, while LDAP entries don't. In order to support this, 231*0Sstevel@tonic-gate * we implement the following for vt_string value types: 232*0Sstevel@tonic-gate * 233*0Sstevel@tonic-gate * If the last byte of the value isn't a NUL, add one to the 234*0Sstevel@tonic-gate * allocated length, so that there always is a NUL after the 235*0Sstevel@tonic-gate * value, making it safe to pass to strcmp() etc. 236*0Sstevel@tonic-gate * 237*0Sstevel@tonic-gate * If 'snipNul' is set (presumably meaning we're inserting a 238*0Sstevel@tonic-gate * value derived from a NIS+ entry), and the last byte of the 239*0Sstevel@tonic-gate * value already is a NUL, decrement the length to be copied by 240*0Sstevel@tonic-gate * one. This (a) doesn't count the NUL in the value length, but 241*0Sstevel@tonic-gate * (b) still leaves a NUL following the value. 242*0Sstevel@tonic-gate * 243*0Sstevel@tonic-gate * In N2L, for all cases we set 'copyLen' to the number of non-0 244*0Sstevel@tonic-gate * characters in 'value'. 245*0Sstevel@tonic-gate */ 246*0Sstevel@tonic-gate if (type == vt_string && valueLen > 0) { 247*0Sstevel@tonic-gate char *charval = value; 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate if (charval[valueLen-1] != '\0') 250*0Sstevel@tonic-gate valueLen += 1; 251*0Sstevel@tonic-gate else if (yp2ldap || snipNul) 252*0Sstevel@tonic-gate copyLen -= 1; 253*0Sstevel@tonic-gate } else if (valueLen == 0) { 254*0Sstevel@tonic-gate /* 255*0Sstevel@tonic-gate * If the 'value' pointer is non-NULL, we create a zero- 256*0Sstevel@tonic-gate * length value with one byte allocated. This takes care 257*0Sstevel@tonic-gate * of empty strings. 258*0Sstevel@tonic-gate */ 259*0Sstevel@tonic-gate valueLen += 1; 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /* If we already have values for this attribute, add another one */ 263*0Sstevel@tonic-gate for (i = 0; i < num; i++) { 264*0Sstevel@tonic-gate if ((*comp)(inName[i], name) == 0) { 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate /* 267*0Sstevel@tonic-gate * Our caller often doesn't know the type of the 268*0Sstevel@tonic-gate * value; this happens because the type (vt_string 269*0Sstevel@tonic-gate * or vt_ber) is determined by the format in the 270*0Sstevel@tonic-gate * rule sets, and we may be invoked as a preparation 271*0Sstevel@tonic-gate * for evaluating the rules. Hence, we only use the 272*0Sstevel@tonic-gate * supplied 'type' if we need to create a value. 273*0Sstevel@tonic-gate * Otherwise, we accept mixed types. 274*0Sstevel@tonic-gate * 275*0Sstevel@tonic-gate * Strings are OK in any case, since we always make 276*0Sstevel@tonic-gate * sure to have a zero byte at the end of any value, 277*0Sstevel@tonic-gate * whatever the type. 278*0Sstevel@tonic-gate */ 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate if (inVal[i].numVals < 0) { 281*0Sstevel@tonic-gate /* 282*0Sstevel@tonic-gate * Used to indicate deletion of attribute, 283*0Sstevel@tonic-gate * so we honor that and don't add a value. 284*0Sstevel@tonic-gate */ 285*0Sstevel@tonic-gate return (0); 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* 289*0Sstevel@tonic-gate * If 'value' is NULL, we should delete, so 290*0Sstevel@tonic-gate * remove any existing values, and set the 291*0Sstevel@tonic-gate * 'numVals' field to -1. 292*0Sstevel@tonic-gate */ 293*0Sstevel@tonic-gate if (value == 0) { 294*0Sstevel@tonic-gate for (j = 0; j < inVal[i].numVals; j++) { 295*0Sstevel@tonic-gate sfree(inVal[i].val[j].value); 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate sfree(inVal[i].val); 298*0Sstevel@tonic-gate inVal[i].val = 0; 299*0Sstevel@tonic-gate inVal[i].numVals = -1; 300*0Sstevel@tonic-gate return (0); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate /* Is the value a duplicate ? */ 304*0Sstevel@tonic-gate for (j = 0; j < inVal[i].numVals; j++) { 305*0Sstevel@tonic-gate if (copyLen == inVal[i].val[j].length && 306*0Sstevel@tonic-gate memcmp(value, inVal[i].val[j].value, 307*0Sstevel@tonic-gate copyLen) == 0) { 308*0Sstevel@tonic-gate break; 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate if (j < inVal[i].numVals) 312*0Sstevel@tonic-gate return (0); 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* Not a duplicate, so add the name/value pair */ 315*0Sstevel@tonic-gate v = realloc(inVal[i].val, 316*0Sstevel@tonic-gate (inVal[i].numVals+1) * 317*0Sstevel@tonic-gate sizeof (inVal[i].val[0])); 318*0Sstevel@tonic-gate if (v == 0) 319*0Sstevel@tonic-gate return (-1); 320*0Sstevel@tonic-gate inVal[i].val = v; 321*0Sstevel@tonic-gate v[inVal[i].numVals].length = copyLen; 322*0Sstevel@tonic-gate v[inVal[i].numVals].value = am(msg, valueLen); 323*0Sstevel@tonic-gate if (v[inVal[i].numVals].value == 0 && 324*0Sstevel@tonic-gate value != 0) { 325*0Sstevel@tonic-gate sfree(v); 326*0Sstevel@tonic-gate return (-1); 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate memcpy(v[inVal[i].numVals].value, value, copyLen); 329*0Sstevel@tonic-gate inVal[i].numVals++; 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate return (0); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* No previous value for this attribute */ 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate /* 338*0Sstevel@tonic-gate * value == 0 means deletion, in which case we create a 339*0Sstevel@tonic-gate * __nis_value_t with the numVals field set to -1. 340*0Sstevel@tonic-gate */ 341*0Sstevel@tonic-gate if (value != 0) { 342*0Sstevel@tonic-gate if ((v = am(msg, sizeof (*v))) == 0) 343*0Sstevel@tonic-gate return (-1); 344*0Sstevel@tonic-gate v->length = copyLen; 345*0Sstevel@tonic-gate v->value = am(msg, valueLen); 346*0Sstevel@tonic-gate if (v->value == 0 && value != 0) { 347*0Sstevel@tonic-gate sfree(v); 348*0Sstevel@tonic-gate return (-1); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate memcpy(v->value, value, copyLen); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate inVal = realloc(inVal, (num+1)*sizeof (inVal[0])); 354*0Sstevel@tonic-gate if (inVal == 0) { 355*0Sstevel@tonic-gate if (value != 0) { 356*0Sstevel@tonic-gate sfree(v->value); 357*0Sstevel@tonic-gate sfree(v); 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate return (-1); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate *inValP = inVal; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate inName = realloc(inName, 364*0Sstevel@tonic-gate (num+1)*sizeof (inName[0])); 365*0Sstevel@tonic-gate if (inName == 0 || (inName[num] = 366*0Sstevel@tonic-gate sdup(msg, T, name)) == 0) { 367*0Sstevel@tonic-gate sfree(v->value); 368*0Sstevel@tonic-gate sfree(v); 369*0Sstevel@tonic-gate return (-1); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate *inNameP = inName; 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate inVal[num].type = type; 374*0Sstevel@tonic-gate inVal[num].repeat = 0; 375*0Sstevel@tonic-gate if (value != 0) { 376*0Sstevel@tonic-gate inVal[num].numVals = 1; 377*0Sstevel@tonic-gate inVal[num].val = v; 378*0Sstevel@tonic-gate } else { 379*0Sstevel@tonic-gate inVal[num].numVals = -1; 380*0Sstevel@tonic-gate inVal[num].val = 0; 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate *numP += 1; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate return (0); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate int 389*0Sstevel@tonic-gate addAttr2RuleValue(__nis_value_type_t type, char *name, void *value, 390*0Sstevel@tonic-gate int valueLen, __nis_rule_value_t *rv) { 391*0Sstevel@tonic-gate char *myself = "addAttr2RuleValue"; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate if (name == 0 || rv == 0) 394*0Sstevel@tonic-gate return (-1); 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate return (addVal2RuleValue(myself, 0, 0, type, name, value, valueLen, 397*0Sstevel@tonic-gate &rv->numAttrs, &rv->attrName, &rv->attrVal)); 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate int 401*0Sstevel@tonic-gate addSAttr2RuleValue(char *name, char *value, __nis_rule_value_t *rv) { 402*0Sstevel@tonic-gate return (addAttr2RuleValue(vt_string, name, value, slen(value), rv)); 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate int 406*0Sstevel@tonic-gate addCol2RuleValue(__nis_value_type_t type, char *name, void *value, 407*0Sstevel@tonic-gate int valueLen, __nis_rule_value_t *rv) { 408*0Sstevel@tonic-gate char *myself = "addCol2RuleValue"; 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate if (name == 0 || rv == 0) 411*0Sstevel@tonic-gate return (-1); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate return (addVal2RuleValue(myself, 1, 1, type, name, value, valueLen, 414*0Sstevel@tonic-gate &rv->numColumns, &rv->colName, &rv->colVal)); 415*0Sstevel@tonic-gate } 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate int 418*0Sstevel@tonic-gate addSCol2RuleValue(char *name, char *value, __nis_rule_value_t *rv) { 419*0Sstevel@tonic-gate return (addCol2RuleValue(vt_string, name, value, slen(value), rv)); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate /* 423*0Sstevel@tonic-gate * Given a table mapping, a NIS+ DB query, and (optionally) an existing 424*0Sstevel@tonic-gate * and compatible __nis_rule_value_t, return a new __nis_rule_value_t 425*0Sstevel@tonic-gate * with the values from the query added. 426*0Sstevel@tonic-gate */ 427*0Sstevel@tonic-gate __nis_rule_value_t * 428*0Sstevel@tonic-gate buildNisPlusRuleValue(__nis_table_mapping_t *t, db_query *q, 429*0Sstevel@tonic-gate __nis_rule_value_t *rv) { 430*0Sstevel@tonic-gate int i; 431*0Sstevel@tonic-gate __nis_single_value_t *sv; 432*0Sstevel@tonic-gate char *myself = "buildNisPlusRuleValue"; 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate if (t == 0 || q == 0) 435*0Sstevel@tonic-gate return (0); 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate rv = initRuleValue(1, rv); 438*0Sstevel@tonic-gate if (rv == 0) 439*0Sstevel@tonic-gate return (0); 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 442*0Sstevel@tonic-gate int ic; 443*0Sstevel@tonic-gate int iv, v, dup; 444*0Sstevel@tonic-gate int len; 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate /* Ignore out-of-range column index */ 447*0Sstevel@tonic-gate if (q->components.components_val[i].which_index >= 448*0Sstevel@tonic-gate t->numColumns) 449*0Sstevel@tonic-gate continue; 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate /* 452*0Sstevel@tonic-gate * Add the query value. A NULL value indicates deletion, 453*0Sstevel@tonic-gate * but addCol2RuleValue() takes care of that for us. 454*0Sstevel@tonic-gate */ 455*0Sstevel@tonic-gate if (addCol2RuleValue(vt_string, 456*0Sstevel@tonic-gate t->column[q->components.components_val[i]. 457*0Sstevel@tonic-gate which_index], 458*0Sstevel@tonic-gate q->components.components_val[i].index_value-> 459*0Sstevel@tonic-gate itemvalue.itemvalue_val, 460*0Sstevel@tonic-gate q->components.components_val[i].index_value-> 461*0Sstevel@tonic-gate itemvalue.itemvalue_len, rv) != 0) { 462*0Sstevel@tonic-gate freeRuleValue(rv, 1); 463*0Sstevel@tonic-gate rv = 0; 464*0Sstevel@tonic-gate break; 465*0Sstevel@tonic-gate } 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate return (rv); 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate /* 473*0Sstevel@tonic-gate * Given a LHS rule 'rl', return an array containing the item names, 474*0Sstevel@tonic-gate * and the number of elements in the array in '*numItems'. 475*0Sstevel@tonic-gate * 476*0Sstevel@tonic-gate * If there are 'me_match' __nis_mapping_element_t's, we use the 477*0Sstevel@tonic-gate * supplied '*rval' (if any) to derive values for the items in 478*0Sstevel@tonic-gate * the 'me_match', and add the values thus derived to '*rval' (in 479*0Sstevel@tonic-gate * which case the '*rval' pointer will change; the old '*rval' 480*0Sstevel@tonic-gate * is deleted). 481*0Sstevel@tonic-gate */ 482*0Sstevel@tonic-gate __nis_mapping_item_t * 483*0Sstevel@tonic-gate buildLvalue(__nis_mapping_rlhs_t *rl, __nis_value_t **rval, int *numItems) { 484*0Sstevel@tonic-gate __nis_value_t *val, *r; 485*0Sstevel@tonic-gate __nis_mapping_item_t *item = 0; 486*0Sstevel@tonic-gate int i, n, ni = 0, nv = 0; 487*0Sstevel@tonic-gate int repeat = 0; 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate if (rl == 0) 490*0Sstevel@tonic-gate return (0); 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate if (rval != 0) { 493*0Sstevel@tonic-gate r = *rval; 494*0Sstevel@tonic-gate repeat = r->repeat; 495*0Sstevel@tonic-gate } else 496*0Sstevel@tonic-gate r = 0; 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate /* If there is more than one element, we concatenate the items */ 499*0Sstevel@tonic-gate for (i = 0; i < rl->numElements; i++) { 500*0Sstevel@tonic-gate __nis_mapping_element_t *e = &rl->element[i]; 501*0Sstevel@tonic-gate __nis_mapping_item_t *olditem, *tmpitem = 0; 502*0Sstevel@tonic-gate __nis_value_t **tmp; 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate switch (e->type) { 505*0Sstevel@tonic-gate case me_item: 506*0Sstevel@tonic-gate tmpitem = cloneItem(&e->element.item); 507*0Sstevel@tonic-gate break; 508*0Sstevel@tonic-gate case me_match: 509*0Sstevel@tonic-gate /* 510*0Sstevel@tonic-gate * Obtain values for the items in the 'me_match' 511*0Sstevel@tonic-gate * element. 512*0Sstevel@tonic-gate */ 513*0Sstevel@tonic-gate tmp = matchMappingItem(e->element.match.fmt, r, &nv, 514*0Sstevel@tonic-gate 0, 0); 515*0Sstevel@tonic-gate if (tmp != 0) { 516*0Sstevel@tonic-gate freeValue(r, 1); 517*0Sstevel@tonic-gate val = 0; 518*0Sstevel@tonic-gate for (n = 0; n < nv; n++) { 519*0Sstevel@tonic-gate r = concatenateValues(val, tmp[n]); 520*0Sstevel@tonic-gate freeValue(val, 1); 521*0Sstevel@tonic-gate freeValue(tmp[n], 1); 522*0Sstevel@tonic-gate val = r; 523*0Sstevel@tonic-gate if (val == 0) { 524*0Sstevel@tonic-gate for (n++; n < nv; n++) { 525*0Sstevel@tonic-gate freeValue(tmp[n], 1); 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate break; 528*0Sstevel@tonic-gate } 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate free(tmp); 531*0Sstevel@tonic-gate if (rval != 0) { 532*0Sstevel@tonic-gate if (repeat && val != 0) 533*0Sstevel@tonic-gate val->repeat = repeat; 534*0Sstevel@tonic-gate *rval = val; 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate for (n = 0; n < e->element.match.numItems; 537*0Sstevel@tonic-gate n++) { 538*0Sstevel@tonic-gate olditem = item; 539*0Sstevel@tonic-gate item = concatenateMappingItem(item, ni, 540*0Sstevel@tonic-gate &e->element.match.item[n]); 541*0Sstevel@tonic-gate freeMappingItem(olditem, ni); 542*0Sstevel@tonic-gate if (item == 0) { 543*0Sstevel@tonic-gate ni = 0; 544*0Sstevel@tonic-gate break; 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate ni++; 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate break; 550*0Sstevel@tonic-gate case me_print: 551*0Sstevel@tonic-gate case me_split: 552*0Sstevel@tonic-gate case me_extract: 553*0Sstevel@tonic-gate default: 554*0Sstevel@tonic-gate /* These shouldn't show up on the LHS; ignore */ 555*0Sstevel@tonic-gate break; 556*0Sstevel@tonic-gate } 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate if (tmpitem != 0) { 559*0Sstevel@tonic-gate olditem = item; 560*0Sstevel@tonic-gate item = concatenateMappingItem(item, ni, tmpitem); 561*0Sstevel@tonic-gate freeMappingItem(olditem, ni); 562*0Sstevel@tonic-gate freeMappingItem(tmpitem, 1); 563*0Sstevel@tonic-gate ni++; 564*0Sstevel@tonic-gate if (item == 0) { 565*0Sstevel@tonic-gate ni = 0; 566*0Sstevel@tonic-gate break; 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate } 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate if (numItems != 0) 572*0Sstevel@tonic-gate *numItems = ni; 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate return (item); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate __nis_value_t * 578*0Sstevel@tonic-gate buildRvalue(__nis_mapping_rlhs_t *rl, __nis_mapping_item_type_t native, 579*0Sstevel@tonic-gate __nis_rule_value_t *rv, int *stat) { 580*0Sstevel@tonic-gate __nis_value_t *val, *vold = 0, *vnew; 581*0Sstevel@tonic-gate int i; 582*0Sstevel@tonic-gate char *myself = "buildRvalue"; 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate if (rl == 0 || rl->numElements <= 0) { 585*0Sstevel@tonic-gate /* 586*0Sstevel@tonic-gate * No RHS indicates deletion, as does a __nis_value_t 587*0Sstevel@tonic-gate * with numVals == -1, so we return such a creature. 588*0Sstevel@tonic-gate */ 589*0Sstevel@tonic-gate val = am(myself, sizeof (*val)); 590*0Sstevel@tonic-gate if (val != 0) { 591*0Sstevel@tonic-gate val->type = vt_string; 592*0Sstevel@tonic-gate val->numVals = -1; 593*0Sstevel@tonic-gate } 594*0Sstevel@tonic-gate return (val); 595*0Sstevel@tonic-gate } 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate /* If there is more than one element, we concatenate the values */ 598*0Sstevel@tonic-gate for (i = 0; i < rl->numElements; i++) { 599*0Sstevel@tonic-gate vnew = getMappingElement(&rl->element[i], native, rv, stat); 600*0Sstevel@tonic-gate val = concatenateValues(vold, vnew); 601*0Sstevel@tonic-gate freeValue(vnew, 1); 602*0Sstevel@tonic-gate freeValue(vold, 1); 603*0Sstevel@tonic-gate vold = val; 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate return (val); 606*0Sstevel@tonic-gate } 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate /* 609*0Sstevel@tonic-gate * Derive values for the LDAP attributes specified by the rule 'r', 610*0Sstevel@tonic-gate * and add them to the rule-value 'rv'. 611*0Sstevel@tonic-gate * 612*0Sstevel@tonic-gate * If 'doAssign' is set, out-of-context assignments are performed, 613*0Sstevel@tonic-gate * otherwise not. 614*0Sstevel@tonic-gate */ 615*0Sstevel@tonic-gate __nis_rule_value_t * 616*0Sstevel@tonic-gate addLdapRuleValue(__nis_table_mapping_t *t, 617*0Sstevel@tonic-gate __nis_mapping_rule_t *r, 618*0Sstevel@tonic-gate __nis_mapping_item_type_t lnative, 619*0Sstevel@tonic-gate __nis_mapping_item_type_t rnative, 620*0Sstevel@tonic-gate __nis_rule_value_t *rv, 621*0Sstevel@tonic-gate int doAssign, int *stat) { 622*0Sstevel@tonic-gate int i, j; 623*0Sstevel@tonic-gate char **new; 624*0Sstevel@tonic-gate __nis_value_t *rval, *lval; 625*0Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 626*0Sstevel@tonic-gate __nis_mapping_item_t *litem; 627*0Sstevel@tonic-gate int numItems; 628*0Sstevel@tonic-gate char **dn = 0; 629*0Sstevel@tonic-gate int numDN = 0; 630*0Sstevel@tonic-gate char *myself = "addLdapRuleValue"; 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate /* Do we have the required values ? */ 634*0Sstevel@tonic-gate if (rv == 0) 635*0Sstevel@tonic-gate return (0); 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate /* 638*0Sstevel@tonic-gate * Establish appropriate search base. For rnative == mit_nisplus, 639*0Sstevel@tonic-gate * we're deriving LDAP attribute values from NIS+ columns; in other 640*0Sstevel@tonic-gate * words, we're writing to LDAP, and should use the write.base value. 641*0Sstevel@tonic-gate */ 642*0Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = (rnative == mit_nisplus) ? 643*0Sstevel@tonic-gate t->objectDN->write.base : t->objectDN->read.base; 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate /* Set escapeFlag if LHS is "dn" to escape special chars */ 646*0Sstevel@tonic-gate if (yp2ldap && r->lhs.numElements == 1 && 647*0Sstevel@tonic-gate r->lhs.element->type == me_item && 648*0Sstevel@tonic-gate r->lhs.element->element.item.type == mit_ldap && 649*0Sstevel@tonic-gate strcasecmp(r->lhs.element->element.item.name, "dn") == 0) { 650*0Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '1'; 651*0Sstevel@tonic-gate } 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate /* Build the RHS value */ 654*0Sstevel@tonic-gate rval = buildRvalue(&r->rhs, rnative, rv, stat); 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* Reset escapeFlag */ 657*0Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '\0'; 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate if (rval == 0) 660*0Sstevel@tonic-gate return (rv); 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate /* 663*0Sstevel@tonic-gate * Special case: If we got no value for the RHS (presumably because 664*0Sstevel@tonic-gate * we're missing one or more item values), we don't produce an lval. 665*0Sstevel@tonic-gate * Note that this isn't the same thing as an empty value, which we 666*0Sstevel@tonic-gate * faithfully try to transmit to LDAP. 667*0Sstevel@tonic-gate */ 668*0Sstevel@tonic-gate if (rval->numVals == 1 && rval->val[0].value == 0) { 669*0Sstevel@tonic-gate freeValue(rval, 1); 670*0Sstevel@tonic-gate return (rv); 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate /* Obtain the LHS item names */ 674*0Sstevel@tonic-gate litem = buildLvalue(&r->lhs, &rval, &numItems); 675*0Sstevel@tonic-gate if (litem == 0) { 676*0Sstevel@tonic-gate freeValue(rval, 1); 677*0Sstevel@tonic-gate return (rv); 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate /* Get string representations of the LHS item names */ 681*0Sstevel@tonic-gate lval = 0; 682*0Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 683*0Sstevel@tonic-gate __nis_value_t *tmpval, *old; 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate tmpval = getMappingItem(&litem[i], lnative, 0, 0, NULL); 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate /* 688*0Sstevel@tonic-gate * If the LHS item is out-of-context, we do the 689*0Sstevel@tonic-gate * assignment right here. 690*0Sstevel@tonic-gate */ 691*0Sstevel@tonic-gate if (doAssign && litem[i].type == mit_nisplus) { 692*0Sstevel@tonic-gate int err; 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate err = storeNisPlus(&litem[i], i, numItems, 695*0Sstevel@tonic-gate rv, t->objName, rval); 696*0Sstevel@tonic-gate if (err != NIS_SUCCESS) { 697*0Sstevel@tonic-gate char *iname = "<unknown>"; 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate if (tmpval != 0 && 700*0Sstevel@tonic-gate tmpval->numVals == 1) 701*0Sstevel@tonic-gate iname = tmpval->val[0].value; 702*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 703*0Sstevel@tonic-gate "%s: NIS+ store \"%s\": %s", 704*0Sstevel@tonic-gate myself, iname, 705*0Sstevel@tonic-gate nis_sperrno(err)); 706*0Sstevel@tonic-gate } 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate freeValue(tmpval, 1); 709*0Sstevel@tonic-gate continue; 710*0Sstevel@tonic-gate } else if (doAssign && litem[i].type == mit_ldap && 711*0Sstevel@tonic-gate litem[i].searchSpec.triple.scope != 712*0Sstevel@tonic-gate LDAP_SCOPE_UNKNOWN && 713*0Sstevel@tonic-gate slen(litem[i].searchSpec.triple.base) > 0 && 714*0Sstevel@tonic-gate (slen(litem[i].searchSpec.triple.attrs) > 0 || 715*0Sstevel@tonic-gate litem[i].searchSpec.triple.element != 0)) { 716*0Sstevel@tonic-gate int stat; 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate if (dn == 0) 719*0Sstevel@tonic-gate dn = findDNs(myself, rv, 1, 720*0Sstevel@tonic-gate t->objectDN->write.base, 721*0Sstevel@tonic-gate &numDN); 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate stat = storeLDAP(&litem[i], i, numItems, rval, 724*0Sstevel@tonic-gate t->objectDN, dn, numDN); 725*0Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 726*0Sstevel@tonic-gate char *iname = "<unknown>"; 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate if (tmpval != 0 && 729*0Sstevel@tonic-gate tmpval->numVals == 1) 730*0Sstevel@tonic-gate iname = tmpval->val[0].value; 731*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 732*0Sstevel@tonic-gate "%s: LDAP store \"%s\": %s", 733*0Sstevel@tonic-gate myself, iname, 734*0Sstevel@tonic-gate ldap_err2string(stat)); 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate freeValue(tmpval, 1); 738*0Sstevel@tonic-gate continue; 739*0Sstevel@tonic-gate } 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate old = lval; 742*0Sstevel@tonic-gate lval = concatenateValues(old, tmpval); 743*0Sstevel@tonic-gate freeValue(tmpval, 1); 744*0Sstevel@tonic-gate freeValue(old, 1); 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate /* Don't need the LHS items themselves anymore */ 748*0Sstevel@tonic-gate freeMappingItem(litem, numItems); 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate /* 751*0Sstevel@tonic-gate * If we don't have an 'lval' (probably because all litem[i]:s 752*0Sstevel@tonic-gate * were out-of-context assignments), we're done. 753*0Sstevel@tonic-gate */ 754*0Sstevel@tonic-gate if (lval == 0 || lval->numVals <= 0) { 755*0Sstevel@tonic-gate freeValue(lval, 1); 756*0Sstevel@tonic-gate freeValue(rval, 1); 757*0Sstevel@tonic-gate return (rv); 758*0Sstevel@tonic-gate } 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate for (i = 0, j = 0; i < lval->numVals; i++) { 761*0Sstevel@tonic-gate /* Special case: rval->numVals < 0 means deletion */ 762*0Sstevel@tonic-gate if (rval->numVals < 0) { 763*0Sstevel@tonic-gate (void) addAttr2RuleValue(rval->type, 764*0Sstevel@tonic-gate lval->val[i].value, 0, 0, rv); 765*0Sstevel@tonic-gate continue; 766*0Sstevel@tonic-gate } 767*0Sstevel@tonic-gate /* If we're out of values, repeat the last one */ 768*0Sstevel@tonic-gate if (j >= rval->numVals) 769*0Sstevel@tonic-gate j = (rval->numVals > 0) ? rval->numVals-1 : 0; 770*0Sstevel@tonic-gate for (0; j < rval->numVals; j++) { 771*0Sstevel@tonic-gate /* 772*0Sstevel@tonic-gate * If this is the 'dn', and the value ends in a 773*0Sstevel@tonic-gate * comma, append the appropriate search base. 774*0Sstevel@tonic-gate */ 775*0Sstevel@tonic-gate if (strcasecmp("dn", lval->val[i].value) == 0 && 776*0Sstevel@tonic-gate lastChar(&rval->val[j]) == ',' && 777*0Sstevel@tonic-gate t->objectDN->write.scope != 778*0Sstevel@tonic-gate LDAP_SCOPE_UNKNOWN) { 779*0Sstevel@tonic-gate void *nval; 780*0Sstevel@tonic-gate int nlen = -1; 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate nval = appendString2SingleVal( 783*0Sstevel@tonic-gate t->objectDN->write.base, &rval->val[j], 784*0Sstevel@tonic-gate &nlen); 785*0Sstevel@tonic-gate if (nval != 0 && nlen >= 0) { 786*0Sstevel@tonic-gate sfree(rval->val[j].value); 787*0Sstevel@tonic-gate rval->val[j].value = nval; 788*0Sstevel@tonic-gate rval->val[j].length = nlen; 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate (void) addAttr2RuleValue(rval->type, 792*0Sstevel@tonic-gate lval->val[i].value, rval->val[j].value, 793*0Sstevel@tonic-gate rval->val[j].length, rv); 794*0Sstevel@tonic-gate /* 795*0Sstevel@tonic-gate * If the lval is multi-valued, go on to the 796*0Sstevel@tonic-gate * other values; otherwise, quit (but increment 797*0Sstevel@tonic-gate * the 'rval' value index). 798*0Sstevel@tonic-gate */ 799*0Sstevel@tonic-gate if (!lval->repeat) { 800*0Sstevel@tonic-gate j++; 801*0Sstevel@tonic-gate break; 802*0Sstevel@tonic-gate } 803*0Sstevel@tonic-gate } 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate /* Clean up */ 807*0Sstevel@tonic-gate freeValue(lval, 1); 808*0Sstevel@tonic-gate freeValue(rval, 1); 809*0Sstevel@tonic-gate 810*0Sstevel@tonic-gate return (rv); 811*0Sstevel@tonic-gate } 812*0Sstevel@tonic-gate 813*0Sstevel@tonic-gate /* 814*0Sstevel@tonic-gate * Remove the indicated attribute, and any values for it, from the 815*0Sstevel@tonic-gate * rule-value. 816*0Sstevel@tonic-gate */ 817*0Sstevel@tonic-gate void 818*0Sstevel@tonic-gate delAttrFromRuleValue(__nis_rule_value_t *rv, char *attrName) { 819*0Sstevel@tonic-gate int i; 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate if (rv == 0 || attrName == 0) 822*0Sstevel@tonic-gate return; 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate for (i = 0; i < rv->numAttrs; i++) { 825*0Sstevel@tonic-gate if (strcasecmp(attrName, rv->attrName[i]) == 0) { 826*0Sstevel@tonic-gate int j; 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate for (j = 0; j < rv->attrVal[i].numVals; j++) 829*0Sstevel@tonic-gate sfree(rv->attrVal[i].val[j].value); 830*0Sstevel@tonic-gate if (rv->attrVal[i].numVals > 0) 831*0Sstevel@tonic-gate sfree(rv->attrVal[i].val); 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate sfree(rv->attrName[i]); 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate /* Move up the rest of the attribute names/values */ 836*0Sstevel@tonic-gate for (j = i+1; j < rv->numAttrs; j++) { 837*0Sstevel@tonic-gate rv->attrName[j-1] = rv->attrName[j]; 838*0Sstevel@tonic-gate rv->attrVal[j-1] = rv->attrVal[j]; 839*0Sstevel@tonic-gate } 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate rv->numAttrs -= 1; 842*0Sstevel@tonic-gate 843*0Sstevel@tonic-gate break; 844*0Sstevel@tonic-gate } 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate } 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate /* 849*0Sstevel@tonic-gate * Remove the indicated column, and any values for it, from the 850*0Sstevel@tonic-gate * rule-value. 851*0Sstevel@tonic-gate */ 852*0Sstevel@tonic-gate void 853*0Sstevel@tonic-gate delColFromRuleValue(__nis_rule_value_t *rv, char *colName) { 854*0Sstevel@tonic-gate int i; 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate if (rv == 0 || colName == 0) 857*0Sstevel@tonic-gate return; 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 860*0Sstevel@tonic-gate if (strcmp(colName, rv->colName[i]) == 0) { 861*0Sstevel@tonic-gate int j; 862*0Sstevel@tonic-gate 863*0Sstevel@tonic-gate for (j = 0; j < rv->colVal[i].numVals; j++) 864*0Sstevel@tonic-gate sfree(rv->colVal[i].val[j].value); 865*0Sstevel@tonic-gate if (rv->colVal[i].numVals > 0) 866*0Sstevel@tonic-gate sfree(rv->colVal[i].val); 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate sfree(rv->colName[i]); 869*0Sstevel@tonic-gate 870*0Sstevel@tonic-gate /* Move up the rest of the column names/values */ 871*0Sstevel@tonic-gate for (j = i+1; j < rv->numColumns; j++) { 872*0Sstevel@tonic-gate rv->colName[j-1] = rv->colName[j]; 873*0Sstevel@tonic-gate rv->colVal[j-1] = rv->colVal[j]; 874*0Sstevel@tonic-gate } 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate rv->numColumns -= 1; 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate break; 879*0Sstevel@tonic-gate } 880*0Sstevel@tonic-gate } 881*0Sstevel@tonic-gate } 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate /* 884*0Sstevel@tonic-gate * Add the write-mode object classes specified by 'objClassAttrs' to the 885*0Sstevel@tonic-gate * rule-value 'rv'. 886*0Sstevel@tonic-gate * If there's an error, 'rv' is deleted, and NULL returned. 887*0Sstevel@tonic-gate */ 888*0Sstevel@tonic-gate __nis_rule_value_t * 889*0Sstevel@tonic-gate addObjectClasses(__nis_rule_value_t *rv, char *objClassAttrs) { 890*0Sstevel@tonic-gate char *filter = 0, **fc = 0; 891*0Sstevel@tonic-gate int i, nfc = 0; 892*0Sstevel@tonic-gate 893*0Sstevel@tonic-gate /* 894*0Sstevel@tonic-gate * Expect to only use this for existing rule-values, so rv == 0 is 895*0Sstevel@tonic-gate * an error. 896*0Sstevel@tonic-gate */ 897*0Sstevel@tonic-gate if (rv == 0) 898*0Sstevel@tonic-gate return (0); 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate /* 901*0Sstevel@tonic-gate * If 'objClassAttrs' is NULL, we trivially have nothing to do. 902*0Sstevel@tonic-gate * Assume the caller knows what it's doing, and return success. 903*0Sstevel@tonic-gate */ 904*0Sstevel@tonic-gate if (objClassAttrs == 0) 905*0Sstevel@tonic-gate return (rv); 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate /* 908*0Sstevel@tonic-gate * Make an AND-filter of the object classes, and split into 909*0Sstevel@tonic-gate * components. (Yes, this is a bit round-about, but leverages 910*0Sstevel@tonic-gate * existing functions.) 911*0Sstevel@tonic-gate */ 912*0Sstevel@tonic-gate filter = makeFilter(objClassAttrs); 913*0Sstevel@tonic-gate if (filter == 0) { 914*0Sstevel@tonic-gate freeRuleValue(rv, 1); 915*0Sstevel@tonic-gate return (0); 916*0Sstevel@tonic-gate } 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate fc = makeFilterComp(filter, &nfc); 919*0Sstevel@tonic-gate if (fc == 0 || nfc <= 0) { 920*0Sstevel@tonic-gate free(filter); 921*0Sstevel@tonic-gate freeRuleValue(rv, 1); 922*0Sstevel@tonic-gate return (0); 923*0Sstevel@tonic-gate } 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate /* Add the objectClass attributes to the rule-value */ 926*0Sstevel@tonic-gate for (i = 0; i < nfc; i++) { 927*0Sstevel@tonic-gate char *name, *value; 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate name = fc[i]; 930*0Sstevel@tonic-gate /* Skip if not of the "name=value" form */ 931*0Sstevel@tonic-gate if ((value = strchr(name, '=')) == 0) 932*0Sstevel@tonic-gate continue; 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate *value = '\0'; 935*0Sstevel@tonic-gate value++; 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate /* Skip if the attribute name isn't "objectClass" */ 938*0Sstevel@tonic-gate if (strcasecmp("objectClass", name) != 0) 939*0Sstevel@tonic-gate continue; 940*0Sstevel@tonic-gate 941*0Sstevel@tonic-gate if (addSAttr2RuleValue(name, value, rv) != 0) { 942*0Sstevel@tonic-gate free(filter); 943*0Sstevel@tonic-gate freeFilterComp(fc, nfc); 944*0Sstevel@tonic-gate freeRuleValue(rv, 1); 945*0Sstevel@tonic-gate return (0); 946*0Sstevel@tonic-gate } 947*0Sstevel@tonic-gate } 948*0Sstevel@tonic-gate 949*0Sstevel@tonic-gate free(filter); 950*0Sstevel@tonic-gate freeFilterComp(fc, nfc); 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate return (rv); 953*0Sstevel@tonic-gate } 954*0Sstevel@tonic-gate 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate static char * 957*0Sstevel@tonic-gate valString(__nis_value_t *val) { 958*0Sstevel@tonic-gate int i; 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate if (val == 0 || val->type != vt_string) 961*0Sstevel@tonic-gate return (0); 962*0Sstevel@tonic-gate 963*0Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 964*0Sstevel@tonic-gate /* Look for a non-NULL, non-zero length value */ 965*0Sstevel@tonic-gate if (val->val[i].value != 0 && val->val[i].length > 0) { 966*0Sstevel@tonic-gate char *v = val->val[i].value; 967*0Sstevel@tonic-gate 968*0Sstevel@tonic-gate /* 969*0Sstevel@tonic-gate * Check that there's a NUL at the end. True, 970*0Sstevel@tonic-gate * if there isn't, we may be looking beyond 971*0Sstevel@tonic-gate * allocated memory. However, we would have done 972*0Sstevel@tonic-gate * so in any case when the supposed string was 973*0Sstevel@tonic-gate * traversed (printed, etc.), very possibly by 974*0Sstevel@tonic-gate * a lot more than one byte. So, it's better to 975*0Sstevel@tonic-gate * take a small risk here than a large one later. 976*0Sstevel@tonic-gate */ 977*0Sstevel@tonic-gate if (v[val->val[i].length-1] == '\0' || 978*0Sstevel@tonic-gate v[val->val[i].length] == '\0') 979*0Sstevel@tonic-gate return (v); 980*0Sstevel@tonic-gate } 981*0Sstevel@tonic-gate } 982*0Sstevel@tonic-gate 983*0Sstevel@tonic-gate return (0); 984*0Sstevel@tonic-gate } 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate char * 987*0Sstevel@tonic-gate findVal(char *name, __nis_rule_value_t *rv, __nis_mapping_item_type_t type) { 988*0Sstevel@tonic-gate int i; 989*0Sstevel@tonic-gate 990*0Sstevel@tonic-gate if (type == mit_nisplus) { 991*0Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 992*0Sstevel@tonic-gate if (rv->colName[i] == 0) 993*0Sstevel@tonic-gate continue; 994*0Sstevel@tonic-gate if (strcmp(name, rv->colName[i]) == 0) { 995*0Sstevel@tonic-gate return (valString(&rv->colVal[i])); 996*0Sstevel@tonic-gate } 997*0Sstevel@tonic-gate } 998*0Sstevel@tonic-gate } else if (type == mit_ldap) { 999*0Sstevel@tonic-gate for (i = 0; i < rv->numAttrs; i++) { 1000*0Sstevel@tonic-gate if (rv->attrName[i] == 0) 1001*0Sstevel@tonic-gate continue; 1002*0Sstevel@tonic-gate if (strcasecmp(name, rv->attrName[i]) == 0) { 1003*0Sstevel@tonic-gate return (valString(&rv->attrVal[i])); 1004*0Sstevel@tonic-gate } 1005*0Sstevel@tonic-gate } 1006*0Sstevel@tonic-gate } 1007*0Sstevel@tonic-gate 1008*0Sstevel@tonic-gate return (0); 1009*0Sstevel@tonic-gate } 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate static char *norv = "<NIL>"; 1012*0Sstevel@tonic-gate static char *unknown = "<unknown>"; 1013*0Sstevel@tonic-gate 1014*0Sstevel@tonic-gate /* 1015*0Sstevel@tonic-gate * Attempt to derive a string identifying the rule-value 'rv'. The 1016*0Sstevel@tonic-gate * returned string is a pointer, either into 'rv', or to static 1017*0Sstevel@tonic-gate * storage, and must not be freed. 1018*0Sstevel@tonic-gate */ 1019*0Sstevel@tonic-gate char * 1020*0Sstevel@tonic-gate rvId(__nis_rule_value_t *rv, __nis_mapping_item_type_t type) { 1021*0Sstevel@tonic-gate char *v; 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate if (rv == 0) 1024*0Sstevel@tonic-gate return (norv); 1025*0Sstevel@tonic-gate 1026*0Sstevel@tonic-gate if (rv->numColumns > 0 && type == mit_nisplus) { 1027*0Sstevel@tonic-gate /* 1028*0Sstevel@tonic-gate * Look for a column called "cname" or "name". 1029*0Sstevel@tonic-gate * If that fails, try "key" or "alias". 1030*0Sstevel@tonic-gate */ 1031*0Sstevel@tonic-gate if ((v = findVal("cname", rv, type)) != 0) 1032*0Sstevel@tonic-gate return (v); 1033*0Sstevel@tonic-gate else if ((v = findVal("name", rv, type)) != 0) 1034*0Sstevel@tonic-gate return (v); 1035*0Sstevel@tonic-gate else if ((v = findVal("key", rv, type)) != 0) 1036*0Sstevel@tonic-gate return (v); 1037*0Sstevel@tonic-gate else if ((v = findVal("alias", rv, type)) != 0) 1038*0Sstevel@tonic-gate return (v); 1039*0Sstevel@tonic-gate } else if (rv->numAttrs > 0 && type == mit_ldap) { 1040*0Sstevel@tonic-gate /* 1041*0Sstevel@tonic-gate * Look for "dn", or "cn". 1042*0Sstevel@tonic-gate */ 1043*0Sstevel@tonic-gate if ((v = findVal("dn", rv, type)) != 0) 1044*0Sstevel@tonic-gate return (v); 1045*0Sstevel@tonic-gate else if ((v = findVal("cn", rv, type)) != 0) 1046*0Sstevel@tonic-gate return (v); 1047*0Sstevel@tonic-gate } 1048*0Sstevel@tonic-gate 1049*0Sstevel@tonic-gate return (unknown); 1050*0Sstevel@tonic-gate } 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate /* 1053*0Sstevel@tonic-gate * Merge the rule-values with the same DN into one. Each rule-value 1054*0Sstevel@tonic-gate * in the returned array will have unique 'dn'. On entry, *numVals 1055*0Sstevel@tonic-gate * contains the number of rule-values in 'rv'. On exit, it contains 1056*0Sstevel@tonic-gate * the number of rule-values in the returned array or -1 on error. 1057*0Sstevel@tonic-gate */ 1058*0Sstevel@tonic-gate __nis_rule_value_t * 1059*0Sstevel@tonic-gate mergeRuleValueWithSameDN(__nis_rule_value_t *rv, int *numVals) { 1060*0Sstevel@tonic-gate __nis_rule_value_t *rvq = 0; 1061*0Sstevel@tonic-gate char *dn, *odn; 1062*0Sstevel@tonic-gate int count = 0; 1063*0Sstevel@tonic-gate int i, j; 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate if (numVals == 0) 1066*0Sstevel@tonic-gate return (0); 1067*0Sstevel@tonic-gate 1068*0Sstevel@tonic-gate for (i = 0; i < *numVals; i++) { 1069*0Sstevel@tonic-gate if ((dn = findVal("dn", &rv[i], mit_ldap)) != 0) { 1070*0Sstevel@tonic-gate for (j = 0; j < count; j++) { 1071*0Sstevel@tonic-gate if ((odn = findVal("dn", &rvq[j], 1072*0Sstevel@tonic-gate mit_ldap)) != 0) { 1073*0Sstevel@tonic-gate /* case sensitive compare */ 1074*0Sstevel@tonic-gate if (strcmp(dn, odn) != 0) 1075*0Sstevel@tonic-gate continue; 1076*0Sstevel@tonic-gate if (mergeRuleValue(&rvq[j], 1077*0Sstevel@tonic-gate &rv[i]) == -1) { 1078*0Sstevel@tonic-gate freeRuleValue(rvq, count); 1079*0Sstevel@tonic-gate *numVals = -1; 1080*0Sstevel@tonic-gate return (0); 1081*0Sstevel@tonic-gate } 1082*0Sstevel@tonic-gate break; 1083*0Sstevel@tonic-gate } else { 1084*0Sstevel@tonic-gate freeRuleValue(rvq, count); 1085*0Sstevel@tonic-gate *numVals = -1; 1086*0Sstevel@tonic-gate return (0); 1087*0Sstevel@tonic-gate } 1088*0Sstevel@tonic-gate } 1089*0Sstevel@tonic-gate /* if no match, then add it to the rulevalue array */ 1090*0Sstevel@tonic-gate if (j == count) { 1091*0Sstevel@tonic-gate rvq = growRuleValue(count, count + 1, rvq, 1092*0Sstevel@tonic-gate &rv[i]); 1093*0Sstevel@tonic-gate if (rvq == 0) { 1094*0Sstevel@tonic-gate *numVals = -1; 1095*0Sstevel@tonic-gate return (0); 1096*0Sstevel@tonic-gate } 1097*0Sstevel@tonic-gate count++; 1098*0Sstevel@tonic-gate } 1099*0Sstevel@tonic-gate } 1100*0Sstevel@tonic-gate } 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate *numVals = count; 1103*0Sstevel@tonic-gate return (rvq); 1104*0Sstevel@tonic-gate } 1105