10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*11262SRajagopal.Andra@Sun.COM * Common Development and Distribution License (the "License"). 6*11262SRajagopal.Andra@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*11262SRajagopal.Andra@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <lber.h> 280Sstevel@tonic-gate #include <ldap.h> 290Sstevel@tonic-gate #include <strings.h> 300Sstevel@tonic-gate #include <errno.h> 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include "nisdb_mt.h" 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include "ldap_util.h" 350Sstevel@tonic-gate #include "ldap_op.h" 360Sstevel@tonic-gate #include "ldap_ruleval.h" 370Sstevel@tonic-gate #include "ldap_attr.h" 380Sstevel@tonic-gate #include "ldap_val.h" 390Sstevel@tonic-gate #include "ldap_ldap.h" 400Sstevel@tonic-gate 410Sstevel@tonic-gate extern int yp2ldap; 420Sstevel@tonic-gate 430Sstevel@tonic-gate 440Sstevel@tonic-gate __nis_mapping_format_t * 450Sstevel@tonic-gate cloneMappingFormat(__nis_mapping_format_t *m) { 460Sstevel@tonic-gate __nis_mapping_format_t *new; 470Sstevel@tonic-gate int i, nf, err; 480Sstevel@tonic-gate char *myself = "cloneMappingFormat"; 490Sstevel@tonic-gate 500Sstevel@tonic-gate if (m == 0) 510Sstevel@tonic-gate return (0); 520Sstevel@tonic-gate 530Sstevel@tonic-gate for (nf = 0; m[nf].type != mmt_end; nf++); 540Sstevel@tonic-gate nf++; 550Sstevel@tonic-gate 560Sstevel@tonic-gate new = am(myself, nf * sizeof (new[0])); 570Sstevel@tonic-gate if (new == 0) 580Sstevel@tonic-gate return (0); 590Sstevel@tonic-gate 600Sstevel@tonic-gate /* Copy the whole array */ 610Sstevel@tonic-gate memcpy(new, m, nf * sizeof (new[0])); 620Sstevel@tonic-gate 630Sstevel@tonic-gate /* Make copies of allocated stuff */ 640Sstevel@tonic-gate for (i = 0, err = 0; i < nf; i++) { 650Sstevel@tonic-gate switch (m[i].type) { 660Sstevel@tonic-gate case mmt_string: 670Sstevel@tonic-gate new[i].match.string = sdup(myself, T, 680Sstevel@tonic-gate m[i].match.string); 690Sstevel@tonic-gate if (new[i].match.string == 0 && m[i].match.string != 0) 700Sstevel@tonic-gate err++; 710Sstevel@tonic-gate break; 720Sstevel@tonic-gate case mmt_single: 730Sstevel@tonic-gate new[i].match.single.lo = 740Sstevel@tonic-gate am(myself, m[i].match.single.numRange * 750Sstevel@tonic-gate sizeof (new[i].match.single.lo[0])); 760Sstevel@tonic-gate new[i].match.single.hi = 770Sstevel@tonic-gate am(myself, m[i].match.single.numRange * 780Sstevel@tonic-gate sizeof (new[i].match.single.hi[0])); 790Sstevel@tonic-gate if (new[i].match.single.lo != 0) 800Sstevel@tonic-gate memcpy(new[i].match.single.lo, 810Sstevel@tonic-gate m[i].match.single.lo, 820Sstevel@tonic-gate m[i].match.single.numRange); 830Sstevel@tonic-gate else if (m[i].match.single.lo != 0) 840Sstevel@tonic-gate err++; 850Sstevel@tonic-gate if (new[i].match.single.hi != 0) 860Sstevel@tonic-gate memcpy(new[i].match.single.hi, 870Sstevel@tonic-gate m[i].match.single.hi, 880Sstevel@tonic-gate m[i].match.single.numRange); 890Sstevel@tonic-gate else if (m[i].match.single.hi != 0) 900Sstevel@tonic-gate err++; 910Sstevel@tonic-gate break; 920Sstevel@tonic-gate case mmt_berstring: 930Sstevel@tonic-gate new[i].match.berString = sdup(myself, T, 940Sstevel@tonic-gate m[i].match.berString); 950Sstevel@tonic-gate if (new[i].match.berString == 0 && 960Sstevel@tonic-gate m[i].match.berString != 0) 970Sstevel@tonic-gate err++; 980Sstevel@tonic-gate break; 990Sstevel@tonic-gate case mmt_item: 1000Sstevel@tonic-gate case mmt_limit: 1010Sstevel@tonic-gate case mmt_any: 1020Sstevel@tonic-gate case mmt_begin: 1030Sstevel@tonic-gate case mmt_end: 1040Sstevel@tonic-gate default: 1050Sstevel@tonic-gate break; 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate /* If there were memory allocation errors, free the copy */ 1100Sstevel@tonic-gate if (err > 0) { 1110Sstevel@tonic-gate freeMappingFormat(new); 1120Sstevel@tonic-gate new = 0; 1130Sstevel@tonic-gate } 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate return (new); 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate void 1190Sstevel@tonic-gate freeMappingFormat(__nis_mapping_format_t *m) { 1200Sstevel@tonic-gate int i; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate if (m == 0) 1230Sstevel@tonic-gate return; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate for (i = 0; m[i].type != mmt_end; i++) { 1260Sstevel@tonic-gate switch (m[i].type) { 1270Sstevel@tonic-gate case mmt_string: 1280Sstevel@tonic-gate sfree(m[i].match.string); 1290Sstevel@tonic-gate break; 1300Sstevel@tonic-gate case mmt_single: 1310Sstevel@tonic-gate sfree(m[i].match.single.lo); 1320Sstevel@tonic-gate sfree(m[i].match.single.hi); 1330Sstevel@tonic-gate break; 1340Sstevel@tonic-gate case mmt_berstring: 1350Sstevel@tonic-gate sfree(m[i].match.berString); 1360Sstevel@tonic-gate break; 1370Sstevel@tonic-gate case mmt_item: 1380Sstevel@tonic-gate case mmt_limit: 1390Sstevel@tonic-gate case mmt_any: 1400Sstevel@tonic-gate case mmt_begin: 1410Sstevel@tonic-gate case mmt_end: 1420Sstevel@tonic-gate default: 1430Sstevel@tonic-gate break; 1440Sstevel@tonic-gate } 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate free(m); 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate void 1520Sstevel@tonic-gate copyIndex(__nis_index_t *old, __nis_index_t *new, int *err) { 1530Sstevel@tonic-gate int i; 1540Sstevel@tonic-gate char *myself = "copyIndex"; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate if (old == 0 || new == 0) { 1570Sstevel@tonic-gate *err = EINVAL; 1580Sstevel@tonic-gate return; 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate for (i = 0; i < old->numIndexes; i++) { 1620Sstevel@tonic-gate new->name[i] = sdup(myself, T, old->name[i]); 1630Sstevel@tonic-gate if (new->name[i] == 0 && old->name[i] != 0) { 1640Sstevel@tonic-gate *err = ENOMEM; 1650Sstevel@tonic-gate return; 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate new->value[i] = cloneMappingFormat(old->value[i]); 1680Sstevel@tonic-gate if (new->value[i] == 0 && old->value[i] != 0) { 1690Sstevel@tonic-gate *err = ENOMEM; 1700Sstevel@tonic-gate return; 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate new->numIndexes = old->numIndexes; 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate __nis_index_t * 1780Sstevel@tonic-gate cloneIndex(__nis_index_t *old) { 1790Sstevel@tonic-gate char *myself = "cloneIndex"; 1800Sstevel@tonic-gate int err = 0; 1810Sstevel@tonic-gate __nis_index_t *new = am(myself, sizeof (*new)); 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate if (old == 0) 1840Sstevel@tonic-gate return (0); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate if (new != 0) { 1870Sstevel@tonic-gate copyIndex(old, new, &err); 1880Sstevel@tonic-gate if (err != 0) { 1890Sstevel@tonic-gate freeIndex(new, 1); 1900Sstevel@tonic-gate new = 0; 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate } 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate return (new); 1950Sstevel@tonic-gate } 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate void 1980Sstevel@tonic-gate freeIndex(__nis_index_t *old, bool_t doFree) { 1990Sstevel@tonic-gate int i; 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate if (old == 0) 2020Sstevel@tonic-gate return; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate for (i = 0; i < old->numIndexes; i++) { 2050Sstevel@tonic-gate sfree(old->name[i]); 2060Sstevel@tonic-gate freeMappingFormat(old->value[i]); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate if (doFree) 2100Sstevel@tonic-gate free(old); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate char ** 2140Sstevel@tonic-gate cloneName(char **name, int numNames) { 2150Sstevel@tonic-gate char **new; 2160Sstevel@tonic-gate int i; 2170Sstevel@tonic-gate char *myself = "cloneName"; 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate if (name == 0 || numNames <= 0) 2200Sstevel@tonic-gate return (0); 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate new = am(myself, numNames * sizeof (new[0])); 2230Sstevel@tonic-gate if (new == 0) 2240Sstevel@tonic-gate return (0); 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate for (i = 0; i < numNames; i++) { 2270Sstevel@tonic-gate if (name[i] != 0) { 2280Sstevel@tonic-gate new[i] = sdup(myself, T, name[i]); 2290Sstevel@tonic-gate if (new[i] == 0) { 2300Sstevel@tonic-gate for (i--; i >= 0; i--) { 2310Sstevel@tonic-gate sfree(new[i]); 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate sfree(new); 2340Sstevel@tonic-gate return (0); 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate } else { 2370Sstevel@tonic-gate new[i] = 0; 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate return (new); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate void 2450Sstevel@tonic-gate freeValue(__nis_value_t *val, int count) { 2460Sstevel@tonic-gate int c, i; 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate if (val == 0) 2490Sstevel@tonic-gate return; 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate for (c = 0; c < count; c++) { 2520Sstevel@tonic-gate if (val[c].val != 0) { 2530Sstevel@tonic-gate for (i = 0; i < val[c].numVals; i++) { 2540Sstevel@tonic-gate sfree(val[c].val[i].value); 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate free(val[c].val); 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate free(val); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate __nis_value_t * 2640Sstevel@tonic-gate cloneValue(__nis_value_t *val, int count) { 2650Sstevel@tonic-gate __nis_value_t *n; 2660Sstevel@tonic-gate int c, i; 2670Sstevel@tonic-gate char *myself = "cloneValue"; 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate if (count <= 0 || val == 0) 2700Sstevel@tonic-gate return (0); 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate n = am(myself, count * sizeof (*n)); 2730Sstevel@tonic-gate if (n == 0) 2740Sstevel@tonic-gate return (0); 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate for (c = 0; c < count; c++) { 2770Sstevel@tonic-gate n[c].type = val[c].type; 2780Sstevel@tonic-gate n[c].repeat = val[c].repeat; 2790Sstevel@tonic-gate n[c].numVals = val[c].numVals; 2800Sstevel@tonic-gate if (n[c].numVals > 0) { 2810Sstevel@tonic-gate n[c].val = am(myself, n[c].numVals * 2820Sstevel@tonic-gate sizeof (n[c].val[0])); 2830Sstevel@tonic-gate if (n[c].val == 0) { 2840Sstevel@tonic-gate freeValue(n, c); 2850Sstevel@tonic-gate return (0); 2860Sstevel@tonic-gate } 2870Sstevel@tonic-gate } else { 2880Sstevel@tonic-gate n[c].val = 0; 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate for (i = 0; i < n[c].numVals; i++) { 2910Sstevel@tonic-gate int amlen = val[c].val[i].length; 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * The functions that create string values try to 2950Sstevel@tonic-gate * make sure that there's a NUL at the end. However, 2960Sstevel@tonic-gate * both NIS+ and LDAP have a tendency to store strings 2970Sstevel@tonic-gate * without a NUL, so the value length may not include 2980Sstevel@tonic-gate * the NUL (even though it's there). In order to 2990Sstevel@tonic-gate * preserve that NUL, we add a byte to the length if 3000Sstevel@tonic-gate * the type is vt_string, and there isn't already a 3010Sstevel@tonic-gate * NUL at the end. The memory allocation function 3020Sstevel@tonic-gate * (am()) will take care of actually putting the NUL 3030Sstevel@tonic-gate * in place, since it allocates zero-initialized 3040Sstevel@tonic-gate * memory. 3050Sstevel@tonic-gate */ 3060Sstevel@tonic-gate n[c].val[i].length = val[c].val[i].length; 3070Sstevel@tonic-gate if (n[c].type == vt_string && amlen > 0 && 3080Sstevel@tonic-gate ((char *)val[c].val[i].value)[amlen-1] != 3090Sstevel@tonic-gate '\0') { 3100Sstevel@tonic-gate amlen++; 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate n[c].val[i].value = am(myself, amlen); 3130Sstevel@tonic-gate if (amlen > 0 && n[c].val[i].value == 0) { 3140Sstevel@tonic-gate freeValue(n, c); 3150Sstevel@tonic-gate return (0); 3160Sstevel@tonic-gate } 3170Sstevel@tonic-gate memcpy(n[c].val[i].value, val[c].val[i].value, 3180Sstevel@tonic-gate n[c].val[i].length); 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate return (n); 3230Sstevel@tonic-gate } 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate /* Define LBER_USE_DER per ber_decode(3LDAP) */ 3260Sstevel@tonic-gate #ifndef LBER_USE_DER 3270Sstevel@tonic-gate #define LBER_USE_DER 0x01 3280Sstevel@tonic-gate #endif /* LBER_USE_DER */ 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate /* 3310Sstevel@tonic-gate * Return a copy of 'valIn' where each value has been replaced by the 3320Sstevel@tonic-gate * BER encoded equivalent specified by 'berstring'. 'valIn' is unchanged. 3330Sstevel@tonic-gate */ 3340Sstevel@tonic-gate __nis_value_t * 3350Sstevel@tonic-gate berEncode(__nis_value_t *valIn, char *berstring) { 3360Sstevel@tonic-gate char *myself = "berEncode"; 3370Sstevel@tonic-gate __nis_value_t *val; 3380Sstevel@tonic-gate int i; 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate if (valIn == 0 || berstring == 0) 3410Sstevel@tonic-gate return (0); 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate val = cloneValue(valIn, 1); 3440Sstevel@tonic-gate if (val == 0) 3450Sstevel@tonic-gate return (0); 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 3480Sstevel@tonic-gate BerElement *ber = ber_alloc(); 3490Sstevel@tonic-gate struct berval *bv = 0; 3500Sstevel@tonic-gate int ret; 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate if (ber == 0) { 3530Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "%s: ber_alloc() => NULL", 3540Sstevel@tonic-gate myself); 3550Sstevel@tonic-gate freeValue(val, 1); 3560Sstevel@tonic-gate return (0); 3570Sstevel@tonic-gate } 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate if ((strcmp("b", berstring) == 0 || 3600Sstevel@tonic-gate strcmp("i", berstring) == 0)) { 3610Sstevel@tonic-gate if (val->val[i].length >= sizeof (int)) { 3620Sstevel@tonic-gate ret = ber_printf(ber, berstring, 3630Sstevel@tonic-gate *((int *)(val->val[i].value))); 3640Sstevel@tonic-gate } else { 3650Sstevel@tonic-gate ret = -1; 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate } else if (strcmp("B", berstring) == 0) { 3680Sstevel@tonic-gate ret = ber_printf(ber, berstring, 3690Sstevel@tonic-gate val->val[i].value, 3700Sstevel@tonic-gate val->val[i].length * 8); 3710Sstevel@tonic-gate } else if (strcmp("n", berstring) == 0) { 3720Sstevel@tonic-gate ret = ber_printf(ber, berstring); 3730Sstevel@tonic-gate } else if (strcmp("o", berstring) == 0) { 3740Sstevel@tonic-gate ret = ber_printf(ber, berstring, 3750Sstevel@tonic-gate val->val[i].value, val->val[i].length); 3760Sstevel@tonic-gate } else if (strcmp("s", berstring) == 0) { 3770Sstevel@tonic-gate char *str = am(myself, val->val[i].length + 1); 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate if (str != 0) { 3800Sstevel@tonic-gate ret = ber_printf(ber, berstring, str); 3810Sstevel@tonic-gate free(str); 3820Sstevel@tonic-gate } else { 3830Sstevel@tonic-gate ret = -1; 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate } else { 3860Sstevel@tonic-gate ret = -1; 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate if (ret == -1) { 3900Sstevel@tonic-gate reportError(NPL_BERENCODE, "%s: BER encoding error", 3910Sstevel@tonic-gate myself); 3920Sstevel@tonic-gate ber_free(ber, 1); 3930Sstevel@tonic-gate freeValue(val, 1); 3940Sstevel@tonic-gate return (0); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate if (ber_flatten(ber, &bv) != 0 || bv == 0) { 3980Sstevel@tonic-gate reportError(NPL_BERENCODE, "%s: ber_flatten() error", 3990Sstevel@tonic-gate myself); 4000Sstevel@tonic-gate ber_free(ber, 1); 4010Sstevel@tonic-gate freeValue(val, 1); 4020Sstevel@tonic-gate return (0); 4030Sstevel@tonic-gate } 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate sfree(val->val[i].value); 4060Sstevel@tonic-gate val->val[i].length = bv->bv_len; 4070Sstevel@tonic-gate val->val[i].value = bv->bv_val; 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate ber_free(ber, 1); 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate val->type = vt_ber; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate return (val); 4150Sstevel@tonic-gate } 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate __nis_value_t * 4180Sstevel@tonic-gate berDecode(__nis_value_t *valIn, char *berstring) { 4190Sstevel@tonic-gate __nis_value_t *val; 4200Sstevel@tonic-gate int i; 4210Sstevel@tonic-gate char *myself = "berDecode"; 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate if (valIn == 0 || berstring == 0) 4240Sstevel@tonic-gate return (0); 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate val = cloneValue(valIn, 1); 4270Sstevel@tonic-gate if (val == 0) 4280Sstevel@tonic-gate return (0); 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 4310Sstevel@tonic-gate void *v = 0; 4320Sstevel@tonic-gate int ret, len = 0; 4330Sstevel@tonic-gate struct berval bv; 4340Sstevel@tonic-gate BerElement *ber; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate if (val->val[i].value == 0 || val->val[i].length <= 0) 4370Sstevel@tonic-gate continue; 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate bv.bv_val = val->val[i].value; 4400Sstevel@tonic-gate bv.bv_len = val->val[i].length; 4410Sstevel@tonic-gate ber = ber_init(&bv); 4420Sstevel@tonic-gate if (ber == 0) { 4430Sstevel@tonic-gate reportError(NPL_BERDECODE, "%s: ber_init() error", 4440Sstevel@tonic-gate myself); 4450Sstevel@tonic-gate freeValue(val, 1); 4460Sstevel@tonic-gate return (0); 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate if ((strcmp("b", berstring) == 0 || 4500Sstevel@tonic-gate strcmp("i", berstring) == 0)) { 4510Sstevel@tonic-gate len = sizeof (int); 4520Sstevel@tonic-gate v = am(myself, len); 4530Sstevel@tonic-gate if (v != 0) { 4540Sstevel@tonic-gate ret = ber_scanf(ber, berstring, v); 4550Sstevel@tonic-gate } else { 4560Sstevel@tonic-gate ret = -1; 4570Sstevel@tonic-gate } 4580Sstevel@tonic-gate } else if (strcmp("B", berstring) == 0) { 4590Sstevel@tonic-gate long llen; 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate ret = ber_scanf(ber, berstring, &v, &llen); 4620Sstevel@tonic-gate if (ret != -1) { 4630Sstevel@tonic-gate len = llen/8; 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate } else if (strcmp("n", berstring) == 0) { 4660Sstevel@tonic-gate ret = 0; 4670Sstevel@tonic-gate } else if (strcmp("o", berstring) == 0) { 4680Sstevel@tonic-gate struct berval *bv = am(myself, sizeof (*bv)); 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate if (bv != 0) { 4710Sstevel@tonic-gate ret = ber_scanf(ber, "O", &bv); 4720Sstevel@tonic-gate if (ret != -1 && bv != 0) { 4730Sstevel@tonic-gate v = bv->bv_val; 4740Sstevel@tonic-gate len = bv->bv_len; 4750Sstevel@tonic-gate } else { 4760Sstevel@tonic-gate ret = -1; 4770Sstevel@tonic-gate } 4780Sstevel@tonic-gate /* Only free 'bv' itself */ 4790Sstevel@tonic-gate free(bv); 4800Sstevel@tonic-gate } else { 4810Sstevel@tonic-gate ret = -1; 4820Sstevel@tonic-gate } 4830Sstevel@tonic-gate } else if (strcmp("s", berstring) == 0) { 4840Sstevel@tonic-gate ret = ber_scanf(ber, "a", &v); 4850Sstevel@tonic-gate if (ret != -1) { 4860Sstevel@tonic-gate len = slen(v); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate } else { 4890Sstevel@tonic-gate ret = -1; 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate if (ret == -1) { 4930Sstevel@tonic-gate reportError(NPL_BERDECODE, "%s: BER decoding error", 4940Sstevel@tonic-gate myself); 4950Sstevel@tonic-gate freeValue(val, 1); 4960Sstevel@tonic-gate return (0); 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate /* Free the old value, and replace it with the decoded one */ 5000Sstevel@tonic-gate sfree(val->val[i].value); 5010Sstevel@tonic-gate val->val[i].value = v; 5020Sstevel@tonic-gate val->val[i].length = len; 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate return (val); 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /* 5090Sstevel@tonic-gate * Return the value of the specified item. 5100Sstevel@tonic-gate */ 5110Sstevel@tonic-gate __nis_value_t * 5120Sstevel@tonic-gate getMappingItemVal(__nis_mapping_item_t *item, __nis_mapping_item_type_t native, 5130Sstevel@tonic-gate __nis_rule_value_t *rv, char *berstring, int *np_ldap_stat) { 5140Sstevel@tonic-gate __nis_value_t *val = 0, *nameVal, *exVal = 0; 5150Sstevel@tonic-gate int numName, caseInsens, cmp; 5160Sstevel@tonic-gate int i, j, k; 5170Sstevel@tonic-gate char **name; 5180Sstevel@tonic-gate enum {rvOnly, rvThenLookup, lookupOnly} check; 5190Sstevel@tonic-gate unsigned char fromldap = '\0'; 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate if (item == 0) 5220Sstevel@tonic-gate return (0); 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate /* 5250Sstevel@tonic-gate * First, we decide if we should look for the value in 'rv', 5260Sstevel@tonic-gate * directly from NIS+/LDAP, or both. 5270Sstevel@tonic-gate */ 5280Sstevel@tonic-gate switch (item->type) { 5290Sstevel@tonic-gate case mit_nisplus: 5300Sstevel@tonic-gate /* Do we have a valid index/object spec ? */ 5310Sstevel@tonic-gate if (item->searchSpec.obj.index.numIndexes <= 0 && 5320Sstevel@tonic-gate item->searchSpec.obj.name == 0) { 5330Sstevel@tonic-gate /* 5340Sstevel@tonic-gate * No valid index/object. If we have a rule-value, 5350Sstevel@tonic-gate * use it. Otherwise, return error. 5360Sstevel@tonic-gate */ 5370Sstevel@tonic-gate if (rv != 0) { 5380Sstevel@tonic-gate name = rv->colName; 5390Sstevel@tonic-gate nameVal = rv->colVal; 5400Sstevel@tonic-gate numName = rv->numColumns; 5410Sstevel@tonic-gate caseInsens = 0; 5420Sstevel@tonic-gate check = rvOnly; 5430Sstevel@tonic-gate } else { 5440Sstevel@tonic-gate return (0); 5450Sstevel@tonic-gate } 5460Sstevel@tonic-gate } else { 5470Sstevel@tonic-gate /* 5480Sstevel@tonic-gate * Valid index, so skip the rule-value and do 5490Sstevel@tonic-gate * a direct NIS+ lookup. 5500Sstevel@tonic-gate */ 5510Sstevel@tonic-gate check = lookupOnly; 5520Sstevel@tonic-gate } 5530Sstevel@tonic-gate break; 5540Sstevel@tonic-gate case mit_ldap: 5550Sstevel@tonic-gate if (rv != 0) { 5560Sstevel@tonic-gate name = rv->attrName; 5570Sstevel@tonic-gate nameVal = rv->attrVal; 5580Sstevel@tonic-gate numName = rv->numAttrs; 5590Sstevel@tonic-gate caseInsens = 1; 5600Sstevel@tonic-gate fromldap = '1'; 5610Sstevel@tonic-gate } 5620Sstevel@tonic-gate /* Do we have a valid triple ? */ 5630Sstevel@tonic-gate if (item->searchSpec.triple.scope == LDAP_SCOPE_UNKNOWN) { 5640Sstevel@tonic-gate /* 5650Sstevel@tonic-gate * No valid triple. If we have a rule-value, use it. 5660Sstevel@tonic-gate * Otherwise, return error. 5670Sstevel@tonic-gate */ 5680Sstevel@tonic-gate if (rv != 0) { 5690Sstevel@tonic-gate check = rvOnly; 5700Sstevel@tonic-gate } else { 5710Sstevel@tonic-gate return (0); 5720Sstevel@tonic-gate } 5730Sstevel@tonic-gate } else if (item->searchSpec.triple.base == 0 && 5740Sstevel@tonic-gate item->searchSpec.triple.scope == 5750Sstevel@tonic-gate LDAP_SCOPE_ONELEVEL && 5760Sstevel@tonic-gate item->searchSpec.triple.attrs == 0 && 5770Sstevel@tonic-gate item->searchSpec.triple.element == 0) { 5780Sstevel@tonic-gate /* 5790Sstevel@tonic-gate * We have a valid triple, but it points to the 5800Sstevel@tonic-gate * current LDAP container. Thus, first look in 5810Sstevel@tonic-gate * the rule-value; if that fails, perform a direct 5820Sstevel@tonic-gate * LDAP lookup. 5830Sstevel@tonic-gate */ 5840Sstevel@tonic-gate if (rv != 0) { 5850Sstevel@tonic-gate check = rvThenLookup; 5860Sstevel@tonic-gate } else { 5870Sstevel@tonic-gate check = lookupOnly; 5880Sstevel@tonic-gate } 5890Sstevel@tonic-gate } else { 5900Sstevel@tonic-gate /* 5910Sstevel@tonic-gate * Valid triple, and it's not the current container 5920Sstevel@tonic-gate * (at least not in the trivial sense). Hence, do 5930Sstevel@tonic-gate * a direct LDAP lookup. 5940Sstevel@tonic-gate */ 5950Sstevel@tonic-gate check = lookupOnly; 5960Sstevel@tonic-gate } 5970Sstevel@tonic-gate break; 5980Sstevel@tonic-gate default: 5990Sstevel@tonic-gate return (0); 6000Sstevel@tonic-gate } 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate /* Check the rule-value */ 6030Sstevel@tonic-gate if (check == rvOnly || check == rvThenLookup) { 6040Sstevel@tonic-gate for (i = 0; i < numName; i++) { 6050Sstevel@tonic-gate if (caseInsens) 6060Sstevel@tonic-gate cmp = strcasecmp(item->name, name[i]); 6070Sstevel@tonic-gate else 6080Sstevel@tonic-gate cmp = strcmp(item->name, name[i]); 6090Sstevel@tonic-gate if (cmp == 0) { 6100Sstevel@tonic-gate if (nameVal[i].numVals <= 0) 6110Sstevel@tonic-gate break; 6120Sstevel@tonic-gate if (berstring == 0) { 6130Sstevel@tonic-gate val = cloneValue(&nameVal[i], 1); 6140Sstevel@tonic-gate } else if (yp2ldap && berstring[0] == 'a') { 6150Sstevel@tonic-gate val = cloneValue(&nameVal[i], 1); 6160Sstevel@tonic-gate } else { 6170Sstevel@tonic-gate val = berDecode(&nameVal[i], 6180Sstevel@tonic-gate berstring); 6190Sstevel@tonic-gate } 6200Sstevel@tonic-gate if (val != 0) { 6210Sstevel@tonic-gate val->repeat = item->repeat; 6220Sstevel@tonic-gate /* 6230Sstevel@tonic-gate * If value for nis+ column is 6240Sstevel@tonic-gate * passed with value, val is 6250Sstevel@tonic-gate * manipulated in cloneValue(). 6260Sstevel@tonic-gate * To decide whether there are 6270Sstevel@tonic-gate * enough nis+ column values 6280Sstevel@tonic-gate * for rule to produce a value, 6290Sstevel@tonic-gate * we need nis+ column values 6300Sstevel@tonic-gate * as well as nis_mapping_element 6310Sstevel@tonic-gate * from the rule. If we are here, 6320Sstevel@tonic-gate * it indicates that the 'val has 6330Sstevel@tonic-gate * an valid value for the column 6340Sstevel@tonic-gate * item-> name. So set 6350Sstevel@tonic-gate * NP_LDAP_MAP_SUCCESS 6360Sstevel@tonic-gate * to np_ldap-stat. 6370Sstevel@tonic-gate */ 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate if (np_ldap_stat != NULL) 6400Sstevel@tonic-gate *np_ldap_stat = 6410Sstevel@tonic-gate NP_LDAP_MAP_SUCCESS; 6420Sstevel@tonic-gate } 6430Sstevel@tonic-gate break; 6440Sstevel@tonic-gate } 6450Sstevel@tonic-gate } 6460Sstevel@tonic-gate } 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate /* Do a direct lookup ? */ 6490Sstevel@tonic-gate if (val == 0 && (check == rvThenLookup || check == lookupOnly)) { 650*11262SRajagopal.Andra@Sun.COM if (item->type == mit_ldap) { 6510Sstevel@tonic-gate int err = 0; 6520Sstevel@tonic-gate __nis_search_triple_t triple; 6530Sstevel@tonic-gate char *baseDN; 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate /* 6560Sstevel@tonic-gate * If item->searchSpec.triple.base is NULL, or ends 6570Sstevel@tonic-gate * in a comma, append the current search base from 6580Sstevel@tonic-gate * the TSD (put there by an upper layer). 6590Sstevel@tonic-gate * 6600Sstevel@tonic-gate * Special case for N2L mode: 6610Sstevel@tonic-gate * if item->searchSpec.triple.base ends in a comma, 6620Sstevel@tonic-gate * the current domain Context is used. 6630Sstevel@tonic-gate */ 6640Sstevel@tonic-gate if (yp2ldap && item->searchSpec.triple.base && 6650Sstevel@tonic-gate strlen(item->searchSpec.triple.base) > 0) { 6660Sstevel@tonic-gate baseDN = __nisdb_get_tsd()->domainContext; 6670Sstevel@tonic-gate } else { 6680Sstevel@tonic-gate baseDN = __nisdb_get_tsd()->searchBase; 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate triple.base = appendBase(item->searchSpec.triple.base, 6710Sstevel@tonic-gate baseDN, &err, 0); 6720Sstevel@tonic-gate if (err == 0) { 6730Sstevel@tonic-gate triple.scope = item->searchSpec.triple.scope; 6740Sstevel@tonic-gate triple.attrs = item->searchSpec.triple.attrs; 6750Sstevel@tonic-gate triple.element = 6760Sstevel@tonic-gate item->searchSpec.triple.element; 6770Sstevel@tonic-gate val = lookupLDAP(&triple, item->name, rv, 0, 6780Sstevel@tonic-gate np_ldap_stat); 6790Sstevel@tonic-gate fromldap = '1'; 6800Sstevel@tonic-gate } else { 6810Sstevel@tonic-gate val = 0; 6820Sstevel@tonic-gate } 6830Sstevel@tonic-gate sfree(triple.base); 6840Sstevel@tonic-gate } 6850Sstevel@tonic-gate } 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate /* Special processing for NIS to LDAP mode */ 6890Sstevel@tonic-gate if (yp2ldap && val != 0) { 6900Sstevel@tonic-gate 6910Sstevel@tonic-gate /* 6920Sstevel@tonic-gate * Escape special chars from dn before sending to DIT, 6930Sstevel@tonic-gate * provided val is not ldap-based 6940Sstevel@tonic-gate */ 6950Sstevel@tonic-gate if (fromldap == '\0' && __nisdb_get_tsd()->escapeFlag == '1') { 6960Sstevel@tonic-gate if (escapeSpecialChars(val) < 0) { 6970Sstevel@tonic-gate freeValue(val, 1); 6980Sstevel@tonic-gate return (0); 6990Sstevel@tonic-gate } 7000Sstevel@tonic-gate } else if (__nisdb_get_tsd()->escapeFlag == '2') { 7010Sstevel@tonic-gate /* Remove escape chars from data received from DIT */ 7020Sstevel@tonic-gate (void) removeEscapeChars(val); 7030Sstevel@tonic-gate } 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate /* 7060Sstevel@tonic-gate * Remove from 'val', any values obtained using 7070Sstevel@tonic-gate * the 'removespec' syntax 7080Sstevel@tonic-gate */ 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate /* Obtain exVal */ 7110Sstevel@tonic-gate if (item->exItem) 7120Sstevel@tonic-gate exVal = getMappingItemVal(item->exItem, native, rv, 7130Sstevel@tonic-gate berstring, NULL); 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate /* delete */ 7160Sstevel@tonic-gate if (exVal != 0) { 7170Sstevel@tonic-gate for (i = 0; i < val->numVals; ) { 7180Sstevel@tonic-gate for (j = 0; j < exVal->numVals; j++) { 7190Sstevel@tonic-gate if (sstrncmp(val->val[i].value, 7200Sstevel@tonic-gate exVal->val[j].value, 7210Sstevel@tonic-gate MAX(val->val[i].length, 7220Sstevel@tonic-gate exVal->val[j].length)) 7230Sstevel@tonic-gate == 0) 7240Sstevel@tonic-gate break; 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate if (j < exVal->numVals) { 7270Sstevel@tonic-gate sfree(val->val[i].value); 7280Sstevel@tonic-gate val->val[i].value = 0; 7290Sstevel@tonic-gate val->val[i].length = 0; 7300Sstevel@tonic-gate for (k = i; k < val->numVals - 1; k++) { 7310Sstevel@tonic-gate val->val[k] = val->val[k + 1]; 7320Sstevel@tonic-gate val->val[k + 1].value = 0; 7330Sstevel@tonic-gate val->val[k + 1].length = 0; 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate val->numVals--; 7360Sstevel@tonic-gate } else 7370Sstevel@tonic-gate i++; 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate freeValue(exVal, 1); 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate /* 7430Sstevel@tonic-gate * If val->numVals <= 0, then we have no val to 7440Sstevel@tonic-gate * return. So free up stuff. 7450Sstevel@tonic-gate */ 7460Sstevel@tonic-gate if (val->numVals <= 0) { 7470Sstevel@tonic-gate free(val->val); 7480Sstevel@tonic-gate val->val = 0; 7490Sstevel@tonic-gate free(val); 7500Sstevel@tonic-gate return (0); 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate } 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate return (val); 7560Sstevel@tonic-gate } 7570Sstevel@tonic-gate 7580Sstevel@tonic-gate __nis_value_t * 7590Sstevel@tonic-gate getMappingFormat(__nis_mapping_format_t *f, __nis_rule_value_t *rv, 7600Sstevel@tonic-gate __nis_format_arg_t at, void *a, int *numArg) { 7610Sstevel@tonic-gate char *myself = "getMappingFormat"; 7620Sstevel@tonic-gate __nis_value_t *val = 0; 7630Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 7640Sstevel@tonic-gate int i; 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate if (f == 0) 7670Sstevel@tonic-gate return (0); 7680Sstevel@tonic-gate 7690Sstevel@tonic-gate if (rv == 0) { 7700Sstevel@tonic-gate val = am(myself, sizeof (*val)); 7710Sstevel@tonic-gate if (val == 0) 7720Sstevel@tonic-gate return (0); 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate switch (f->type) { 7750Sstevel@tonic-gate case mmt_item: 7760Sstevel@tonic-gate bp2buf(myself, &b, "%%s"); 7770Sstevel@tonic-gate break; 7780Sstevel@tonic-gate case mmt_string: 7790Sstevel@tonic-gate bp2buf(myself, &b, "%s", NIL(f->match.string)); 7800Sstevel@tonic-gate break; 7810Sstevel@tonic-gate case mmt_single: 7820Sstevel@tonic-gate bp2buf(myself, &b, "["); 7830Sstevel@tonic-gate for (i = 0; i < f->match.single.numRange; i++) { 7840Sstevel@tonic-gate if (f->match.single.lo[i] == 7850Sstevel@tonic-gate f->match.single.hi[i]) 7860Sstevel@tonic-gate bp2buf(myself, &b, "%c", 7870Sstevel@tonic-gate f->match.single.lo[i]); 7880Sstevel@tonic-gate else 7890Sstevel@tonic-gate bp2buf(myself, &b, "%c-%c", 7900Sstevel@tonic-gate f->match.single.lo[i], 7910Sstevel@tonic-gate f->match.single.hi[i]); 7920Sstevel@tonic-gate } 7930Sstevel@tonic-gate bp2buf(myself, &b, "]"); 7940Sstevel@tonic-gate break; 7950Sstevel@tonic-gate case mmt_limit: 7960Sstevel@tonic-gate break; 7970Sstevel@tonic-gate case mmt_any: 7980Sstevel@tonic-gate bp2buf(myself, &b, "*"); 7990Sstevel@tonic-gate break; 8000Sstevel@tonic-gate case mmt_berstring: 8010Sstevel@tonic-gate bp2buf(myself, &b, "%s", NIL(f->match.berString)); 8020Sstevel@tonic-gate break; 8030Sstevel@tonic-gate case mmt_begin: 8040Sstevel@tonic-gate case mmt_end: 8050Sstevel@tonic-gate bp2buf(myself, &b, "\""); 8060Sstevel@tonic-gate break; 8070Sstevel@tonic-gate default: 8080Sstevel@tonic-gate bp2buf(myself, &b, "<unknown>"); 8090Sstevel@tonic-gate } 8100Sstevel@tonic-gate val->type = vt_string; 8110Sstevel@tonic-gate val->numVals = 1; 8120Sstevel@tonic-gate val->val = am(myself, sizeof (val->val[0])); 8130Sstevel@tonic-gate if (val->val == 0) { 8140Sstevel@tonic-gate sfree(val); 8150Sstevel@tonic-gate return (0); 8160Sstevel@tonic-gate } 8170Sstevel@tonic-gate val->val[0].value = b.buf; 8180Sstevel@tonic-gate val->val[0].length = b.len; 8190Sstevel@tonic-gate } else { 8200Sstevel@tonic-gate switch (f->type) { 8210Sstevel@tonic-gate case mmt_item: 8220Sstevel@tonic-gate case mmt_berstring: 8230Sstevel@tonic-gate if (a != 0) { 8240Sstevel@tonic-gate if (at == fa_item) { 8250Sstevel@tonic-gate val = getMappingItemVal( 8260Sstevel@tonic-gate (__nis_mapping_item_t *)a, 8270Sstevel@tonic-gate mit_any, rv, 8280Sstevel@tonic-gate (f->type == mmt_berstring) ? f->match.berString : 0, NULL); 8290Sstevel@tonic-gate if (numArg != 0) 8300Sstevel@tonic-gate (*numArg)++; 8310Sstevel@tonic-gate } else { 8320Sstevel@tonic-gate val = cloneValue( 8330Sstevel@tonic-gate (__nis_value_t *)a, 1); 8340Sstevel@tonic-gate if (numArg != 0) 8350Sstevel@tonic-gate (*numArg)++; 8360Sstevel@tonic-gate } 8370Sstevel@tonic-gate } 8380Sstevel@tonic-gate break; 8390Sstevel@tonic-gate case mmt_string: 8400Sstevel@tonic-gate val = am(myself, sizeof (*val)); 8410Sstevel@tonic-gate if (val == 0) 8420Sstevel@tonic-gate return (0); 8430Sstevel@tonic-gate val->type = vt_string; 8440Sstevel@tonic-gate val->numVals = 1; 8450Sstevel@tonic-gate val->val = am(myself, sizeof (val->val[0])); 8460Sstevel@tonic-gate if (val->val == 0) { 8470Sstevel@tonic-gate sfree(val); 8480Sstevel@tonic-gate return (0); 8490Sstevel@tonic-gate } 8500Sstevel@tonic-gate val->val[0].value = sdup(myself, T, f->match.string); 8510Sstevel@tonic-gate val->val[0].length = strlen(val->val[0].value); 8520Sstevel@tonic-gate break; 8530Sstevel@tonic-gate case mmt_single: 8540Sstevel@tonic-gate case mmt_limit: 8550Sstevel@tonic-gate case mmt_any: 8560Sstevel@tonic-gate case mmt_begin: 8570Sstevel@tonic-gate case mmt_end: 8580Sstevel@tonic-gate /* Not an error, so return an empty value */ 8590Sstevel@tonic-gate val = am(myself, sizeof (*val)); 8600Sstevel@tonic-gate if (val == 0) 8610Sstevel@tonic-gate return (0); 8620Sstevel@tonic-gate val->type = vt_string; 8630Sstevel@tonic-gate val->numVals = 0; 8640Sstevel@tonic-gate val->val = 0; 8650Sstevel@tonic-gate break; 8660Sstevel@tonic-gate default: 8670Sstevel@tonic-gate /* Do nothing */ 8680Sstevel@tonic-gate val = 0; 8690Sstevel@tonic-gate break; 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate } 8720Sstevel@tonic-gate return (val); 8730Sstevel@tonic-gate } 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate /* 8760Sstevel@tonic-gate * Used when evaluating an expression. Typically, the value of the 8770Sstevel@tonic-gate * expression so far will be kept in 'v1', and 'v2' is the value 8780Sstevel@tonic-gate * of the current component of the expression. In the general case, 8790Sstevel@tonic-gate * both will be multi-valued, and the result is an "explosion" 8800Sstevel@tonic-gate * resulting in N*M new values (if 'v1' had N values, and 'v2' 8810Sstevel@tonic-gate * M ditto). 8820Sstevel@tonic-gate * 8830Sstevel@tonic-gate * For example, if v1 = {"ab", "cd", "ef"}, and v2 = {"gh", "ij", "kl"}, 8840Sstevel@tonic-gate * the result will be {"abgh", "abij", "abkl", "cdgh", "cdij", "cdkl", 8850Sstevel@tonic-gate * "efgh", "efij", "efkl"}. 8860Sstevel@tonic-gate * 8870Sstevel@tonic-gate * There are special cases when v1->repeat and/or v2->repeat are set. 8880Sstevel@tonic-gate * Repeat mostly makes sense with single values; for example, if 8890Sstevel@tonic-gate * v1 = {"x="} with repeat on, and v2 = {"1", "2", "3"}, the result 8900Sstevel@tonic-gate * is {"x=1", "x=2", "x=3"}. 8910Sstevel@tonic-gate * 8920Sstevel@tonic-gate * The result if v2 also had repeat on would be {"x=1x=2x=3"}. It's 8930Sstevel@tonic-gate * not clear if there's a useful application for this, but the code's 8940Sstevel@tonic-gate * there for the sake of orthogonality. 8950Sstevel@tonic-gate */ 8960Sstevel@tonic-gate __nis_value_t * 8970Sstevel@tonic-gate explodeValues(__nis_value_t *v1, __nis_value_t *v2) { 8980Sstevel@tonic-gate int i1, i2, n, nv; 8990Sstevel@tonic-gate __nis_value_t *v; 9000Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 9010Sstevel@tonic-gate char *myself = "explodeValues"; 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate if (v1 == 0 || v1->numVals <= 0) 9040Sstevel@tonic-gate return (cloneValue(v2, 1)); 9050Sstevel@tonic-gate if (v2 == 0 || v2->numVals <= 0) 9060Sstevel@tonic-gate return (cloneValue(v1, 1)); 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate /* 9090Sstevel@tonic-gate * XXX What should we do if (v1->type != v2->type) ? 9100Sstevel@tonic-gate * Policy: Just explode anyway, even though the result is 9110Sstevel@tonic-gate * unlikely to be very useful. 9120Sstevel@tonic-gate */ 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate v = am(myself, sizeof (*v)); 9150Sstevel@tonic-gate if (v == 0) 9160Sstevel@tonic-gate return (0); 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate if (!v1->repeat && !v2->repeat) 9190Sstevel@tonic-gate nv = v1->numVals * v2->numVals; 9200Sstevel@tonic-gate else if (v1->repeat && !v2->repeat) 9210Sstevel@tonic-gate nv = v2->numVals; 9220Sstevel@tonic-gate else if (!v1->repeat && v2->repeat) 9230Sstevel@tonic-gate nv = v1->numVals; 9240Sstevel@tonic-gate else /* v1->repeat && v2->repeat */ 9250Sstevel@tonic-gate nv = 1; 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate v->val = am(myself, nv * sizeof (v->val[0])); 9280Sstevel@tonic-gate if (v->val == 0) { 9290Sstevel@tonic-gate free(v); 9300Sstevel@tonic-gate return (0); 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate /* 9340Sstevel@tonic-gate * Four different cases, depending on the 'repeat' flags. 9350Sstevel@tonic-gate */ 9360Sstevel@tonic-gate if (!v1->repeat && !v2->repeat) { 9370Sstevel@tonic-gate for (i1 = 0, n = 0; i1 < v1->numVals; i1++) { 9380Sstevel@tonic-gate for (i2 = 0; i2 < v2->numVals; i2++) { 9390Sstevel@tonic-gate if (v1->type == vt_string) 9400Sstevel@tonic-gate sbc2buf(myself, v1->val[i1].value, 9410Sstevel@tonic-gate v1->val[i1].length, 9420Sstevel@tonic-gate &b); 9430Sstevel@tonic-gate else 9440Sstevel@tonic-gate bc2buf(myself, v1->val[i1].value, 9450Sstevel@tonic-gate v1->val[i1].length, 9460Sstevel@tonic-gate &b); 9470Sstevel@tonic-gate if (v2->type == vt_string) 9480Sstevel@tonic-gate sbc2buf(myself, v2->val[i2].value, 9490Sstevel@tonic-gate v2->val[i2].length, 9500Sstevel@tonic-gate &b); 9510Sstevel@tonic-gate else 9520Sstevel@tonic-gate bc2buf(myself, v2->val[i2].value, 9530Sstevel@tonic-gate v2->val[i2].length, 9540Sstevel@tonic-gate &b); 9550Sstevel@tonic-gate v->val[n].value = b.buf; 9560Sstevel@tonic-gate v->val[n].length = b.len; 9570Sstevel@tonic-gate n++; 9580Sstevel@tonic-gate b.buf = 0; 9590Sstevel@tonic-gate b.len = 0; 9600Sstevel@tonic-gate } 9610Sstevel@tonic-gate } 9620Sstevel@tonic-gate } else if (v1->repeat && !v2->repeat) { 9630Sstevel@tonic-gate for (i2 = 0; i2 < v2->numVals; i2++) { 9640Sstevel@tonic-gate for (i1 = 0, n = 0; i1 < v1->numVals; i1++) { 9650Sstevel@tonic-gate if (v1->type == vt_string) 9660Sstevel@tonic-gate sbc2buf(myself, v1->val[i1].value, 9670Sstevel@tonic-gate v1->val[i1].length, 9680Sstevel@tonic-gate &b); 9690Sstevel@tonic-gate else 9700Sstevel@tonic-gate bc2buf(myself, v1->val[i1].value, 9710Sstevel@tonic-gate v1->val[i1].length, 9720Sstevel@tonic-gate &b); 9730Sstevel@tonic-gate if (v2->type == vt_string) 9740Sstevel@tonic-gate sbc2buf(myself, v2->val[i2].value, 9750Sstevel@tonic-gate v2->val[i2].length, 9760Sstevel@tonic-gate &b); 9770Sstevel@tonic-gate else 9780Sstevel@tonic-gate bc2buf(myself, v2->val[i2].value, 9790Sstevel@tonic-gate v2->val[i2].length, 9800Sstevel@tonic-gate &b); 9810Sstevel@tonic-gate } 9820Sstevel@tonic-gate v->val[n].value = b.buf; 9830Sstevel@tonic-gate v->val[n].length = b.len; 9840Sstevel@tonic-gate n++; 9850Sstevel@tonic-gate b.buf = 0; 9860Sstevel@tonic-gate b.len = 0; 9870Sstevel@tonic-gate } 9880Sstevel@tonic-gate } else if (!v1->repeat && v2->repeat) { 9890Sstevel@tonic-gate for (i1 = 0, n = 0; i1 < v1->numVals; i1++) { 9900Sstevel@tonic-gate for (i2 = 0; i2 < v2->numVals; i2++) { 9910Sstevel@tonic-gate if (v1->type == vt_string) 9920Sstevel@tonic-gate sbc2buf(myself, v1->val[i1].value, 9930Sstevel@tonic-gate v1->val[i1].length, 9940Sstevel@tonic-gate &b); 9950Sstevel@tonic-gate else 9960Sstevel@tonic-gate bc2buf(myself, v1->val[i1].value, 9970Sstevel@tonic-gate v1->val[i1].length, 9980Sstevel@tonic-gate &b); 9990Sstevel@tonic-gate if (v2->type == vt_string) 10000Sstevel@tonic-gate sbc2buf(myself, v2->val[i2].value, 10010Sstevel@tonic-gate v2->val[i2].length, 10020Sstevel@tonic-gate &b); 10030Sstevel@tonic-gate else 10040Sstevel@tonic-gate bc2buf(myself, v2->val[i2].value, 10050Sstevel@tonic-gate v2->val[i2].length, 10060Sstevel@tonic-gate &b); 10070Sstevel@tonic-gate } 10080Sstevel@tonic-gate v->val[n].value = b.buf; 10090Sstevel@tonic-gate v->val[n].length = b.len; 10100Sstevel@tonic-gate n++; 10110Sstevel@tonic-gate b.buf = 0; 10120Sstevel@tonic-gate b.len = 0; 10130Sstevel@tonic-gate } 10140Sstevel@tonic-gate } else { /* v1->repeat && v2->repeat */ 10150Sstevel@tonic-gate for (i1 = 0, n = 0; i1 < v1->numVals; i1++) { 10160Sstevel@tonic-gate for (i2 = 0; i2 < v2->numVals; i2++) { 10170Sstevel@tonic-gate if (v1->type == vt_string) 10180Sstevel@tonic-gate sbc2buf(myself, v1->val[i1].value, 10190Sstevel@tonic-gate v1->val[i1].length, 10200Sstevel@tonic-gate &b); 10210Sstevel@tonic-gate else 10220Sstevel@tonic-gate bc2buf(myself, v1->val[i1].value, 10230Sstevel@tonic-gate v1->val[i1].length, 10240Sstevel@tonic-gate &b); 10250Sstevel@tonic-gate if (v2->type == vt_string) 10260Sstevel@tonic-gate sbc2buf(myself, v2->val[i2].value, 10270Sstevel@tonic-gate v2->val[i2].length, 10280Sstevel@tonic-gate &b); 10290Sstevel@tonic-gate else 10300Sstevel@tonic-gate bc2buf(myself, v2->val[i2].value, 10310Sstevel@tonic-gate v2->val[i2].length, 10320Sstevel@tonic-gate &b); 10330Sstevel@tonic-gate } 10340Sstevel@tonic-gate } 10350Sstevel@tonic-gate v->val[n].value = b.buf; 10360Sstevel@tonic-gate v->val[n].length = b.len; 10370Sstevel@tonic-gate n++; 10380Sstevel@tonic-gate b.buf = 0; 10390Sstevel@tonic-gate b.len = 0; 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 10430Sstevel@tonic-gate /* Sanity check */ 10440Sstevel@tonic-gate if (n != nv) 10450Sstevel@tonic-gate abort(); 10460Sstevel@tonic-gate #endif /* NISD__LDAP_DEBUG */ 10470Sstevel@tonic-gate 10480Sstevel@tonic-gate v->type = (v1->type == vt_string) ? 10490Sstevel@tonic-gate ((v2->type == vt_string) ? 10500Sstevel@tonic-gate vt_string : vt_ber) : vt_ber; 10510Sstevel@tonic-gate v->repeat = 0; 10520Sstevel@tonic-gate v->numVals = n; 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate return (v); 10550Sstevel@tonic-gate } 10560Sstevel@tonic-gate 10570Sstevel@tonic-gate __nis_value_t * 10580Sstevel@tonic-gate getMappingFormatArray(__nis_mapping_format_t *a, __nis_rule_value_t *rv, 10590Sstevel@tonic-gate __nis_format_arg_t at, int numArgs, void *arg) { 10600Sstevel@tonic-gate int i, ia = 0; 10610Sstevel@tonic-gate __nis_value_t *val, *v = 0; 10620Sstevel@tonic-gate bool_t moreFormat = (a != 0); 10630Sstevel@tonic-gate bool_t moreArgs = (numArgs > 0); 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate while (moreFormat && (arg == 0 || ia < numArgs)) { 10660Sstevel@tonic-gate for (i = 0; moreFormat; i++) { 10670Sstevel@tonic-gate moreFormat = (a[i].type != mmt_end); 10680Sstevel@tonic-gate if (at == fa_item) { 10690Sstevel@tonic-gate __nis_mapping_item_t *item = arg; 10700Sstevel@tonic-gate val = getMappingFormat(&a[i], rv, at, 10710Sstevel@tonic-gate ((item != 0) ? &item[ia] : 0), &ia); 10720Sstevel@tonic-gate } else { 10730Sstevel@tonic-gate __nis_value_t **ival = arg; 10740Sstevel@tonic-gate val = getMappingFormat(&a[i], rv, at, 10750Sstevel@tonic-gate ((ival != 0) ? ival[ia] : 0), &ia); 10760Sstevel@tonic-gate } 10770Sstevel@tonic-gate if (val != 0) { 10780Sstevel@tonic-gate __nis_value_t *new = explodeValues(v, val); 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate freeValue(v, 1); 10810Sstevel@tonic-gate freeValue(val, 1); 10820Sstevel@tonic-gate if (new == 0) 10830Sstevel@tonic-gate return (0); 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate v = new; 10860Sstevel@tonic-gate } else { 10870Sstevel@tonic-gate freeValue(v, 1); 10880Sstevel@tonic-gate return (0); 10890Sstevel@tonic-gate } 10900Sstevel@tonic-gate /* 10910Sstevel@tonic-gate * If we run out of arguments, but still have format 10920Sstevel@tonic-gate * remaining, repeat the last argument. Keep track of 10930Sstevel@tonic-gate * the fact that we've really consumed all arguments. 10940Sstevel@tonic-gate */ 10950Sstevel@tonic-gate if (moreFormat && ia >= numArgs) { 10960Sstevel@tonic-gate ia = (numArgs > 0) ? numArgs - 1 : 0; 10970Sstevel@tonic-gate moreArgs = FALSE; 10980Sstevel@tonic-gate } 10990Sstevel@tonic-gate } 11000Sstevel@tonic-gate /* 11010Sstevel@tonic-gate * We've run out of format, so if we still have arguments 11020Sstevel@tonic-gate * left, start over on the format. 11030Sstevel@tonic-gate */ 11040Sstevel@tonic-gate if (ia < numArgs && moreArgs) { 11050Sstevel@tonic-gate /* 11060Sstevel@tonic-gate * However, if we didn't consume any arguments going 11070Sstevel@tonic-gate * through the format once, abort to avoid an infinite 11080Sstevel@tonic-gate * loop. 11090Sstevel@tonic-gate */ 11100Sstevel@tonic-gate if (numArgs > 0 && ia <= 0) { 11110Sstevel@tonic-gate freeValue(v, 1); 11120Sstevel@tonic-gate return (0); 11130Sstevel@tonic-gate } 11140Sstevel@tonic-gate moreFormat = 1; 11150Sstevel@tonic-gate } 11160Sstevel@tonic-gate } 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate return (v); 11190Sstevel@tonic-gate } 11200Sstevel@tonic-gate 11210Sstevel@tonic-gate /* 11220Sstevel@tonic-gate * Returns a string representation (such as "[name=foo, value=bar]") 11230Sstevel@tonic-gate * of a nis_index_t. 11240Sstevel@tonic-gate */ 11250Sstevel@tonic-gate char * 11260Sstevel@tonic-gate getIndex(__nis_index_t *i, int *len) { 11270Sstevel@tonic-gate int n; 11280Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 11290Sstevel@tonic-gate char *myself = "getIndex"; 11300Sstevel@tonic-gate 11310Sstevel@tonic-gate if (i == 0) 11320Sstevel@tonic-gate return (0); 11330Sstevel@tonic-gate 11340Sstevel@tonic-gate if (i->numIndexes > 0) { 11350Sstevel@tonic-gate bp2buf(myself, &b, "["); 11360Sstevel@tonic-gate for (n = 0; n < i->numIndexes; n++) { 11370Sstevel@tonic-gate __nis_value_t *val; 11380Sstevel@tonic-gate int j; 11390Sstevel@tonic-gate 11400Sstevel@tonic-gate val = getMappingFormatArray(i->value[n], 11410Sstevel@tonic-gate 0, fa_any, 0, 0); 11420Sstevel@tonic-gate if (n > 0) 11430Sstevel@tonic-gate bp2buf(myself, &b, ", "); 11440Sstevel@tonic-gate bp2buf(myself, &b, "%s=", i->name[n]); 11450Sstevel@tonic-gate if (val != 0) { 11460Sstevel@tonic-gate for (j = 0; j < val->numVals; j++) { 11470Sstevel@tonic-gate bc2buf(myself, val->val[j].value, 11480Sstevel@tonic-gate val->val[j].length, &b); 11490Sstevel@tonic-gate } 11500Sstevel@tonic-gate } else { 11510Sstevel@tonic-gate bp2buf(myself, &b, "<no-vals>"); 11520Sstevel@tonic-gate } 11530Sstevel@tonic-gate freeValue(val, 1); 11540Sstevel@tonic-gate } 11550Sstevel@tonic-gate bp2buf(myself, &b, "]"); 11560Sstevel@tonic-gate } 11570Sstevel@tonic-gate if (len != 0) 11580Sstevel@tonic-gate *len = b.len; 11590Sstevel@tonic-gate return (b.buf); 11600Sstevel@tonic-gate } 11610Sstevel@tonic-gate 11620Sstevel@tonic-gate char * 11630Sstevel@tonic-gate getObjSpec(__nis_obj_spec_t *o, int *len) { 11640Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 11650Sstevel@tonic-gate char *myself = "getObjSpec"; 11660Sstevel@tonic-gate 11670Sstevel@tonic-gate if (o == 0) 11680Sstevel@tonic-gate return (0); 11690Sstevel@tonic-gate 11700Sstevel@tonic-gate b.buf = getIndex(&o->index, &b.len); 11710Sstevel@tonic-gate sbc2buf(myself, o->name, slen(o->name), &b); 11720Sstevel@tonic-gate if (len != 0) 11730Sstevel@tonic-gate *len = b.len; 11740Sstevel@tonic-gate return (b.buf); 11750Sstevel@tonic-gate } 11760Sstevel@tonic-gate 11770Sstevel@tonic-gate /* 11780Sstevel@tonic-gate * Returns a string representation of the LDAP scope. Note that the 11790Sstevel@tonic-gate * returned value is a static entity, and must be copied by the 11800Sstevel@tonic-gate * caller (but, obviously, must not be freed). 11810Sstevel@tonic-gate */ 11820Sstevel@tonic-gate char * 11830Sstevel@tonic-gate getScope(int scope) { 11840Sstevel@tonic-gate switch (scope) { 11850Sstevel@tonic-gate case LDAP_SCOPE_BASE: 11860Sstevel@tonic-gate return ("base"); 11870Sstevel@tonic-gate case LDAP_SCOPE_ONELEVEL: 11880Sstevel@tonic-gate return ("one"); 11890Sstevel@tonic-gate case LDAP_SCOPE_SUBTREE: 11900Sstevel@tonic-gate return ("sub"); 11910Sstevel@tonic-gate default: 11920Sstevel@tonic-gate return ("one"); 11930Sstevel@tonic-gate } 11940Sstevel@tonic-gate } 11950Sstevel@tonic-gate 11960Sstevel@tonic-gate /* 11970Sstevel@tonic-gate * Return a string representation of an LDAP search triple (such as 11980Sstevel@tonic-gate * "ou=Hosts,dc=eng,dc=sun,dc=com?one?cn=xyzzy"). 11990Sstevel@tonic-gate */ 12000Sstevel@tonic-gate char * 12010Sstevel@tonic-gate getSearchTriple(__nis_search_triple_t *s, int *len) { 12020Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 12030Sstevel@tonic-gate char *a; 12040Sstevel@tonic-gate int l; 12050Sstevel@tonic-gate char *myself = "getSearchTriple"; 12060Sstevel@tonic-gate 12070Sstevel@tonic-gate /* If the scope is LDAP_SCOPE_UNKNOWN, the search triple is unused */ 12080Sstevel@tonic-gate if (s == 0 || s->scope == LDAP_SCOPE_UNKNOWN) { 12090Sstevel@tonic-gate if (len != 0) 12100Sstevel@tonic-gate *len = 0; 12110Sstevel@tonic-gate return (0); 12120Sstevel@tonic-gate } 12130Sstevel@tonic-gate 12140Sstevel@tonic-gate if (s->base != 0) 12150Sstevel@tonic-gate sbc2buf(myself, s->base, slen(s->base), &b); 12160Sstevel@tonic-gate if (!(s->scope == LDAP_SCOPE_ONELEVEL && 12170Sstevel@tonic-gate (s->base == 0 || s->base[0] == '\0'))) { 12180Sstevel@tonic-gate bp2buf(myself, &b, "?%s?", getScope(s->scope)); 12190Sstevel@tonic-gate } 12200Sstevel@tonic-gate if ((l = slen(s->attrs)) > 0) { 12210Sstevel@tonic-gate /* 12220Sstevel@tonic-gate * Remove white space from the filter/attribute list. 12230Sstevel@tonic-gate * The parser usually keeps any white space from the 12240Sstevel@tonic-gate * config file (or LDAP/command line), but we don't 12250Sstevel@tonic-gate * want it. 12260Sstevel@tonic-gate */ 12270Sstevel@tonic-gate a = am(myself, l+1); 12280Sstevel@tonic-gate if (a != 0) { 12290Sstevel@tonic-gate int i, la; 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate for (i = 0, la = 0; i < l; i++) { 12320Sstevel@tonic-gate if (s->attrs[i] != ' ' && 12330Sstevel@tonic-gate s->attrs[i] != '\t') 12340Sstevel@tonic-gate a[la++] = s->attrs[i]; 12350Sstevel@tonic-gate } 12360Sstevel@tonic-gate sbc2buf(myself, a, la, &b); 12370Sstevel@tonic-gate sfree(a); 12380Sstevel@tonic-gate } else { 12390Sstevel@tonic-gate sbc2buf(myself, s->attrs, slen(s->attrs), &b); 12400Sstevel@tonic-gate } 12410Sstevel@tonic-gate } 12420Sstevel@tonic-gate 12430Sstevel@tonic-gate if (len != 0) 12440Sstevel@tonic-gate *len = b.len; 12450Sstevel@tonic-gate return (b.buf); 12460Sstevel@tonic-gate } 12470Sstevel@tonic-gate 12480Sstevel@tonic-gate __nis_value_t * 12490Sstevel@tonic-gate getMappingItem(__nis_mapping_item_t *i, __nis_mapping_item_type_t native, 12500Sstevel@tonic-gate __nis_rule_value_t *rv, char *berstring, int *np_ldap_stat) { 12510Sstevel@tonic-gate char *myself = "getMappingItem"; 12520Sstevel@tonic-gate __nis_value_t *val = 0; 12530Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 12540Sstevel@tonic-gate int len = 0; 12550Sstevel@tonic-gate char *buf; 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate if (i == 0) 12580Sstevel@tonic-gate return (0); 12590Sstevel@tonic-gate 12600Sstevel@tonic-gate if (rv != 0) 12610Sstevel@tonic-gate return (getMappingItemVal(i, native, rv, berstring, 12620Sstevel@tonic-gate np_ldap_stat)); 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate val = am(myself, sizeof (*val)); 12650Sstevel@tonic-gate if (val == 0) 12660Sstevel@tonic-gate return (0); 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate switch (i->type) { 12690Sstevel@tonic-gate case mit_nisplus: 12700Sstevel@tonic-gate if (native != mit_nisplus) 12710Sstevel@tonic-gate bp2buf(myself, &b, "nis+:"); 12720Sstevel@tonic-gate bp2buf(myself, &b, "%s", NIL(i->name)); 12730Sstevel@tonic-gate buf = getObjSpec(&i->searchSpec.obj, &len); 12740Sstevel@tonic-gate if (buf != 0 && len > 0) { 12750Sstevel@tonic-gate bc2buf(myself, ":", 1, &b); 12760Sstevel@tonic-gate sbc2buf(myself, buf, len, &b); 12770Sstevel@tonic-gate } 12780Sstevel@tonic-gate sfree(buf); 12790Sstevel@tonic-gate val->type = vt_string; 12800Sstevel@tonic-gate val->repeat = i->repeat; 12810Sstevel@tonic-gate val->numVals = 1; 12820Sstevel@tonic-gate val->val = am(myself, sizeof (val->val[0])); 12830Sstevel@tonic-gate if (val->val == 0) { 12840Sstevel@tonic-gate sfree(b.buf); 12850Sstevel@tonic-gate free(val); 12860Sstevel@tonic-gate return (0); 12870Sstevel@tonic-gate } 12880Sstevel@tonic-gate val->val[0].value = b.buf; 12890Sstevel@tonic-gate val->val[0].length = b.len; 12900Sstevel@tonic-gate break; 12910Sstevel@tonic-gate case mit_ldap: 12920Sstevel@tonic-gate if (native != mit_ldap) 12930Sstevel@tonic-gate bp2buf(myself, &b, "ldap:"); 12940Sstevel@tonic-gate bp2buf(myself, &b, "%s", NIL(i->name)); 12950Sstevel@tonic-gate buf = getSearchTriple(&i->searchSpec.triple, &len); 12960Sstevel@tonic-gate if (buf != 0 && len > 0) { 12970Sstevel@tonic-gate bc2buf(myself, ":", 1, &b); 12980Sstevel@tonic-gate sbc2buf(myself, buf, len, &b); 12990Sstevel@tonic-gate } 13000Sstevel@tonic-gate sfree(buf); 13010Sstevel@tonic-gate val->type = vt_string; 13020Sstevel@tonic-gate val->repeat = i->repeat; 13030Sstevel@tonic-gate val->numVals = 1; 13040Sstevel@tonic-gate val->val = am(myself, sizeof (val->val[0])); 13050Sstevel@tonic-gate if (val->val == 0) { 13060Sstevel@tonic-gate sfree(b.buf); 13070Sstevel@tonic-gate free(val); 13080Sstevel@tonic-gate return (0); 13090Sstevel@tonic-gate } 13100Sstevel@tonic-gate val->val[0].value = b.buf; 13110Sstevel@tonic-gate val->val[0].length = b.len; 13120Sstevel@tonic-gate break; 13130Sstevel@tonic-gate default: 13140Sstevel@tonic-gate p2buf(myself, "<unknown>:"); 13150Sstevel@tonic-gate p2buf(myself, "%s", NIL(i->name)); 13160Sstevel@tonic-gate break; 13170Sstevel@tonic-gate } 13180Sstevel@tonic-gate 13190Sstevel@tonic-gate return (val); 13200Sstevel@tonic-gate } 13210Sstevel@tonic-gate 13220Sstevel@tonic-gate void 13230Sstevel@tonic-gate copyObjSpec(__nis_obj_spec_t *old, __nis_obj_spec_t *new, int *err) { 13240Sstevel@tonic-gate char *myself = "copyObjSpec"; 13250Sstevel@tonic-gate 13260Sstevel@tonic-gate if (old == 0 || new == 0) { 13270Sstevel@tonic-gate *err = EINVAL; 13280Sstevel@tonic-gate return; 13290Sstevel@tonic-gate } 13300Sstevel@tonic-gate 13310Sstevel@tonic-gate if (new->index.name == 0) { 13320Sstevel@tonic-gate new->index.name = am(myself, old->index.numIndexes * 13330Sstevel@tonic-gate sizeof (new->index.name[0])); 13340Sstevel@tonic-gate if (old->index.numIndexes > 0 && new->index.name == 0) { 13350Sstevel@tonic-gate *err = ENOMEM; 13360Sstevel@tonic-gate return; 13370Sstevel@tonic-gate } 13380Sstevel@tonic-gate new->index.value = am(myself, old->index.numIndexes * 13390Sstevel@tonic-gate sizeof (new->index.value[0])); 13400Sstevel@tonic-gate if (old->index.numIndexes > 0 && new->index.value == 0) { 13410Sstevel@tonic-gate *err = ENOMEM; 13420Sstevel@tonic-gate return; 13430Sstevel@tonic-gate } 13440Sstevel@tonic-gate } 13450Sstevel@tonic-gate new->name = sdup(myself, T, old->name); 13460Sstevel@tonic-gate if (new->name == 0 && old->name != 0) { 13470Sstevel@tonic-gate *err = ENOMEM; 13480Sstevel@tonic-gate return; 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate copyIndex(&old->index, &new->index, err); 13510Sstevel@tonic-gate } 13520Sstevel@tonic-gate 13530Sstevel@tonic-gate __nis_obj_spec_t * 13540Sstevel@tonic-gate cloneObjSpec(__nis_obj_spec_t *old) { 13550Sstevel@tonic-gate char *myself = "cloneObjSpec"; 13560Sstevel@tonic-gate int err = 0; 13570Sstevel@tonic-gate __nis_obj_spec_t *new = am(myself, sizeof (*new)); 13580Sstevel@tonic-gate 13590Sstevel@tonic-gate if (new != 0) { 13600Sstevel@tonic-gate copyObjSpec(old, new, &err); 13610Sstevel@tonic-gate if (err != 0) { 13620Sstevel@tonic-gate freeObjSpec(new, 1); 13630Sstevel@tonic-gate new = 0; 13640Sstevel@tonic-gate } 13650Sstevel@tonic-gate } 13660Sstevel@tonic-gate 13670Sstevel@tonic-gate return (new); 13680Sstevel@tonic-gate } 13690Sstevel@tonic-gate 13700Sstevel@tonic-gate void 13710Sstevel@tonic-gate freeObjSpec(__nis_obj_spec_t *old, bool_t doFree) { 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate if (old == 0) 13740Sstevel@tonic-gate return; 13750Sstevel@tonic-gate 13760Sstevel@tonic-gate sfree(old->name); 13770Sstevel@tonic-gate freeIndex(&old->index, FALSE); 13780Sstevel@tonic-gate if (doFree) 13790Sstevel@tonic-gate free(old); 13800Sstevel@tonic-gate } 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate void 13830Sstevel@tonic-gate copySearchTriple(__nis_search_triple_t *old, __nis_search_triple_t *new, 13840Sstevel@tonic-gate int *err) { 13850Sstevel@tonic-gate char *myself = "copySearchTriple"; 13860Sstevel@tonic-gate 13870Sstevel@tonic-gate *err = 0; 13880Sstevel@tonic-gate 13890Sstevel@tonic-gate if (old == 0 || new == 0) { 13900Sstevel@tonic-gate *err = EINVAL; 13910Sstevel@tonic-gate return; 13920Sstevel@tonic-gate } 13930Sstevel@tonic-gate 13940Sstevel@tonic-gate if (old->base != NULL) 13950Sstevel@tonic-gate new->base = sdup(myself, T, old->base); 13960Sstevel@tonic-gate else 13970Sstevel@tonic-gate new->base = NULL; 13980Sstevel@tonic-gate if (old->attrs != NULL) 13990Sstevel@tonic-gate new->attrs = sdup(myself, T, old->attrs); 14000Sstevel@tonic-gate else 14010Sstevel@tonic-gate new->attrs = NULL; 14020Sstevel@tonic-gate if ((new->base == 0 && old->base != 0) || 14030Sstevel@tonic-gate (new->attrs == 0 && old->attrs != 0)) { 14040Sstevel@tonic-gate sfree(new->base); 14050Sstevel@tonic-gate new->base = 0; 14060Sstevel@tonic-gate sfree(new->attrs); 14070Sstevel@tonic-gate new->attrs = 0; 14080Sstevel@tonic-gate *err = ENOMEM; 14090Sstevel@tonic-gate return; 14100Sstevel@tonic-gate } 14110Sstevel@tonic-gate new->scope = old->scope; 14120Sstevel@tonic-gate /* 14130Sstevel@tonic-gate * XXX Really should have a cloneMappingElement() function. 14140Sstevel@tonic-gate * However, since whatever the 'element' field points to 14150Sstevel@tonic-gate * is allocated at parse time, and never is freed or modified, 14160Sstevel@tonic-gate * it's sufficient to copy the pointer value. 14170Sstevel@tonic-gate */ 14180Sstevel@tonic-gate new->element = old->element; 14190Sstevel@tonic-gate } 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate __nis_search_triple_t * 14220Sstevel@tonic-gate cloneSearchTriple(__nis_search_triple_t *old) { 14230Sstevel@tonic-gate char *myself = "cloneSearchTriple"; 14240Sstevel@tonic-gate int err = 0; 14250Sstevel@tonic-gate __nis_search_triple_t *new = am(myself, sizeof (*new)); 14260Sstevel@tonic-gate 14270Sstevel@tonic-gate if (new != 0) { 14280Sstevel@tonic-gate copySearchTriple(old, new, &err); 14290Sstevel@tonic-gate if (err != 0) { 14300Sstevel@tonic-gate freeSearchTriple(new, 1); 14310Sstevel@tonic-gate new = 0; 14320Sstevel@tonic-gate } 14330Sstevel@tonic-gate } 14340Sstevel@tonic-gate 14350Sstevel@tonic-gate return (new); 14360Sstevel@tonic-gate } 14370Sstevel@tonic-gate 14380Sstevel@tonic-gate void 14390Sstevel@tonic-gate freeSearchTriple(__nis_search_triple_t *old, bool_t doFree) { 14400Sstevel@tonic-gate 14410Sstevel@tonic-gate if (old == 0) 14420Sstevel@tonic-gate return; 14430Sstevel@tonic-gate 14440Sstevel@tonic-gate sfree(old->base); 14450Sstevel@tonic-gate sfree(old->attrs); 14460Sstevel@tonic-gate /* 14470Sstevel@tonic-gate * Since we only copied the element pointer when this structure 14480Sstevel@tonic-gate * was created, we don't free old->element. 14490Sstevel@tonic-gate */ 14500Sstevel@tonic-gate if (doFree) 14510Sstevel@tonic-gate free(old); 14520Sstevel@tonic-gate } 14530Sstevel@tonic-gate 14540Sstevel@tonic-gate void 14550Sstevel@tonic-gate copyTripleOrObj(__nis_mapping_item_type_t type, 14560Sstevel@tonic-gate __nis_triple_or_obj_t *old, __nis_triple_or_obj_t *new, 14570Sstevel@tonic-gate int *err) { 14580Sstevel@tonic-gate 14590Sstevel@tonic-gate *err = 0; 14600Sstevel@tonic-gate 14610Sstevel@tonic-gate if (old == 0 || new == 0) { 14620Sstevel@tonic-gate *err = EINVAL; 14630Sstevel@tonic-gate return; 14640Sstevel@tonic-gate } 14650Sstevel@tonic-gate 14660Sstevel@tonic-gate if (type == mit_nisplus) { 14670Sstevel@tonic-gate copyObjSpec(&old->obj, &new->obj, err); 14680Sstevel@tonic-gate } else if (type == mit_ldap) { 14690Sstevel@tonic-gate copySearchTriple(&old->triple, &new->triple, err); 14700Sstevel@tonic-gate } 14710Sstevel@tonic-gate } 14720Sstevel@tonic-gate 14730Sstevel@tonic-gate __nis_triple_or_obj_t * 14740Sstevel@tonic-gate cloneTripleOrObj(__nis_mapping_item_type_t type, __nis_triple_or_obj_t *old) { 14750Sstevel@tonic-gate char *myself = "cloneTripleOrObj"; 14760Sstevel@tonic-gate int err = 0; 14770Sstevel@tonic-gate __nis_triple_or_obj_t *new = am(myself, sizeof (*new)); 14780Sstevel@tonic-gate 14790Sstevel@tonic-gate if (new != 0) { 14800Sstevel@tonic-gate copyTripleOrObj(type, old, new, &err); 14810Sstevel@tonic-gate if (err != 0) { 14820Sstevel@tonic-gate freeTripleOrObj(type, new, 1); 14830Sstevel@tonic-gate new = 0; 14840Sstevel@tonic-gate } 14850Sstevel@tonic-gate } 14860Sstevel@tonic-gate 14870Sstevel@tonic-gate return (new); 14880Sstevel@tonic-gate } 14890Sstevel@tonic-gate 14900Sstevel@tonic-gate void 14910Sstevel@tonic-gate freeTripleOrObj(__nis_mapping_item_type_t type, __nis_triple_or_obj_t *old, 14920Sstevel@tonic-gate bool_t doFree) { 14930Sstevel@tonic-gate 14940Sstevel@tonic-gate if (old == 0) 14950Sstevel@tonic-gate return; 14960Sstevel@tonic-gate 14970Sstevel@tonic-gate if (type == mit_nisplus) 14980Sstevel@tonic-gate freeObjSpec(&old->obj, doFree); 14990Sstevel@tonic-gate else if (type == mit_ldap) 15000Sstevel@tonic-gate freeSearchTriple(&old->triple, doFree); 15010Sstevel@tonic-gate 15020Sstevel@tonic-gate if (doFree) 15030Sstevel@tonic-gate free(old); 15040Sstevel@tonic-gate } 15050Sstevel@tonic-gate 15060Sstevel@tonic-gate void 15070Sstevel@tonic-gate copyItem(__nis_mapping_item_t *old, __nis_mapping_item_t *new, int *err) { 15080Sstevel@tonic-gate 15090Sstevel@tonic-gate *err = 0; 15100Sstevel@tonic-gate 15110Sstevel@tonic-gate if (old == 0 || new == 0) { 15120Sstevel@tonic-gate *err = EINVAL; 15130Sstevel@tonic-gate return; 15140Sstevel@tonic-gate } 15150Sstevel@tonic-gate 15160Sstevel@tonic-gate new->type = old->type; 15170Sstevel@tonic-gate new->repeat = old->repeat; 15180Sstevel@tonic-gate if (old->name != 0) { 15190Sstevel@tonic-gate new->name = strdup(old->name); 15200Sstevel@tonic-gate if (new->name == 0) { 15210Sstevel@tonic-gate *err = ENOMEM; 15220Sstevel@tonic-gate return; 15230Sstevel@tonic-gate } 15240Sstevel@tonic-gate } else { 15250Sstevel@tonic-gate new->name = 0; 15260Sstevel@tonic-gate } 15270Sstevel@tonic-gate if (old->type == mit_nisplus || old->type == mit_ldap) 15280Sstevel@tonic-gate copyTripleOrObj(old->type, &old->searchSpec, &new->searchSpec, 15290Sstevel@tonic-gate err); 15300Sstevel@tonic-gate else 15310Sstevel@tonic-gate memset(&new->searchSpec, 0, sizeof (new->searchSpec)); 15320Sstevel@tonic-gate } 15330Sstevel@tonic-gate 15340Sstevel@tonic-gate __nis_mapping_item_t * 15350Sstevel@tonic-gate cloneItem(__nis_mapping_item_t *old) { 15360Sstevel@tonic-gate __nis_mapping_item_t *new; 15370Sstevel@tonic-gate int err = 0; 15380Sstevel@tonic-gate char *myself = "cloneItem"; 15390Sstevel@tonic-gate 15400Sstevel@tonic-gate if (old == 0) 15410Sstevel@tonic-gate return (0); 15420Sstevel@tonic-gate 15430Sstevel@tonic-gate new = am(myself, sizeof (*new)); 15440Sstevel@tonic-gate if (new == 0) 15450Sstevel@tonic-gate return (0); 15460Sstevel@tonic-gate 15470Sstevel@tonic-gate copyItem(old, new, &err); 15480Sstevel@tonic-gate if (err != 0) { 15490Sstevel@tonic-gate freeMappingItem(new, 1); 15500Sstevel@tonic-gate return (0); 15510Sstevel@tonic-gate } 15520Sstevel@tonic-gate 15530Sstevel@tonic-gate return (new); 15540Sstevel@tonic-gate } 15550Sstevel@tonic-gate 15560Sstevel@tonic-gate void 15570Sstevel@tonic-gate freeMappingItem(__nis_mapping_item_t *item, int numItems) { 15580Sstevel@tonic-gate int i; 15590Sstevel@tonic-gate 15600Sstevel@tonic-gate if (item == 0) 15610Sstevel@tonic-gate return; 15620Sstevel@tonic-gate 15630Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 15640Sstevel@tonic-gate sfree(item[i].name); 15650Sstevel@tonic-gate freeTripleOrObj(item[i].type, &item[i].searchSpec, FALSE); 15660Sstevel@tonic-gate } 15670Sstevel@tonic-gate sfree(item); 15680Sstevel@tonic-gate } 15690Sstevel@tonic-gate 15700Sstevel@tonic-gate __nis_mapping_item_t * 15710Sstevel@tonic-gate concatenateMappingItem(__nis_mapping_item_t *old, int numItems, 15720Sstevel@tonic-gate __nis_mapping_item_t *cat) { 15730Sstevel@tonic-gate __nis_mapping_item_t *new; 15740Sstevel@tonic-gate int i, err = 0; 15750Sstevel@tonic-gate char *myself = "concatenateMappingItem"; 15760Sstevel@tonic-gate 15770Sstevel@tonic-gate if (old == 0 || numItems < 1) 15780Sstevel@tonic-gate return (cloneItem(cat)); 15790Sstevel@tonic-gate 15800Sstevel@tonic-gate new = am(myself, (numItems + 1) * sizeof (*new)); 15810Sstevel@tonic-gate if (new == 0) 15820Sstevel@tonic-gate return (0); 15830Sstevel@tonic-gate 15840Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 15850Sstevel@tonic-gate copyItem(&old[i], &new[i], &err); 15860Sstevel@tonic-gate if (err != 0) { 15870Sstevel@tonic-gate freeMappingItem(new, i); 15880Sstevel@tonic-gate return (0); 15890Sstevel@tonic-gate } 15900Sstevel@tonic-gate } 15910Sstevel@tonic-gate copyItem(cat, &new[numItems], &err); 15920Sstevel@tonic-gate if (err != 0) { 15930Sstevel@tonic-gate freeMappingItem(new, numItems); 15940Sstevel@tonic-gate new = 0; 15950Sstevel@tonic-gate } 15960Sstevel@tonic-gate 15970Sstevel@tonic-gate return (new); 15980Sstevel@tonic-gate } 15990Sstevel@tonic-gate 16000Sstevel@tonic-gate __nis_value_t * 16010Sstevel@tonic-gate concatenateValues(__nis_value_t *v1, __nis_value_t *v2) { 16020Sstevel@tonic-gate int i, n, a; 16030Sstevel@tonic-gate __nis_value_t *v; 16040Sstevel@tonic-gate char *myself = "concatenateValues"; 16050Sstevel@tonic-gate 16060Sstevel@tonic-gate if (v1 == 0 || v1->numVals <= 0) 16070Sstevel@tonic-gate return (cloneValue(v2, 1)); 16080Sstevel@tonic-gate if (v2 == 0 || v2->numVals <= 0) 16090Sstevel@tonic-gate return (cloneValue(v1, 1)); 16100Sstevel@tonic-gate 16110Sstevel@tonic-gate if (v1->type != v2->type) 16120Sstevel@tonic-gate return (0); 16130Sstevel@tonic-gate 16140Sstevel@tonic-gate n = v1->numVals + v2->numVals; 16150Sstevel@tonic-gate v = am(myself, sizeof (*v)); 16160Sstevel@tonic-gate if (v == 0) 16170Sstevel@tonic-gate return (0); 16180Sstevel@tonic-gate v->val = am(myself, n * sizeof (v->val[0])); 16190Sstevel@tonic-gate if (v->val == 0) { 16200Sstevel@tonic-gate free(v); 16210Sstevel@tonic-gate return (0); 16220Sstevel@tonic-gate } 16230Sstevel@tonic-gate v->type = v1->type; 16240Sstevel@tonic-gate v->numVals = 0; 16250Sstevel@tonic-gate 16260Sstevel@tonic-gate for (a = 0; a < 2; a++) { 16270Sstevel@tonic-gate __nis_single_value_t *val = (a == 0) ? v1->val : v2->val; 16280Sstevel@tonic-gate int numv = (a == 0) ? v1->numVals : 16290Sstevel@tonic-gate v2->numVals; 16300Sstevel@tonic-gate for (i = 0; i < numv; i++) { 16310Sstevel@tonic-gate int clen, alen = val[i].length; 16320Sstevel@tonic-gate 16330Sstevel@tonic-gate clen = alen; 16340Sstevel@tonic-gate 16350Sstevel@tonic-gate /* 16360Sstevel@tonic-gate * Make sure there's a NUL at the end of a string, 16370Sstevel@tonic-gate * but avoid adding to the allocated length if there's 16380Sstevel@tonic-gate * already a NUL at the end. 16390Sstevel@tonic-gate */ 16400Sstevel@tonic-gate if (alen > 0 && v->type == vt_string && 16410Sstevel@tonic-gate ((char *)val[i].value)[alen-1] != '\0') 16420Sstevel@tonic-gate alen += 1; 16430Sstevel@tonic-gate v->val[v->numVals].value = am(myself, alen); 16440Sstevel@tonic-gate if (v->val[v->numVals].value == 0) { 16450Sstevel@tonic-gate freeValue(v, 1); 16460Sstevel@tonic-gate return (0); 16470Sstevel@tonic-gate } 16480Sstevel@tonic-gate memcpy(v->val[v->numVals].value, val[i].value, clen); 16490Sstevel@tonic-gate v->val[v->numVals].length = val[i].length; 16500Sstevel@tonic-gate v->numVals++; 16510Sstevel@tonic-gate } 16520Sstevel@tonic-gate } 16530Sstevel@tonic-gate 16540Sstevel@tonic-gate return (v); 16550Sstevel@tonic-gate } 16560Sstevel@tonic-gate 16570Sstevel@tonic-gate __nis_value_t * 16580Sstevel@tonic-gate splitMappingItem(__nis_mapping_item_t *item, char delim, 16590Sstevel@tonic-gate __nis_rule_value_t *rv) { 16600Sstevel@tonic-gate __nis_value_t *val = getMappingItem(item, mit_any, 16610Sstevel@tonic-gate rv, 0, NULL); 16620Sstevel@tonic-gate __nis_single_value_t *nval; 16630Sstevel@tonic-gate int i, n, nv; 16640Sstevel@tonic-gate 16650Sstevel@tonic-gate if (val == 0) 16660Sstevel@tonic-gate return (0); 16670Sstevel@tonic-gate else if (delim == 0 || val->val == 0 || val->numVals <= 0 || 16680Sstevel@tonic-gate val->type != vt_string) { 16690Sstevel@tonic-gate freeValue(val, 1); 16700Sstevel@tonic-gate return (0); 16710Sstevel@tonic-gate } 16720Sstevel@tonic-gate 16730Sstevel@tonic-gate nval = val->val; 16740Sstevel@tonic-gate nv = val->numVals; 16750Sstevel@tonic-gate val->repeat = FALSE; 16760Sstevel@tonic-gate val->val = 0; 16770Sstevel@tonic-gate val->numVals = 0; 16780Sstevel@tonic-gate 16790Sstevel@tonic-gate /* In N2L, space and tab delimiters are treated the same */ 16800Sstevel@tonic-gate if (yp2ldap && delim == '\t') 16810Sstevel@tonic-gate delim = ' '; 16820Sstevel@tonic-gate 16830Sstevel@tonic-gate /* If the item has multiple values, we split each one independently */ 16840Sstevel@tonic-gate for (i = 0; i < nv; i++) { 16850Sstevel@tonic-gate char *str; 16860Sstevel@tonic-gate int s, e; 16870Sstevel@tonic-gate char *newstr; 16880Sstevel@tonic-gate __nis_single_value_t *newval; 16890Sstevel@tonic-gate 16900Sstevel@tonic-gate if (yp2ldap && delim == ' ') 16910Sstevel@tonic-gate nval[i].value = trimWhiteSpaces(nval[i].value, 16920Sstevel@tonic-gate &nval[i].length, 1); 16930Sstevel@tonic-gate 16940Sstevel@tonic-gate str = nval[i].value; 16950Sstevel@tonic-gate 16960Sstevel@tonic-gate if (nval[i].value == 0) 16970Sstevel@tonic-gate continue; 16980Sstevel@tonic-gate 16990Sstevel@tonic-gate for (s = 0; s < nval[i].length; s = e+1) { 17000Sstevel@tonic-gate /* Find the next delimiter, or end-of-string */ 17010Sstevel@tonic-gate for (e = s; str[e] != '\0' && str[e] != delim; e++); 17020Sstevel@tonic-gate /* 17030Sstevel@tonic-gate * 'str[e]' is either a delimiter, or the concluding 17040Sstevel@tonic-gate * NUL. Make sure it's NUL. 17050Sstevel@tonic-gate */ 17060Sstevel@tonic-gate str[e] = '\0'; 17070Sstevel@tonic-gate /* Add to val->val */ 17080Sstevel@tonic-gate newstr = strdup(&str[s]); 17090Sstevel@tonic-gate newval = realloc(val->val, 17100Sstevel@tonic-gate (val->numVals+1) * 17110Sstevel@tonic-gate sizeof (val->val[0])); 17120Sstevel@tonic-gate if (newval != 0) 17130Sstevel@tonic-gate val->val = newval; 17140Sstevel@tonic-gate if (newstr == 0 || newval == 0) { 17150Sstevel@tonic-gate freeValue(val, 1); 17160Sstevel@tonic-gate for (n = i; n < nv; n++) { 17170Sstevel@tonic-gate sfree(nval[n].value); 17180Sstevel@tonic-gate } 17190Sstevel@tonic-gate free(nval); 17200Sstevel@tonic-gate sfree(newstr); 17210Sstevel@tonic-gate return (0); 17220Sstevel@tonic-gate } 17230Sstevel@tonic-gate val->val[val->numVals].value = newstr; 17240Sstevel@tonic-gate val->val[val->numVals].length = strlen(newstr) + 1; 17250Sstevel@tonic-gate val->numVals++; 17260Sstevel@tonic-gate } 17270Sstevel@tonic-gate free(nval[i].value); 17280Sstevel@tonic-gate nval[i].value = 0; 17290Sstevel@tonic-gate } 17300Sstevel@tonic-gate /* Already freed the nval[i].value's as we traversed nval */ 17310Sstevel@tonic-gate free(nval); 17320Sstevel@tonic-gate 17330Sstevel@tonic-gate return (val); 17340Sstevel@tonic-gate } 17350Sstevel@tonic-gate 17360Sstevel@tonic-gate /* 17370Sstevel@tonic-gate * Match the format spec 'f[curf]' to the input value string 'str'. 17380Sstevel@tonic-gate * 17390Sstevel@tonic-gate * If successful, returns the updated position in the value string 'str'. 17400Sstevel@tonic-gate * Otherwise, NULL is returned. 17410Sstevel@tonic-gate * 17420Sstevel@tonic-gate * curf Current index (i.e., the one we should look at) in 'f' 17430Sstevel@tonic-gate * nf Number of elements in 'f', including 'mmt_end' 17440Sstevel@tonic-gate * str The value string we're scanning 17450Sstevel@tonic-gate * val Pointer to where an item value (if any) should be returned 17460Sstevel@tonic-gate * Set to NULL if not an 'mmt_item'. 17470Sstevel@tonic-gate * fmtstart If non-zero on entry, skip characters in 'str' until we find 17480Sstevel@tonic-gate * the f[curf].type data, if doing so makes any sense. On exit, 17490Sstevel@tonic-gate * set to the start of the fmt element data (which will be 'str', 17500Sstevel@tonic-gate * unless we did skip characters) 17510Sstevel@tonic-gate * sepset List of separators 17520Sstevel@tonic-gate */ 17530Sstevel@tonic-gate char * 17540Sstevel@tonic-gate scanMappingFormat(__nis_mapping_format_t *f, int curf, int nf, char *str, 17550Sstevel@tonic-gate char **val, char **fmtstart, char *sepset) { 17560Sstevel@tonic-gate char *mstr, *next, *start = 0, *tmpstr; 17570Sstevel@tonic-gate int i, len; 17580Sstevel@tonic-gate bool_t match; 17590Sstevel@tonic-gate char *myself = "scanMappingFormat"; 17600Sstevel@tonic-gate /* N2L variables */ 17610Sstevel@tonic-gate int af, skipspaces = 0; 17620Sstevel@tonic-gate bool_t ipaddr = FALSE; 17630Sstevel@tonic-gate char *spacestr = " ", *emptystr = ""; 17640Sstevel@tonic-gate 17650Sstevel@tonic-gate 17660Sstevel@tonic-gate if (f == 0 || curf < 0 || nf <= 0 || str == 0) 17670Sstevel@tonic-gate return (0); 17680Sstevel@tonic-gate 17690Sstevel@tonic-gate /* 17700Sstevel@tonic-gate * If separator list is NULL (which will be the case for 17710Sstevel@tonic-gate * nis+2ldap), then simply use empty string 17720Sstevel@tonic-gate */ 17730Sstevel@tonic-gate if (sepset == 0) 17740Sstevel@tonic-gate sepset = emptystr; 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate if (curf >= nf) { 17770Sstevel@tonic-gate /* OK if the string also is exhausted */ 17780Sstevel@tonic-gate if (strchr(sepset, *str) != 0) 17790Sstevel@tonic-gate return (str); 17800Sstevel@tonic-gate else 17810Sstevel@tonic-gate return (0); 17820Sstevel@tonic-gate } 17830Sstevel@tonic-gate 17840Sstevel@tonic-gate switch (f[curf].type) { 17850Sstevel@tonic-gate case mmt_berstring: 17860Sstevel@tonic-gate if (f[curf].match.berString[0] != 'a') { 17870Sstevel@tonic-gate /* Not a matchable element */ 17880Sstevel@tonic-gate return (0); 17890Sstevel@tonic-gate } 17900Sstevel@tonic-gate 17910Sstevel@tonic-gate /* 17920Sstevel@tonic-gate * If here, it means it's an IP address (N2L case) 17930Sstevel@tonic-gate * So continue processing as if it was mmt_item 17940Sstevel@tonic-gate */ 17950Sstevel@tonic-gate ipaddr = TRUE; 17960Sstevel@tonic-gate 17970Sstevel@tonic-gate case mmt_item: 17980Sstevel@tonic-gate /* 17990Sstevel@tonic-gate * In order to find the end of the item value, we must look 18000Sstevel@tonic-gate * ahead and determine the start of the next formatting element. 18010Sstevel@tonic-gate * If successful, 'next' will be the start of the fmt element 18020Sstevel@tonic-gate * after the next one; we don't care about that, other than to 18030Sstevel@tonic-gate * check for error. 18040Sstevel@tonic-gate * 18050Sstevel@tonic-gate * Since an item match is somewhat like an any match, in that 18060Sstevel@tonic-gate * we don't know a priori if the first occurence of the next 18070Sstevel@tonic-gate * element really is the one we want, we have to scan ahead 18080Sstevel@tonic-gate * until we've reached the end. 18090Sstevel@tonic-gate */ 18100Sstevel@tonic-gate tmpstr = str; 18110Sstevel@tonic-gate while ((next = scanMappingFormat(f, curf+1, nf, tmpstr, 0, 18120Sstevel@tonic-gate &start, sepset)) != 0) { 18130Sstevel@tonic-gate char *tmp = next; 18140Sstevel@tonic-gate int cf; 18150Sstevel@tonic-gate 18160Sstevel@tonic-gate for (cf = curf+2; cf < nf; cf++) { 18170Sstevel@tonic-gate tmp = scanMappingFormat(f, cf, nf, tmp, 0, 18180Sstevel@tonic-gate 0, sepset); 18190Sstevel@tonic-gate if (tmp == 0) 18200Sstevel@tonic-gate break; 18210Sstevel@tonic-gate } 18220Sstevel@tonic-gate if (tmp == 0) { 18230Sstevel@tonic-gate tmpstr = next; 18240Sstevel@tonic-gate } else if (strchr(sepset, *tmp) != 0) { 18250Sstevel@tonic-gate break; 18260Sstevel@tonic-gate } else { 18270Sstevel@tonic-gate return (0); 18280Sstevel@tonic-gate } 18290Sstevel@tonic-gate 18300Sstevel@tonic-gate } 18310Sstevel@tonic-gate if (next == 0 || start == 0) 18320Sstevel@tonic-gate return (0); 18330Sstevel@tonic-gate 18340Sstevel@tonic-gate if (val != 0) { 18350Sstevel@tonic-gate len = (int)((long)start - (long)str); 18360Sstevel@tonic-gate *val = am(myself, len + 1); 18370Sstevel@tonic-gate if (*val == 0) 18380Sstevel@tonic-gate return (0); 18390Sstevel@tonic-gate memcpy(*val, str, len); 18400Sstevel@tonic-gate (*val)[len] = '\0'; 18410Sstevel@tonic-gate 18420Sstevel@tonic-gate if (ipaddr == TRUE) { 18430Sstevel@tonic-gate /* 18440Sstevel@tonic-gate * In N2L, we need to check if *val is truly an 18450Sstevel@tonic-gate * IP address 18460Sstevel@tonic-gate */ 18470Sstevel@tonic-gate af = checkIPaddress(*val, len, &tmpstr); 18480Sstevel@tonic-gate 18490Sstevel@tonic-gate if (af == -2) { 18500Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 18510Sstevel@tonic-gate "%s:Internal error while " 18520Sstevel@tonic-gate "processing IPaddress %s", 18530Sstevel@tonic-gate myself, *val); 18540Sstevel@tonic-gate sfree(*val); 18550Sstevel@tonic-gate return (0); 18560Sstevel@tonic-gate } else if (af == -1) { 18570Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 18580Sstevel@tonic-gate "%s:%s is not an IP address", 18590Sstevel@tonic-gate myself, *val); 18600Sstevel@tonic-gate sfree(*val); 18610Sstevel@tonic-gate return (0); 18620Sstevel@tonic-gate } else if (af == 0) { 18630Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 18640Sstevel@tonic-gate "%s:IP address %s is not " 18650Sstevel@tonic-gate "supported by rfc2307bis", 18660Sstevel@tonic-gate myself, *val); 18670Sstevel@tonic-gate sfree(*val); 18680Sstevel@tonic-gate return (0); 18690Sstevel@tonic-gate } else if (sstrncmp(*val, tmpstr, len) != 0) { 18700Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 18710Sstevel@tonic-gate "%s:IPaddress %s converted " 18720Sstevel@tonic-gate "to %s", myself, *val, tmpstr); 18730Sstevel@tonic-gate } 18740Sstevel@tonic-gate 18750Sstevel@tonic-gate sfree(*val); 18760Sstevel@tonic-gate *val = tmpstr; 18770Sstevel@tonic-gate } 18780Sstevel@tonic-gate } 18790Sstevel@tonic-gate 18800Sstevel@tonic-gate if (fmtstart != 0) 18810Sstevel@tonic-gate *fmtstart = str; 18820Sstevel@tonic-gate 18830Sstevel@tonic-gate return (start); 18840Sstevel@tonic-gate 18850Sstevel@tonic-gate case mmt_string: 18860Sstevel@tonic-gate if ((mstr = f[curf].match.string) == 0 || *mstr == '\0') { 18870Sstevel@tonic-gate /* 18880Sstevel@tonic-gate * Count this as a successful match of an empty 18890Sstevel@tonic-gate * string. 18900Sstevel@tonic-gate */ 18910Sstevel@tonic-gate if (fmtstart != 0) 18920Sstevel@tonic-gate *fmtstart = str; 18930Sstevel@tonic-gate return (str); 18940Sstevel@tonic-gate } 18950Sstevel@tonic-gate 18960Sstevel@tonic-gate /* 18970Sstevel@tonic-gate * In N2L, if the format string 'mstr' contains only 18980Sstevel@tonic-gate * whitespaces (spaces and tabs), then it should 18990Sstevel@tonic-gate * match one or more whitespaces from the input 19000Sstevel@tonic-gate * string 'str'. 19010Sstevel@tonic-gate */ 19020Sstevel@tonic-gate if (yp2ldap && strspn(mstr, " \t") == strlen(mstr)) { 19030Sstevel@tonic-gate mstr = spacestr; 19040Sstevel@tonic-gate skipspaces = 1; 19050Sstevel@tonic-gate next = str + strcspn(str, " \t"); 19060Sstevel@tonic-gate /* 19070Sstevel@tonic-gate * Even if there is no whitespace in 'str', 19080Sstevel@tonic-gate * it's OK. This is to allow formats like 19090Sstevel@tonic-gate * "%s %s %s" to match inputs like "foo bar". 19100Sstevel@tonic-gate */ 19110Sstevel@tonic-gate if (*next == '\0') 19120Sstevel@tonic-gate mstr = emptystr; 19130Sstevel@tonic-gate } else { 19140Sstevel@tonic-gate /* No match string in 'str' => failure */ 19150Sstevel@tonic-gate if ((next = strstr(str, mstr)) == 0) 19160Sstevel@tonic-gate return (0); 19170Sstevel@tonic-gate } 19180Sstevel@tonic-gate 19190Sstevel@tonic-gate /* If 'fmtstart' == 0, we require 'next' == 'str' */ 19200Sstevel@tonic-gate if (fmtstart == 0 && next != str) 19210Sstevel@tonic-gate return (0); 19220Sstevel@tonic-gate /* Success; save start of match string if requested */ 19230Sstevel@tonic-gate if (fmtstart != 0) 19240Sstevel@tonic-gate *fmtstart = next; 19250Sstevel@tonic-gate /* Update position in the value string */ 19260Sstevel@tonic-gate str = (char *)((long)next + (long)strlen(mstr)); 19270Sstevel@tonic-gate 19280Sstevel@tonic-gate /* Skip whitespaces for N2L */ 19290Sstevel@tonic-gate if (skipspaces == 1) 19300Sstevel@tonic-gate for (; *str == ' ' || *str == '\t'; str++); 19310Sstevel@tonic-gate 19320Sstevel@tonic-gate return (str); 19330Sstevel@tonic-gate 19340Sstevel@tonic-gate case mmt_single: 19350Sstevel@tonic-gate if (fmtstart != 0) { 19360Sstevel@tonic-gate match = FALSE; 19370Sstevel@tonic-gate /* Skip ahead until we match */ 19380Sstevel@tonic-gate for (next = str; *next != '\0'; next++) { 19390Sstevel@tonic-gate unsigned char *lo = f[curf].match.single.lo; 19400Sstevel@tonic-gate unsigned char *hi = f[curf].match.single.hi; 19410Sstevel@tonic-gate 19420Sstevel@tonic-gate for (i = 0; i < f[curf].match.single.numRange; 19430Sstevel@tonic-gate i++) { 19440Sstevel@tonic-gate if (*next >= lo[i] && *next <= hi[i]) { 19450Sstevel@tonic-gate match = TRUE; 19460Sstevel@tonic-gate break; 19470Sstevel@tonic-gate } 19480Sstevel@tonic-gate } 19490Sstevel@tonic-gate if (match) 19500Sstevel@tonic-gate break; 19510Sstevel@tonic-gate } 19520Sstevel@tonic-gate if (!match) 19530Sstevel@tonic-gate return (0); 19540Sstevel@tonic-gate *fmtstart = next; 19550Sstevel@tonic-gate str = next; 19560Sstevel@tonic-gate } else { 19570Sstevel@tonic-gate match = FALSE; 19580Sstevel@tonic-gate for (i = 0; i < f[curf].match.single.numRange; i++) { 19590Sstevel@tonic-gate if (*str >= f[curf].match.single.lo[i] && 19600Sstevel@tonic-gate *str <= f[curf].match.single.hi[i]) { 19610Sstevel@tonic-gate match = TRUE; 19620Sstevel@tonic-gate break; 19630Sstevel@tonic-gate } 19640Sstevel@tonic-gate } 19650Sstevel@tonic-gate if (!match) 19660Sstevel@tonic-gate return (0); 19670Sstevel@tonic-gate } 19680Sstevel@tonic-gate /* Step over the matched character */ 19690Sstevel@tonic-gate str++; 19700Sstevel@tonic-gate return (str); 19710Sstevel@tonic-gate 19720Sstevel@tonic-gate case mmt_any: 19730Sstevel@tonic-gate /* 19740Sstevel@tonic-gate * Look ahead to find the beginning of the next element. 19750Sstevel@tonic-gate * Because a wildcard-match isn't necessarily uniquely 19760Sstevel@tonic-gate * determined until we've reached the end, we then continue 19770Sstevel@tonic-gate * to scan ahead. 19780Sstevel@tonic-gate */ 19790Sstevel@tonic-gate while ((next = scanMappingFormat(f, curf+1, nf, str, 0, 19800Sstevel@tonic-gate &start, sepset)) != 0) { 19810Sstevel@tonic-gate char *tmp = next; 19820Sstevel@tonic-gate int cf; 19830Sstevel@tonic-gate 19840Sstevel@tonic-gate for (cf = curf+2; cf < nf; cf++) { 19850Sstevel@tonic-gate tmp = scanMappingFormat(f, cf, nf, tmp, 0, 19860Sstevel@tonic-gate 0, sepset); 19870Sstevel@tonic-gate if (tmp == 0) 19880Sstevel@tonic-gate break; 19890Sstevel@tonic-gate } 19900Sstevel@tonic-gate if (tmp == 0) { 19910Sstevel@tonic-gate str = next; 19920Sstevel@tonic-gate } else if (*tmp == '\0') { 19930Sstevel@tonic-gate break; 19940Sstevel@tonic-gate } else { 19950Sstevel@tonic-gate return (0); 19960Sstevel@tonic-gate } 19970Sstevel@tonic-gate } 19980Sstevel@tonic-gate if (next == 0 || start == 0) 19990Sstevel@tonic-gate return (0); 20000Sstevel@tonic-gate 20010Sstevel@tonic-gate if (fmtstart != 0) 20020Sstevel@tonic-gate *fmtstart = str; 20030Sstevel@tonic-gate 20040Sstevel@tonic-gate return (start); 20050Sstevel@tonic-gate 20060Sstevel@tonic-gate case mmt_limit: 20070Sstevel@tonic-gate if (f[curf].match.limit == eos) { 20080Sstevel@tonic-gate if (fmtstart != 0) { 20090Sstevel@tonic-gate /* Skip to the end */ 20100Sstevel@tonic-gate str = str + strcspn(str, sepset); 20110Sstevel@tonic-gate *fmtstart = str; 20120Sstevel@tonic-gate } else if (strchr(sepset, *str) == 0) { 20130Sstevel@tonic-gate return (0); 20140Sstevel@tonic-gate } 20150Sstevel@tonic-gate } 20160Sstevel@tonic-gate return (str); 20170Sstevel@tonic-gate 20180Sstevel@tonic-gate case mmt_begin: 20190Sstevel@tonic-gate if (fmtstart != 0) 20200Sstevel@tonic-gate *fmtstart = str; 20210Sstevel@tonic-gate return (str); 20220Sstevel@tonic-gate 20230Sstevel@tonic-gate case mmt_end: 20240Sstevel@tonic-gate if (fmtstart != 0) { 20250Sstevel@tonic-gate /* Skip to the end */ 20260Sstevel@tonic-gate str = str + strcspn(str, sepset); 20270Sstevel@tonic-gate *fmtstart = str; 20280Sstevel@tonic-gate return (str); 20290Sstevel@tonic-gate } 20300Sstevel@tonic-gate /* No skipping, so we must be at the end of the value */ 20310Sstevel@tonic-gate if (strchr(sepset, *str) == 0) 20320Sstevel@tonic-gate return (0); 20330Sstevel@tonic-gate return (str); 20340Sstevel@tonic-gate 20350Sstevel@tonic-gate default: 20360Sstevel@tonic-gate break; 20370Sstevel@tonic-gate } 20380Sstevel@tonic-gate 20390Sstevel@tonic-gate return (0); 20400Sstevel@tonic-gate } 20410Sstevel@tonic-gate 20420Sstevel@tonic-gate /* 20430Sstevel@tonic-gate * Verify that the string 'str' matches the mapping format array 'f'. 20440Sstevel@tonic-gate * Returns 1 in case of a match, 0 otherwise. 20450Sstevel@tonic-gate */ 20460Sstevel@tonic-gate int 20470Sstevel@tonic-gate verifyMappingMatch(__nis_mapping_format_t *f, char *str) { 20480Sstevel@tonic-gate int n, nf; 20490Sstevel@tonic-gate __nis_mapping_format_t *ftmp; 20500Sstevel@tonic-gate 20510Sstevel@tonic-gate /* Count the number of format elements in the format */ 20520Sstevel@tonic-gate for (nf = 0, ftmp = f; ftmp->type != mmt_end; ftmp++) { 20530Sstevel@tonic-gate nf++; 20540Sstevel@tonic-gate } 20550Sstevel@tonic-gate /* Count the mmt_end as well */ 20560Sstevel@tonic-gate nf++; 20570Sstevel@tonic-gate 20580Sstevel@tonic-gate for (n = 0; n < nf; n++) { 20590Sstevel@tonic-gate str = scanMappingFormat(f, n, nf, str, 0, 0, 0); 20600Sstevel@tonic-gate if (str == 0) 20610Sstevel@tonic-gate break; 20620Sstevel@tonic-gate } 20630Sstevel@tonic-gate 20640Sstevel@tonic-gate return ((str != 0) ? 1 : 0); 20650Sstevel@tonic-gate } 20660Sstevel@tonic-gate 20670Sstevel@tonic-gate /* 20680Sstevel@tonic-gate * Perform a match operation. For example, given the rule 20690Sstevel@tonic-gate * ("{%s}%s", auth_name, public_data)=nisPublicKey 20700Sstevel@tonic-gate * and assuming that 'nisPublicKey' has the value "{dh640-0}abcdef12345", 20710Sstevel@tonic-gate * assign "dh640-0" to 'auth_name' and "abcdef12345" to 'public_data'. 20720Sstevel@tonic-gate * 20730Sstevel@tonic-gate * Note that this function doesn't perform the actual assignment. Rather, 20740Sstevel@tonic-gate * it returns an array of __nis_value_t's, with element zero of the value 20750Sstevel@tonic-gate * array being the new value of the first matched item, element one the 20760Sstevel@tonic-gate * value of the second matched item, etc. In the example above, we'd 20770Sstevel@tonic-gate * return a value array with two elements. 20780Sstevel@tonic-gate * 20790Sstevel@tonic-gate * If there is more than one input value (inVal->numVals > 1), the 20800Sstevel@tonic-gate * output array elements will also be multi-valued. 20810Sstevel@tonic-gate * 20820Sstevel@tonic-gate * f The match format 20830Sstevel@tonic-gate * inVal Input value(s) 20840Sstevel@tonic-gate * numVal Number of elements in the output value array 20850Sstevel@tonic-gate * sepset List of separators 20860Sstevel@tonic-gate * outstr Points to the updated position upto which the 20870Sstevel@tonic-gate * input string has been matched 20880Sstevel@tonic-gate */ 20890Sstevel@tonic-gate __nis_value_t ** 20900Sstevel@tonic-gate matchMappingItem(__nis_mapping_format_t *f, __nis_value_t *inVal, 20910Sstevel@tonic-gate int *numVals, char *sepset, char **outstr) { 20920Sstevel@tonic-gate __nis_value_t **v = 0; 20930Sstevel@tonic-gate int i, n, ni, numItems, nf, nv = 0; 20940Sstevel@tonic-gate char *str, *valstr; 20950Sstevel@tonic-gate __nis_mapping_format_t *ftmp; 20960Sstevel@tonic-gate char *myself = "matchMappingItem"; 20970Sstevel@tonic-gate 20980Sstevel@tonic-gate if (f == 0 || 20990Sstevel@tonic-gate inVal == 0 || inVal->numVals < 1 || inVal->type != vt_string) 21000Sstevel@tonic-gate return (0); 21010Sstevel@tonic-gate 21020Sstevel@tonic-gate /* Count the number of format elements and items in the format */ 21030Sstevel@tonic-gate for (nf = numItems = 0, ftmp = f; ftmp->type != mmt_end; ftmp++) { 21040Sstevel@tonic-gate nf++; 21050Sstevel@tonic-gate 21060Sstevel@tonic-gate /* 21070Sstevel@tonic-gate * Count mmt_item and mmt_berstring (used by N2L to 21080Sstevel@tonic-gate * represent address %a) 21090Sstevel@tonic-gate */ 21100Sstevel@tonic-gate if (ftmp->type == mmt_item) 21110Sstevel@tonic-gate numItems++; 21120Sstevel@tonic-gate else if (ftmp->type == mmt_berstring && ftmp->match.berString && 21130Sstevel@tonic-gate ftmp->match.berString[0] == 'a') 21140Sstevel@tonic-gate numItems++; 21150Sstevel@tonic-gate } 21160Sstevel@tonic-gate /* Count the mmt_end as well */ 21170Sstevel@tonic-gate nf++; 21180Sstevel@tonic-gate 21190Sstevel@tonic-gate /* 21200Sstevel@tonic-gate * If no items, there will be no values. This isn't exactly an error 21210Sstevel@tonic-gate * from the limited point of view of this function, so we return a 21220Sstevel@tonic-gate * __nis_value_t with zero values. 21230Sstevel@tonic-gate */ 21240Sstevel@tonic-gate if (numItems <= 0) { 21250Sstevel@tonic-gate v = am(myself, sizeof (v[0])); 21260Sstevel@tonic-gate if (v == 0) 21270Sstevel@tonic-gate return (0); 21280Sstevel@tonic-gate v[0] = am(myself, sizeof (*v[0])); 21290Sstevel@tonic-gate if (v[0] == 0) { 21300Sstevel@tonic-gate sfree(v); 21310Sstevel@tonic-gate return (0); 21320Sstevel@tonic-gate } 21330Sstevel@tonic-gate v[0]->type = vt_string; 21340Sstevel@tonic-gate v[0]->numVals = 0; 21350Sstevel@tonic-gate v[0]->val = 0; 21360Sstevel@tonic-gate if (numVals != 0) 21370Sstevel@tonic-gate *numVals = 1; 21380Sstevel@tonic-gate return (v); 21390Sstevel@tonic-gate } 21400Sstevel@tonic-gate 21410Sstevel@tonic-gate /* Allocate and initialize the return array */ 21420Sstevel@tonic-gate v = am(myself, numItems * sizeof (v[0])); 21430Sstevel@tonic-gate if (v == 0) 21440Sstevel@tonic-gate return (0); 21450Sstevel@tonic-gate for (n = 0; n < numItems; n++) { 21460Sstevel@tonic-gate v[n] = am(myself, sizeof (*v[n])); 21470Sstevel@tonic-gate if (v[n] == 0) { 21480Sstevel@tonic-gate int j; 21490Sstevel@tonic-gate 21500Sstevel@tonic-gate for (j = 0; j < n; j++) 21510Sstevel@tonic-gate freeValue(v[j], 1); 21520Sstevel@tonic-gate sfree(v); 21530Sstevel@tonic-gate return (0); 21540Sstevel@tonic-gate } 21550Sstevel@tonic-gate v[n]->type = vt_string; 21560Sstevel@tonic-gate v[n]->numVals = 0; 21570Sstevel@tonic-gate v[n]->val = am(myself, inVal->numVals * sizeof (v[n]->val[0])); 21580Sstevel@tonic-gate if (v[n]->val == 0) { 21590Sstevel@tonic-gate int j; 21600Sstevel@tonic-gate 21610Sstevel@tonic-gate for (j = 0; j < n; j++) 21620Sstevel@tonic-gate freeValue(v[j], 1); 21630Sstevel@tonic-gate sfree(v); 21640Sstevel@tonic-gate return (0); 21650Sstevel@tonic-gate } 21660Sstevel@tonic-gate for (i = 0; i < inVal->numVals; i++) { 21670Sstevel@tonic-gate v[n]->val[i].length = 0; 21680Sstevel@tonic-gate v[n]->val[i].value = 0; 21690Sstevel@tonic-gate } 21700Sstevel@tonic-gate } 21710Sstevel@tonic-gate 21720Sstevel@tonic-gate /* For each input value, perform the match operation */ 21730Sstevel@tonic-gate for (i = 0; i < inVal->numVals; i++) { 21740Sstevel@tonic-gate str = inVal->val[i].value; 21750Sstevel@tonic-gate if (str == 0) 21760Sstevel@tonic-gate continue; 21770Sstevel@tonic-gate for (n = 0, ni = 0; n < nf; n++) { 21780Sstevel@tonic-gate valstr = 0; 21790Sstevel@tonic-gate str = scanMappingFormat(f, n, nf, str, &valstr, 21800Sstevel@tonic-gate 0, sepset); 21810Sstevel@tonic-gate if (str == 0) 21820Sstevel@tonic-gate break; 21830Sstevel@tonic-gate if (valstr != 0 && ni < numItems && 21840Sstevel@tonic-gate v[ni]->numVals < inVal->numVals) { 21850Sstevel@tonic-gate v[ni]->val[v[ni]->numVals].value = valstr; 21860Sstevel@tonic-gate v[ni]->val[v[ni]->numVals].length = 21870Sstevel@tonic-gate strlen(valstr) + 1; 21880Sstevel@tonic-gate v[ni]->numVals++; 21890Sstevel@tonic-gate ni++; 21900Sstevel@tonic-gate } else if (valstr != 0) { 21910Sstevel@tonic-gate sfree(valstr); 21920Sstevel@tonic-gate } 21930Sstevel@tonic-gate } 21940Sstevel@tonic-gate if (str == 0) { 21950Sstevel@tonic-gate for (n = 0; n < numItems; n++) 21960Sstevel@tonic-gate freeValue(v[n], 1); 21970Sstevel@tonic-gate sfree(v); 21980Sstevel@tonic-gate return (0); 21990Sstevel@tonic-gate } 22000Sstevel@tonic-gate } 22010Sstevel@tonic-gate 22020Sstevel@tonic-gate if (numVals != 0) 22030Sstevel@tonic-gate *numVals = numItems; 22040Sstevel@tonic-gate 22050Sstevel@tonic-gate /* 22060Sstevel@tonic-gate * Update the return string upto the point it has been matched 22070Sstevel@tonic-gate * This string will be used by the N2L code in its next call 22080Sstevel@tonic-gate * to this function 22090Sstevel@tonic-gate */ 22100Sstevel@tonic-gate if (outstr != 0) 22110Sstevel@tonic-gate *outstr = str; 22120Sstevel@tonic-gate 22130Sstevel@tonic-gate return (v); 22140Sstevel@tonic-gate } 22150Sstevel@tonic-gate 22160Sstevel@tonic-gate /* 22170Sstevel@tonic-gate * Perform an extract operation. For example, given the expression 22180Sstevel@tonic-gate * (name, "%s.*") 22190Sstevel@tonic-gate * and assuming 'name' is an item with the value "some.thing", the 22200Sstevel@tonic-gate * value returned by the extract is "some". 22210Sstevel@tonic-gate */ 22220Sstevel@tonic-gate __nis_value_t * 22230Sstevel@tonic-gate extractMappingItem(__nis_mapping_item_t *item, __nis_mapping_format_t *f, 22240Sstevel@tonic-gate __nis_rule_value_t *rv, int *stat) { 22250Sstevel@tonic-gate __nis_value_t *val = getMappingItem(item, mit_any, 22260Sstevel@tonic-gate rv, 0, stat); 22270Sstevel@tonic-gate __nis_single_value_t *nval; 22280Sstevel@tonic-gate int i, n, nv, nf; 22290Sstevel@tonic-gate __nis_mapping_format_t *ftmp; 22300Sstevel@tonic-gate 22310Sstevel@tonic-gate if (val == 0) 22320Sstevel@tonic-gate return (0); 22330Sstevel@tonic-gate else if (f == 0 || rv == 0 || val->val == 0 || 22340Sstevel@tonic-gate val->numVals <= 0 || val->type != vt_string) { 22350Sstevel@tonic-gate freeValue(val, 1); 22360Sstevel@tonic-gate return (0); 22370Sstevel@tonic-gate } 22380Sstevel@tonic-gate 22390Sstevel@tonic-gate /* Sanity check the format; it must have one and only one mmt_item */ 22400Sstevel@tonic-gate { 22410Sstevel@tonic-gate int numitem; 22420Sstevel@tonic-gate 22430Sstevel@tonic-gate for (nf = numitem = 0, ftmp = f; ftmp->type != mmt_end; 22440Sstevel@tonic-gate ftmp++) { 22450Sstevel@tonic-gate nf++; 22460Sstevel@tonic-gate if (ftmp->type == mmt_item) 22470Sstevel@tonic-gate numitem++; 22480Sstevel@tonic-gate } 22490Sstevel@tonic-gate /* Count the mmt_end as well */ 22500Sstevel@tonic-gate nf++; 22510Sstevel@tonic-gate if (numitem != 1) { 22520Sstevel@tonic-gate freeValue(val, 1); 22530Sstevel@tonic-gate return (0); 22540Sstevel@tonic-gate } 22550Sstevel@tonic-gate } 22560Sstevel@tonic-gate 22570Sstevel@tonic-gate nval = val->val; 22580Sstevel@tonic-gate nv = val->numVals; 22590Sstevel@tonic-gate val->repeat = FALSE; 22600Sstevel@tonic-gate val->val = 0; 22610Sstevel@tonic-gate val->numVals = 0; 22620Sstevel@tonic-gate 22630Sstevel@tonic-gate /* If the item has multiple values, we extract each one independently */ 22640Sstevel@tonic-gate for (i = 0; i < nv; i++) { 22650Sstevel@tonic-gate char *str = nval[i].value; 22660Sstevel@tonic-gate char *newstr = 0; 22670Sstevel@tonic-gate __nis_single_value_t *newval; 22680Sstevel@tonic-gate 22690Sstevel@tonic-gate if (nval[i].value == 0) 22700Sstevel@tonic-gate continue; 22710Sstevel@tonic-gate 22720Sstevel@tonic-gate /* 22730Sstevel@tonic-gate * We match the whole string, even if we find a value for 22740Sstevel@tonic-gate * the item before exhausting all format elements. By doing 22750Sstevel@tonic-gate * this, we ensure that the string really matches the complete 22760Sstevel@tonic-gate * format specification. 22770Sstevel@tonic-gate */ 22780Sstevel@tonic-gate for (n = 0; n < nf; n++) { 22790Sstevel@tonic-gate str = scanMappingFormat(f, n, nf, str, &newstr, 0, 0); 22800Sstevel@tonic-gate if (str == 0) 22810Sstevel@tonic-gate break; 22820Sstevel@tonic-gate } 22830Sstevel@tonic-gate 22840Sstevel@tonic-gate /* 22850Sstevel@tonic-gate * *str should now be NUL, meaning we've reached the end of 22860Sstevel@tonic-gate * the string (value), and it completely matched the format. 22870Sstevel@tonic-gate * If 'str' is NULL, there was an error, and if 'newstr' is 22880Sstevel@tonic-gate * 0, we somehow failed to obtain a value. 22890Sstevel@tonic-gate */ 22900Sstevel@tonic-gate if (str == 0 || *str != '\0' || newstr == 0 || 22910Sstevel@tonic-gate (newval = realloc(val->val, 22920Sstevel@tonic-gate (val->numVals+1) * 22930Sstevel@tonic-gate sizeof (val->val[0]))) == 0) { 22940Sstevel@tonic-gate freeValue(val, 1); 22950Sstevel@tonic-gate for (n = 0; n < nv; n++) { 22960Sstevel@tonic-gate sfree(nval[n].value); 22970Sstevel@tonic-gate } 22980Sstevel@tonic-gate free(nval); 22990Sstevel@tonic-gate sfree(newstr); 23000Sstevel@tonic-gate return (0); 23010Sstevel@tonic-gate } 23020Sstevel@tonic-gate 23030Sstevel@tonic-gate val->val = newval; 23040Sstevel@tonic-gate val->val[val->numVals].value = newstr; 23050Sstevel@tonic-gate val->val[val->numVals].length = strlen(newstr) + 1; 23060Sstevel@tonic-gate val->numVals++; 23070Sstevel@tonic-gate 23080Sstevel@tonic-gate free(nval[i].value); 23090Sstevel@tonic-gate nval[i].value = 0; 23100Sstevel@tonic-gate } 23110Sstevel@tonic-gate free(nval); 23120Sstevel@tonic-gate 23130Sstevel@tonic-gate return (val); 23140Sstevel@tonic-gate } 23150Sstevel@tonic-gate 23160Sstevel@tonic-gate /* 23170Sstevel@tonic-gate * For each value in 'val', remove the last character, provided that 23180Sstevel@tonic-gate * it matches 'elide'. 23190Sstevel@tonic-gate */ 23200Sstevel@tonic-gate void 23210Sstevel@tonic-gate stringElide(__nis_value_t *val, char elide) { 23220Sstevel@tonic-gate 23230Sstevel@tonic-gate if (val != 0 && val->type == vt_string) { 23240Sstevel@tonic-gate int i; 23250Sstevel@tonic-gate 23260Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 23270Sstevel@tonic-gate int end = val->val[i].length; 23280Sstevel@tonic-gate char *str = val->val[i].value; 23290Sstevel@tonic-gate 23300Sstevel@tonic-gate if (str == 0 || end <= 0) 23310Sstevel@tonic-gate continue; 23320Sstevel@tonic-gate 23330Sstevel@tonic-gate /* 23340Sstevel@tonic-gate * If the NUL was counted in the length, step back 23350Sstevel@tonic-gate * over it. 23360Sstevel@tonic-gate */ 23370Sstevel@tonic-gate if (str[end-1] == '\0') 23380Sstevel@tonic-gate end--; 23390Sstevel@tonic-gate if (end > 0 && str[end-1] == elide) { 23400Sstevel@tonic-gate str[end-1] = '\0'; 23410Sstevel@tonic-gate val->val[i].length--; 23420Sstevel@tonic-gate } 23430Sstevel@tonic-gate } 23440Sstevel@tonic-gate } 23450Sstevel@tonic-gate } 23460Sstevel@tonic-gate 23470Sstevel@tonic-gate /* 23480Sstevel@tonic-gate * Obtain the value for the mapping sub-element 'e', given the input 23490Sstevel@tonic-gate * rule-value 'rv'. 23500Sstevel@tonic-gate */ 23510Sstevel@tonic-gate __nis_value_t * 23520Sstevel@tonic-gate getMappingSubElement(__nis_mapping_sub_element_t *e, 23530Sstevel@tonic-gate __nis_rule_value_t *rv, int *np_ldap_stat) { 23540Sstevel@tonic-gate __nis_value_t *val; 23550Sstevel@tonic-gate 23560Sstevel@tonic-gate if (e == 0) 23570Sstevel@tonic-gate return (0); 23580Sstevel@tonic-gate 23590Sstevel@tonic-gate switch (e->type) { 23600Sstevel@tonic-gate case me_item: 23610Sstevel@tonic-gate val = getMappingItem(&e->element.item, mit_any, rv, 0, 23620Sstevel@tonic-gate np_ldap_stat); 23630Sstevel@tonic-gate break; 23640Sstevel@tonic-gate case me_print: 23650Sstevel@tonic-gate val = getMappingFormatArray(e->element.print.fmt, rv, 23660Sstevel@tonic-gate fa_item, 23670Sstevel@tonic-gate e->element.print.numItems, 23680Sstevel@tonic-gate e->element.print.item); 23690Sstevel@tonic-gate if (e->element.print.doElide) 23700Sstevel@tonic-gate stringElide(val, e->element.print.elide); 23710Sstevel@tonic-gate break; 23720Sstevel@tonic-gate case me_split: 23730Sstevel@tonic-gate val = splitMappingItem(&e->element.split.item, 23740Sstevel@tonic-gate e->element.split.delim, 23750Sstevel@tonic-gate rv); 23760Sstevel@tonic-gate break; 23770Sstevel@tonic-gate case me_extract: 23780Sstevel@tonic-gate val = extractMappingItem(&e->element.extract.item, 23790Sstevel@tonic-gate e->element.extract.fmt, 23800Sstevel@tonic-gate rv, np_ldap_stat); 23810Sstevel@tonic-gate break; 23820Sstevel@tonic-gate case me_match: 23830Sstevel@tonic-gate default: 23840Sstevel@tonic-gate val = 0; 23850Sstevel@tonic-gate break; 23860Sstevel@tonic-gate } 23870Sstevel@tonic-gate 23880Sstevel@tonic-gate return (val); 23890Sstevel@tonic-gate } 23900Sstevel@tonic-gate 23910Sstevel@tonic-gate /* 23920Sstevel@tonic-gate * Obtain the value of the mapping element 'e', given the input rule- 23930Sstevel@tonic-gate * value 'rv'. The 'native' mapping type is used when 'rv' is NULL, 23940Sstevel@tonic-gate * and the result is a string representation of the mapping element; 23950Sstevel@tonic-gate * in that case, items of the 'native' type are printed without their 23960Sstevel@tonic-gate * type designation ("nis+" or "ldap"). 23970Sstevel@tonic-gate */ 23980Sstevel@tonic-gate __nis_value_t * 23990Sstevel@tonic-gate getMappingElement(__nis_mapping_element_t *e, __nis_mapping_item_type_t native, 24000Sstevel@tonic-gate __nis_rule_value_t *rv, int *stat) { 24010Sstevel@tonic-gate __nis_value_t *val, **tv; 24020Sstevel@tonic-gate int i, success = 0, novalue = 0; 24030Sstevel@tonic-gate int *np_ldap_stat; 24040Sstevel@tonic-gate char *myself = "getMappingElement"; 24050Sstevel@tonic-gate 24060Sstevel@tonic-gate switch (e->type) { 24070Sstevel@tonic-gate case me_item: 24080Sstevel@tonic-gate val = getMappingItem(&e->element.item, native, rv, 0, NULL); 24090Sstevel@tonic-gate break; 24100Sstevel@tonic-gate case me_print: 24110Sstevel@tonic-gate tv = am(myself, e->element.print.numSubElements * 24120Sstevel@tonic-gate sizeof (tv[0])); 24130Sstevel@tonic-gate np_ldap_stat = am(myself, 24140Sstevel@tonic-gate e->element.print.numSubElements * sizeof (int)); 24150Sstevel@tonic-gate if ((e->element.print.numSubElements > 0) && 24160Sstevel@tonic-gate (tv == 0 || np_ldap_stat == 0)) { 24170Sstevel@tonic-gate val = 0; 24180Sstevel@tonic-gate sfree(tv); 24190Sstevel@tonic-gate sfree(np_ldap_stat); 24200Sstevel@tonic-gate break; 24210Sstevel@tonic-gate } 24220Sstevel@tonic-gate for (i = 0; i < e->element.print.numSubElements; i++) { 24230Sstevel@tonic-gate np_ldap_stat[i] = 0; 24240Sstevel@tonic-gate tv[i] = getMappingSubElement( 24250Sstevel@tonic-gate &e->element.print.subElement[i], 24260Sstevel@tonic-gate rv, &np_ldap_stat[i]); 24270Sstevel@tonic-gate } 24280Sstevel@tonic-gate /* 24290Sstevel@tonic-gate * if we get NP_LDAP_NO_VALUE to any of the subelement 24300Sstevel@tonic-gate * and we get NP_LDAP_MAP_SUCCESS to all other subelement 24310Sstevel@tonic-gate * then we had enough nis+ column values which can 24320Sstevel@tonic-gate * produce value for this rule, but didn't. So return 24330Sstevel@tonic-gate * NP_LDAP_RULES_NO_VALUE to indicate to proceed to 24340Sstevel@tonic-gate * next database id. 24350Sstevel@tonic-gate */ 24360Sstevel@tonic-gate for (i = 0; i < e->element.print.numSubElements; i++) { 24370Sstevel@tonic-gate if (np_ldap_stat[i] == NP_LDAP_MAP_SUCCESS) 24380Sstevel@tonic-gate success++; 24390Sstevel@tonic-gate if (np_ldap_stat[i] == NP_LDAP_NO_VALUE) 24400Sstevel@tonic-gate novalue++; 24410Sstevel@tonic-gate } 24420Sstevel@tonic-gate if (stat != NULL && novalue > 0 && 24430Sstevel@tonic-gate ((novalue+success) == 24440Sstevel@tonic-gate e->element.print.numSubElements)) 24450Sstevel@tonic-gate *stat = NP_LDAP_RULES_NO_VALUE; 24460Sstevel@tonic-gate val = getMappingFormatArray(e->element.print.fmt, rv, 24470Sstevel@tonic-gate fa_value, 24480Sstevel@tonic-gate e->element.print.numSubElements, 24490Sstevel@tonic-gate tv); 24500Sstevel@tonic-gate for (i = 0; i < e->element.print.numSubElements; i++) { 24510Sstevel@tonic-gate freeValue(tv[i], 1); 24520Sstevel@tonic-gate } 24530Sstevel@tonic-gate sfree(tv); 24540Sstevel@tonic-gate sfree(np_ldap_stat); 24550Sstevel@tonic-gate if (e->element.print.doElide) 24560Sstevel@tonic-gate stringElide(val, e->element.print.elide); 24570Sstevel@tonic-gate break; 24580Sstevel@tonic-gate case me_split: 24590Sstevel@tonic-gate val = splitMappingItem(&e->element.split.item, 24600Sstevel@tonic-gate e->element.split.delim, 24610Sstevel@tonic-gate rv); 24620Sstevel@tonic-gate break; 24630Sstevel@tonic-gate case me_match: 24640Sstevel@tonic-gate /* 24650Sstevel@tonic-gate * A match doesn't produce an assignable value per se, 24660Sstevel@tonic-gate * so we shouldn't get one here. 24670Sstevel@tonic-gate */ 24680Sstevel@tonic-gate val = 0; 24690Sstevel@tonic-gate break; 24700Sstevel@tonic-gate case me_extract: 24710Sstevel@tonic-gate val = extractMappingItem(&e->element.extract.item, 24720Sstevel@tonic-gate e->element.extract.fmt, 24730Sstevel@tonic-gate rv, NULL); 24740Sstevel@tonic-gate break; 24750Sstevel@tonic-gate default: 24760Sstevel@tonic-gate val = 0; 24770Sstevel@tonic-gate break; 24780Sstevel@tonic-gate } 24790Sstevel@tonic-gate 24800Sstevel@tonic-gate return (val); 24810Sstevel@tonic-gate } 2482