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 2005 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 /* 30*0Sstevel@tonic-gate * DESCRIPTION: Contains dit_access interface support functions. 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate #include <sys/systeminfo.h> 33*0Sstevel@tonic-gate #include <unistd.h> 34*0Sstevel@tonic-gate #include <stdlib.h> 35*0Sstevel@tonic-gate #include <sys/types.h> 36*0Sstevel@tonic-gate #include <sys/stat.h> 37*0Sstevel@tonic-gate #include <sys/systeminfo.h> 38*0Sstevel@tonic-gate #include <unistd.h> 39*0Sstevel@tonic-gate #include <stdlib.h> 40*0Sstevel@tonic-gate #include <syslog.h> 41*0Sstevel@tonic-gate #include <ndbm.h> 42*0Sstevel@tonic-gate #include <strings.h> 43*0Sstevel@tonic-gate #include <errno.h> 44*0Sstevel@tonic-gate #include "../ldap_util.h" 45*0Sstevel@tonic-gate #include "../ldap_map.h" 46*0Sstevel@tonic-gate #include "../ldap_parse.h" 47*0Sstevel@tonic-gate #include "../ldap_structs.h" 48*0Sstevel@tonic-gate #include "../ldap_val.h" 49*0Sstevel@tonic-gate #include "../ldap_ruleval.h" 50*0Sstevel@tonic-gate #include "../ldap_op.h" 51*0Sstevel@tonic-gate #include "../ldap_attr.h" 52*0Sstevel@tonic-gate #include "../ldap_nisdbquery.h" 53*0Sstevel@tonic-gate #include "../nisdb_mt.h" 54*0Sstevel@tonic-gate #include "shim.h" 55*0Sstevel@tonic-gate #include "yptol.h" 56*0Sstevel@tonic-gate #include "dit_access_utils.h" 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* 59*0Sstevel@tonic-gate * Returns 'map,domain.' 60*0Sstevel@tonic-gate */ 61*0Sstevel@tonic-gate char * 62*0Sstevel@tonic-gate getFullMapName(char *map, char *domain) { 63*0Sstevel@tonic-gate char *myself = "getFullMapName"; 64*0Sstevel@tonic-gate char *objPath; 65*0Sstevel@tonic-gate if (map == 0 || domain == 0) { 66*0Sstevel@tonic-gate return (0); 67*0Sstevel@tonic-gate } 68*0Sstevel@tonic-gate objPath = scat(myself, T, scat(myself, F, map, ","), 69*0Sstevel@tonic-gate scat(myself, F, domain, ".")); 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate return (objPath); 72*0Sstevel@tonic-gate } 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate /* 75*0Sstevel@tonic-gate * Convert string to __nis_value_t 76*0Sstevel@tonic-gate */ 77*0Sstevel@tonic-gate __nis_value_t *stringToValue(char *dptr, int dsize) { 78*0Sstevel@tonic-gate char *myself = "stringToValue"; 79*0Sstevel@tonic-gate char *emptystr = ""; 80*0Sstevel@tonic-gate __nis_value_t *val; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate if ((val = am(myself, sizeof (*val))) == 0) { 83*0Sstevel@tonic-gate return (0); 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate val->type = vt_string; 87*0Sstevel@tonic-gate val->repeat = 0; 88*0Sstevel@tonic-gate val->numVals = 1; 89*0Sstevel@tonic-gate if ((val->val = am(myself, sizeof (val->val[0]))) == 0) { 90*0Sstevel@tonic-gate sfree(val); 91*0Sstevel@tonic-gate return (0); 92*0Sstevel@tonic-gate } 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate /* 95*0Sstevel@tonic-gate * Null strings or strings with length 0 are treated 96*0Sstevel@tonic-gate * as empty strings with length 1 97*0Sstevel@tonic-gate */ 98*0Sstevel@tonic-gate if (dptr == 0 || dsize <= 0) { 99*0Sstevel@tonic-gate dptr = emptystr; 100*0Sstevel@tonic-gate dsize = 1; 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate val->val->length = dsize; 104*0Sstevel@tonic-gate if (dptr[dsize - 1] != '\0') { 105*0Sstevel@tonic-gate val->val->length = dsize + 1; 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate val->val->value = am(myself, val->val->length); 109*0Sstevel@tonic-gate if (val->val->value == 0) { 110*0Sstevel@tonic-gate freeValue(val, 1); 111*0Sstevel@tonic-gate return (0); 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate (void) memcpy(val->val->value, dptr, dsize); 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate return (val); 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* 119*0Sstevel@tonic-gate * Returns an array of rule-values corresponding to the 120*0Sstevel@tonic-gate * splitfields. 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate __nis_rule_value_t * 123*0Sstevel@tonic-gate processSplitField(__nis_table_mapping_t *sf, __nis_value_t *inVal, 124*0Sstevel@tonic-gate int *nv, int *statP) { 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate char *sepset; 127*0Sstevel@tonic-gate __nis_rule_value_t *rvq; 128*0Sstevel@tonic-gate __nis_mapping_format_t *ftmp; 129*0Sstevel@tonic-gate __nis_value_t **valA, *tempVal; 130*0Sstevel@tonic-gate int i, j, res, numVals, oldlen, count; 131*0Sstevel@tonic-gate char *str, *oldstr; 132*0Sstevel@tonic-gate char *myself = "processSplitField"; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* sf will be non NULL */ 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate if (inVal == 0 || inVal->type != vt_string) { 137*0Sstevel@tonic-gate *statP = MAP_PARAM_ERROR; 138*0Sstevel@tonic-gate return (0); 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate /* Get the separator list */ 142*0Sstevel@tonic-gate sepset = sf->separatorStr; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate /* Initialize rule-value */ 145*0Sstevel@tonic-gate rvq = 0; 146*0Sstevel@tonic-gate count = 0; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if ((tempVal = stringToValue(inVal->val->value, 149*0Sstevel@tonic-gate inVal->val->length)) == 0) { 150*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 151*0Sstevel@tonic-gate return (0); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate str = oldstr = tempVal->val->value; 155*0Sstevel@tonic-gate oldlen = tempVal->val->length; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate while (str) { 158*0Sstevel@tonic-gate tempVal->val->value = str; 159*0Sstevel@tonic-gate tempVal->val->length = strlen(str) + 1; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate /* Loop to check which format matches str */ 162*0Sstevel@tonic-gate for (i = 0; i <= sf->numSplits; i++) { 163*0Sstevel@tonic-gate valA = matchMappingItem(sf->e[i].element.match.fmt, 164*0Sstevel@tonic-gate tempVal, &numVals, sepset, &str); 165*0Sstevel@tonic-gate if (valA == 0) { 166*0Sstevel@tonic-gate /* The format didn't match. Try the next one */ 167*0Sstevel@tonic-gate continue; 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate /* 171*0Sstevel@tonic-gate * If we are here means we had a match. 172*0Sstevel@tonic-gate * Each new set of values obtained from the match is 173*0Sstevel@tonic-gate * added to a new rule-value. This is to preserve the 174*0Sstevel@tonic-gate * the distinction between each set. 175*0Sstevel@tonic-gate */ 176*0Sstevel@tonic-gate rvq = growRuleValue(count, count + 1, rvq, 0); 177*0Sstevel@tonic-gate if (rvq == 0) { 178*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 179*0Sstevel@tonic-gate for (j = 0; j < numVals; j++) 180*0Sstevel@tonic-gate freeValue(valA[j], 1); 181*0Sstevel@tonic-gate sfree(valA); 182*0Sstevel@tonic-gate tempVal->val->value = oldstr; 183*0Sstevel@tonic-gate tempVal->val->length = oldlen; 184*0Sstevel@tonic-gate freeValue(tempVal, 1); 185*0Sstevel@tonic-gate return (0); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate count++; 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate for (j = 0; j < numVals; j++) { 190*0Sstevel@tonic-gate res = addCol2RuleValue(vt_string, 191*0Sstevel@tonic-gate sf->e[i].element.match.item[j].name, 192*0Sstevel@tonic-gate valA[j]->val->value, 193*0Sstevel@tonic-gate valA[j]->val->length, 194*0Sstevel@tonic-gate &rvq[count - 1]); 195*0Sstevel@tonic-gate if (res == -1) { 196*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 197*0Sstevel@tonic-gate for (; j < numVals; j++) 198*0Sstevel@tonic-gate freeValue(valA[j], 1); 199*0Sstevel@tonic-gate sfree(valA); 200*0Sstevel@tonic-gate tempVal->val->value = oldstr; 201*0Sstevel@tonic-gate tempVal->val->length = oldlen; 202*0Sstevel@tonic-gate freeValue(tempVal, 1); 203*0Sstevel@tonic-gate freeRuleValue(rvq, count); 204*0Sstevel@tonic-gate return (0); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate freeValue(valA[j], 1); 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate sfree(valA); 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate /* 211*0Sstevel@tonic-gate * Since we had a match, break out of this loop 212*0Sstevel@tonic-gate * to parse remainder of str 213*0Sstevel@tonic-gate */ 214*0Sstevel@tonic-gate break; 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate /* Didn't find any match, so get out of the loop */ 218*0Sstevel@tonic-gate if (i > sf->numSplits) { 219*0Sstevel@tonic-gate str = 0; 220*0Sstevel@tonic-gate break; 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* Skip the separators before looping back */ 224*0Sstevel@tonic-gate if (str) { 225*0Sstevel@tonic-gate str = str + strspn(str, sepset); 226*0Sstevel@tonic-gate if (*str == '\0') 227*0Sstevel@tonic-gate break; 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate tempVal->val->value = oldstr; 232*0Sstevel@tonic-gate tempVal->val->length = oldlen; 233*0Sstevel@tonic-gate freeValue(tempVal, 1); 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate if (str == 0) { 236*0Sstevel@tonic-gate freeRuleValue(rvq, count); 237*0Sstevel@tonic-gate return (0); 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate if (nv != 0) 241*0Sstevel@tonic-gate *nv = count; 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate return (rvq); 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate /* 247*0Sstevel@tonic-gate * Convert the datum to an array of RuleValues 248*0Sstevel@tonic-gate */ 249*0Sstevel@tonic-gate __nis_rule_value_t * 250*0Sstevel@tonic-gate datumToRuleValue(datum *key, datum *value, __nis_table_mapping_t *t, 251*0Sstevel@tonic-gate int *nv, char *domain, bool_t readonly, int *statP) { 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate __nis_rule_value_t *rvq, *subrvq, *newrvq; 254*0Sstevel@tonic-gate __nis_value_t *val; 255*0Sstevel@tonic-gate __nis_value_t **valA; 256*0Sstevel@tonic-gate __nis_table_mapping_t *sf; 257*0Sstevel@tonic-gate int valueLen, comLen, numVals, nr, count = 1; 258*0Sstevel@tonic-gate int i, j, k, l, af; 259*0Sstevel@tonic-gate char *ipaddr, *ipvalue; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* At this point, 't' is always non NULL */ 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate /* Initialize rule-value */ 264*0Sstevel@tonic-gate if ((rvq = initRuleValue(1, 0)) == 0) { 265*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 266*0Sstevel@tonic-gate return (0); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate /* Add domainname to rule-value */ 270*0Sstevel@tonic-gate if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain), 271*0Sstevel@tonic-gate rvq)) { 272*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 273*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 274*0Sstevel@tonic-gate return (0); 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate /* Handle key */ 278*0Sstevel@tonic-gate if (key != 0) { 279*0Sstevel@tonic-gate /* Add field=value pair for N2LKEY */ 280*0Sstevel@tonic-gate i = addCol2RuleValue(vt_string, N2LKEY, key->dptr, key->dsize, 281*0Sstevel@tonic-gate rvq); 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate /* For readonly, add field=value pair for N2LSEARCHKEY */ 284*0Sstevel@tonic-gate if (readonly == TRUE && i == 0) { 285*0Sstevel@tonic-gate i = addCol2RuleValue(vt_string, N2LSEARCHKEY, key->dptr, 286*0Sstevel@tonic-gate key->dsize, rvq); 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate if (i) { 289*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 290*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 291*0Sstevel@tonic-gate return (0); 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate /* Add field=value pairs for IP addresses */ 295*0Sstevel@tonic-gate if (checkIPaddress(key->dptr, key->dsize, &ipaddr) > 0) { 296*0Sstevel@tonic-gate /* If key is IPaddress, use preferred format */ 297*0Sstevel@tonic-gate ipvalue = ipaddr; 298*0Sstevel@tonic-gate valueLen = strlen(ipaddr); 299*0Sstevel@tonic-gate i = addCol2RuleValue(vt_string, N2LIPKEY, ipvalue, 300*0Sstevel@tonic-gate valueLen, rvq); 301*0Sstevel@tonic-gate } else { 302*0Sstevel@tonic-gate /* If not, use original value for N2LSEARCHIPKEY */ 303*0Sstevel@tonic-gate ipaddr = 0; 304*0Sstevel@tonic-gate ipvalue = key->dptr; 305*0Sstevel@tonic-gate valueLen = key->dsize; 306*0Sstevel@tonic-gate i = 0; 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate if (readonly == TRUE && i == 0) { 310*0Sstevel@tonic-gate i = addCol2RuleValue(vt_string, N2LSEARCHIPKEY, ipvalue, 311*0Sstevel@tonic-gate valueLen, rvq); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate sfree(ipaddr); 314*0Sstevel@tonic-gate if (i) { 315*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 316*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 317*0Sstevel@tonic-gate return (0); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* Handle datum value */ 322*0Sstevel@tonic-gate if (value != 0 && t->e) { 323*0Sstevel@tonic-gate valueLen = value->dsize; 324*0Sstevel@tonic-gate /* 325*0Sstevel@tonic-gate * Extract the comment, if any, and add it to 326*0Sstevel@tonic-gate * the rule-value. 327*0Sstevel@tonic-gate */ 328*0Sstevel@tonic-gate if (t->commentChar != '\0') { 329*0Sstevel@tonic-gate /* 330*0Sstevel@tonic-gate * We loop on value->dsize because value->dptr 331*0Sstevel@tonic-gate * may not be NULL-terminated. 332*0Sstevel@tonic-gate */ 333*0Sstevel@tonic-gate for (i = 0; i < value->dsize; i++) { 334*0Sstevel@tonic-gate if (value->dptr[i] == t->commentChar) { 335*0Sstevel@tonic-gate valueLen = i; 336*0Sstevel@tonic-gate comLen = value->dsize - i - 1; 337*0Sstevel@tonic-gate if (comLen == 0) 338*0Sstevel@tonic-gate break; 339*0Sstevel@tonic-gate if (addCol2RuleValue(vt_string, 340*0Sstevel@tonic-gate N2LCOMMENT, value->dptr + i + 1, 341*0Sstevel@tonic-gate comLen, rvq)) { 342*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 343*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 344*0Sstevel@tonic-gate return (0); 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate break; 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate /* Skip trailing whitespaces */ 352*0Sstevel@tonic-gate for (; valueLen > 0 && (value->dptr[valueLen - 1] == ' ' || 353*0Sstevel@tonic-gate value->dptr[valueLen - 1] == '\t'); valueLen--); 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate /* 356*0Sstevel@tonic-gate * At this point valueLen is the effective length of 357*0Sstevel@tonic-gate * the data. Convert value into __nis_value_t so that 358*0Sstevel@tonic-gate * we can use the matchMappingItem function to break it 359*0Sstevel@tonic-gate * into fields. 360*0Sstevel@tonic-gate */ 361*0Sstevel@tonic-gate if ((val = stringToValue(value->dptr, valueLen)) == 0) { 362*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 363*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 364*0Sstevel@tonic-gate return (0); 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate /* Perform namefield match */ 368*0Sstevel@tonic-gate valA = matchMappingItem(t->e->element.match.fmt, val, 369*0Sstevel@tonic-gate &numVals, 0, 0); 370*0Sstevel@tonic-gate if (valA == 0) { 371*0Sstevel@tonic-gate freeValue(val, 1); 372*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 373*0Sstevel@tonic-gate *statP = MAP_NAMEFIELD_MATCH_ERROR; 374*0Sstevel@tonic-gate return (0); 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate /* We don't need val anymore, so free it */ 378*0Sstevel@tonic-gate freeValue(val, 1); 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate /* 381*0Sstevel@tonic-gate * Since matchMappingItem only returns us an array of 382*0Sstevel@tonic-gate * __nis_value_t's, we need to associate each value 383*0Sstevel@tonic-gate * in the array with the corresponding item name. 384*0Sstevel@tonic-gate * This code assumes that numVals will be less than or 385*0Sstevel@tonic-gate * equal to the number of item names associated with 386*0Sstevel@tonic-gate * the format. 387*0Sstevel@tonic-gate * These name=value pairs are added to rvq. 388*0Sstevel@tonic-gate */ 389*0Sstevel@tonic-gate for (i = 0, *statP = SUCCESS; i < numVals; i++) { 390*0Sstevel@tonic-gate for (j = 0; j < count; j++) { 391*0Sstevel@tonic-gate if (addCol2RuleValue(vt_string, 392*0Sstevel@tonic-gate t->e->element.match.item[i].name, 393*0Sstevel@tonic-gate valA[i]->val->value, 394*0Sstevel@tonic-gate valA[i]->val->length, &rvq[j])) { 395*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 396*0Sstevel@tonic-gate break; 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate if (*statP == MAP_INTERNAL_ERROR) 400*0Sstevel@tonic-gate break; 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate /* 403*0Sstevel@tonic-gate * Check if splitField exists for the field. 404*0Sstevel@tonic-gate * Since splitfields are also stored as mapping 405*0Sstevel@tonic-gate * structures, we need to get the hash table entry 406*0Sstevel@tonic-gate * corresponding to the splitfield name 407*0Sstevel@tonic-gate */ 408*0Sstevel@tonic-gate sf = mappingFromMap(t->e->element.match.item[i].name, 409*0Sstevel@tonic-gate domain, statP); 410*0Sstevel@tonic-gate if (*statP == MAP_NO_MEMORY) 411*0Sstevel@tonic-gate break; 412*0Sstevel@tonic-gate *statP = SUCCESS; 413*0Sstevel@tonic-gate if (sf == 0) 414*0Sstevel@tonic-gate continue; 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate /* 417*0Sstevel@tonic-gate * Process and add splitFields to rule-value rvq 418*0Sstevel@tonic-gate */ 419*0Sstevel@tonic-gate subrvq = processSplitField(sf, valA[i], &nr, statP); 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate if (subrvq == 0) { 422*0Sstevel@tonic-gate /* statP would have been set */ 423*0Sstevel@tonic-gate break; 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate /* 427*0Sstevel@tonic-gate * We merge 'count' rule-values in rvq with 'nr' 428*0Sstevel@tonic-gate * rule-values from subrvq to give us a whopping 429*0Sstevel@tonic-gate * 'count * nr' rule-values 430*0Sstevel@tonic-gate */ 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate /* Initialize the new rule-value array */ 433*0Sstevel@tonic-gate if ((newrvq = initRuleValue(count * nr, 0)) == 0) { 434*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 435*0Sstevel@tonic-gate freeRuleValue(subrvq, nr); 436*0Sstevel@tonic-gate break; 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate for (j = 0, l = 0; j < nr; j++) { 440*0Sstevel@tonic-gate for (k = 0; k < count; k++, l++) { 441*0Sstevel@tonic-gate if ((mergeRuleValue(&newrvq[l], 442*0Sstevel@tonic-gate &rvq[k]) == -1) || 443*0Sstevel@tonic-gate (mergeRuleValue( 444*0Sstevel@tonic-gate &newrvq[l], 445*0Sstevel@tonic-gate &subrvq[j]) == -1)) { 446*0Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR; 447*0Sstevel@tonic-gate for (i = 0; i < numVals; i++) 448*0Sstevel@tonic-gate freeValue(valA[i], 1); 449*0Sstevel@tonic-gate sfree(valA); 450*0Sstevel@tonic-gate freeRuleValue(rvq, count); 451*0Sstevel@tonic-gate freeRuleValue(newrvq, 452*0Sstevel@tonic-gate count * nr); 453*0Sstevel@tonic-gate freeRuleValue(subrvq, nr); 454*0Sstevel@tonic-gate return (0); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate freeRuleValue(rvq, count); 460*0Sstevel@tonic-gate rvq = newrvq; 461*0Sstevel@tonic-gate count = l; 462*0Sstevel@tonic-gate freeRuleValue(subrvq, nr); 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate /* We don't need valA anymore, so free it */ 467*0Sstevel@tonic-gate for (i = 0; i < numVals; i++) 468*0Sstevel@tonic-gate freeValue(valA[i], 1); 469*0Sstevel@tonic-gate sfree(valA); 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate if (*statP != SUCCESS) { 472*0Sstevel@tonic-gate freeRuleValue(rvq, count); 473*0Sstevel@tonic-gate return (0); 474*0Sstevel@tonic-gate } 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate } /* if value */ 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate if (nv != 0) 479*0Sstevel@tonic-gate *nv = count; 480*0Sstevel@tonic-gate return (rvq); 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate } 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate /* 485*0Sstevel@tonic-gate * Generate name=values pairs for splitfield names 486*0Sstevel@tonic-gate * 487*0Sstevel@tonic-gate * Consider Example: 488*0Sstevel@tonic-gate * nisLDAPnameFields club: 489*0Sstevel@tonic-gate * ("%s %s %s", name, code, members) 490*0Sstevel@tonic-gate * nisLDAPsplitField members: 491*0Sstevel@tonic-gate * ("(%s,%s,%s)", host, user, domain), 492*0Sstevel@tonic-gate * ("%s", group) 493*0Sstevel@tonic-gate * On entry, 494*0Sstevel@tonic-gate * - rv is an array of numVals rule-values each containing 495*0Sstevel@tonic-gate * name=value pairs for names occuring in nisLDAPsplitField. 496*0Sstevel@tonic-gate * (i.e host, user, domain, group) 497*0Sstevel@tonic-gate * - trv contains name=value pairs for names occuring in 498*0Sstevel@tonic-gate * nisLDAPnameFields. (i.e name, code but not members) 499*0Sstevel@tonic-gate * 500*0Sstevel@tonic-gate * For every name in nisLDAPnamefields that is a splitfield, 501*0Sstevel@tonic-gate * this function applies the data in rv to the corresponding 502*0Sstevel@tonic-gate * splitfield formats (accessed thru t), to generate a single 503*0Sstevel@tonic-gate * string value for the corresponding splitfield (members). 504*0Sstevel@tonic-gate * This new name=value pair is then added to trv. 505*0Sstevel@tonic-gate * Besides, any uninitialized namefield names are set to empty strings. 506*0Sstevel@tonic-gate */ 507*0Sstevel@tonic-gate suc_code 508*0Sstevel@tonic-gate addSplitFieldValues(__nis_table_mapping_t *t, __nis_rule_value_t *rv, 509*0Sstevel@tonic-gate __nis_rule_value_t *trv, int numVals, char *domain) { 510*0Sstevel@tonic-gate __nis_table_mapping_t *sf; 511*0Sstevel@tonic-gate __nis_value_t *val; 512*0Sstevel@tonic-gate int i, j, k, nitems, res, statP; 513*0Sstevel@tonic-gate char *str, *tempstr; 514*0Sstevel@tonic-gate char delim[2] = {0, 0}; 515*0Sstevel@tonic-gate char *emptystr = ""; 516*0Sstevel@tonic-gate char *myself = "addSplitFieldValues"; 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate if (trv == 0) 519*0Sstevel@tonic-gate return (MAP_INTERNAL_ERROR); 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate if (t->e == 0) 522*0Sstevel@tonic-gate return (SUCCESS); 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate nitems = t->e->element.match.numItems; 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate /* 527*0Sstevel@tonic-gate * Procedure: 528*0Sstevel@tonic-gate * - Check each name in nisLDAPnamefield 529*0Sstevel@tonic-gate * - if it's a splifield, construct its value and add it to trv 530*0Sstevel@tonic-gate * - if not, check if it has a value 531*0Sstevel@tonic-gate * - if not, add empty string 532*0Sstevel@tonic-gate */ 533*0Sstevel@tonic-gate for (i = 0, sf = 0; i < nitems; i++) { 534*0Sstevel@tonic-gate if (rv) { 535*0Sstevel@tonic-gate /* 536*0Sstevel@tonic-gate * str will eventually contain the single string 537*0Sstevel@tonic-gate * value for the corresponding splitfield. 538*0Sstevel@tonic-gate * No point initializing str if rv == 0 because 539*0Sstevel@tonic-gate * splitfield cannot be constructed without rv. 540*0Sstevel@tonic-gate * So, only initialized here. 541*0Sstevel@tonic-gate */ 542*0Sstevel@tonic-gate str = 0; 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate /* Check if it's a splitfield name */ 545*0Sstevel@tonic-gate sf = mappingFromMap(t->e->element.match.item[i].name, 546*0Sstevel@tonic-gate domain, &statP); 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate /* 549*0Sstevel@tonic-gate * Return only incase of memory allocation failure. 550*0Sstevel@tonic-gate * The other error case (MAP_NO_MAPPING_EXISTS), 551*0Sstevel@tonic-gate * indicates that the item name is not a splitfieldname 552*0Sstevel@tonic-gate * i.e it's a namefieldname. This case is handled by 553*0Sstevel@tonic-gate * the following if (sf == 0) 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate if (statP == MAP_NO_MEMORY) 556*0Sstevel@tonic-gate return (statP); 557*0Sstevel@tonic-gate } 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate if (sf == 0) { 560*0Sstevel@tonic-gate /* 561*0Sstevel@tonic-gate * Not a splitfield name. Verify if it has a value 562*0Sstevel@tonic-gate */ 563*0Sstevel@tonic-gate if (findVal(t->e->element.match.item[i].name, 564*0Sstevel@tonic-gate trv, mit_nisplus) == 0) { 565*0Sstevel@tonic-gate /* if not, use empty string */ 566*0Sstevel@tonic-gate res = addCol2RuleValue(vt_string, 567*0Sstevel@tonic-gate t->e->element.match.item[i].name, 568*0Sstevel@tonic-gate emptystr, 0, trv); 569*0Sstevel@tonic-gate if (res == -1) { 570*0Sstevel@tonic-gate return (MAP_INTERNAL_ERROR); 571*0Sstevel@tonic-gate } 572*0Sstevel@tonic-gate } 573*0Sstevel@tonic-gate /* 574*0Sstevel@tonic-gate * If rv == 0 then sf == 0 so we will continue here 575*0Sstevel@tonic-gate * i.e. does not matter that str is not yet set up. 576*0Sstevel@tonic-gate */ 577*0Sstevel@tonic-gate continue; 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate /* Code to construct a single value */ 581*0Sstevel@tonic-gate 582*0Sstevel@tonic-gate /* Use the first separator character as the delimiter */ 583*0Sstevel@tonic-gate delim[0] = sf->separatorStr[0]; 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate for (j = 0; j < numVals; j++) { 586*0Sstevel@tonic-gate /* sf->numSplits is zero-based */ 587*0Sstevel@tonic-gate for (k = 0; k <= sf->numSplits; k++) { 588*0Sstevel@tonic-gate val = getMappingFormatArray( 589*0Sstevel@tonic-gate sf->e[k].element.match.fmt, &rv[j], 590*0Sstevel@tonic-gate fa_item, 591*0Sstevel@tonic-gate sf->e[k].element.match.numItems, 592*0Sstevel@tonic-gate sf->e[k].element.match.item); 593*0Sstevel@tonic-gate if (val == 0) 594*0Sstevel@tonic-gate continue; 595*0Sstevel@tonic-gate if (val->numVals > 0) { 596*0Sstevel@tonic-gate if (str) { 597*0Sstevel@tonic-gate tempstr = scat(myself, 598*0Sstevel@tonic-gate 0, str, delim); 599*0Sstevel@tonic-gate sfree(str); 600*0Sstevel@tonic-gate if (tempstr) 601*0Sstevel@tonic-gate str = tempstr; 602*0Sstevel@tonic-gate else { 603*0Sstevel@tonic-gate freeValue(val, 1); 604*0Sstevel@tonic-gate return (MAP_NO_MEMORY); 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate } 607*0Sstevel@tonic-gate tempstr = scat(myself, 0, str, 608*0Sstevel@tonic-gate val->val->value); 609*0Sstevel@tonic-gate sfree(str); 610*0Sstevel@tonic-gate if (tempstr) 611*0Sstevel@tonic-gate str = tempstr; 612*0Sstevel@tonic-gate else { 613*0Sstevel@tonic-gate freeValue(val, 1); 614*0Sstevel@tonic-gate return (MAP_NO_MEMORY); 615*0Sstevel@tonic-gate } 616*0Sstevel@tonic-gate } 617*0Sstevel@tonic-gate freeValue(val, 1); 618*0Sstevel@tonic-gate } 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate if (str == 0) 621*0Sstevel@tonic-gate str = emptystr; 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate res = addCol2RuleValue(vt_string, 624*0Sstevel@tonic-gate t->e->element.match.item[i].name, 625*0Sstevel@tonic-gate str, strlen(str), trv); 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate if (str != emptystr) 628*0Sstevel@tonic-gate sfree(str); 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate if (res == -1) { 631*0Sstevel@tonic-gate return (MAP_INTERNAL_ERROR); 632*0Sstevel@tonic-gate } 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate return (SUCCESS); 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate /* 639*0Sstevel@tonic-gate * Updates 'rv' with NIS name=value pairs suitable to 640*0Sstevel@tonic-gate * construct datum from namefield information. 641*0Sstevel@tonic-gate * Some part based on createNisPlusEntry (from ldap_nisdbquery.c) 642*0Sstevel@tonic-gate * This code assumes that from a given LDAP entry, applying the 643*0Sstevel@tonic-gate * mapping rules, would give us one or more NIS entries, differing 644*0Sstevel@tonic-gate * only in key. 645*0Sstevel@tonic-gate */ 646*0Sstevel@tonic-gate suc_code 647*0Sstevel@tonic-gate buildNISRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv, 648*0Sstevel@tonic-gate char *domain) { 649*0Sstevel@tonic-gate int r, i, j, k, l, index, nrq, res, len; 650*0Sstevel@tonic-gate int numItems, splitname, count, statP; 651*0Sstevel@tonic-gate __nis_value_t *rval; 652*0Sstevel@tonic-gate __nis_mapping_item_t *litem; 653*0Sstevel@tonic-gate __nis_mapping_rule_t *rl; 654*0Sstevel@tonic-gate __nis_rule_value_t *rvq; 655*0Sstevel@tonic-gate char *value, *emptystr = ""; 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate statP = SUCCESS; 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate /* Initialize default base */ 660*0Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = t->objectDN->read.base; 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate /* Initialize rule-value rvq */ 663*0Sstevel@tonic-gate rvq = 0; 664*0Sstevel@tonic-gate count = 0; 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate /* Add domainname to rule-value */ 667*0Sstevel@tonic-gate if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain), 668*0Sstevel@tonic-gate rv)) { 669*0Sstevel@tonic-gate return (MAP_INTERNAL_ERROR); 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate for (r = 0; r < t->numRulesFromLDAP; r++) { 673*0Sstevel@tonic-gate rl = t->ruleFromLDAP[r]; 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* Set escapeFlag if RHS is "dn" to remove escape chars */ 676*0Sstevel@tonic-gate if (rl->rhs.numElements == 1 && 677*0Sstevel@tonic-gate rl->rhs.element->type == me_item && 678*0Sstevel@tonic-gate rl->rhs.element->element.item.type == mit_ldap && 679*0Sstevel@tonic-gate strcasecmp(rl->rhs.element->element.item.name, "dn") 680*0Sstevel@tonic-gate == 0) { 681*0Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '2'; 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate rval = buildRvalue(&rl->rhs, mit_ldap, rv, NULL); 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate /* Reset escapeFlag */ 687*0Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '\0'; 688*0Sstevel@tonic-gate 689*0Sstevel@tonic-gate if (rval == 0) { 690*0Sstevel@tonic-gate continue; 691*0Sstevel@tonic-gate } 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate if (rval->numVals <= 0) { 694*0Sstevel@tonic-gate /* Treat as invalid */ 695*0Sstevel@tonic-gate freeValue(rval, 1); 696*0Sstevel@tonic-gate continue; 697*0Sstevel@tonic-gate } 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate litem = buildLvalue(&rl->lhs, &rval, &numItems); 700*0Sstevel@tonic-gate if (litem == 0) { 701*0Sstevel@tonic-gate /* This will take care of numItems == 0 */ 702*0Sstevel@tonic-gate freeValue(rval, 1); 703*0Sstevel@tonic-gate continue; 704*0Sstevel@tonic-gate } 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate if (rval->numVals > 1) { 707*0Sstevel@tonic-gate if (numItems == 1 && litem->repeat) 708*0Sstevel@tonic-gate nrq = rval->numVals; 709*0Sstevel@tonic-gate else if (numItems > 1 && rval->repeat) 710*0Sstevel@tonic-gate nrq = 1 + ((rval->numVals-1)/numItems); 711*0Sstevel@tonic-gate else 712*0Sstevel@tonic-gate nrq = 1; 713*0Sstevel@tonic-gate } else 714*0Sstevel@tonic-gate nrq = 1; 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate /* Set splitname if splitfield names are specified */ 717*0Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 718*0Sstevel@tonic-gate if (strcasecmp(litem[i].name, N2LKEY) == 0 || 719*0Sstevel@tonic-gate strcasecmp(litem[i].name, N2LIPKEY) == 0 || 720*0Sstevel@tonic-gate strcasecmp(litem[i].name, N2LCOMMENT) == 0) 721*0Sstevel@tonic-gate continue; 722*0Sstevel@tonic-gate for (j = 0; j < t->numColumns; j++) { 723*0Sstevel@tonic-gate if (strcmp(litem[i].name, t->column[j]) == 0) 724*0Sstevel@tonic-gate break; 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate if (j == t->numColumns) 727*0Sstevel@tonic-gate break; 728*0Sstevel@tonic-gate } 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate splitname = (i < numItems)?1:0; 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate for (j = 0; j < nrq; j++) { 733*0Sstevel@tonic-gate if (splitname == 1) { 734*0Sstevel@tonic-gate /* 735*0Sstevel@tonic-gate * Put every value of splitfieldname in a new 736*0Sstevel@tonic-gate * rule-value. Helps generating splitfields. 737*0Sstevel@tonic-gate */ 738*0Sstevel@tonic-gate rvq = growRuleValue(count, count + 1, rvq, 0); 739*0Sstevel@tonic-gate if (rvq == 0) { 740*0Sstevel@tonic-gate freeRuleValue(rvq, count); 741*0Sstevel@tonic-gate freeValue(rval, 1); 742*0Sstevel@tonic-gate freeMappingItem(litem, numItems); 743*0Sstevel@tonic-gate return (MAP_INTERNAL_ERROR); 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate count++; 746*0Sstevel@tonic-gate } 747*0Sstevel@tonic-gate 748*0Sstevel@tonic-gate for (k = j % nrq, l = 0; l < numItems; k += nrq, l++) { 749*0Sstevel@tonic-gate /* If we run out of values, use empty strings */ 750*0Sstevel@tonic-gate if (k >= rval->numVals) { 751*0Sstevel@tonic-gate value = emptystr; 752*0Sstevel@tonic-gate len = 0; 753*0Sstevel@tonic-gate } else { 754*0Sstevel@tonic-gate value = rval->val[k].value; 755*0Sstevel@tonic-gate len = rval->val[k].length; 756*0Sstevel@tonic-gate } 757*0Sstevel@tonic-gate res = (splitname == 1)?addCol2RuleValue( 758*0Sstevel@tonic-gate vt_string, litem[l].name, value, 759*0Sstevel@tonic-gate len, &rvq[count - 1]):0; 760*0Sstevel@tonic-gate if (res != -1) 761*0Sstevel@tonic-gate res = addCol2RuleValue(vt_string, 762*0Sstevel@tonic-gate litem[l].name, value, len, rv); 763*0Sstevel@tonic-gate if (res == -1) { 764*0Sstevel@tonic-gate freeRuleValue(rvq, count); 765*0Sstevel@tonic-gate freeValue(rval, 1); 766*0Sstevel@tonic-gate freeMappingItem(litem, numItems); 767*0Sstevel@tonic-gate return (MAP_INTERNAL_ERROR); 768*0Sstevel@tonic-gate } 769*0Sstevel@tonic-gate } 770*0Sstevel@tonic-gate } 771*0Sstevel@tonic-gate freeValue(rval, 1); 772*0Sstevel@tonic-gate rval = 0; 773*0Sstevel@tonic-gate freeMappingItem(litem, numItems); 774*0Sstevel@tonic-gate litem = 0; 775*0Sstevel@tonic-gate numItems = 0; 776*0Sstevel@tonic-gate } /* for r < t->numRulesFromLDAP */ 777*0Sstevel@tonic-gate 778*0Sstevel@tonic-gate statP = addSplitFieldValues(t, rvq, rv, count, domain); 779*0Sstevel@tonic-gate 780*0Sstevel@tonic-gate if (rvq) 781*0Sstevel@tonic-gate freeRuleValue(rvq, count); 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate if (verifyIndexMatch(t, 0, rv, 0, 0) == 0) 784*0Sstevel@tonic-gate return (MAP_INDEXLIST_ERROR); 785*0Sstevel@tonic-gate return (statP); 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate } /* end of buildNISRuleValue */ 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate /* 790*0Sstevel@tonic-gate * Convert rule-value to datum using namefield information 791*0Sstevel@tonic-gate */ 792*0Sstevel@tonic-gate datum * 793*0Sstevel@tonic-gate ruleValueToDatum(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *statP) { 794*0Sstevel@tonic-gate __nis_value_t *val; 795*0Sstevel@tonic-gate datum *value; 796*0Sstevel@tonic-gate char *str, *cstr, commentSep[3] = {' ', 0, 0}; 797*0Sstevel@tonic-gate char *myself = "ruleValueToDatum"; 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate /* No error yet */ 800*0Sstevel@tonic-gate *statP = 0; 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate /* Return empty datum if no namefield information available */ 803*0Sstevel@tonic-gate if (t->e == 0) { 804*0Sstevel@tonic-gate if ((value = am(myself, sizeof (*value))) == 0) 805*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 806*0Sstevel@tonic-gate return (value); 807*0Sstevel@tonic-gate } 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate val = getMappingFormatArray(t->e->element.match.fmt, rv, 810*0Sstevel@tonic-gate fa_item, t->e->element.match.numItems, 811*0Sstevel@tonic-gate t->e->element.match.item); 812*0Sstevel@tonic-gate 813*0Sstevel@tonic-gate if (val && val->val && val->val->value) { 814*0Sstevel@tonic-gate if ((value = am(myself, sizeof (*value))) == 0) { 815*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 816*0Sstevel@tonic-gate freeValue(val, 1); 817*0Sstevel@tonic-gate return (0); 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate /* Strip trailing whitespaces */ 821*0Sstevel@tonic-gate cstr = (char *)val->val->value + val->val->length; 822*0Sstevel@tonic-gate for (; cstr >= (char *)val->val->value && 823*0Sstevel@tonic-gate (*cstr == ' ' || *cstr == '\t'); *cstr-- = '\0'); 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate if (t->commentChar != '\0' && 826*0Sstevel@tonic-gate (str = findVal(N2LCOMMENT, rv, mit_nisplus)) != 0 && 827*0Sstevel@tonic-gate *str != '\0') { 828*0Sstevel@tonic-gate commentSep[1] = t->commentChar; 829*0Sstevel@tonic-gate cstr = scat(myself, F, commentSep, str); 830*0Sstevel@tonic-gate if (cstr) { 831*0Sstevel@tonic-gate value->dptr = scat(myself, F, 832*0Sstevel@tonic-gate val->val->value, cstr); 833*0Sstevel@tonic-gate sfree(cstr); 834*0Sstevel@tonic-gate } 835*0Sstevel@tonic-gate } else { 836*0Sstevel@tonic-gate value->dptr = sdup(myself, T, val->val->value); 837*0Sstevel@tonic-gate } 838*0Sstevel@tonic-gate freeValue(val, 1); 839*0Sstevel@tonic-gate if (value->dptr) { 840*0Sstevel@tonic-gate value->dsize = strlen(value->dptr); 841*0Sstevel@tonic-gate return (value); 842*0Sstevel@tonic-gate } else { 843*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 844*0Sstevel@tonic-gate sfree(value); 845*0Sstevel@tonic-gate return (0); 846*0Sstevel@tonic-gate } 847*0Sstevel@tonic-gate } 848*0Sstevel@tonic-gate 849*0Sstevel@tonic-gate *statP = MAP_NAMEFIELD_MATCH_ERROR; 850*0Sstevel@tonic-gate return (0); 851*0Sstevel@tonic-gate } 852*0Sstevel@tonic-gate 853*0Sstevel@tonic-gate datum * 854*0Sstevel@tonic-gate getKeyFromRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *nv, 855*0Sstevel@tonic-gate int *statP) { 856*0Sstevel@tonic-gate int i, j; 857*0Sstevel@tonic-gate datum *key = 0; 858*0Sstevel@tonic-gate char *str; 859*0Sstevel@tonic-gate char *myself = "getKeyFromRuleValue"; 860*0Sstevel@tonic-gate 861*0Sstevel@tonic-gate /* No error yet */ 862*0Sstevel@tonic-gate *statP = 0; 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate if (rv == 0 || nv == 0) 865*0Sstevel@tonic-gate return (0); 866*0Sstevel@tonic-gate 867*0Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 868*0Sstevel@tonic-gate if (rv->colName[i] == 0) 869*0Sstevel@tonic-gate continue; 870*0Sstevel@tonic-gate if (strcasecmp(N2LKEY, rv->colName[i]) == 0 || 871*0Sstevel@tonic-gate strcasecmp(N2LIPKEY, rv->colName[i]) == 0) { 872*0Sstevel@tonic-gate if ((*nv = rv->colVal[i].numVals) == 0) 873*0Sstevel@tonic-gate return (0); 874*0Sstevel@tonic-gate if ((key = am(myself, sizeof (key[0]) * *nv)) == 0) { 875*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 876*0Sstevel@tonic-gate return (0); 877*0Sstevel@tonic-gate } 878*0Sstevel@tonic-gate for (j = 0; j < *nv; j++) { 879*0Sstevel@tonic-gate if ((str = rv->colVal[i].val[j].value) == 0) { 880*0Sstevel@tonic-gate key[j].dsize = 0; 881*0Sstevel@tonic-gate key[j].dptr = 0; 882*0Sstevel@tonic-gate } else { 883*0Sstevel@tonic-gate if (verifyIndexMatch(t, 0, 0, 884*0Sstevel@tonic-gate rv->colName[i], 885*0Sstevel@tonic-gate str) == 0) { 886*0Sstevel@tonic-gate key[j].dsize = 0; 887*0Sstevel@tonic-gate key[j].dptr = 0; 888*0Sstevel@tonic-gate continue; 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate key[j].dsize = strlen(str); 891*0Sstevel@tonic-gate key[j].dptr = am(myself, 892*0Sstevel@tonic-gate key[j].dsize + 1); 893*0Sstevel@tonic-gate if (key[j].dptr == 0) { 894*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 895*0Sstevel@tonic-gate for (--j; j >= 0; j--) 896*0Sstevel@tonic-gate sfree(key[j].dptr); 897*0Sstevel@tonic-gate sfree(key); 898*0Sstevel@tonic-gate return (0); 899*0Sstevel@tonic-gate } 900*0Sstevel@tonic-gate bcopy(str, key[j].dptr, key[j].dsize); 901*0Sstevel@tonic-gate } 902*0Sstevel@tonic-gate } 903*0Sstevel@tonic-gate return (key); 904*0Sstevel@tonic-gate } 905*0Sstevel@tonic-gate } 906*0Sstevel@tonic-gate return (0); 907*0Sstevel@tonic-gate } 908*0Sstevel@tonic-gate 909*0Sstevel@tonic-gate /* 910*0Sstevel@tonic-gate * Get the mapping structure corresponding to `map,domain.' 911*0Sstevel@tonic-gate */ 912*0Sstevel@tonic-gate __nis_table_mapping_t * 913*0Sstevel@tonic-gate mappingFromMap(char *map, char *domain, int *statP) { 914*0Sstevel@tonic-gate char *mapPath; 915*0Sstevel@tonic-gate __nis_table_mapping_t *t; 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate /* No error yet */ 918*0Sstevel@tonic-gate *statP = 0; 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate /* Construct map,domain. */ 921*0Sstevel@tonic-gate if ((mapPath = getFullMapName(map, domain)) == 0) { 922*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 923*0Sstevel@tonic-gate return (0); 924*0Sstevel@tonic-gate } 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate /* Get the hash table entry for the mapPath */ 927*0Sstevel@tonic-gate if ((t = __nis_find_item_mt(mapPath, &ldapMappingList, 1, 0)) 928*0Sstevel@tonic-gate == 0) { 929*0Sstevel@tonic-gate *statP = MAP_NO_MAPPING_EXISTS; 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate sfree(mapPath); 932*0Sstevel@tonic-gate return (t); 933*0Sstevel@tonic-gate } 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate /* 936*0Sstevel@tonic-gate * Verify at least one key value obtained from DIT matches the search key 937*0Sstevel@tonic-gate * RETURNS: 1 MATCH 938*0Sstevel@tonic-gate * 0 NO MATCH 939*0Sstevel@tonic-gate * -1 NO KEY FOUND 940*0Sstevel@tonic-gate */ 941*0Sstevel@tonic-gate static int 942*0Sstevel@tonic-gate verifyKey(char *key, __nis_rule_value_t *rv) { 943*0Sstevel@tonic-gate int i, j; 944*0Sstevel@tonic-gate char *sipkey, *str; 945*0Sstevel@tonic-gate 946*0Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 947*0Sstevel@tonic-gate if (rv->colName[i] == 0) 948*0Sstevel@tonic-gate continue; 949*0Sstevel@tonic-gate if (strcasecmp(N2LKEY, rv->colName[i]) == 0) { 950*0Sstevel@tonic-gate if (rv->colVal[i].val == 0) 951*0Sstevel@tonic-gate return (0); 952*0Sstevel@tonic-gate for (j = 0; j < rv->colVal[i].numVals; j++) { 953*0Sstevel@tonic-gate str = (char *)rv->colVal[i].val[j].value; 954*0Sstevel@tonic-gate if (str && strcmp(str, key) == 0) 955*0Sstevel@tonic-gate return (1); 956*0Sstevel@tonic-gate } 957*0Sstevel@tonic-gate return (0); 958*0Sstevel@tonic-gate } else if (strcasecmp(N2LIPKEY, rv->colName[i]) == 0) { 959*0Sstevel@tonic-gate if (checkIPaddress(key, strlen(key), &sipkey) > 0) { 960*0Sstevel@tonic-gate if (rv->colVal[i].val == 0) 961*0Sstevel@tonic-gate return (0); 962*0Sstevel@tonic-gate for (j = 0; j < rv->colVal[i].numVals; j++) { 963*0Sstevel@tonic-gate str = rv->colVal[i].val[j].value; 964*0Sstevel@tonic-gate if (str && strcmp(str, sipkey) == 0) { 965*0Sstevel@tonic-gate sfree(sipkey); 966*0Sstevel@tonic-gate return (1); 967*0Sstevel@tonic-gate } 968*0Sstevel@tonic-gate } 969*0Sstevel@tonic-gate sfree(sipkey); 970*0Sstevel@tonic-gate } 971*0Sstevel@tonic-gate return (0); 972*0Sstevel@tonic-gate } 973*0Sstevel@tonic-gate } 974*0Sstevel@tonic-gate return (-1); 975*0Sstevel@tonic-gate } 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate /* 978*0Sstevel@tonic-gate * Read (i.e get and map) a single NIS entry from the LDAP DIT 979*0Sstevel@tonic-gate */ 980*0Sstevel@tonic-gate bool_t 981*0Sstevel@tonic-gate singleReadFromDIT(char *map, char *domain, datum *key, datum *value, 982*0Sstevel@tonic-gate int *statP) { 983*0Sstevel@tonic-gate __nis_table_mapping_t *t; 984*0Sstevel@tonic-gate __nis_rule_value_t *rv_request = 0, *rv_result = 0; 985*0Sstevel@tonic-gate __nis_ldap_search_t *ls; 986*0Sstevel@tonic-gate __nis_object_dn_t *objectDN = NULL; 987*0Sstevel@tonic-gate int i, rc, nr = 0, nv = 0; 988*0Sstevel@tonic-gate datum *datval = 0; 989*0Sstevel@tonic-gate char *skey, *str, *sipkey; 990*0Sstevel@tonic-gate char *myself = "singleReadFromDIT"; 991*0Sstevel@tonic-gate 992*0Sstevel@tonic-gate *statP = SUCCESS; 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate if (!map || !domain || !key || !value) { 995*0Sstevel@tonic-gate *statP = MAP_PARAM_ERROR; 996*0Sstevel@tonic-gate return (FALSE); 997*0Sstevel@tonic-gate } 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate /* Get the mapping information for the map */ 1001*0Sstevel@tonic-gate if ((t = mappingFromMap(map, domain, statP)) == 0) { 1002*0Sstevel@tonic-gate /* 1003*0Sstevel@tonic-gate * No problem. We don't handle this map and domain. Maybe it's 1004*0Sstevel@tonic-gate * handled by a service other than NIS. 1005*0Sstevel@tonic-gate */ 1006*0Sstevel@tonic-gate return (FALSE); 1007*0Sstevel@tonic-gate } 1008*0Sstevel@tonic-gate 1009*0Sstevel@tonic-gate /* NULL-terminated version of datum key for logging */ 1010*0Sstevel@tonic-gate if ((skey = am(myself, key->dsize + 1)) == 0) { 1011*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 1012*0Sstevel@tonic-gate return (FALSE); 1013*0Sstevel@tonic-gate } 1014*0Sstevel@tonic-gate (void) memcpy(skey, key->dptr, key->dsize); 1015*0Sstevel@tonic-gate 1016*0Sstevel@tonic-gate if ((str = getFullMapName(map, domain)) == 0) { 1017*0Sstevel@tonic-gate *statP = MAP_NO_MEMORY; 1018*0Sstevel@tonic-gate return (FALSE); 1019*0Sstevel@tonic-gate } 1020*0Sstevel@tonic-gate 1021*0Sstevel@tonic-gate /* For each alternate mapping */ 1022*0Sstevel@tonic-gate for (; t != 0; t = t->next) { 1023*0Sstevel@tonic-gate /* Verify objName */ 1024*0Sstevel@tonic-gate if (strcmp(str, t->objName) != 0) { 1025*0Sstevel@tonic-gate continue; 1026*0Sstevel@tonic-gate } 1027*0Sstevel@tonic-gate 1028*0Sstevel@tonic-gate /* Verify if key matches the index */ 1029*0Sstevel@tonic-gate if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 || 1030*0Sstevel@tonic-gate verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0) 1031*0Sstevel@tonic-gate continue; 1032*0Sstevel@tonic-gate 1033*0Sstevel@tonic-gate /* Check if rulesFromLDAP are provided */ 1034*0Sstevel@tonic-gate if (t->numRulesFromLDAP == 0) { 1035*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1036*0Sstevel@tonic-gate "%s: No rulesFromLDAP information available " 1037*0Sstevel@tonic-gate "for %s (%s)", myself, t->dbId, map); 1038*0Sstevel@tonic-gate continue; 1039*0Sstevel@tonic-gate } 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* Convert key into rule-value */ 1042*0Sstevel@tonic-gate if ((rv_request = datumToRuleValue(key, 0, t, 0, domain, TRUE, 1043*0Sstevel@tonic-gate statP)) == 0) { 1044*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1045*0Sstevel@tonic-gate "%s: Conversion error %d (NIS to name=value " 1046*0Sstevel@tonic-gate "pairs) for NIS key (%s) for %s (%s)", 1047*0Sstevel@tonic-gate myself, *statP, skey, t->dbId, map); 1048*0Sstevel@tonic-gate continue; 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate /* Convert rule-value into ldap request */ 1051*0Sstevel@tonic-gate for (objectDN = t->objectDN; objectDN && 1052*0Sstevel@tonic-gate objectDN->read.base; 1053*0Sstevel@tonic-gate objectDN = objectDN->next) { 1054*0Sstevel@tonic-gate ls = createLdapRequest(t, rv_request, 0, 1, NULL, 1055*0Sstevel@tonic-gate objectDN); 1056*0Sstevel@tonic-gate if (ls == 0) { 1057*0Sstevel@tonic-gate *statP = MAP_CREATE_LDAP_REQUEST_ERROR; 1058*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1059*0Sstevel@tonic-gate "%s: Failed to create ldapSearch " 1060*0Sstevel@tonic-gate "request for " 1061*0Sstevel@tonic-gate "NIS key (%s) for %s (%s) " 1062*0Sstevel@tonic-gate "for base %s", 1063*0Sstevel@tonic-gate myself, skey, t->dbId, map, 1064*0Sstevel@tonic-gate objectDN->read.base); 1065*0Sstevel@tonic-gate continue; 1066*0Sstevel@tonic-gate } 1067*0Sstevel@tonic-gate ls->timeout.tv_sec = SINGLE_ACCESS_TIMEOUT_SEC; 1068*0Sstevel@tonic-gate ls->timeout.tv_usec = SINGLE_ACCESS_TIMEOUT_USEC; 1069*0Sstevel@tonic-gate /* Query LDAP */ 1070*0Sstevel@tonic-gate nr = (ls->isDN)?0:-1; 1071*0Sstevel@tonic-gate rv_result = ldapSearch(ls, &nr, 0, statP); 1072*0Sstevel@tonic-gate freeLdapSearch(ls); 1073*0Sstevel@tonic-gate if (rv_result == 0) { 1074*0Sstevel@tonic-gate if (*statP == LDAP_NO_SUCH_OBJECT) { 1075*0Sstevel@tonic-gate /* Entry does not exist in */ 1076*0Sstevel@tonic-gate /* the ldap server */ 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate continue; 1079*0Sstevel@tonic-gate } 1080*0Sstevel@tonic-gate freeRuleValue(rv_request, 1); 1081*0Sstevel@tonic-gate rv_request = 0; 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate /* if result > 1, first match will be returned */ 1084*0Sstevel@tonic-gate if (nr > 1) { 1085*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1086*0Sstevel@tonic-gate "%s: %d ldapSearch results " 1087*0Sstevel@tonic-gate "for NIS key (%s) " 1088*0Sstevel@tonic-gate "for %s (%s) for base %s. " 1089*0Sstevel@tonic-gate "First match will be returned ", 1090*0Sstevel@tonic-gate myself, nr, skey, t->dbId, map, 1091*0Sstevel@tonic-gate objectDN->read.base); 1092*0Sstevel@tonic-gate } 1093*0Sstevel@tonic-gate 1094*0Sstevel@tonic-gate for (i = 0; i < nr; i++) { 1095*0Sstevel@tonic-gate /* Convert LDAP data to NIS equivalents */ 1096*0Sstevel@tonic-gate *statP = buildNISRuleValue(t, &rv_result[i], 1097*0Sstevel@tonic-gate domain); 1098*0Sstevel@tonic-gate if (*statP == MAP_INDEXLIST_ERROR) 1099*0Sstevel@tonic-gate continue; 1100*0Sstevel@tonic-gate 1101*0Sstevel@tonic-gate if (*statP != SUCCESS) { 1102*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1103*0Sstevel@tonic-gate "%s: Conversion error %d (LDAP to " 1104*0Sstevel@tonic-gate "name=value pairs) for NIS key (%s) " 1105*0Sstevel@tonic-gate "for %s (%s) for base %s", myself, 1106*0Sstevel@tonic-gate *statP, skey, 1107*0Sstevel@tonic-gate t->dbId, map, objectDN->read.base); 1108*0Sstevel@tonic-gate continue; 1109*0Sstevel@tonic-gate } 1110*0Sstevel@tonic-gate 1111*0Sstevel@tonic-gate /* 1112*0Sstevel@tonic-gate * Check if 'key' from the ldap result matches the key 1113*0Sstevel@tonic-gate * provided by our caller 1114*0Sstevel@tonic-gate */ 1115*0Sstevel@tonic-gate if ((rc = verifyKey(skey, &rv_result[i])) 1116*0Sstevel@tonic-gate == -1) { 1117*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1118*0Sstevel@tonic-gate "%s: Cannot verify key from ldap " 1119*0Sstevel@tonic-gate "result for NIS key (%s) for %s (%s) " 1120*0Sstevel@tonic-gate "for base %s", 1121*0Sstevel@tonic-gate myself, skey, t->dbId, map, 1122*0Sstevel@tonic-gate objectDN->read.base); 1123*0Sstevel@tonic-gate continue; 1124*0Sstevel@tonic-gate } 1125*0Sstevel@tonic-gate 1126*0Sstevel@tonic-gate if (rc == 1) { 1127*0Sstevel@tonic-gate datval = ruleValueToDatum(t, 1128*0Sstevel@tonic-gate &rv_result[i], statP); 1129*0Sstevel@tonic-gate if (datval == 0) { 1130*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 1131*0Sstevel@tonic-gate LOG_WARNING, 1132*0Sstevel@tonic-gate "%s: Conversion error %d " 1133*0Sstevel@tonic-gate "(name=value pairs to NIS) " 1134*0Sstevel@tonic-gate "for NIS key (%s) for %s (%s)" 1135*0Sstevel@tonic-gate " for base %s", 1136*0Sstevel@tonic-gate myself, 1137*0Sstevel@tonic-gate *statP, skey, t->dbId, map, 1138*0Sstevel@tonic-gate objectDN->read.base); 1139*0Sstevel@tonic-gate continue; 1140*0Sstevel@tonic-gate } 1141*0Sstevel@tonic-gate if (value) { 1142*0Sstevel@tonic-gate value->dptr = datval->dptr; 1143*0Sstevel@tonic-gate value->dsize = datval->dsize; 1144*0Sstevel@tonic-gate } 1145*0Sstevel@tonic-gate sfree(datval); 1146*0Sstevel@tonic-gate sfree(skey); 1147*0Sstevel@tonic-gate freeRuleValue(rv_result, nr); 1148*0Sstevel@tonic-gate rv_result = 0; 1149*0Sstevel@tonic-gate *statP = SUCCESS; 1150*0Sstevel@tonic-gate 1151*0Sstevel@tonic-gate /* Free full map name */ 1152*0Sstevel@tonic-gate sfree(str); 1153*0Sstevel@tonic-gate 1154*0Sstevel@tonic-gate return (TRUE); 1155*0Sstevel@tonic-gate } 1156*0Sstevel@tonic-gate } 1157*0Sstevel@tonic-gate freeRuleValue(rv_result, nr); 1158*0Sstevel@tonic-gate rv_result = 0; 1159*0Sstevel@tonic-gate } /* end of for over objectDN */ 1160*0Sstevel@tonic-gate 1161*0Sstevel@tonic-gate if (rv_request != 0) { 1162*0Sstevel@tonic-gate freeRuleValue(rv_request, 1); 1163*0Sstevel@tonic-gate rv_request = 0; 1164*0Sstevel@tonic-gate } 1165*0Sstevel@tonic-gate if (rv_result != 0) { 1166*0Sstevel@tonic-gate freeRuleValue(rv_result, nr); 1167*0Sstevel@tonic-gate rv_result = 0; 1168*0Sstevel@tonic-gate } 1169*0Sstevel@tonic-gate } 1170*0Sstevel@tonic-gate sfree(skey); 1171*0Sstevel@tonic-gate *statP = MAP_NO_MATCHING_KEY; 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate /* Free full map name */ 1174*0Sstevel@tonic-gate sfree(str); 1175*0Sstevel@tonic-gate 1176*0Sstevel@tonic-gate return (FALSE); 1177*0Sstevel@tonic-gate } 1178*0Sstevel@tonic-gate 1179*0Sstevel@tonic-gate 1180*0Sstevel@tonic-gate /* 1181*0Sstevel@tonic-gate * Maps and writes a single NIS entry to the LDAP DIT 1182*0Sstevel@tonic-gate */ 1183*0Sstevel@tonic-gate int 1184*0Sstevel@tonic-gate singleWriteToDIT(char *map, char *domain, datum *key, datum *value, 1185*0Sstevel@tonic-gate bool_t replace) { 1186*0Sstevel@tonic-gate __nis_table_mapping_t *t; 1187*0Sstevel@tonic-gate __nis_rule_value_t *rv, *frv; 1188*0Sstevel@tonic-gate __nis_ldap_search_t *ls; 1189*0Sstevel@tonic-gate int statP = SUCCESS, flag; 1190*0Sstevel@tonic-gate int nv, nr, i, rc, collapse; 1191*0Sstevel@tonic-gate char *dn = 0, *skey, *svalue, *str; 1192*0Sstevel@tonic-gate char *myself = "singleWriteToDIT"; 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate if (!map || !domain || !key || !value) { 1195*0Sstevel@tonic-gate return (MAP_PARAM_ERROR); 1196*0Sstevel@tonic-gate } 1197*0Sstevel@tonic-gate 1198*0Sstevel@tonic-gate /* Return SUCCESS for empty or whitespace key */ 1199*0Sstevel@tonic-gate for (i = 0; i < key->dsize && (key->dptr[i] == 0 || 1200*0Sstevel@tonic-gate key->dptr[i] == ' ' || key->dptr[i] == '\t'); i++); 1201*0Sstevel@tonic-gate if (i >= key->dsize) 1202*0Sstevel@tonic-gate return (SUCCESS); 1203*0Sstevel@tonic-gate 1204*0Sstevel@tonic-gate /* Get the mapping information for the map */ 1205*0Sstevel@tonic-gate if ((t = mappingFromMap(map, domain, &statP)) == 0) { 1206*0Sstevel@tonic-gate /* 1207*0Sstevel@tonic-gate * No problem. We don't handle this map and domain. Maybe it's 1208*0Sstevel@tonic-gate * handled by a service other than NIS. 1209*0Sstevel@tonic-gate */ 1210*0Sstevel@tonic-gate return (statP); 1211*0Sstevel@tonic-gate } 1212*0Sstevel@tonic-gate 1213*0Sstevel@tonic-gate /* NULL-terminated version of key and value for logging */ 1214*0Sstevel@tonic-gate if ((skey = am(myself, key->dsize + 1)) == 0) 1215*0Sstevel@tonic-gate return (MAP_NO_MEMORY); 1216*0Sstevel@tonic-gate (void) memcpy(skey, key->dptr, key->dsize); 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gate if ((svalue = am(myself, value->dsize + 1)) == 0) { 1219*0Sstevel@tonic-gate sfree(skey); 1220*0Sstevel@tonic-gate return (MAP_NO_MEMORY); 1221*0Sstevel@tonic-gate } 1222*0Sstevel@tonic-gate (void) memcpy(svalue, value->dptr, value->dsize); 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gate if ((str = getFullMapName(map, domain)) == 0) { 1225*0Sstevel@tonic-gate sfree(skey); 1226*0Sstevel@tonic-gate sfree(svalue); 1227*0Sstevel@tonic-gate return (MAP_NO_MEMORY); 1228*0Sstevel@tonic-gate } 1229*0Sstevel@tonic-gate 1230*0Sstevel@tonic-gate /* For each alternate mapping */ 1231*0Sstevel@tonic-gate for (flag = 0; t != 0; t = t->next) { 1232*0Sstevel@tonic-gate /* Verify objName */ 1233*0Sstevel@tonic-gate if (strcmp(str, t->objName) != 0) { 1234*0Sstevel@tonic-gate continue; 1235*0Sstevel@tonic-gate } 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate /* Verify if key matches the index */ 1238*0Sstevel@tonic-gate if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 || 1239*0Sstevel@tonic-gate verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0) 1240*0Sstevel@tonic-gate continue; 1241*0Sstevel@tonic-gate 1242*0Sstevel@tonic-gate /* Check the writespecs */ 1243*0Sstevel@tonic-gate if (t->objectDN->write.base == 0) { 1244*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1245*0Sstevel@tonic-gate "%s: No baseDN in writespec. Write disabled " 1246*0Sstevel@tonic-gate "for %s (%s)", myself, t->dbId, map); 1247*0Sstevel@tonic-gate continue; 1248*0Sstevel@tonic-gate } 1249*0Sstevel@tonic-gate 1250*0Sstevel@tonic-gate /* Check if rulesToLDAP are provided */ 1251*0Sstevel@tonic-gate if (t->numRulesToLDAP == 0) { 1252*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1253*0Sstevel@tonic-gate "%s: No rulesToLDAP. Write disabled for " 1254*0Sstevel@tonic-gate "%s (%s)", myself, t->dbId, map); 1255*0Sstevel@tonic-gate continue; 1256*0Sstevel@tonic-gate } 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate /* Set flag to indicate write is enabled */ 1259*0Sstevel@tonic-gate flag = 1; 1260*0Sstevel@tonic-gate 1261*0Sstevel@tonic-gate /* Convert key and value into an array of rule-values */ 1262*0Sstevel@tonic-gate if ((rv = datumToRuleValue(key, value, t, &nv, domain, FALSE, 1263*0Sstevel@tonic-gate &statP)) == 0) { 1264*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1265*0Sstevel@tonic-gate "%s: Conversion error %d (NIS to name=value " 1266*0Sstevel@tonic-gate "pairs) for NIS data (key=%s, value=%s) " 1267*0Sstevel@tonic-gate "for %s (%s)", 1268*0Sstevel@tonic-gate myself, statP, skey, svalue, t->dbId, map); 1269*0Sstevel@tonic-gate sfree(skey); 1270*0Sstevel@tonic-gate sfree(svalue); 1271*0Sstevel@tonic-gate 1272*0Sstevel@tonic-gate /* Free full map name */ 1273*0Sstevel@tonic-gate sfree(str); 1274*0Sstevel@tonic-gate 1275*0Sstevel@tonic-gate return (statP); 1276*0Sstevel@tonic-gate } 1277*0Sstevel@tonic-gate 1278*0Sstevel@tonic-gate /* Convert NIS data to LDAP equivalents for each rule-value */ 1279*0Sstevel@tonic-gate for (i = 0; i < nv; i++) { 1280*0Sstevel@tonic-gate /* Verify indexlist with name=value pairs */ 1281*0Sstevel@tonic-gate if (verifyIndexMatch(t, 0, &rv[i], 0, 0) == 0) 1282*0Sstevel@tonic-gate break; 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate /* Create LDAP request and LDAP name=value pairs */ 1285*0Sstevel@tonic-gate if ((ls = createLdapRequest(t, &rv[i], 1286*0Sstevel@tonic-gate 0, 0, NULL, NULL)) == 0) { 1287*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1288*0Sstevel@tonic-gate "%s: Conversion error (name=value pairs" 1289*0Sstevel@tonic-gate " to LDAP) for NIS data " 1290*0Sstevel@tonic-gate "(key=%s, value=%s) for %s (%s)", 1291*0Sstevel@tonic-gate myself, skey, svalue, t->dbId, map); 1292*0Sstevel@tonic-gate freeRuleValue(rv, nv); 1293*0Sstevel@tonic-gate sfree(skey); 1294*0Sstevel@tonic-gate sfree(svalue); 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate /* Free full map name */ 1297*0Sstevel@tonic-gate sfree(str); 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate return (MAP_CREATE_LDAP_REQUEST_ERROR); 1300*0Sstevel@tonic-gate } 1301*0Sstevel@tonic-gate freeLdapSearch(ls); 1302*0Sstevel@tonic-gate /* printRuleValue(&rv[i]); */ 1303*0Sstevel@tonic-gate } 1304*0Sstevel@tonic-gate 1305*0Sstevel@tonic-gate /* If i < nv then this alternate mapping isn't the one */ 1306*0Sstevel@tonic-gate if (i < nv) 1307*0Sstevel@tonic-gate continue; 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate /* 1310*0Sstevel@tonic-gate * Merge rule-values with the same DN so that we have 1311*0Sstevel@tonic-gate * one ldap write request for each DN 1312*0Sstevel@tonic-gate */ 1313*0Sstevel@tonic-gate nr = nv; 1314*0Sstevel@tonic-gate frv = mergeRuleValueWithSameDN(rv, &nr); 1315*0Sstevel@tonic-gate freeRuleValue(rv, nv); 1316*0Sstevel@tonic-gate if (frv == 0) { 1317*0Sstevel@tonic-gate if (nr == -1) { 1318*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1319*0Sstevel@tonic-gate "%s: Unable to merge LDAP write " 1320*0Sstevel@tonic-gate "requests to same DN for NIS data " 1321*0Sstevel@tonic-gate "(key=%s, value=%s) for %s (%s)", 1322*0Sstevel@tonic-gate myself, skey, svalue, t->dbId, map); 1323*0Sstevel@tonic-gate statP = MAP_INTERNAL_ERROR; 1324*0Sstevel@tonic-gate } else if (nr == 0) { 1325*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1326*0Sstevel@tonic-gate "%s: Cannot generate write DN due to " 1327*0Sstevel@tonic-gate "missing information for NIS data " 1328*0Sstevel@tonic-gate "(key=%s, value=%s) for %s (%s)", 1329*0Sstevel@tonic-gate myself, skey, svalue, t->dbId, map); 1330*0Sstevel@tonic-gate statP = MAP_NO_DN; 1331*0Sstevel@tonic-gate } 1332*0Sstevel@tonic-gate sfree(skey); 1333*0Sstevel@tonic-gate sfree(svalue); 1334*0Sstevel@tonic-gate 1335*0Sstevel@tonic-gate /* Free full map name */ 1336*0Sstevel@tonic-gate sfree(str); 1337*0Sstevel@tonic-gate 1338*0Sstevel@tonic-gate return (statP); 1339*0Sstevel@tonic-gate } 1340*0Sstevel@tonic-gate 1341*0Sstevel@tonic-gate /* Write to the LDAP server */ 1342*0Sstevel@tonic-gate for (collapse = 0, i = 0; i < nr; i++) { 1343*0Sstevel@tonic-gate if ((dn = findVal("dn", &frv[i], mit_ldap)) != 0) { 1344*0Sstevel@tonic-gate if (replace == FALSE) { 1345*0Sstevel@tonic-gate /* ldap add */ 1346*0Sstevel@tonic-gate rc = ldapAdd(dn, &frv[i], 1347*0Sstevel@tonic-gate t->objectDN->write.attrs, 0); 1348*0Sstevel@tonic-gate } else { 1349*0Sstevel@tonic-gate /* ldap modify with addFirst set */ 1350*0Sstevel@tonic-gate rc = ldapModify(dn, &frv[i], 1351*0Sstevel@tonic-gate t->objectDN->write.attrs, 1); 1352*0Sstevel@tonic-gate } 1353*0Sstevel@tonic-gate 1354*0Sstevel@tonic-gate /* if we get err=20, collapse and try again */ 1355*0Sstevel@tonic-gate if (!collapse && 1356*0Sstevel@tonic-gate (rc == LDAP_TYPE_OR_VALUE_EXISTS) && 1357*0Sstevel@tonic-gate (collapseRuleValue(&frv[i]) == 1)) { 1358*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1359*0Sstevel@tonic-gate "%s: Ignoring values differing " 1360*0Sstevel@tonic-gate "in case from NIS data (key=%s," 1361*0Sstevel@tonic-gate " value=%s) for (dn: %s) for " 1362*0Sstevel@tonic-gate "%s (%s)", myself, skey, 1363*0Sstevel@tonic-gate svalue, dn, t->dbId, map); 1364*0Sstevel@tonic-gate collapse = 1; 1365*0Sstevel@tonic-gate i--; 1366*0Sstevel@tonic-gate continue; 1367*0Sstevel@tonic-gate } 1368*0Sstevel@tonic-gate 1369*0Sstevel@tonic-gate collapse = 0; 1370*0Sstevel@tonic-gate if (rc != LDAP_SUCCESS) { 1371*0Sstevel@tonic-gate /* Log error */ 1372*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1373*0Sstevel@tonic-gate "%s: %s error %d (%s) for " 1374*0Sstevel@tonic-gate "(dn: %s) for NIS data " 1375*0Sstevel@tonic-gate "(key=%s, value=%s) " 1376*0Sstevel@tonic-gate "for %s (%s)", 1377*0Sstevel@tonic-gate myself, (replace == TRUE) ? 1378*0Sstevel@tonic-gate "ldapModify" : "ldapAdd", rc, 1379*0Sstevel@tonic-gate ldap_err2string(rc), dn, skey, 1380*0Sstevel@tonic-gate svalue, t->dbId, map); 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate /* Dumping failed call may be useful */ 1383*0Sstevel@tonic-gate /* printRuleValue(&frv[i]); */ 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate /* 1386*0Sstevel@tonic-gate * Return the error code and let wrapper 1387*0Sstevel@tonic-gate * sort out if mapping should continue 1388*0Sstevel@tonic-gate * or abort. 1389*0Sstevel@tonic-gate */ 1390*0Sstevel@tonic-gate statP = rc; 1391*0Sstevel@tonic-gate sfree(skey); 1392*0Sstevel@tonic-gate sfree(svalue); 1393*0Sstevel@tonic-gate freeRuleValue(frv, nr); 1394*0Sstevel@tonic-gate 1395*0Sstevel@tonic-gate /* Free full map name */ 1396*0Sstevel@tonic-gate sfree(str); 1397*0Sstevel@tonic-gate 1398*0Sstevel@tonic-gate return (statP); 1399*0Sstevel@tonic-gate } 1400*0Sstevel@tonic-gate } 1401*0Sstevel@tonic-gate } 1402*0Sstevel@tonic-gate 1403*0Sstevel@tonic-gate freeRuleValue(frv, nr); 1404*0Sstevel@tonic-gate } 1405*0Sstevel@tonic-gate 1406*0Sstevel@tonic-gate sfree(skey); 1407*0Sstevel@tonic-gate sfree(svalue); 1408*0Sstevel@tonic-gate 1409*0Sstevel@tonic-gate /* Free full map name */ 1410*0Sstevel@tonic-gate sfree(str); 1411*0Sstevel@tonic-gate 1412*0Sstevel@tonic-gate return ((flag)?SUCCESS:MAP_WRITE_DISABLED); 1413*0Sstevel@tonic-gate } 1414*0Sstevel@tonic-gate 1415*0Sstevel@tonic-gate suc_code 1416*0Sstevel@tonic-gate collapseRuleValue(__nis_rule_value_t *rv) { 1417*0Sstevel@tonic-gate int i, j, k, flag; 1418*0Sstevel@tonic-gate 1419*0Sstevel@tonic-gate /* Using 'val' to appease cstyle's 80 chars/line limit */ 1420*0Sstevel@tonic-gate __nis_value_t *val; 1421*0Sstevel@tonic-gate 1422*0Sstevel@tonic-gate for (i = 0, flag = 0; i < rv->numAttrs; i++) { 1423*0Sstevel@tonic-gate val = &rv->attrVal[i]; 1424*0Sstevel@tonic-gate for (j = 1; j < val->numVals; j++) { 1425*0Sstevel@tonic-gate for (k = 0; k < j; k++) { 1426*0Sstevel@tonic-gate if (val->val[j].length != val->val[k].length) 1427*0Sstevel@tonic-gate continue; 1428*0Sstevel@tonic-gate if (val->val[k].length == 0) 1429*0Sstevel@tonic-gate continue; 1430*0Sstevel@tonic-gate if (strncasecmp(val->val[j].value, 1431*0Sstevel@tonic-gate val->val[k].value, 1432*0Sstevel@tonic-gate val->val[j].length) != 0) 1433*0Sstevel@tonic-gate continue; 1434*0Sstevel@tonic-gate flag = 1; 1435*0Sstevel@tonic-gate sfree(val->val[j].value); 1436*0Sstevel@tonic-gate 1437*0Sstevel@tonic-gate #ifdef ORDER_NOT_IMPORTANT 1438*0Sstevel@tonic-gate val->val[j--] = val->val[--val->numVals]; 1439*0Sstevel@tonic-gate #else 1440*0Sstevel@tonic-gate /* Order needs to be maintained */ 1441*0Sstevel@tonic-gate for (k = j + 1; k < val->numVals; k++) 1442*0Sstevel@tonic-gate val->val[k - 1] = val->val[k]; 1443*0Sstevel@tonic-gate j--; 1444*0Sstevel@tonic-gate val->numVals--; 1445*0Sstevel@tonic-gate #endif 1446*0Sstevel@tonic-gate break; 1447*0Sstevel@tonic-gate } 1448*0Sstevel@tonic-gate } 1449*0Sstevel@tonic-gate } 1450*0Sstevel@tonic-gate return (flag); 1451*0Sstevel@tonic-gate } 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate /* ObjectClass lookup table */ 1454*0Sstevel@tonic-gate static struct { 1455*0Sstevel@tonic-gate const char *attrType; 1456*0Sstevel@tonic-gate const char *objectClass; 1457*0Sstevel@tonic-gate } oc_lookup[] = { 1458*0Sstevel@tonic-gate { "o", "objectclass=organization"}, 1459*0Sstevel@tonic-gate { "organizationname", "objectclass=organization"}, 1460*0Sstevel@tonic-gate { "2.5.4.10", "objectclass=organization"}, 1461*0Sstevel@tonic-gate { "ou", "objectclass=organizationalunit"}, 1462*0Sstevel@tonic-gate { "organizationalunitname", "objectclass=organizationalunit"}, 1463*0Sstevel@tonic-gate { "2.5.4.11", "objectclass=organizationalunit"}, 1464*0Sstevel@tonic-gate { "c", "objectclass=country"}, 1465*0Sstevel@tonic-gate { "countryname", "objectclass=country"}, 1466*0Sstevel@tonic-gate { "2.5.4.6", "objectclass=country"}, 1467*0Sstevel@tonic-gate { "dc", "objectclass=domain"}, 1468*0Sstevel@tonic-gate { "domaincomponent", "objectclass=domain"}, 1469*0Sstevel@tonic-gate { "0.9.2342.19200300.100.1.25", "objectclass=domain"}, 1470*0Sstevel@tonic-gate { "nismapname", "objectclass=nismap"}, 1471*0Sstevel@tonic-gate { "1.3.6.1.1.1.1.26", "objectclass=nismap"}, 1472*0Sstevel@tonic-gate { "automountmapname", "objectclass=automountmap"}, 1473*0Sstevel@tonic-gate { "1.3.6.1.1.1.1.31", "objectclass=automountmap"}, 1474*0Sstevel@tonic-gate { 0, 0} 1475*0Sstevel@tonic-gate }; 1476*0Sstevel@tonic-gate 1477*0Sstevel@tonic-gate /* 1478*0Sstevel@tonic-gate * Returns the name of the objectclass to which the object 1479*0Sstevel@tonic-gate * represented by the given 'rdn' will most likely belong to. 1480*0Sstevel@tonic-gate * The return value is in static memory so it should not be 1481*0Sstevel@tonic-gate * freed 1482*0Sstevel@tonic-gate */ 1483*0Sstevel@tonic-gate const char * 1484*0Sstevel@tonic-gate getObjectClass(char *rdn) { 1485*0Sstevel@tonic-gate 1486*0Sstevel@tonic-gate char *attrtype, *p; 1487*0Sstevel@tonic-gate int len, i; 1488*0Sstevel@tonic-gate 1489*0Sstevel@tonic-gate /* Skip leading whitespaces */ 1490*0Sstevel@tonic-gate for (p = rdn; *p == ' ' || *p == '\t'; p++); 1491*0Sstevel@tonic-gate if (*p == '\0') 1492*0Sstevel@tonic-gate return (0); 1493*0Sstevel@tonic-gate attrtype = p; 1494*0Sstevel@tonic-gate 1495*0Sstevel@tonic-gate /* Find '=' */ 1496*0Sstevel@tonic-gate if ((p = strchr(attrtype, '=')) == 0 || p == attrtype || 1497*0Sstevel@tonic-gate *(p - 1) == '\\') 1498*0Sstevel@tonic-gate return (0); 1499*0Sstevel@tonic-gate 1500*0Sstevel@tonic-gate /* 1501*0Sstevel@tonic-gate * Skip trailing whitespaces in attrtype 1502*0Sstevel@tonic-gate * Don't worry, p won't decrease beyond attrtype 1503*0Sstevel@tonic-gate */ 1504*0Sstevel@tonic-gate for (--p; *p == ' ' || *p == '\t'; p--); 1505*0Sstevel@tonic-gate len = p - attrtype + 1; 1506*0Sstevel@tonic-gate 1507*0Sstevel@tonic-gate for (i = 0; oc_lookup[i].attrType; i++) 1508*0Sstevel@tonic-gate if (!strncasecmp(oc_lookup[i].attrType, attrtype, len)) 1509*0Sstevel@tonic-gate /* Check length is right */ 1510*0Sstevel@tonic-gate if (len == strlen(oc_lookup[i].attrType)) 1511*0Sstevel@tonic-gate return (oc_lookup[i].objectClass); 1512*0Sstevel@tonic-gate 1513*0Sstevel@tonic-gate return (0); 1514*0Sstevel@tonic-gate } 1515*0Sstevel@tonic-gate 1516*0Sstevel@tonic-gate /* 1517*0Sstevel@tonic-gate * Split 'dn' into rdn and parentdn based on the first 1518*0Sstevel@tonic-gate * occurrence of unescaped 'comma' or 'semicolon'. rdn 1519*0Sstevel@tonic-gate * lies on the LHS while parentdn lies on the RHS of the 1520*0Sstevel@tonic-gate * split. If none found, then an empty string ("") is 1521*0Sstevel@tonic-gate * assigned to parentdn 1522*0Sstevel@tonic-gate */ 1523*0Sstevel@tonic-gate int 1524*0Sstevel@tonic-gate splitDN(char *dn, char **rdn, char **parentdn) { 1525*0Sstevel@tonic-gate char *value, *name; 1526*0Sstevel@tonic-gate char *myself = "splitDN"; 1527*0Sstevel@tonic-gate 1528*0Sstevel@tonic-gate if ((name = sdup(myself, T, dn)) == 0) 1529*0Sstevel@tonic-gate return (-1); 1530*0Sstevel@tonic-gate 1531*0Sstevel@tonic-gate for (value = name; *value != '\0'; value++) { 1532*0Sstevel@tonic-gate if (*value == ',' || *value == ';') 1533*0Sstevel@tonic-gate if (value == name || *(value - 1) != '\\') 1534*0Sstevel@tonic-gate break; 1535*0Sstevel@tonic-gate } 1536*0Sstevel@tonic-gate 1537*0Sstevel@tonic-gate if (*value != '\0') { 1538*0Sstevel@tonic-gate *value = '\0'; 1539*0Sstevel@tonic-gate value++; 1540*0Sstevel@tonic-gate } else 1541*0Sstevel@tonic-gate value = 0; 1542*0Sstevel@tonic-gate 1543*0Sstevel@tonic-gate if (parentdn) { 1544*0Sstevel@tonic-gate if ((*parentdn = sdup(myself, T, value)) == 0) { 1545*0Sstevel@tonic-gate sfree(name); 1546*0Sstevel@tonic-gate return (-1); 1547*0Sstevel@tonic-gate } 1548*0Sstevel@tonic-gate } 1549*0Sstevel@tonic-gate if (rdn) 1550*0Sstevel@tonic-gate *rdn = name; 1551*0Sstevel@tonic-gate else 1552*0Sstevel@tonic-gate sfree(name); 1553*0Sstevel@tonic-gate 1554*0Sstevel@tonic-gate return (1); 1555*0Sstevel@tonic-gate } 1556*0Sstevel@tonic-gate 1557*0Sstevel@tonic-gate /* 1558*0Sstevel@tonic-gate * FUNCTION : makeNISObject() 1559*0Sstevel@tonic-gate * 1560*0Sstevel@tonic-gate * DESCRIPTION: Sets up a nis Object in the DIT. 1561*0Sstevel@tonic-gate * 1562*0Sstevel@tonic-gate * GIVEN : 1563*0Sstevel@tonic-gate * Case 1: Both 'domain' and 'dn' are non-NULL 1564*0Sstevel@tonic-gate * Create nisDomainObject with the given information 1565*0Sstevel@tonic-gate * Case 2: Only 'domain' is non-NULL 1566*0Sstevel@tonic-gate * Obtain the 'dn' from the nisLDAPdomainContext list 1567*0Sstevel@tonic-gate * Create nisDomainObject with the above information 1568*0Sstevel@tonic-gate * Case 3: Only 'dn' is non-NULL 1569*0Sstevel@tonic-gate * Create an object with the 'dn' 1570*0Sstevel@tonic-gate * Here we guess the objectclass attribute, based on 1571*0Sstevel@tonic-gate * oc_lookup table 1572*0Sstevel@tonic-gate * Case 4: Both 'domain' and 'dn' are NULL 1573*0Sstevel@tonic-gate * Error 1574*0Sstevel@tonic-gate * 1575*0Sstevel@tonic-gate * RETURNS : SUCCESS = It worked 1576*0Sstevel@tonic-gate * FAILURE = There was a problem. 1577*0Sstevel@tonic-gate */ 1578*0Sstevel@tonic-gate suc_code 1579*0Sstevel@tonic-gate makeNISObject(char *domain, char *dn) { 1580*0Sstevel@tonic-gate __nis_rule_value_t *rv; 1581*0Sstevel@tonic-gate __nis_ldap_search_t *ls; 1582*0Sstevel@tonic-gate int i, rc, nr, add_rc; 1583*0Sstevel@tonic-gate char *val; 1584*0Sstevel@tonic-gate char *myself = "makeNISObject"; 1585*0Sstevel@tonic-gate 1586*0Sstevel@tonic-gate if (!dn && !domain) 1587*0Sstevel@tonic-gate return (FAILURE); 1588*0Sstevel@tonic-gate 1589*0Sstevel@tonic-gate /* 1590*0Sstevel@tonic-gate * If only 'domain' name is provided, then 1591*0Sstevel@tonic-gate * try to find dn from the nisLDAPdomainContext 1592*0Sstevel@tonic-gate * list generated by the parser 1593*0Sstevel@tonic-gate */ 1594*0Sstevel@tonic-gate if (!dn) { 1595*0Sstevel@tonic-gate for (i = 0; i < ypDomains.numDomains; i++) { 1596*0Sstevel@tonic-gate if (ypDomains.domainLabels[i] == 0) 1597*0Sstevel@tonic-gate continue; 1598*0Sstevel@tonic-gate if (strcasecmp(domain, ypDomains.domainLabels[i]) 1599*0Sstevel@tonic-gate == 0) { 1600*0Sstevel@tonic-gate dn = ypDomains.domains[i]; 1601*0Sstevel@tonic-gate break; 1602*0Sstevel@tonic-gate } 1603*0Sstevel@tonic-gate } 1604*0Sstevel@tonic-gate if (!dn) 1605*0Sstevel@tonic-gate return (FAILURE); 1606*0Sstevel@tonic-gate } 1607*0Sstevel@tonic-gate 1608*0Sstevel@tonic-gate /* 1609*0Sstevel@tonic-gate * If only 'dn' is given, then it means that the 1610*0Sstevel@tonic-gate * caller simply wants to a create an entry for 1611*0Sstevel@tonic-gate * that 'dn'. 1612*0Sstevel@tonic-gate * 1613*0Sstevel@tonic-gate * If 'domain' is given, then check if the 'dn' 1614*0Sstevel@tonic-gate * has already been set up as a nis domain object. 1615*0Sstevel@tonic-gate * If not, see if we can make it become one. 1616*0Sstevel@tonic-gate */ 1617*0Sstevel@tonic-gate if (domain) { 1618*0Sstevel@tonic-gate /* 1619*0Sstevel@tonic-gate * Check to see if the nis domain object has 1620*0Sstevel@tonic-gate * already been set up 1621*0Sstevel@tonic-gate */ 1622*0Sstevel@tonic-gate ls = buildLdapSearch(dn, LDAP_SCOPE_BASE, 0, 0, 1623*0Sstevel@tonic-gate "objectclass=*", 0, 0, 0); 1624*0Sstevel@tonic-gate if (ls == 0) { 1625*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1626*0Sstevel@tonic-gate "%s: Unable to create ldapSearch " 1627*0Sstevel@tonic-gate "request for dn: %s", myself, dn); 1628*0Sstevel@tonic-gate return (FAILURE); 1629*0Sstevel@tonic-gate } 1630*0Sstevel@tonic-gate nr = -1; 1631*0Sstevel@tonic-gate rv = ldapSearch(ls, &nr, 0, &rc); 1632*0Sstevel@tonic-gate freeLdapSearch(ls); 1633*0Sstevel@tonic-gate if (rc == LDAP_SUCCESS) { 1634*0Sstevel@tonic-gate val = findVal("nisDomain", rv, mit_ldap); 1635*0Sstevel@tonic-gate if (val != NULL) { 1636*0Sstevel@tonic-gate /* 1637*0Sstevel@tonic-gate * Yes, nis domain object found. Check 1638*0Sstevel@tonic-gate * to see if the domain names match. 1639*0Sstevel@tonic-gate * If so, we are done. If not, log 1640*0Sstevel@tonic-gate * a warning message, and return SUCCESS. 1641*0Sstevel@tonic-gate */ 1642*0Sstevel@tonic-gate if (strcasecmp(val, domain) == 0) { 1643*0Sstevel@tonic-gate freeRuleValue(rv, nr); 1644*0Sstevel@tonic-gate return (SUCCESS); 1645*0Sstevel@tonic-gate } else { 1646*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 1647*0Sstevel@tonic-gate LOG_WARNING, 1648*0Sstevel@tonic-gate "%s: Entry (dn: %s) already " 1649*0Sstevel@tonic-gate "contains a nis domain name " 1650*0Sstevel@tonic-gate "(%s). The domain name (%s) " 1651*0Sstevel@tonic-gate "is not added.", 1652*0Sstevel@tonic-gate myself, dn, val, domain); 1653*0Sstevel@tonic-gate freeRuleValue(rv, nr); 1654*0Sstevel@tonic-gate return (SUCCESS); 1655*0Sstevel@tonic-gate } 1656*0Sstevel@tonic-gate } else { 1657*0Sstevel@tonic-gate freeRuleValue(rv, nr); 1658*0Sstevel@tonic-gate /* 1659*0Sstevel@tonic-gate * Entry for the 'dn' exists, but it 1660*0Sstevel@tonic-gate * is not a nis domain object yet. 1661*0Sstevel@tonic-gate * Add the nisDoamin attribute and 1662*0Sstevel@tonic-gate * the nisDomainObject objectclass to 1663*0Sstevel@tonic-gate * the entry. 1664*0Sstevel@tonic-gate */ 1665*0Sstevel@tonic-gate if ((rv = initRuleValue(1, 0)) == 0) 1666*0Sstevel@tonic-gate return (FAILURE); 1667*0Sstevel@tonic-gate 1668*0Sstevel@tonic-gate if (addSAttr2RuleValue("nisDomain", 1669*0Sstevel@tonic-gate domain, rv) == -1) { 1670*0Sstevel@tonic-gate freeRuleValue(rv, 1); 1671*0Sstevel@tonic-gate return (FAILURE); 1672*0Sstevel@tonic-gate } 1673*0Sstevel@tonic-gate rc = ldapModify(dn, rv, 1674*0Sstevel@tonic-gate "objectclass=nisDomainObject", 1675*0Sstevel@tonic-gate 0); 1676*0Sstevel@tonic-gate freeRuleValue(rv, 1); 1677*0Sstevel@tonic-gate if (rc == LDAP_SUCCESS) { 1678*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 1679*0Sstevel@tonic-gate LOG_INFO, 1680*0Sstevel@tonic-gate "%s: entry (dn: %s) " 1681*0Sstevel@tonic-gate "modified to be an " 1682*0Sstevel@tonic-gate "nis domain object", 1683*0Sstevel@tonic-gate myself, dn); 1684*0Sstevel@tonic-gate return (SUCCESS); 1685*0Sstevel@tonic-gate } else { 1686*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 1687*0Sstevel@tonic-gate LOG_ERR, 1688*0Sstevel@tonic-gate "%s: unable to modify " 1689*0Sstevel@tonic-gate "entry (dn: %s) to be " 1690*0Sstevel@tonic-gate "a nis domain object: " 1691*0Sstevel@tonic-gate "ldapModify error %d (%s)", 1692*0Sstevel@tonic-gate myself, dn, rc, 1693*0Sstevel@tonic-gate ldap_err2string(rc)); 1694*0Sstevel@tonic-gate return (FAILURE); 1695*0Sstevel@tonic-gate } 1696*0Sstevel@tonic-gate } 1697*0Sstevel@tonic-gate } else { /* search for 'dn' failed */ 1698*0Sstevel@tonic-gate freeRuleValue(rv, nr); 1699*0Sstevel@tonic-gate 1700*0Sstevel@tonic-gate /* 1701*0Sstevel@tonic-gate * It is OK if no such object, otherwise 1702*0Sstevel@tonic-gate * log an error. 1703*0Sstevel@tonic-gate */ 1704*0Sstevel@tonic-gate if (rc != LDAP_NO_SUCH_OBJECT) { 1705*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1706*0Sstevel@tonic-gate "%s: unable to retrieve " 1707*0Sstevel@tonic-gate "entry (dn: %s): " 1708*0Sstevel@tonic-gate "ldapSearch error %d (%s)", 1709*0Sstevel@tonic-gate myself, dn, rc, 1710*0Sstevel@tonic-gate ldap_err2string(rc)); 1711*0Sstevel@tonic-gate return (FAILURE); 1712*0Sstevel@tonic-gate } 1713*0Sstevel@tonic-gate } 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate /* 1716*0Sstevel@tonic-gate * If the 'dn' is actually the naming context of 1717*0Sstevel@tonic-gate * the DIT, we should be able to make it a nis domain 1718*0Sstevel@tonic-gate * object without worrying about missing parent 1719*0Sstevel@tonic-gate * entries. If unable to add the entry for the 'dn' 1720*0Sstevel@tonic-gate * due to missing parent entries, fall through 1721*0Sstevel@tonic-gate * to create them and then add the nis domain object. 1722*0Sstevel@tonic-gate */ 1723*0Sstevel@tonic-gate if (addNISObject(domain, dn, &add_rc) == SUCCESS) 1724*0Sstevel@tonic-gate return (SUCCESS); 1725*0Sstevel@tonic-gate else if (add_rc != LDAP_NO_SUCH_OBJECT) 1726*0Sstevel@tonic-gate return (FAILURE); 1727*0Sstevel@tonic-gate } 1728*0Sstevel@tonic-gate 1729*0Sstevel@tonic-gate /* Create parent */ 1730*0Sstevel@tonic-gate if (addParent(dn, NULL) == FAILURE) 1731*0Sstevel@tonic-gate return (FAILURE); 1732*0Sstevel@tonic-gate 1733*0Sstevel@tonic-gate if (addNISObject(domain, dn, NULL) == FAILURE) 1734*0Sstevel@tonic-gate return (FAILURE); 1735*0Sstevel@tonic-gate 1736*0Sstevel@tonic-gate return (SUCCESS); 1737*0Sstevel@tonic-gate } 1738*0Sstevel@tonic-gate 1739*0Sstevel@tonic-gate suc_code 1740*0Sstevel@tonic-gate addParent(char *dn, char **attr) { 1741*0Sstevel@tonic-gate __nis_rule_value_t *rv; 1742*0Sstevel@tonic-gate __nis_ldap_search_t *ls; 1743*0Sstevel@tonic-gate int rc, nr; 1744*0Sstevel@tonic-gate char *parentdn = 0, *rdn = 0; 1745*0Sstevel@tonic-gate char *myself = "addParent"; 1746*0Sstevel@tonic-gate 1747*0Sstevel@tonic-gate /* Obtain parentdn */ 1748*0Sstevel@tonic-gate if (splitDN(dn, &rdn, &parentdn) == -1) 1749*0Sstevel@tonic-gate return (FAILURE); 1750*0Sstevel@tonic-gate if (!parentdn) { 1751*0Sstevel@tonic-gate sfree(rdn); 1752*0Sstevel@tonic-gate return (FAILURE); 1753*0Sstevel@tonic-gate } 1754*0Sstevel@tonic-gate 1755*0Sstevel@tonic-gate /* Check if parentdn exists */ 1756*0Sstevel@tonic-gate ls = buildLdapSearch(parentdn, LDAP_SCOPE_BASE, 0, 0, 1757*0Sstevel@tonic-gate "objectclass=*", 0, 0, 0); 1758*0Sstevel@tonic-gate if (ls == 0) { 1759*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1760*0Sstevel@tonic-gate "%s: Unable to create ldapSearch request for " 1761*0Sstevel@tonic-gate "parent (dn: %s) of (dn: %s)", 1762*0Sstevel@tonic-gate myself, parentdn, dn); 1763*0Sstevel@tonic-gate sfree(parentdn); 1764*0Sstevel@tonic-gate sfree(rdn); 1765*0Sstevel@tonic-gate return (FAILURE); 1766*0Sstevel@tonic-gate } 1767*0Sstevel@tonic-gate nr = -1; 1768*0Sstevel@tonic-gate rv = ldapSearch(ls, &nr, 0, &rc); 1769*0Sstevel@tonic-gate freeLdapSearch(ls); 1770*0Sstevel@tonic-gate freeRuleValue(rv, nr); 1771*0Sstevel@tonic-gate 1772*0Sstevel@tonic-gate /* Create parent if it doesn't exists */ 1773*0Sstevel@tonic-gate if (rc == LDAP_NO_SUCH_OBJECT) { 1774*0Sstevel@tonic-gate if (makeNISObject(0, parentdn) == FAILURE) { 1775*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1776*0Sstevel@tonic-gate "%s: Unable to create parent (dn: %s) of " 1777*0Sstevel@tonic-gate "(dn: %s) in the DIT", myself, parentdn, dn); 1778*0Sstevel@tonic-gate sfree(parentdn); 1779*0Sstevel@tonic-gate sfree(rdn); 1780*0Sstevel@tonic-gate return (FAILURE); 1781*0Sstevel@tonic-gate } 1782*0Sstevel@tonic-gate } 1783*0Sstevel@tonic-gate sfree(parentdn); 1784*0Sstevel@tonic-gate 1785*0Sstevel@tonic-gate if (attr && rdn) 1786*0Sstevel@tonic-gate *attr = (char *)getObjectClass(rdn); 1787*0Sstevel@tonic-gate sfree(rdn); 1788*0Sstevel@tonic-gate 1789*0Sstevel@tonic-gate return (SUCCESS); 1790*0Sstevel@tonic-gate } 1791*0Sstevel@tonic-gate 1792*0Sstevel@tonic-gate 1793*0Sstevel@tonic-gate 1794*0Sstevel@tonic-gate /* 1795*0Sstevel@tonic-gate * FUNCTION : is_fatal_error() 1796*0Sstevel@tonic-gate * 1797*0Sstevel@tonic-gate * DESCRIPTION: Works out if a failed mapping operation should be retried. 1798*0Sstevel@tonic-gate * 1799*0Sstevel@tonic-gate * INPUTS : Result code from operation 1800*0Sstevel@tonic-gate * 1801*0Sstevel@tonic-gate * OUTPUTS : TRUE = Fatal error, don't retry. 1802*0Sstevel@tonic-gate * FALSE = Temporary error, retry. 1803*0Sstevel@tonic-gate */ 1804*0Sstevel@tonic-gate bool_t 1805*0Sstevel@tonic-gate is_fatal_error(int res) 1806*0Sstevel@tonic-gate { 1807*0Sstevel@tonic-gate 1808*0Sstevel@tonic-gate if (0 > res) 1809*0Sstevel@tonic-gate /* An internal mapping error. Not going to go away. */ 1810*0Sstevel@tonic-gate return (TRUE); 1811*0Sstevel@tonic-gate 1812*0Sstevel@tonic-gate switch (res) { 1813*0Sstevel@tonic-gate case (LDAP_PROTOCOL_ERROR): 1814*0Sstevel@tonic-gate case (LDAP_TIMELIMIT_EXCEEDED): 1815*0Sstevel@tonic-gate case (LDAP_PARTIAL_RESULTS): 1816*0Sstevel@tonic-gate case (LDAP_BUSY): 1817*0Sstevel@tonic-gate case (LDAP_UNAVAILABLE): 1818*0Sstevel@tonic-gate case (LDAP_UNWILLING_TO_PERFORM): 1819*0Sstevel@tonic-gate case (LDAP_OTHER): 1820*0Sstevel@tonic-gate case (LDAP_SERVER_DOWN): 1821*0Sstevel@tonic-gate case (LDAP_LOCAL_ERROR): 1822*0Sstevel@tonic-gate case (LDAP_TIMEOUT): 1823*0Sstevel@tonic-gate case (LDAP_NO_MEMORY): 1824*0Sstevel@tonic-gate /* Probably worth a retry */ 1825*0Sstevel@tonic-gate return (FALSE); 1826*0Sstevel@tonic-gate 1827*0Sstevel@tonic-gate default: 1828*0Sstevel@tonic-gate return (TRUE); 1829*0Sstevel@tonic-gate } 1830*0Sstevel@tonic-gate } 1831*0Sstevel@tonic-gate 1832*0Sstevel@tonic-gate /* 1833*0Sstevel@tonic-gate * FUNCTION : addNISObject() 1834*0Sstevel@tonic-gate * 1835*0Sstevel@tonic-gate * DESCRIPTION: Add a nis Object in the DIT. 1836*0Sstevel@tonic-gate * 1837*0Sstevel@tonic-gate * GIVEN : 1838*0Sstevel@tonic-gate * Case 1: 'dn' is NULL 1839*0Sstevel@tonic-gate * Error 1840*0Sstevel@tonic-gate * Case 2: 'domain' is non-NULL 1841*0Sstevel@tonic-gate * Create nisDomainObject with the given information 1842*0Sstevel@tonic-gate * Case 3: 'domain' is NULL 1843*0Sstevel@tonic-gate * Create an object with the 'dn' 1844*0Sstevel@tonic-gate * Here we guess the objectclass attribute, based on 1845*0Sstevel@tonic-gate * oc_lookup table 1846*0Sstevel@tonic-gate * 1847*0Sstevel@tonic-gate * RETURNS : SUCCESS = It worked 1848*0Sstevel@tonic-gate * FAILURE = There was a problem. If the ldap add 1849*0Sstevel@tonic-gate * operation failed, ldap_rc will be set 1850*0Sstevel@tonic-gate * to the ldap error code. 1851*0Sstevel@tonic-gate */ 1852*0Sstevel@tonic-gate suc_code 1853*0Sstevel@tonic-gate addNISObject(char *domain, char *dn, int *ldap_rc) { 1854*0Sstevel@tonic-gate __nis_rule_value_t *rv; 1855*0Sstevel@tonic-gate int rc; 1856*0Sstevel@tonic-gate char *objClassAttrs = NULL, *attrs; 1857*0Sstevel@tonic-gate char *value, *svalue, *rdn = NULL; 1858*0Sstevel@tonic-gate char *myself = "addNISObject"; 1859*0Sstevel@tonic-gate 1860*0Sstevel@tonic-gate if (!dn) 1861*0Sstevel@tonic-gate return (FAILURE); 1862*0Sstevel@tonic-gate 1863*0Sstevel@tonic-gate if ((rv = initRuleValue(1, 0)) == 0) 1864*0Sstevel@tonic-gate return (FAILURE); 1865*0Sstevel@tonic-gate 1866*0Sstevel@tonic-gate if (ldap_rc) 1867*0Sstevel@tonic-gate *ldap_rc = -1; 1868*0Sstevel@tonic-gate 1869*0Sstevel@tonic-gate /* 1870*0Sstevel@tonic-gate * Add name=value pairs from RDN. Although this is not required 1871*0Sstevel@tonic-gate * for SunOne Directory Server, during openldap interoperabilty 1872*0Sstevel@tonic-gate * tests, it was found out that openldap server returned object 1873*0Sstevel@tonic-gate * class violation errors if MUST attributes were not specified 1874*0Sstevel@tonic-gate * explicitly. 1875*0Sstevel@tonic-gate */ 1876*0Sstevel@tonic-gate if (splitDN(dn, &rdn, 0) == -1) 1877*0Sstevel@tonic-gate return (FAILURE); 1878*0Sstevel@tonic-gate if (rdn != NULL) { 1879*0Sstevel@tonic-gate objClassAttrs = (char *)getObjectClass(rdn); 1880*0Sstevel@tonic-gate if (objClassAttrs == NULL) { 1881*0Sstevel@tonic-gate sfree(rdn); 1882*0Sstevel@tonic-gate return (FAILURE); 1883*0Sstevel@tonic-gate } 1884*0Sstevel@tonic-gate 1885*0Sstevel@tonic-gate /* 1886*0Sstevel@tonic-gate * RDN can be composed of multiple name=value pairs 1887*0Sstevel@tonic-gate * concatenated by '+'. Hence, we need to determine each 1888*0Sstevel@tonic-gate * pair and add it to 'rv' 1889*0Sstevel@tonic-gate */ 1890*0Sstevel@tonic-gate for (value = rdn, svalue = NULL; *value != '\0'; value++) { 1891*0Sstevel@tonic-gate if (*value == '+') { 1892*0Sstevel@tonic-gate /* Make sure it's not escaped */ 1893*0Sstevel@tonic-gate if (value == rdn || *(value - 1) != '\\') { 1894*0Sstevel@tonic-gate /* 1895*0Sstevel@tonic-gate * We are at the start of the new 1896*0Sstevel@tonic-gate * pair. 'svalue' now contains the 1897*0Sstevel@tonic-gate * value for the previous pair. Add 1898*0Sstevel@tonic-gate * the previous pair to 'rv' 1899*0Sstevel@tonic-gate */ 1900*0Sstevel@tonic-gate *value = '\0'; 1901*0Sstevel@tonic-gate if (svalue && 1902*0Sstevel@tonic-gate addSAttr2RuleValue(rdn, svalue, rv) 1903*0Sstevel@tonic-gate == -1) { 1904*0Sstevel@tonic-gate sfree(rdn); 1905*0Sstevel@tonic-gate freeRuleValue(rv, 1); 1906*0Sstevel@tonic-gate return (FAILURE); 1907*0Sstevel@tonic-gate } 1908*0Sstevel@tonic-gate svalue = NULL; 1909*0Sstevel@tonic-gate rdn = value + 1; 1910*0Sstevel@tonic-gate continue; 1911*0Sstevel@tonic-gate } 1912*0Sstevel@tonic-gate } 1913*0Sstevel@tonic-gate 1914*0Sstevel@tonic-gate if (*value == '=') { 1915*0Sstevel@tonic-gate if (value == rdn || *(value - 1) != '\\') { 1916*0Sstevel@tonic-gate /* 1917*0Sstevel@tonic-gate * 'rdn' now contains the name. 1918*0Sstevel@tonic-gate * Whatever follows till the next 1919*0Sstevel@tonic-gate * unescaped '+' or '\0' is the 1920*0Sstevel@tonic-gate * value for this pair. 1921*0Sstevel@tonic-gate */ 1922*0Sstevel@tonic-gate *value = '\0'; 1923*0Sstevel@tonic-gate svalue = value + 1; 1924*0Sstevel@tonic-gate continue; 1925*0Sstevel@tonic-gate } 1926*0Sstevel@tonic-gate } 1927*0Sstevel@tonic-gate } 1928*0Sstevel@tonic-gate 1929*0Sstevel@tonic-gate /* 1930*0Sstevel@tonic-gate * End of String. Add the previous name=value pair to 'rv' 1931*0Sstevel@tonic-gate */ 1932*0Sstevel@tonic-gate if (svalue && addSAttr2RuleValue(rdn, svalue, rv) == -1) { 1933*0Sstevel@tonic-gate sfree(rdn); 1934*0Sstevel@tonic-gate freeRuleValue(rv, 1); 1935*0Sstevel@tonic-gate return (FAILURE); 1936*0Sstevel@tonic-gate } 1937*0Sstevel@tonic-gate sfree(rdn); 1938*0Sstevel@tonic-gate } else /* rdn == NULL */ 1939*0Sstevel@tonic-gate return (FAILURE); 1940*0Sstevel@tonic-gate 1941*0Sstevel@tonic-gate /* Create the entry */ 1942*0Sstevel@tonic-gate if (domain) { 1943*0Sstevel@tonic-gate if (addSAttr2RuleValue("nisDomain", domain, rv) == -1) { 1944*0Sstevel@tonic-gate freeRuleValue(rv, 1); 1945*0Sstevel@tonic-gate return (FAILURE); 1946*0Sstevel@tonic-gate } 1947*0Sstevel@tonic-gate attrs = scat(myself, F, "objectclass=nisdomainobject,", 1948*0Sstevel@tonic-gate objClassAttrs); 1949*0Sstevel@tonic-gate if (!attrs) { 1950*0Sstevel@tonic-gate freeRuleValue(rv, 1); 1951*0Sstevel@tonic-gate return (FAILURE); 1952*0Sstevel@tonic-gate } 1953*0Sstevel@tonic-gate rc = ldapAdd(dn, rv, attrs, 0); 1954*0Sstevel@tonic-gate sfree(attrs); 1955*0Sstevel@tonic-gate } else { 1956*0Sstevel@tonic-gate rc = ldapAdd(dn, rv, objClassAttrs, 0); 1957*0Sstevel@tonic-gate } 1958*0Sstevel@tonic-gate 1959*0Sstevel@tonic-gate if (rc == LDAP_SUCCESS) 1960*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1961*0Sstevel@tonic-gate "%s: Entry (dn: %s) added to DIT", 1962*0Sstevel@tonic-gate myself, dn); 1963*0Sstevel@tonic-gate else if (rc == LDAP_ALREADY_EXISTS) 1964*0Sstevel@tonic-gate /* Treat this as success */ 1965*0Sstevel@tonic-gate rc = LDAP_SUCCESS; 1966*0Sstevel@tonic-gate else 1967*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1968*0Sstevel@tonic-gate "%s: ldapAdd error %d (%s) for (dn: %s)", 1969*0Sstevel@tonic-gate myself, rc, ldap_err2string(rc), dn); 1970*0Sstevel@tonic-gate 1971*0Sstevel@tonic-gate freeRuleValue(rv, 1); 1972*0Sstevel@tonic-gate if (ldap_rc) 1973*0Sstevel@tonic-gate *ldap_rc = rc; 1974*0Sstevel@tonic-gate return ((rc == LDAP_SUCCESS)?SUCCESS:FAILURE); 1975*0Sstevel@tonic-gate } 1976