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 #include <strings.h> 270Sstevel@tonic-gate #include <sys/types.h> 280Sstevel@tonic-gate #include <sys/stat.h> 290Sstevel@tonic-gate #include <errno.h> 300Sstevel@tonic-gate #include <stdio.h> 310Sstevel@tonic-gate #include <rpcsvc/nis.h> 320Sstevel@tonic-gate #include <rpc/xdr.h> 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include "ldap_util.h" 350Sstevel@tonic-gate #include "ldap_attr.h" 360Sstevel@tonic-gate #include "ldap_ruleval.h" 370Sstevel@tonic-gate #include "ldap_op.h" 380Sstevel@tonic-gate #include "ldap_map.h" 390Sstevel@tonic-gate #include "ldap_glob.h" 400Sstevel@tonic-gate #include "ldap_xdr.h" 410Sstevel@tonic-gate #include "ldap_val.h" 420Sstevel@tonic-gate 430Sstevel@tonic-gate /* From yptol/dit_access_utils.h */ 440Sstevel@tonic-gate #define N2LKEY "rf_key" 450Sstevel@tonic-gate #define N2LIPKEY "rf_ipkey" 460Sstevel@tonic-gate 470Sstevel@tonic-gate __nis_hash_table_mt ldapMappingList = NIS_HASH_TABLE_MT_INIT; 480Sstevel@tonic-gate extern int yp2ldap; 490Sstevel@tonic-gate 500Sstevel@tonic-gate 510Sstevel@tonic-gate int 520Sstevel@tonic-gate setColumnNames(__nis_table_mapping_t *t) { 53*11262SRajagopal.Andra@Sun.COM int i, j, nic, noc; 540Sstevel@tonic-gate char **col; 550Sstevel@tonic-gate zotypes type; 560Sstevel@tonic-gate char *myself = "setColumnNames"; 570Sstevel@tonic-gate 580Sstevel@tonic-gate if (t == 0) 590Sstevel@tonic-gate return (0); 600Sstevel@tonic-gate 610Sstevel@tonic-gate type = t->objType; 620Sstevel@tonic-gate col = t->column; 630Sstevel@tonic-gate nic = (col != 0) ? t->numColumns : -1; 640Sstevel@tonic-gate 650Sstevel@tonic-gate t->objType = NIS_BOGUS_OBJ; 660Sstevel@tonic-gate t->obj = 0; 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* 690Sstevel@tonic-gate * If it's a table object, but there are no translation rules, 700Sstevel@tonic-gate * this mapping is for the table object itself. In that case, 710Sstevel@tonic-gate * we throw away the column names (if any). 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate if (t->objType == NIS_TABLE_OBJ && t->numRulesFromLDAP == 0 && 740Sstevel@tonic-gate t->numRulesToLDAP == 0) { 750Sstevel@tonic-gate for (i = 0; i < t->numColumns; i++) 760Sstevel@tonic-gate sfree(t->column[i]); 770Sstevel@tonic-gate sfree(t->column); 780Sstevel@tonic-gate t->column = 0; 790Sstevel@tonic-gate t->numColumns = 0; 800Sstevel@tonic-gate noc = 0; 810Sstevel@tonic-gate } 820Sstevel@tonic-gate 830Sstevel@tonic-gate /* 840Sstevel@tonic-gate * Verify that all column names found by the parser 850Sstevel@tonic-gate * are present in the actual column list. 860Sstevel@tonic-gate */ 870Sstevel@tonic-gate if (verbose) { 880Sstevel@tonic-gate for (i = 0, noc = 0; i < nic; i++) { 890Sstevel@tonic-gate int found = 0; 900Sstevel@tonic-gate 910Sstevel@tonic-gate if (col[i] == 0) 920Sstevel@tonic-gate continue; 930Sstevel@tonic-gate /* Skip the 'zo_*' special column names */ 940Sstevel@tonic-gate if (isObjAttrString(col[i])) 950Sstevel@tonic-gate continue; 960Sstevel@tonic-gate for (j = 0; j < t->numColumns; j++) { 970Sstevel@tonic-gate if (strcmp(col[i], t->column[j]) == 0) { 980Sstevel@tonic-gate noc++; 990Sstevel@tonic-gate found = 1; 1000Sstevel@tonic-gate break; 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate if (!found) { 1040Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1050Sstevel@tonic-gate "%s: No column \"%s\" in \"%s\"", 1060Sstevel@tonic-gate myself, NIL(col[i]), NIL(t->objName)); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /* Remove any setup by the parser */ 1120Sstevel@tonic-gate for (i = 0; i < nic; i++) { 1130Sstevel@tonic-gate sfree(col[i]); 1140Sstevel@tonic-gate } 1150Sstevel@tonic-gate sfree(col); 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate return (0); 1180Sstevel@tonic-gate } 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate void 1210Sstevel@tonic-gate freeSingleObjAttr(__nis_obj_attr_t *attr) { 1220Sstevel@tonic-gate if (attr == 0) 1230Sstevel@tonic-gate return; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate sfree(attr->zo_owner); 1260Sstevel@tonic-gate sfree(attr->zo_group); 1270Sstevel@tonic-gate sfree(attr->zo_domain); 1280Sstevel@tonic-gate sfree(attr); 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate void 1320Sstevel@tonic-gate freeObjAttr(__nis_obj_attr_t **attr, int numAttr) { 1330Sstevel@tonic-gate int i; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate if (attr == 0) 1360Sstevel@tonic-gate return; 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate for (i = 0; i < numAttr; i++) { 1390Sstevel@tonic-gate freeSingleObjAttr(attr[i]); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate sfree(attr); 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate __nis_obj_attr_t * 1460Sstevel@tonic-gate cloneObjAttr(__nis_obj_attr_t *old) { 1470Sstevel@tonic-gate __nis_obj_attr_t *new; 1480Sstevel@tonic-gate char *myself = "cloneObjAttr"; 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate if (old == 0) 1510Sstevel@tonic-gate return (0); 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate new = am(myself, sizeof (*new)); 1540Sstevel@tonic-gate if (new == 0) 1550Sstevel@tonic-gate return (0); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate new->zo_owner = sdup(myself, T, old->zo_owner); 1580Sstevel@tonic-gate if (new->zo_owner == 0 && old->zo_owner != 0) 1590Sstevel@tonic-gate goto cleanup; 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate new->zo_group = sdup(myself, T, old->zo_group); 1620Sstevel@tonic-gate if (new->zo_group == 0 && old->zo_group != 0) 1630Sstevel@tonic-gate goto cleanup; 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate new->zo_domain = sdup(myself, T, old->zo_domain); 1660Sstevel@tonic-gate if (new->zo_domain == 0 && old->zo_domain != 0) 1670Sstevel@tonic-gate goto cleanup; 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate new->zo_access = old->zo_access; 1700Sstevel@tonic-gate new->zo_ttl = old->zo_ttl; 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate return (new); 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate cleanup: 1750Sstevel@tonic-gate freeSingleObjAttr(new); 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate return (0); 1780Sstevel@tonic-gate } 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate /* 1820Sstevel@tonic-gate * Obtain NIS+ entries (in the form of db_query's) from the supplied table 1830Sstevel@tonic-gate * mapping and db_query. 1840Sstevel@tonic-gate * 1850Sstevel@tonic-gate * If 'qin' is NULL, enumeration is desired. 1860Sstevel@tonic-gate * 1870Sstevel@tonic-gate * On exit, '*numQueries' contains the number of (db_query *)'s in the 1880Sstevel@tonic-gate * return array, '*ldapStat' the LDAP operation status, and '*objAttr' 1890Sstevel@tonic-gate * a pointer to an array (of '*numQueries elements) of object attributes 1900Sstevel@tonic-gate * (zo_owner, etc.). If no object attributes were retrieved, '*objAttr' 1910Sstevel@tonic-gate * is NULL; any and all of the (*objAttr)[i]'s may be NULL. 1920Sstevel@tonic-gate */ 1930Sstevel@tonic-gate db_query ** 1940Sstevel@tonic-gate mapFromLDAP(__nis_table_mapping_t *t, db_query *qin, int *numQueries, 1950Sstevel@tonic-gate char *dbId, int *ldapStat, __nis_obj_attr_t ***objAttr) { 1960Sstevel@tonic-gate __nis_table_mapping_t **tp; 1970Sstevel@tonic-gate db_query **q; 1980Sstevel@tonic-gate __nis_rule_value_t *rv; 1990Sstevel@tonic-gate __nis_ldap_search_t *ls; 2000Sstevel@tonic-gate int n, numVals, numMatches = 0; 2010Sstevel@tonic-gate int stat; 2020Sstevel@tonic-gate __nis_obj_attr_t **attr; 2030Sstevel@tonic-gate char *myself = "mapFromLDAP"; 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate if (ldapStat == 0) 2060Sstevel@tonic-gate ldapStat = &stat; 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate if (t == 0 || numQueries == 0) { 2090Sstevel@tonic-gate *ldapStat = LDAP_PARAM_ERROR; 2100Sstevel@tonic-gate return (0); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate /* Select the correct table mapping(s) */ 2140Sstevel@tonic-gate tp = selectTableMapping(t, qin, 0, 0, dbId, &numMatches); 2150Sstevel@tonic-gate if (tp == 0 || numMatches <= 0) { 2160Sstevel@tonic-gate /* 2170Sstevel@tonic-gate * Not really an error; just no matching mapping 2180Sstevel@tonic-gate * for the query. 2190Sstevel@tonic-gate */ 2200Sstevel@tonic-gate *ldapStat = LDAP_SUCCESS; 2210Sstevel@tonic-gate return (0); 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate q = 0; 2250Sstevel@tonic-gate attr = 0; 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate /* For each mapping */ 2280Sstevel@tonic-gate for (numVals = 0, n = 0; n < numMatches; n++) { 2290Sstevel@tonic-gate db_query **qt; 2300Sstevel@tonic-gate int i, nqt = 0, filterOnQin, res = 0; 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate t = tp[n]; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate if (qin != 0) { 2350Sstevel@tonic-gate rv = buildNisPlusRuleValue(t, qin, 0); 2360Sstevel@tonic-gate if (rv != 0) { 2370Sstevel@tonic-gate /* 2380Sstevel@tonic-gate * Depending on the value of res, we shall 2390Sstevel@tonic-gate * proceed to next table mapping. 2400Sstevel@tonic-gate */ 2410Sstevel@tonic-gate ls = createLdapRequest(t, rv, 0, 1, &res, NULL); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate else 2440Sstevel@tonic-gate ls = 0; 2450Sstevel@tonic-gate } else { 2460Sstevel@tonic-gate /* Build enumeration request */ 2470Sstevel@tonic-gate rv = 0; 2480Sstevel@tonic-gate ls = createLdapRequest(t, 0, 0, 1, NULL, NULL); 2490Sstevel@tonic-gate } 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate freeRuleValue(rv, 1); 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate if (ls == 0) { 2540Sstevel@tonic-gate /* 2550Sstevel@tonic-gate * if the res is NP_LDAP_RULES_NO_VALUE, that means we 2560Sstevel@tonic-gate * have enough NIS+ columns for the rules to produce 2570Sstevel@tonic-gate * values, but none of them did, so continue to the 2580Sstevel@tonic-gate * next table mapping. Otherwise do cleanup and return 2590Sstevel@tonic-gate * error. 2600Sstevel@tonic-gate */ 2610Sstevel@tonic-gate if (res == NP_LDAP_RULES_NO_VALUE) 2620Sstevel@tonic-gate continue; 2630Sstevel@tonic-gate for (i = 0; i < numVals; i++) 2640Sstevel@tonic-gate freeQuery(q[i]); 2650Sstevel@tonic-gate sfree(q); 2660Sstevel@tonic-gate free(tp); 2670Sstevel@tonic-gate *ldapStat = LDAP_OPERATIONS_ERROR; 2680Sstevel@tonic-gate return (0); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* Query LDAP */ 2720Sstevel@tonic-gate nqt = (ls->isDN || qin != 0) ? 0 : -1; 2730Sstevel@tonic-gate rv = ldapSearch(ls, &nqt, 0, ldapStat); 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate /* 2760Sstevel@tonic-gate * If qin != 0, then we need to make sure that the 2770Sstevel@tonic-gate * LDAP search is filtered so that only entries that 2780Sstevel@tonic-gate * are compatible with 'qin' are retained. This will 2790Sstevel@tonic-gate * happen automatically if we do a DN search (in which 2800Sstevel@tonic-gate * case, no need to filter on 'qin'). 2810Sstevel@tonic-gate */ 2820Sstevel@tonic-gate if (ls->isDN || qin == 0) 2830Sstevel@tonic-gate filterOnQin = 0; 2840Sstevel@tonic-gate else 2850Sstevel@tonic-gate filterOnQin = 1; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate freeLdapSearch(ls); 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate /* Convert rule-values to db_query's */ 2900Sstevel@tonic-gate if (rv != 0 && nqt > 0) { 2910Sstevel@tonic-gate int nrv = nqt; 2920Sstevel@tonic-gate __nis_obj_attr_t **at = 0; 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate qt = ruleValue2Query(t, rv, 2950Sstevel@tonic-gate (filterOnQin) ? qin : 0, &at, &nqt); 2960Sstevel@tonic-gate freeRuleValue(rv, nrv); 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate if (qt != 0 && q == 0) { 2990Sstevel@tonic-gate q = qt; 3000Sstevel@tonic-gate attr = at; 3010Sstevel@tonic-gate numVals = nqt; 3020Sstevel@tonic-gate } else if (qt != 0) { 3030Sstevel@tonic-gate db_query **tmp; 3040Sstevel@tonic-gate __nis_obj_attr_t **atmp; 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate /* Extend the 'q' array */ 3070Sstevel@tonic-gate tmp = realloc(q, 3080Sstevel@tonic-gate (numVals+nqt) * sizeof (q[0])); 3090Sstevel@tonic-gate /* ... and the 'attr' array */ 3100Sstevel@tonic-gate atmp = realloc(attr, 3110Sstevel@tonic-gate (numVals+nqt) * sizeof (attr[0])); 3120Sstevel@tonic-gate if (tmp == 0 || atmp == 0) { 3130Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 3140Sstevel@tonic-gate "%s: realloc(%d) => NULL", 3150Sstevel@tonic-gate myself, 3160Sstevel@tonic-gate (numVals+nqt) * sizeof (q[0])); 3170Sstevel@tonic-gate for (i = 0; i < numVals; i++) 3180Sstevel@tonic-gate freeQuery(q[i]); 3190Sstevel@tonic-gate for (i = 0; i < nqt; i++) 3200Sstevel@tonic-gate freeQuery(qt[i]); 3210Sstevel@tonic-gate sfree(tmp); 3220Sstevel@tonic-gate sfree(atmp); 3230Sstevel@tonic-gate sfree(q); 3240Sstevel@tonic-gate sfree(qt); 3250Sstevel@tonic-gate sfree(tp); 3260Sstevel@tonic-gate freeObjAttr(at, nqt); 3270Sstevel@tonic-gate freeObjAttr(attr, numVals); 3280Sstevel@tonic-gate *ldapStat = LDAP_NO_MEMORY; 3290Sstevel@tonic-gate return (0); 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate q = tmp; 3320Sstevel@tonic-gate attr = atmp; 3330Sstevel@tonic-gate /* Add the results for this 't' */ 3340Sstevel@tonic-gate (void) memcpy(&q[numVals], qt, 3350Sstevel@tonic-gate nqt * sizeof (qt[0])); 3360Sstevel@tonic-gate (void) memcpy(&attr[numVals], at, 3370Sstevel@tonic-gate nqt * sizeof (at[0])); 3380Sstevel@tonic-gate numVals += nqt; 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate sfree(qt); 3410Sstevel@tonic-gate sfree(at); 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate *numQueries = numVals; 3470Sstevel@tonic-gate if (objAttr != 0) 3480Sstevel@tonic-gate *objAttr = attr; 3490Sstevel@tonic-gate else 3500Sstevel@tonic-gate freeObjAttr(attr, numVals); 3510Sstevel@tonic-gate sfree(tp); 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate return (q); 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate /* 3570Sstevel@tonic-gate * Add the object attributes (zo_owner, etc.) to the rule-value 'rv'. 3580Sstevel@tonic-gate * Returns a pointer to the (possibly newly allocated) rule-value, 3590Sstevel@tonic-gate * or NULL in case of failure. If not returning 'rvIn', the latter 3600Sstevel@tonic-gate * will have been freed. 3610Sstevel@tonic-gate */ 3620Sstevel@tonic-gate __nis_rule_value_t * 3630Sstevel@tonic-gate addObjAttr2RuleValue(nis_object *obj, __nis_rule_value_t *rvIn) { 3640Sstevel@tonic-gate __nis_rule_value_t *rv; 3650Sstevel@tonic-gate char abuf[2 * sizeof (obj->zo_access) + 1]; 3660Sstevel@tonic-gate char tbuf[2 * sizeof (obj->zo_ttl) + 1]; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate if (obj == 0) 3690Sstevel@tonic-gate return (0); 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate if (rvIn != 0) { 3720Sstevel@tonic-gate rv = rvIn; 3730Sstevel@tonic-gate } else { 3740Sstevel@tonic-gate rv = initRuleValue(1, 0); 3750Sstevel@tonic-gate if (rv == 0) 3760Sstevel@tonic-gate return (0); 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate if (obj->zo_owner != 0) { 3800Sstevel@tonic-gate if (addSCol2RuleValue("zo_owner", obj->zo_owner, rv) != 0) { 3810Sstevel@tonic-gate freeRuleValue(rv, 1); 3820Sstevel@tonic-gate return (0); 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate if (obj->zo_group != 0) { 3870Sstevel@tonic-gate if (addSCol2RuleValue("zo_group", obj->zo_group, rv) != 0) { 3880Sstevel@tonic-gate freeRuleValue(rv, 1); 3890Sstevel@tonic-gate return (0); 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate if (obj->zo_domain != 0) { 3940Sstevel@tonic-gate if (addSCol2RuleValue("zo_domain", obj->zo_domain, rv) != 0) { 3950Sstevel@tonic-gate freeRuleValue(rv, 1); 3960Sstevel@tonic-gate return (0); 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate (void) memset(abuf, 0, sizeof (abuf)); 4010Sstevel@tonic-gate (void) memset(tbuf, 0, sizeof (tbuf)); 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate sprintf(abuf, "%x", obj->zo_access); 4040Sstevel@tonic-gate sprintf(tbuf, "%x", obj->zo_ttl); 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate if (addSCol2RuleValue("zo_access", abuf, rv) != 0) { 4070Sstevel@tonic-gate freeRuleValue(rv, 1); 4080Sstevel@tonic-gate return (0); 4090Sstevel@tonic-gate } 4100Sstevel@tonic-gate if (addSCol2RuleValue("zo_ttl", tbuf, rv) != 0) { 4110Sstevel@tonic-gate freeRuleValue(rv, 1); 4120Sstevel@tonic-gate return (0); 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate return (rv); 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate /* 4190Sstevel@tonic-gate * Returns a pointer to (NOT a copy of) the value for the specified 4200Sstevel@tonic-gate * column 'col' in the rule-value 'rv'. 4210Sstevel@tonic-gate */ 4220Sstevel@tonic-gate __nis_value_t * 4230Sstevel@tonic-gate findColValue(char *col, __nis_rule_value_t *rv) { 4240Sstevel@tonic-gate int i; 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate if (col == 0 || rv == 0 || rv->numColumns <= 0) 4270Sstevel@tonic-gate return (0); 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) { 4300Sstevel@tonic-gate if (strcmp(col, rv->colName[i]) == 0) 4310Sstevel@tonic-gate return (&rv->colVal[i]); 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate return (0); 4350Sstevel@tonic-gate } 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * Return the NIS+ object attributes (if any) in the rule-value 'rv'. 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate __nis_obj_attr_t * 4410Sstevel@tonic-gate ruleValue2ObjAttr(__nis_rule_value_t *rv) { 4420Sstevel@tonic-gate __nis_obj_attr_t *attr; 4430Sstevel@tonic-gate __nis_value_t *val; 4440Sstevel@tonic-gate char *myself = "ruleValue2ObjAttr"; 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate if (rv == 0 || rv->numColumns <= 0) 4470Sstevel@tonic-gate return (0); 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate attr = am(myself, sizeof (*attr)); 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate if ((val = findColValue("zo_owner", rv)) != 0 && 4520Sstevel@tonic-gate val->type == vt_string && val->numVals == 1 && 4530Sstevel@tonic-gate val->val[0].value != 0) { 4540Sstevel@tonic-gate attr->zo_owner = sdup(myself, T, val->val[0].value); 4550Sstevel@tonic-gate if (attr->zo_owner == 0) { 4560Sstevel@tonic-gate freeSingleObjAttr(attr); 4570Sstevel@tonic-gate return (0); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate if ((val = findColValue("zo_group", rv)) != 0 && 4620Sstevel@tonic-gate val->type == vt_string && val->numVals == 1 && 4630Sstevel@tonic-gate val->val[0].value != 0) { 4640Sstevel@tonic-gate attr->zo_group = sdup(myself, T, val->val[0].value); 4650Sstevel@tonic-gate if (attr->zo_group == 0) { 4660Sstevel@tonic-gate freeSingleObjAttr(attr); 4670Sstevel@tonic-gate return (0); 4680Sstevel@tonic-gate } 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate if ((val = findColValue("zo_domain", rv)) != 0 && 4720Sstevel@tonic-gate val->type == vt_string && val->numVals == 1 && 4730Sstevel@tonic-gate val->val[0].value != 0) { 4740Sstevel@tonic-gate attr->zo_domain = sdup(myself, T, val->val[0].value); 4750Sstevel@tonic-gate if (attr->zo_domain == 0) { 4760Sstevel@tonic-gate freeSingleObjAttr(attr); 4770Sstevel@tonic-gate return (0); 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate if ((val = findColValue("zo_access", rv)) != 0 && 4820Sstevel@tonic-gate val->type == vt_string && val->numVals == 1 && 4830Sstevel@tonic-gate val->val[0].value != 0) { 4840Sstevel@tonic-gate if (sscanf(val->val[0].value, "%x", &attr->zo_access) != 1) { 4850Sstevel@tonic-gate freeSingleObjAttr(attr); 4860Sstevel@tonic-gate return (0); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate if ((val = findColValue("zo_ttl", rv)) != 0 && 4910Sstevel@tonic-gate val->type == vt_string && val->numVals == 1 && 4920Sstevel@tonic-gate val->val[0].value != 0) { 4930Sstevel@tonic-gate if (sscanf(val->val[0].value, "%x", &attr->zo_ttl) != 1) { 4940Sstevel@tonic-gate freeSingleObjAttr(attr); 4950Sstevel@tonic-gate return (0); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate return (attr); 5000Sstevel@tonic-gate } 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate /* 5030Sstevel@tonic-gate * If the supplied string is one of the object attributes, return one. 5040Sstevel@tonic-gate * Otherwise, return zero. 5050Sstevel@tonic-gate */ 5060Sstevel@tonic-gate int 5070Sstevel@tonic-gate isObjAttrString(char *str) { 5080Sstevel@tonic-gate if (str == 0) 5090Sstevel@tonic-gate return (0); 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate if (strcmp("zo_owner", str) == 0 || 5120Sstevel@tonic-gate strcmp("zo_group", str) == 0 || 5130Sstevel@tonic-gate strcmp("zo_domain", str) == 0 || 5140Sstevel@tonic-gate strcmp("zo_access", str) == 0 || 5150Sstevel@tonic-gate strcmp("zo_ttl", str) == 0) 5160Sstevel@tonic-gate return (1); 5170Sstevel@tonic-gate else 5180Sstevel@tonic-gate return (0); 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate /* 5230Sstevel@tonic-gate * If the supplied value is one of the object attribute strings, return 5240Sstevel@tonic-gate * a pointer to the string. Otherwise, return NULL. 5250Sstevel@tonic-gate */ 5260Sstevel@tonic-gate char * 5270Sstevel@tonic-gate isObjAttr(__nis_single_value_t *val) { 5280Sstevel@tonic-gate if (val == 0 || val->length <= 0 || val->value == 0) 5290Sstevel@tonic-gate return (0); 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate if (isObjAttrString(val->value)) 5320Sstevel@tonic-gate return (val->value); 5330Sstevel@tonic-gate else 5340Sstevel@tonic-gate return (0); 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate int 5380Sstevel@tonic-gate setObjAttrField(char *attrName, __nis_single_value_t *val, 5390Sstevel@tonic-gate __nis_obj_attr_t **objAttr) { 5400Sstevel@tonic-gate __nis_obj_attr_t *attr; 5410Sstevel@tonic-gate char *myself = "setObjAttrField"; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate if (attrName == 0 || val == 0 || objAttr == 0 || 5440Sstevel@tonic-gate val->value == 0 || val->length <= 0) 5450Sstevel@tonic-gate return (-1); 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate if (*objAttr != 0) { 5480Sstevel@tonic-gate attr = *objAttr; 5490Sstevel@tonic-gate } else { 5500Sstevel@tonic-gate attr = am(myself, sizeof (*attr)); 5510Sstevel@tonic-gate if (attr == 0) 5520Sstevel@tonic-gate return (-2); 5530Sstevel@tonic-gate *objAttr = attr; 5540Sstevel@tonic-gate } 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate if (strcmp("zo_owner", attrName) == 0) { 5570Sstevel@tonic-gate if (attr->zo_owner == 0) { 5580Sstevel@tonic-gate attr->zo_owner = sdup(myself, T, val->value); 5590Sstevel@tonic-gate if (attr->zo_owner == 0) 5600Sstevel@tonic-gate return (-11); 5610Sstevel@tonic-gate } 5620Sstevel@tonic-gate } else if (strcmp("zo_group", attrName) == 0) { 5630Sstevel@tonic-gate if (attr->zo_group == 0) { 5640Sstevel@tonic-gate attr->zo_group = sdup(myself, T, val->value); 5650Sstevel@tonic-gate if (attr->zo_group == 0) 5660Sstevel@tonic-gate return (-12); 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate } else if (strcmp("zo_domain", attrName) == 0) { 5690Sstevel@tonic-gate if (attr->zo_domain == 0) { 5700Sstevel@tonic-gate attr->zo_domain = sdup(myself, T, val->value); 5710Sstevel@tonic-gate if (attr->zo_domain == 0) 5720Sstevel@tonic-gate return (-13); 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate } else if (strcmp("zo_access", attrName) == 0) { 5750Sstevel@tonic-gate if (attr->zo_access == 0) { 5760Sstevel@tonic-gate if (sscanf(val->value, "%x", &attr->zo_access) != 1) 5770Sstevel@tonic-gate return (-14); 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate } else if (strcmp("zo_ttl", attrName) == 0) { 5800Sstevel@tonic-gate if (attr->zo_ttl == 0) { 5810Sstevel@tonic-gate if (sscanf(val->value, "%x", &attr->zo_ttl) != 1) 5820Sstevel@tonic-gate return (-15); 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate return (0); 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate /* 5900Sstevel@tonic-gate * Return a DN and rule-value for the supplied mapping, db_query's, and 5910Sstevel@tonic-gate * input rule-value. This function only works on a single mapping. See 5920Sstevel@tonic-gate * mapToLDAP() below for a description of the action depending on the 5930Sstevel@tonic-gate * values of 'old' and 'new'. 5940Sstevel@tonic-gate * 5950Sstevel@tonic-gate * If both 'old' and 'new' are supplied, and the modify would result 5960Sstevel@tonic-gate * in a change to the DN, '*oldDN' will contain the old DN. Otherwise 5970Sstevel@tonic-gate * (and normally), '*oldDN' will be NULL. 5980Sstevel@tonic-gate */ 5990Sstevel@tonic-gate char * 6000Sstevel@tonic-gate map1qToLDAP(__nis_table_mapping_t *t, db_query *old, db_query *new, 6010Sstevel@tonic-gate __nis_rule_value_t *rvIn, __nis_rule_value_t **rvOutP, 6020Sstevel@tonic-gate char **oldDnP) { 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate __nis_rule_value_t *rv, *rvt; 6050Sstevel@tonic-gate __nis_ldap_search_t *ls; 6060Sstevel@tonic-gate char *dn = 0, *oldDn = 0; 6070Sstevel@tonic-gate __nis_table_mapping_t del; 6080Sstevel@tonic-gate char *myself = "map1qToLDAP"; 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate if (t == 0 || (old == 0 && new == 0) || rvOutP == 0) 6110Sstevel@tonic-gate return (0); 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate /* 6140Sstevel@tonic-gate * If entry should be deleted, we look at the delete 6150Sstevel@tonic-gate * policy in the table mapping. Should it specify a 6160Sstevel@tonic-gate * rule set, we use that rule set to build a rule- 6170Sstevel@tonic-gate * value, and the delete actually becomes a modify 6180Sstevel@tonic-gate * operation. 6190Sstevel@tonic-gate */ 6200Sstevel@tonic-gate if (old != 0 && new == 0) { 6210Sstevel@tonic-gate if (t->objectDN->delDisp == dd_perDbId) { 6220Sstevel@tonic-gate /* 6230Sstevel@tonic-gate * The functions that build a rule-value from a 6240Sstevel@tonic-gate * rule set expect a __nis_table_mapping_t, but the 6250Sstevel@tonic-gate * rule set in the __nis_object_dn_t isn't of that 6260Sstevel@tonic-gate * form. So, build a pseudo-__nis_table_mapping_t that 6270Sstevel@tonic-gate * borrows heavily from 't'. 6280Sstevel@tonic-gate */ 6290Sstevel@tonic-gate del = *t; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate del.numRulesToLDAP = del.objectDN->numDbIds; 6320Sstevel@tonic-gate del.ruleToLDAP = del.objectDN->dbId; 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate /* 6350Sstevel@tonic-gate * Do a modify with the pseudo-table 6360Sstevel@tonic-gate * mapping, and the 'old' db_query 6370Sstevel@tonic-gate * supplying input to the delete rule 6380Sstevel@tonic-gate * set. 6390Sstevel@tonic-gate */ 6400Sstevel@tonic-gate t = &del; 6410Sstevel@tonic-gate new = old; 6420Sstevel@tonic-gate } else if (t->objectDN->delDisp == dd_always) { 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate /* Nothing to do here; all handled below */ 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate } else if (t->objectDN->delDisp == dd_never) { 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate return (0); 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate } else { 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate logmsg(MSG_INVALIDDELDISP, LOG_WARNING, 6530Sstevel@tonic-gate "%s: Invalid delete disposition %d for \"%s\"", 6540Sstevel@tonic-gate myself, t->objectDN->delDisp, 6550Sstevel@tonic-gate NIL(t->dbId)); 6560Sstevel@tonic-gate return (0); 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate } 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate /* Make a copy of the input rule-value */ 6620Sstevel@tonic-gate if (rvIn != 0) { 6630Sstevel@tonic-gate rv = initRuleValue(1, rvIn); 6640Sstevel@tonic-gate if (rv == 0) 6650Sstevel@tonic-gate return (0); 6660Sstevel@tonic-gate } else { 6670Sstevel@tonic-gate rv = 0; 6680Sstevel@tonic-gate } 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate /* First get a rule-value from the supplied NIS+ entry. */ 6710Sstevel@tonic-gate rvt = rv; 6720Sstevel@tonic-gate rv = buildNisPlusRuleValue(t, ((old != 0) ? old : new), rvt); 6730Sstevel@tonic-gate freeRuleValue(rvt, 1); 6740Sstevel@tonic-gate if (rv == 0) { 6750Sstevel@tonic-gate logmsg(MSG_NORULEVALUE, LOG_WARNING, 6760Sstevel@tonic-gate "%s: No in-query rule-value derived for \"%s\"", 6770Sstevel@tonic-gate myself, NIL(t->dbId)); 6780Sstevel@tonic-gate return (0); 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate /* 6820Sstevel@tonic-gate * Create a request (really only care about the DN) from the 6830Sstevel@tonic-gate * supplied NIS+ entry data. 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate ls = createLdapRequest(t, rv, &dn, 0, NULL, NULL); 6860Sstevel@tonic-gate if (ls == 0 || dn == 0) { 6870Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 6880Sstevel@tonic-gate "%s: Unable to create LDAP request for %s: %s", 6890Sstevel@tonic-gate myself, NIL(t->dbId), 6900Sstevel@tonic-gate (dn != 0) ? dn : rvId(rv, mit_nisplus)); 6910Sstevel@tonic-gate sfree(dn); 6920Sstevel@tonic-gate freeLdapSearch(ls); 6930Sstevel@tonic-gate freeRuleValue(rv, 1); 6940Sstevel@tonic-gate return (0); 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate freeLdapSearch(ls); 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate if (new != 0) { 7000Sstevel@tonic-gate /* 7010Sstevel@tonic-gate * Create a rule-value from the new NIS+ entry. 7020Sstevel@tonic-gate * Don't want to mix in the rule-value derived 7030Sstevel@tonic-gate * from 'old', so delete it. However, we still 7040Sstevel@tonic-gate * want the owner, group, etc., from 'rvIn'. 7050Sstevel@tonic-gate */ 7060Sstevel@tonic-gate if (old != 0) { 7070Sstevel@tonic-gate freeRuleValue(rv, 1); 7080Sstevel@tonic-gate if (rvIn != 0) { 7090Sstevel@tonic-gate rv = initRuleValue(1, rvIn); 7100Sstevel@tonic-gate if (rv == 0) { 7110Sstevel@tonic-gate sfree(dn); 7120Sstevel@tonic-gate return (0); 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate } else { 7150Sstevel@tonic-gate rv = 0; 7160Sstevel@tonic-gate } 7170Sstevel@tonic-gate } 7180Sstevel@tonic-gate rvt = rv; 7190Sstevel@tonic-gate rv = buildNisPlusRuleValue(t, new, rvt); 7200Sstevel@tonic-gate freeRuleValue(rvt, 1); 7210Sstevel@tonic-gate if (rv == 0) { 7220Sstevel@tonic-gate logmsg(MSG_NORULEVALUE, LOG_WARNING, 7230Sstevel@tonic-gate "%s: No new rule-value derived for \"%s: %s\"", 7240Sstevel@tonic-gate myself, NIL(t->dbId), dn); 7250Sstevel@tonic-gate sfree(dn); 7260Sstevel@tonic-gate return (0); 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate /* 7290Sstevel@tonic-gate * Check if the proposed modification would result in a 7300Sstevel@tonic-gate * a change to the DN. 7310Sstevel@tonic-gate */ 7320Sstevel@tonic-gate if (old != 0) { 7330Sstevel@tonic-gate oldDn = dn; 7340Sstevel@tonic-gate dn = 0; 7350Sstevel@tonic-gate ls = createLdapRequest(t, rv, &dn, 0, NULL, NULL); 7360Sstevel@tonic-gate if (ls == 0 || dn == 0) { 7370Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 7380Sstevel@tonic-gate "%s: Unable to create new DN for \"%s: %s\"", 7390Sstevel@tonic-gate myself, NIL(t->dbId), oldDn); 7400Sstevel@tonic-gate sfree(oldDn); 7410Sstevel@tonic-gate freeLdapSearch(ls); 7420Sstevel@tonic-gate freeRuleValue(rv, 1); 7430Sstevel@tonic-gate return (0); 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate freeLdapSearch(ls); 7460Sstevel@tonic-gate if (strcasecmp(oldDn, dn) == 0) { 7470Sstevel@tonic-gate sfree(oldDn); 7480Sstevel@tonic-gate oldDn = 0; 7490Sstevel@tonic-gate } 7500Sstevel@tonic-gate } 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate *rvOutP = rv; 7550Sstevel@tonic-gate if (oldDnP != 0) 7560Sstevel@tonic-gate *oldDnP = oldDn; 7570Sstevel@tonic-gate 7580Sstevel@tonic-gate return (dn); 7590Sstevel@tonic-gate } 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate /* 7620Sstevel@tonic-gate * Since the DN hash list is an automatic variable, there's no need for 7630Sstevel@tonic-gate * locking, and we remove the locking overhead by using the libnsl 7640Sstevel@tonic-gate * hash functions. 7650Sstevel@tonic-gate */ 766*11262SRajagopal.Andra@Sun.COM #undef NIS_HASH_ITEM 767*11262SRajagopal.Andra@Sun.COM #undef NIS_HASH_TABLE 7680Sstevel@tonic-gate 7690Sstevel@tonic-gate typedef struct { 7700Sstevel@tonic-gate NIS_HASH_ITEM item; 7710Sstevel@tonic-gate int index; 7720Sstevel@tonic-gate char *oldDn; 7730Sstevel@tonic-gate } __dn_item_t; 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate /* 7760Sstevel@tonic-gate * Update LDAP per the supplied table mapping and db_query's. 7770Sstevel@tonic-gate * 7780Sstevel@tonic-gate * 'nq' is the number of elements in the 'old', 'new', and 'rvIn' 7790Sstevel@tonic-gate * arrays. mapToLDAP() generally performs one update for each 7800Sstevel@tonic-gate * element; however, if one or more of the individual queries 7810Sstevel@tonic-gate * produce the same DN, they're merged into a single update. 7820Sstevel@tonic-gate * 7830Sstevel@tonic-gate * There are four cases, depending on the values of 'old[iq]' and 7840Sstevel@tonic-gate * 'new[iq]': 7850Sstevel@tonic-gate * 7860Sstevel@tonic-gate * (1) old[iq] == 0 && new[iq] == 0 7870Sstevel@tonic-gate * No action; skip to next query 7880Sstevel@tonic-gate * 7890Sstevel@tonic-gate * (2) old[iq] == 0 && new[iq] != 0 7900Sstevel@tonic-gate * Attempt to use the 'new' db_query to get a DN, and try to create 7910Sstevel@tonic-gate * the corresponding LDAP entry. 7920Sstevel@tonic-gate * 7930Sstevel@tonic-gate * (3) old[iq] != 0 && new[iq] == 0 7940Sstevel@tonic-gate * Use the 'old' db_query to get a DN, and try to delete the LDAP 7950Sstevel@tonic-gate * entry per the table mapping. 7960Sstevel@tonic-gate * 7970Sstevel@tonic-gate * (4) old[iq] != 0 && new[iq] != 0 7980Sstevel@tonic-gate * Use the 'old' db_query to get a DN, and update (possibly create) 7990Sstevel@tonic-gate * the corresponding LDAP entry per the 'new' db_query. 8000Sstevel@tonic-gate * 8010Sstevel@tonic-gate * If 'rvIn' is non-NULL, it is expected to contain the object attributes 8020Sstevel@tonic-gate * (zo_owner, etc.) to be written to LDAP. 'rvIn' is an array with 'nq' 8030Sstevel@tonic-gate * elements. 8040Sstevel@tonic-gate * 8050Sstevel@tonic-gate * If 'firstOnly' is set, only the first old[iq]/new[iq] pair is used 8060Sstevel@tonic-gate * to perform the actual update. Any additional queries specified will 8070Sstevel@tonic-gate * have their values folded in, but are not used to derive update targets. 8080Sstevel@tonic-gate * This mode is inteded to support the case where multiple NIS+ entries 8090Sstevel@tonic-gate * map to one and the same LDAP entry. Note that 'rvIn' must still be 8100Sstevel@tonic-gate * an array of 'nq' elements, though if 'firstOnly' is set, it should be 8110Sstevel@tonic-gate * OK to leave all but 'rvIn[0]' empty. 8120Sstevel@tonic-gate * 8130Sstevel@tonic-gate * 'dbId' is used to further narow down the selection of mapping candidates 8140Sstevel@tonic-gate * to those matching the 'dbId' value. 8150Sstevel@tonic-gate */ 8160Sstevel@tonic-gate int 8170Sstevel@tonic-gate mapToLDAP(__nis_table_mapping_t *tm, int nq, db_query **old, db_query **new, 8180Sstevel@tonic-gate __nis_rule_value_t *rvIn, int firstOnly, char *dbId) { 8190Sstevel@tonic-gate __nis_table_mapping_t **tp, **tpa; 8200Sstevel@tonic-gate int i, n, rnq, iq, r, ret = LDAP_SUCCESS; 8210Sstevel@tonic-gate int maxMatches, numMatches = 0; 8220Sstevel@tonic-gate __nis_ldap_search_t *ls; 8230Sstevel@tonic-gate char **dn = 0, **odn = 0; 8240Sstevel@tonic-gate __nis_rule_value_t **rv; 8250Sstevel@tonic-gate __dn_item_t *dni; 8260Sstevel@tonic-gate char *myself = "mapToLDAP"; 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate if (tm == 0 || (old == 0 && new == 0) || nq <= 0) 8300Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate /* Determine maximum number of table mapping matches */ 8330Sstevel@tonic-gate if (nq == 1) { 8340Sstevel@tonic-gate tp = selectTableMapping(tm, 8350Sstevel@tonic-gate (old != 0 && old[0] != 0) ? old[0] : new[0], 1, 0, 8360Sstevel@tonic-gate dbId, &maxMatches); 8370Sstevel@tonic-gate numMatches = maxMatches; 8380Sstevel@tonic-gate } else { 8390Sstevel@tonic-gate tp = selectTableMapping(tm, 0, 1, 0, dbId, &maxMatches); 8400Sstevel@tonic-gate } 8410Sstevel@tonic-gate 8420Sstevel@tonic-gate /* 8430Sstevel@tonic-gate * If no matching mapping, we're not mapping to LDAP in this 8440Sstevel@tonic-gate * particular case. 8450Sstevel@tonic-gate */ 8460Sstevel@tonic-gate if (tp == 0 || maxMatches == 0) { 8470Sstevel@tonic-gate sfree(tp); 8480Sstevel@tonic-gate return (LDAP_SUCCESS); 8490Sstevel@tonic-gate } 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate /* 8520Sstevel@tonic-gate * Allocate the 'rv', 'dn', and 'tpa' arrays. Worst case is that 8530Sstevel@tonic-gate * we need nq * maxMatches elements in each array. However, if 8540Sstevel@tonic-gate * 'firstOnly' is set, we only need one element per matching 8550Sstevel@tonic-gate * mapping in each. 8560Sstevel@tonic-gate */ 8570Sstevel@tonic-gate dn = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (dn[0])); 8580Sstevel@tonic-gate odn = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (odn[0])); 8590Sstevel@tonic-gate rv = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (rv[0])); 8600Sstevel@tonic-gate tpa = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (tpa[0])); 8610Sstevel@tonic-gate if (dn == 0 || odn == 0 || rv == 0 || tpa == 0) { 8620Sstevel@tonic-gate sfree(tp); 8630Sstevel@tonic-gate sfree(dn); 8640Sstevel@tonic-gate sfree(odn); 8650Sstevel@tonic-gate sfree(rv); 8660Sstevel@tonic-gate sfree(tpa); 8670Sstevel@tonic-gate return (LDAP_NO_MEMORY); 8680Sstevel@tonic-gate } 8690Sstevel@tonic-gate 8700Sstevel@tonic-gate /* Unless nq == 1, we don't need the 'tp' value */ 8710Sstevel@tonic-gate if (nq != 1) 8720Sstevel@tonic-gate sfree(tp); 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 8750Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 8760Sstevel@tonic-gate LOG_WARNING, 8770Sstevel@tonic-gate #else 8780Sstevel@tonic-gate LOG_INFO, 8790Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 8800Sstevel@tonic-gate "%s: %s: %d * %d potential updates", 8810Sstevel@tonic-gate myself, NIL(tm->objName), nq, maxMatches); 8820Sstevel@tonic-gate 8830Sstevel@tonic-gate /* 8840Sstevel@tonic-gate * Create DNs, column and attribute values, and merge duplicate DNs. 8850Sstevel@tonic-gate */ 8860Sstevel@tonic-gate for (iq = 0, rnq = 0; iq < nq; iq++) { 8870Sstevel@tonic-gate int idx; 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate if ((old == 0 || old[iq] == 0) && 8900Sstevel@tonic-gate (new == 0 || new[iq] == 0)) 8910Sstevel@tonic-gate continue; 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate /* 8940Sstevel@tonic-gate * Select matching table mappings; if nq == 1, we've already 8950Sstevel@tonic-gate * got the 'tp' array from above. We expect this to be the 8960Sstevel@tonic-gate * most common case, so it's worth special treatment. 8970Sstevel@tonic-gate */ 8980Sstevel@tonic-gate if (nq != 1) 8990Sstevel@tonic-gate tp = selectTableMapping(tm, 9000Sstevel@tonic-gate (old != 0 && old[iq] != 0) ? old[iq] : new[iq], 1, 0, 9010Sstevel@tonic-gate dbId, &numMatches); 9020Sstevel@tonic-gate if (tp == 0) 9030Sstevel@tonic-gate continue; 9040Sstevel@tonic-gate else if (numMatches <= 0) { 9050Sstevel@tonic-gate sfree(tp); 9060Sstevel@tonic-gate continue; 9070Sstevel@tonic-gate } 9080Sstevel@tonic-gate 9090Sstevel@tonic-gate idx = iq * maxMatches; 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate if (idx == 0 || !firstOnly) 9120Sstevel@tonic-gate (void) memcpy(&tpa[idx], tp, 9130Sstevel@tonic-gate numMatches * sizeof (tpa[idx])); 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate for (n = 0; n < numMatches; n++) { 9160Sstevel@tonic-gate char *dnt, *odnt; 9170Sstevel@tonic-gate __nis_rule_value_t *rvt = 0; 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate if (tp[n] == 0) 9200Sstevel@tonic-gate continue; 9210Sstevel@tonic-gate 9220Sstevel@tonic-gate dnt = map1qToLDAP(tp[n], 9230Sstevel@tonic-gate (old != 0) ? old[iq] : 0, 9240Sstevel@tonic-gate (new != 0) ? new[iq] : 0, 9250Sstevel@tonic-gate (rvIn != 0) ? &rvIn[iq] : 0, 9260Sstevel@tonic-gate &rvt, &odnt); 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate if (dnt == 0) 9290Sstevel@tonic-gate continue; 9300Sstevel@tonic-gate if (rvt == 0) { 9310Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 9320Sstevel@tonic-gate abort(); 9330Sstevel@tonic-gate #else 9340Sstevel@tonic-gate sfree(dnt); 9350Sstevel@tonic-gate sfree(odnt); 9360Sstevel@tonic-gate continue; 9370Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 9380Sstevel@tonic-gate } 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate /* 9410Sstevel@tonic-gate * Create a request to get a rule-value with 9420Sstevel@tonic-gate * NIS+ data translated to LDAP equivalents. 9430Sstevel@tonic-gate */ 9440Sstevel@tonic-gate ls = createLdapRequest(tp[n], rvt, 0, 0, NULL, NULL); 9450Sstevel@tonic-gate if (ls == 0) { 9460Sstevel@tonic-gate if (ret == LDAP_SUCCESS) 9470Sstevel@tonic-gate ret = LDAP_OPERATIONS_ERROR; 9480Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 9490Sstevel@tonic-gate "%s: Unable to map to LDAP attrs for %s:dn=%s", 9500Sstevel@tonic-gate myself, NIL(tp[n]->dbId), dnt); 9510Sstevel@tonic-gate sfree(dnt); 9520Sstevel@tonic-gate freeRuleValue(rvt, 1); 9530Sstevel@tonic-gate continue; 9540Sstevel@tonic-gate } 9550Sstevel@tonic-gate freeLdapSearch(ls); 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate /* 9580Sstevel@tonic-gate * If the DN is the same as one we already know 9590Sstevel@tonic-gate * about, merge the rule-values. 9600Sstevel@tonic-gate */ 9610Sstevel@tonic-gate 962*11262SRajagopal.Andra@Sun.COM if ((iq == 0 || !firstOnly) && dnt != 0) { 9630Sstevel@tonic-gate dni = am(myself, sizeof (*dni)); 9640Sstevel@tonic-gate if (dni != 0) { 9650Sstevel@tonic-gate dni->item.name = dnt; 9660Sstevel@tonic-gate dni->index = idx + n; 9670Sstevel@tonic-gate dni->oldDn = odnt; 9680Sstevel@tonic-gate } else { 9690Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 9700Sstevel@tonic-gate "%s: Skipping update for dn=\"%s\"", 9710Sstevel@tonic-gate myself, dnt); 9720Sstevel@tonic-gate sfree(dnt); 9730Sstevel@tonic-gate dnt = 0; 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate if (dnt != 0) { 9760Sstevel@tonic-gate dn[idx+n] = dnt; 9770Sstevel@tonic-gate odn[idx+n] = odnt; 9780Sstevel@tonic-gate rv[idx+n] = rvt; 9790Sstevel@tonic-gate rnq++; 9800Sstevel@tonic-gate } else { 9810Sstevel@tonic-gate freeRuleValue(rvt, 1); 9820Sstevel@tonic-gate rvt = 0; 9830Sstevel@tonic-gate } 9840Sstevel@tonic-gate } else if (dnt != 0) { 9850Sstevel@tonic-gate sfree(dnt); 9860Sstevel@tonic-gate sfree(odnt); 9870Sstevel@tonic-gate freeRuleValue(rvt, 1); 9880Sstevel@tonic-gate } 9890Sstevel@tonic-gate } 9900Sstevel@tonic-gate sfree(tp); 9910Sstevel@tonic-gate } 9920Sstevel@tonic-gate 9930Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 9940Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 9950Sstevel@tonic-gate LOG_WARNING, 9960Sstevel@tonic-gate #else 9970Sstevel@tonic-gate LOG_INFO, 9980Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 9990Sstevel@tonic-gate "%s: %s: %d update%s requested", 10000Sstevel@tonic-gate myself, NIL(tm->objName), rnq, rnq != 1 ? "s" : ""); 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate /* Perform the updates */ 10030Sstevel@tonic-gate for (i = rnq = 0; i < (firstOnly ? maxMatches : nq*maxMatches); i++) { 10040Sstevel@tonic-gate int delPerDbId; 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate if (dn[i] == 0) 10070Sstevel@tonic-gate continue; 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 10100Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 10110Sstevel@tonic-gate "%s: %s %s:dn=%s", 10120Sstevel@tonic-gate myself, 10130Sstevel@tonic-gate (new != 0 && new[i/maxMatches] != 0) ? 10140Sstevel@tonic-gate "modify" : "delete", 10150Sstevel@tonic-gate NIL(tpa[i]->dbId), dn[i]); 10160Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 10170Sstevel@tonic-gate 10180Sstevel@tonic-gate delPerDbId = (tpa[i]->objectDN->delDisp == dd_perDbId); 10190Sstevel@tonic-gate if ((new != 0 && new[i/maxMatches] != 0) || delPerDbId) { 10200Sstevel@tonic-gate /* 10210Sstevel@tonic-gate * Try to modify/create the specified DN. First, 10220Sstevel@tonic-gate * however, if the update changes the DN, make 10230Sstevel@tonic-gate * that change. 10240Sstevel@tonic-gate */ 10250Sstevel@tonic-gate if (odn[i] == 0 || (r = ldapChangeDN(odn[i], dn[i])) == 10260Sstevel@tonic-gate LDAP_SUCCESS) { 10270Sstevel@tonic-gate int addFirst; 10280Sstevel@tonic-gate 10290Sstevel@tonic-gate addFirst = (new != 0 && 10300Sstevel@tonic-gate new[i/maxMatches] != 0 && 10310Sstevel@tonic-gate !delPerDbId); 10320Sstevel@tonic-gate r = ldapModify(dn[i], rv[i], 10330Sstevel@tonic-gate tpa[i]->objectDN->write.attrs, 10340Sstevel@tonic-gate addFirst); 10350Sstevel@tonic-gate } 10360Sstevel@tonic-gate } else { 10370Sstevel@tonic-gate /* Try to delete the specified DN */ 10380Sstevel@tonic-gate r = ldapModify(dn[i], 0, 10390Sstevel@tonic-gate tpa[i]->objectDN->write.attrs, 0); 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate if (r == LDAP_SUCCESS) { 10430Sstevel@tonic-gate rnq++; 10440Sstevel@tonic-gate } else { 10450Sstevel@tonic-gate if (ret == LDAP_SUCCESS) 10460Sstevel@tonic-gate ret = r; 10470Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 10480Sstevel@tonic-gate "%s: LDAP %s request error %d for %s:dn=%s", 10490Sstevel@tonic-gate myself, 10500Sstevel@tonic-gate (new != 0 && new[i/maxMatches] != 0) ? 10510Sstevel@tonic-gate "modify" : "delete", 10520Sstevel@tonic-gate r, NIL(tpa[i]->dbId), dn[i]); 10530Sstevel@tonic-gate } 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate sfree(dn[i]); 10560Sstevel@tonic-gate dn[i] = 0; 10570Sstevel@tonic-gate freeRuleValue(rv[i], 1); 10580Sstevel@tonic-gate rv[i] = 0; 10590Sstevel@tonic-gate } 10600Sstevel@tonic-gate 10610Sstevel@tonic-gate sfree(dn); 10620Sstevel@tonic-gate sfree(odn); 10630Sstevel@tonic-gate sfree(rv); 10640Sstevel@tonic-gate sfree(tpa); 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 10670Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 10680Sstevel@tonic-gate LOG_WARNING, 10690Sstevel@tonic-gate #else 10700Sstevel@tonic-gate LOG_INFO, 10710Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 10720Sstevel@tonic-gate "%s: %s: %d update%s performed", 10730Sstevel@tonic-gate myself, NIL(tm->objName), rnq, rnq != 1 ? "s" : ""); 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate return (ret); 10760Sstevel@tonic-gate } 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate /* 10790Sstevel@tonic-gate * In nis+2ldap, check if the query 'q' matches the selector index 'x->index'. 10800Sstevel@tonic-gate * 10810Sstevel@tonic-gate * In nis2ldap, if 'name' is provided then check if its value in 'val' 10820Sstevel@tonic-gate * matches the selector index. If 'name' is NULL, then check if rule-value 'rv' 10830Sstevel@tonic-gate * matches the index. 10840Sstevel@tonic-gate * To match the selector index, all fieldspecs in the indexlist should match 10850Sstevel@tonic-gate * (AND). In nis2ldap, an exception is, if there are multiple fieldspecs with 10860Sstevel@tonic-gate * the same fieldname then only one of them needs to match (OR). 10870Sstevel@tonic-gate * Example: 10880Sstevel@tonic-gate * Indexlist = [host="H*", host="I*", user="U*", domain="D*"] 10890Sstevel@tonic-gate * Then, 10900Sstevel@tonic-gate * host = "H1", user="U1", domain="D1" ==> pass 10910Sstevel@tonic-gate * host = "I1", user="U1", domain="D1" ==> pass 10920Sstevel@tonic-gate * host = "X1", user="U1", domain="D1" ==> fail 10930Sstevel@tonic-gate * host = "H1", user="X1", domain="D1" ==> fail 10940Sstevel@tonic-gate * host = "H1", user="U1" ==> fail 10950Sstevel@tonic-gate * 10960Sstevel@tonic-gate * Return 1 in case of a match, 0 otherwise. 10970Sstevel@tonic-gate */ 10980Sstevel@tonic-gate int 10990Sstevel@tonic-gate verifyIndexMatch(__nis_table_mapping_t *x, db_query *q, 11000Sstevel@tonic-gate __nis_rule_value_t *rv, char *name, char *val) { 11010Sstevel@tonic-gate int i, j, k, match = 1; 11020Sstevel@tonic-gate char *myself = "verifyIndexMatch"; 11030Sstevel@tonic-gate 11040Sstevel@tonic-gate /* 11050Sstevel@tonic-gate * The pass and fail arrays are used by N2L to keep track of 11060Sstevel@tonic-gate * index matches. This saves us from having matches in a 11070Sstevel@tonic-gate * nested loop to decide OR or AND. 11080Sstevel@tonic-gate */ 11090Sstevel@tonic-gate int ppos, fpos; 11100Sstevel@tonic-gate char **pass, **fail; 11110Sstevel@tonic-gate 11120Sstevel@tonic-gate if (x == 0) 11130Sstevel@tonic-gate return (0); 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate /* Trivial match */ 11160Sstevel@tonic-gate if (x->index.numIndexes <= 0 || (!yp2ldap && q == 0)) 11170Sstevel@tonic-gate return (1); 11180Sstevel@tonic-gate 11190Sstevel@tonic-gate if (yp2ldap) { 11200Sstevel@tonic-gate if (!(pass = am(myself, x->index.numIndexes * sizeof (char *)))) 11210Sstevel@tonic-gate return (0); 11220Sstevel@tonic-gate if (!(fail = am(myself, 11230Sstevel@tonic-gate x->index.numIndexes * sizeof (char *)))) { 11240Sstevel@tonic-gate sfree(pass); 11250Sstevel@tonic-gate return (0); 11260Sstevel@tonic-gate } 11270Sstevel@tonic-gate ppos = fpos = 0; 11280Sstevel@tonic-gate } 11290Sstevel@tonic-gate 11300Sstevel@tonic-gate /* Check each index */ 11310Sstevel@tonic-gate for (i = 0; i < x->index.numIndexes; i++) { 11320Sstevel@tonic-gate int len = 0; 11330Sstevel@tonic-gate char *value = 0; 11340Sstevel@tonic-gate 11350Sstevel@tonic-gate /* Skip NULL index names */ 11360Sstevel@tonic-gate if (x->index.name[i] == 0) 11370Sstevel@tonic-gate continue; 11380Sstevel@tonic-gate 11390Sstevel@tonic-gate /* Check N2L values */ 11400Sstevel@tonic-gate if (yp2ldap) { 11410Sstevel@tonic-gate if (name) { 11420Sstevel@tonic-gate if (strcasecmp(x->index.name[i], name) == 0) 11430Sstevel@tonic-gate value = val; 11440Sstevel@tonic-gate else 11450Sstevel@tonic-gate continue; 11460Sstevel@tonic-gate } else if (rv) { 11470Sstevel@tonic-gate if (strcasecmp(x->index.name[i], N2LKEY) == 0 || 11480Sstevel@tonic-gate strcasecmp(x->index.name[i], N2LIPKEY) 11490Sstevel@tonic-gate == 0) 11500Sstevel@tonic-gate continue; 11510Sstevel@tonic-gate value = findVal(x->index.name[i], rv, 11520Sstevel@tonic-gate mit_nisplus); 11530Sstevel@tonic-gate } 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate if (value && verifyMappingMatch(x->index.value[i], 11560Sstevel@tonic-gate value)) 11570Sstevel@tonic-gate pass[ppos++] = x->index.name[i]; 11580Sstevel@tonic-gate else 11590Sstevel@tonic-gate fail[fpos++] = x->index.name[i]; 11600Sstevel@tonic-gate continue; 11610Sstevel@tonic-gate } 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate /* If here, means nis+2ldap */ 11640Sstevel@tonic-gate 11650Sstevel@tonic-gate /* Is the index name a known column ? */ 11660Sstevel@tonic-gate for (j = 0; j < x->numColumns; j++) { 11670Sstevel@tonic-gate if (strcmp(x->index.name[i], x->column[j]) == 0) { 11680Sstevel@tonic-gate /* 11690Sstevel@tonic-gate * Do we have a value for the column ? 11700Sstevel@tonic-gate */ 11710Sstevel@tonic-gate for (k = 0; k < q->components.components_len; 11720Sstevel@tonic-gate k++) { 11730Sstevel@tonic-gate if (q->components.components_val[k]. 11740Sstevel@tonic-gate which_index == j) { 11750Sstevel@tonic-gate value = q->components. 11760Sstevel@tonic-gate components_val[k]. 11770Sstevel@tonic-gate index_value-> 11780Sstevel@tonic-gate itemvalue. 11790Sstevel@tonic-gate itemvalue_val; 11800Sstevel@tonic-gate len = q->components. 11810Sstevel@tonic-gate components_val[k]. 11820Sstevel@tonic-gate index_value-> 11830Sstevel@tonic-gate itemvalue. 11840Sstevel@tonic-gate itemvalue_len; 11850Sstevel@tonic-gate break; 11860Sstevel@tonic-gate } 11870Sstevel@tonic-gate } 11880Sstevel@tonic-gate if (value != 0) 11890Sstevel@tonic-gate break; 11900Sstevel@tonic-gate } 11910Sstevel@tonic-gate } 11920Sstevel@tonic-gate 11930Sstevel@tonic-gate /* 11940Sstevel@tonic-gate * If we found a value, check if it matches the 11950Sstevel@tonic-gate * format. If no value found or no match, this 11960Sstevel@tonic-gate * mapping is _not_ an alternative. Otherwise, 11970Sstevel@tonic-gate * we continue checking any other indexes. 11980Sstevel@tonic-gate */ 11990Sstevel@tonic-gate if (value == 0 || 12000Sstevel@tonic-gate !verifyMappingMatch(x->index.value[i], 12010Sstevel@tonic-gate value)) { 12020Sstevel@tonic-gate match = 0; 12030Sstevel@tonic-gate break; 12040Sstevel@tonic-gate } 12050Sstevel@tonic-gate } 12060Sstevel@tonic-gate 12070Sstevel@tonic-gate if (yp2ldap) { 12080Sstevel@tonic-gate for (--fpos; fpos >= 0; fpos--) { 12090Sstevel@tonic-gate for (i = 0; i < ppos; i++) { 12100Sstevel@tonic-gate if (strcmp(pass[i], fail[fpos]) == 0) 12110Sstevel@tonic-gate break; 12120Sstevel@tonic-gate } 12130Sstevel@tonic-gate if (i == ppos) { 12140Sstevel@tonic-gate match = 0; 12150Sstevel@tonic-gate break; 12160Sstevel@tonic-gate } 12170Sstevel@tonic-gate } 12180Sstevel@tonic-gate sfree(pass); 12190Sstevel@tonic-gate sfree(fail); 12200Sstevel@tonic-gate } 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate return (match); 12230Sstevel@tonic-gate } 12240Sstevel@tonic-gate 12250Sstevel@tonic-gate /* 12260Sstevel@tonic-gate * Return all table mappings that match the column values in 'q'. 12270Sstevel@tonic-gate * If there's no match, return those alternative mappings that don't 12280Sstevel@tonic-gate * have an index; if no such mapping exists, return NULL. 12290Sstevel@tonic-gate * 12300Sstevel@tonic-gate * If 'wantWrite' is set, we want mappings for writing (i.e., data 12310Sstevel@tonic-gate * to LDAP); otherwise, we want mappings for reading. 12320Sstevel@tonic-gate * 12330Sstevel@tonic-gate * If 'wantObj' is set, we want object mappings only (i.e., _not_ 12340Sstevel@tonic-gate * those used to map entries in tables). 12350Sstevel@tonic-gate * 12360Sstevel@tonic-gate * If 'dbId' is non-NULL, we select mappings with a matching dbId field. 12370Sstevel@tonic-gate */ 12380Sstevel@tonic-gate __nis_table_mapping_t ** 12390Sstevel@tonic-gate selectTableMapping(__nis_table_mapping_t *t, db_query *q, 12400Sstevel@tonic-gate int wantWrite, int wantObj, char *dbId, 12410Sstevel@tonic-gate int *numMatches) { 12420Sstevel@tonic-gate __nis_table_mapping_t *r, *x, **tp; 12430Sstevel@tonic-gate int i, j, k, nm, numap; 12440Sstevel@tonic-gate char *myself = "selectTableMapping"; 12450Sstevel@tonic-gate 12460Sstevel@tonic-gate if (numMatches == 0) 12470Sstevel@tonic-gate numMatches = &nm; 12480Sstevel@tonic-gate 12490Sstevel@tonic-gate /* 12500Sstevel@tonic-gate * Count the number of possible mappings, so that we can 12510Sstevel@tonic-gate * allocate the 'tp' array up front. 12520Sstevel@tonic-gate */ 12530Sstevel@tonic-gate for (numap = 0, x = t; x != 0; numap++, x = x->next); 12540Sstevel@tonic-gate 12550Sstevel@tonic-gate if (numap == 0) { 12560Sstevel@tonic-gate *numMatches = 0; 12570Sstevel@tonic-gate return (0); 12580Sstevel@tonic-gate } 12590Sstevel@tonic-gate 12600Sstevel@tonic-gate tp = am(myself, numap * sizeof (tp[0])); 12610Sstevel@tonic-gate if (tp == 0) { 12620Sstevel@tonic-gate *numMatches = -1; 12630Sstevel@tonic-gate return (0); 12640Sstevel@tonic-gate } 12650Sstevel@tonic-gate 12660Sstevel@tonic-gate /* 12670Sstevel@tonic-gate * Special cases: 12680Sstevel@tonic-gate * 12690Sstevel@tonic-gate * q == 0 trivially matches any 't' of the correct object type 12700Sstevel@tonic-gate * 12710Sstevel@tonic-gate * wantObj != 0 means we ignore 'q' 12720Sstevel@tonic-gate */ 12730Sstevel@tonic-gate if (q == 0 || wantObj) { 12740Sstevel@tonic-gate for (i = 0, x = t, nm = 0; i < numap; i++, x = x->next) { 12750Sstevel@tonic-gate if (x->objectDN == 0) 12760Sstevel@tonic-gate continue; 12770Sstevel@tonic-gate if (wantWrite) { 12780Sstevel@tonic-gate if (x->objectDN->write.scope == 12790Sstevel@tonic-gate LDAP_SCOPE_UNKNOWN) 12800Sstevel@tonic-gate continue; 12810Sstevel@tonic-gate } else { 12820Sstevel@tonic-gate if (x->objectDN->read.scope == 12830Sstevel@tonic-gate LDAP_SCOPE_UNKNOWN) 12840Sstevel@tonic-gate continue; 12850Sstevel@tonic-gate } 12860Sstevel@tonic-gate if (wantObj) { 12870Sstevel@tonic-gate if (x->numColumns > 0) 12880Sstevel@tonic-gate continue; 12890Sstevel@tonic-gate } else { 12900Sstevel@tonic-gate if (x->numColumns <= 0) 12910Sstevel@tonic-gate continue; 12920Sstevel@tonic-gate } 12930Sstevel@tonic-gate if (dbId != 0 && x->dbId != 0 && 12940Sstevel@tonic-gate strcmp(dbId, x->dbId) != 0) 12950Sstevel@tonic-gate continue; 12960Sstevel@tonic-gate tp[nm] = x; 12970Sstevel@tonic-gate nm++; 12980Sstevel@tonic-gate } 12990Sstevel@tonic-gate *numMatches = nm; 13000Sstevel@tonic-gate if (nm == 0) { 13010Sstevel@tonic-gate sfree(tp); 13020Sstevel@tonic-gate tp = 0; 13030Sstevel@tonic-gate } 13040Sstevel@tonic-gate return (tp); 13050Sstevel@tonic-gate } 13060Sstevel@tonic-gate 13070Sstevel@tonic-gate /* Scan all mappings, and collect candidates */ 13080Sstevel@tonic-gate for (nm = 0, r = 0, x = t; x != 0; x = x->next) { 13090Sstevel@tonic-gate if (x->objectDN == 0) 13100Sstevel@tonic-gate continue; 13110Sstevel@tonic-gate if (wantWrite) { 13120Sstevel@tonic-gate if (x->objectDN->write.scope == LDAP_SCOPE_UNKNOWN) 13130Sstevel@tonic-gate continue; 13140Sstevel@tonic-gate } else { 13150Sstevel@tonic-gate if (x->objectDN->read.scope == LDAP_SCOPE_UNKNOWN) 13160Sstevel@tonic-gate continue; 13170Sstevel@tonic-gate } 13180Sstevel@tonic-gate /* Only want table/entry mappings */ 13190Sstevel@tonic-gate if (x->numColumns <= 0) 13200Sstevel@tonic-gate continue; 13210Sstevel@tonic-gate if (dbId != 0 && x->dbId != 0 && 13220Sstevel@tonic-gate strcmp(dbId, x->dbId) != 0) 13230Sstevel@tonic-gate continue; 13240Sstevel@tonic-gate /* 13250Sstevel@tonic-gate * It's a match if: there are no indexes, or we actually 13260Sstevel@tonic-gate * match the query with the indexes. 13270Sstevel@tonic-gate */ 13280Sstevel@tonic-gate if (x->index.numIndexes <= 0 || 13290Sstevel@tonic-gate verifyIndexMatch(x, q, 0, 0, 0)) { 13300Sstevel@tonic-gate tp[nm] = x; 13310Sstevel@tonic-gate nm++; 13320Sstevel@tonic-gate } 13330Sstevel@tonic-gate } 13340Sstevel@tonic-gate 13350Sstevel@tonic-gate if (nm == 0) { 13360Sstevel@tonic-gate free(tp); 13370Sstevel@tonic-gate tp = 0; 13380Sstevel@tonic-gate } 13390Sstevel@tonic-gate 13400Sstevel@tonic-gate *numMatches = nm; 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate return (tp); 13430Sstevel@tonic-gate } 13440Sstevel@tonic-gate 13450Sstevel@tonic-gate /* 13460Sstevel@tonic-gate * Return 1 if there's an indexed mapping, 0 otherwise. 13470Sstevel@tonic-gate */ 13480Sstevel@tonic-gate int 13490Sstevel@tonic-gate haveIndexedMapping(__nis_table_mapping_t *t) { 13500Sstevel@tonic-gate __nis_table_mapping_t *x; 13510Sstevel@tonic-gate 13520Sstevel@tonic-gate for (x = t; x != 0; x = x->next) { 13530Sstevel@tonic-gate if (x->index.numIndexes > 0) 13540Sstevel@tonic-gate return (1); 13550Sstevel@tonic-gate } 13560Sstevel@tonic-gate 13570Sstevel@tonic-gate return (0); 13580Sstevel@tonic-gate } 13590Sstevel@tonic-gate 13600Sstevel@tonic-gate /* 13610Sstevel@tonic-gate * Given an input string 'attrs' of the form "attr1=val1,attr2=val2,...", 13620Sstevel@tonic-gate * or a filter, return the value associated with the attribute 'attrName'. 13630Sstevel@tonic-gate * If no instance of 'attrName' is found, return 'default'. In all cases, 13640Sstevel@tonic-gate * the return value is a copy, and must be freed by the caller. 13650Sstevel@tonic-gate * 13660Sstevel@tonic-gate * Of course, return NULL in case of failure. 13670Sstevel@tonic-gate */ 13680Sstevel@tonic-gate static char * 13690Sstevel@tonic-gate attrVal(char *msg, char *attrName, char *def, char *attrs) { 13700Sstevel@tonic-gate char *val, *filter, **fc = 0; 13710Sstevel@tonic-gate int i, nfc; 13720Sstevel@tonic-gate char *myself = "attrVal"; 13730Sstevel@tonic-gate 13740Sstevel@tonic-gate if (attrName == 0 || attrs == 0) 13750Sstevel@tonic-gate return (0); 13760Sstevel@tonic-gate 13770Sstevel@tonic-gate if (msg == 0) 13780Sstevel@tonic-gate msg = myself; 13790Sstevel@tonic-gate 13800Sstevel@tonic-gate val = def; 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate filter = makeFilter(attrs); 13830Sstevel@tonic-gate if (filter != 0 && (fc = makeFilterComp(filter, &nfc)) != 0 && 13840Sstevel@tonic-gate nfc > 0) { 13850Sstevel@tonic-gate for (i = 0; i < nfc; i++) { 13860Sstevel@tonic-gate char *name, *value; 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate name = fc[i]; 13890Sstevel@tonic-gate /* Skip if not of attr=value form */ 13900Sstevel@tonic-gate if ((value = strchr(name, '=')) == 0) 13910Sstevel@tonic-gate continue; 13920Sstevel@tonic-gate 13930Sstevel@tonic-gate *value = '\0'; 13940Sstevel@tonic-gate value++; 13950Sstevel@tonic-gate 13960Sstevel@tonic-gate if (strcasecmp(attrName, name) == 0) { 13970Sstevel@tonic-gate val = value; 13980Sstevel@tonic-gate break; 13990Sstevel@tonic-gate } 14000Sstevel@tonic-gate } 14010Sstevel@tonic-gate } 14020Sstevel@tonic-gate 14030Sstevel@tonic-gate if (val != 0) 14040Sstevel@tonic-gate val = sdup(msg, T, val); 14050Sstevel@tonic-gate 14060Sstevel@tonic-gate sfree(filter); 14070Sstevel@tonic-gate freeFilterComp(fc, nfc); 14080Sstevel@tonic-gate 14090Sstevel@tonic-gate return (val); 14100Sstevel@tonic-gate } 14110Sstevel@tonic-gate 14120Sstevel@tonic-gate extern bool_t xdr_nis_object(register XDR *xdrs, nis_object *objp); 14130Sstevel@tonic-gate 14140Sstevel@tonic-gate /* 14150Sstevel@tonic-gate * Copy an XDR:ed version of the NIS+ object 'o' (or the one indicated 14160Sstevel@tonic-gate * by 't->objName' if 'o' is NULL) to the place indicated by 14170Sstevel@tonic-gate * 't->objectDN->write'. Return an appropriate LDAP status code. 14180Sstevel@tonic-gate */ 14190Sstevel@tonic-gate int 14200Sstevel@tonic-gate objToLDAP(__nis_table_mapping_t *t, nis_object *o, entry_obj **ea, int numEa) { 14210Sstevel@tonic-gate __nis_table_mapping_t **tp; 14220Sstevel@tonic-gate XDR xdr; 14230Sstevel@tonic-gate char *objName; 14240Sstevel@tonic-gate int stat, osize, n, numMatches = 0; 14250Sstevel@tonic-gate void *buf; 14260Sstevel@tonic-gate __nis_rule_value_t *rv; 14270Sstevel@tonic-gate __nis_value_t *val; 14280Sstevel@tonic-gate __nis_single_value_t *sv; 14290Sstevel@tonic-gate char **attrName, *dn; 14300Sstevel@tonic-gate char *myself = "objToLDAP"; 14310Sstevel@tonic-gate 14320Sstevel@tonic-gate if (t == 0) 14330Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 14340Sstevel@tonic-gate 14350Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 14360Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 14370Sstevel@tonic-gate LOG_WARNING, 14380Sstevel@tonic-gate #else 14390Sstevel@tonic-gate LOG_INFO, 14400Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 14410Sstevel@tonic-gate "%s: %s", myself, NIL(t->objName)); 14420Sstevel@tonic-gate 14430Sstevel@tonic-gate tp = selectTableMapping(t, 0, 1, 1, 0, &numMatches); 14440Sstevel@tonic-gate if (tp == 0 || numMatches <= 0) { 14450Sstevel@tonic-gate sfree(tp); 14460Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 14470Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 14480Sstevel@tonic-gate LOG_WARNING, 14490Sstevel@tonic-gate #else 14500Sstevel@tonic-gate LOG_INFO, 14510Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 14520Sstevel@tonic-gate "%s: %s (no mapping)", myself, NIL(t->objName)); 14530Sstevel@tonic-gate return (LDAP_SUCCESS); 14540Sstevel@tonic-gate } 14550Sstevel@tonic-gate 14560Sstevel@tonic-gate for (n = 0; n < numMatches; n++) { 14570Sstevel@tonic-gate 14580Sstevel@tonic-gate t = tp[n]; 14590Sstevel@tonic-gate 14600Sstevel@tonic-gate if (o == 0) { 1461*11262SRajagopal.Andra@Sun.COM sfree(tp); 1462*11262SRajagopal.Andra@Sun.COM return (LDAP_OPERATIONS_ERROR); 14630Sstevel@tonic-gate } 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate buf = (char *)xdrNisObject(o, ea, numEa, &osize); 14660Sstevel@tonic-gate if (buf == 0) { 14670Sstevel@tonic-gate sfree(tp); 14680Sstevel@tonic-gate return (LDAP_OPERATIONS_ERROR); 14690Sstevel@tonic-gate } 14700Sstevel@tonic-gate 14710Sstevel@tonic-gate /* 14720Sstevel@tonic-gate * Prepare to build a rule-value containing the XDR:ed 14730Sstevel@tonic-gate * object 14740Sstevel@tonic-gate */ 14750Sstevel@tonic-gate rv = am(myself, sizeof (*rv)); 14760Sstevel@tonic-gate sv = am(myself, sizeof (*sv)); 14770Sstevel@tonic-gate val = am(myself, sizeof (*val)); 14780Sstevel@tonic-gate attrName = am(myself, sizeof (attrName[0])); 14790Sstevel@tonic-gate if (attrName != 0) 14800Sstevel@tonic-gate attrName[0] = attrVal(myself, "nisplusObject", 14810Sstevel@tonic-gate "nisplusObject", 14820Sstevel@tonic-gate t->objectDN->write.attrs); 14830Sstevel@tonic-gate if (rv == 0 || sv == 0 || val == 0 || attrName == 0 || 14840Sstevel@tonic-gate attrName[0] == 0) { 14850Sstevel@tonic-gate sfree(tp); 14860Sstevel@tonic-gate sfree(buf); 14870Sstevel@tonic-gate sfree(rv); 14880Sstevel@tonic-gate sfree(sv); 14890Sstevel@tonic-gate sfree(val); 14900Sstevel@tonic-gate sfree(attrName); 14910Sstevel@tonic-gate return (LDAP_NO_MEMORY); 14920Sstevel@tonic-gate } 14930Sstevel@tonic-gate 14940Sstevel@tonic-gate sv->length = osize; 14950Sstevel@tonic-gate sv->value = buf; 14960Sstevel@tonic-gate 14970Sstevel@tonic-gate /* 'vt_ber' just means "not a NUL-terminated string" */ 14980Sstevel@tonic-gate val->type = vt_ber; 14990Sstevel@tonic-gate val->repeat = 0; 15000Sstevel@tonic-gate val->numVals = 1; 15010Sstevel@tonic-gate val->val = sv; 15020Sstevel@tonic-gate 15030Sstevel@tonic-gate rv->numAttrs = 1; 15040Sstevel@tonic-gate rv->attrName = attrName; 15050Sstevel@tonic-gate rv->attrVal = val; 15060Sstevel@tonic-gate 15070Sstevel@tonic-gate /* 15080Sstevel@tonic-gate * The 'write.base' is the actual DN of the entry (and the 15090Sstevel@tonic-gate * scope had better be 'base', but we don't check that). 15100Sstevel@tonic-gate */ 15110Sstevel@tonic-gate dn = t->objectDN->write.base; 15120Sstevel@tonic-gate 15130Sstevel@tonic-gate stat = ldapModify(dn, rv, t->objectDN->write.attrs, 1); 15140Sstevel@tonic-gate 15150Sstevel@tonic-gate freeRuleValue(rv, 1); 15160Sstevel@tonic-gate 15170Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 15180Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 15190Sstevel@tonic-gate LOG_WARNING, 15200Sstevel@tonic-gate #else 15210Sstevel@tonic-gate LOG_INFO, 15220Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 15230Sstevel@tonic-gate "%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat)); 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate if (stat != LDAP_SUCCESS) 15260Sstevel@tonic-gate break; 15270Sstevel@tonic-gate 15280Sstevel@tonic-gate } 15290Sstevel@tonic-gate 15300Sstevel@tonic-gate sfree(tp); 15310Sstevel@tonic-gate 15320Sstevel@tonic-gate return (stat); 15330Sstevel@tonic-gate } 15340Sstevel@tonic-gate 15350Sstevel@tonic-gate /* 15360Sstevel@tonic-gate * Retrieve a copy of the 't->objName' object from LDAP, where it's 15370Sstevel@tonic-gate * stored in XDR:ed form in the place indicated by 't->objectDN->read'. 15380Sstevel@tonic-gate * Un-XDR the object, and return a pointer to it in '*obj'; it's the 15390Sstevel@tonic-gate * responsibility of the caller to free the object when it's no 15400Sstevel@tonic-gate * longer needed. 15410Sstevel@tonic-gate * 15420Sstevel@tonic-gate * Returns an appropriate LDAP status. 15430Sstevel@tonic-gate */ 15440Sstevel@tonic-gate int 15450Sstevel@tonic-gate objFromLDAP(__nis_table_mapping_t *t, nis_object **obj, 15460Sstevel@tonic-gate entry_obj ***eaP, int *numEaP) { 15470Sstevel@tonic-gate __nis_table_mapping_t **tp; 15480Sstevel@tonic-gate XDR xdr; 15490Sstevel@tonic-gate nis_object *o; 15500Sstevel@tonic-gate __nis_rule_value_t *rv; 15510Sstevel@tonic-gate __nis_ldap_search_t *ls; 15520Sstevel@tonic-gate char *attrs[2], *filter, **fc = 0; 15530Sstevel@tonic-gate void *buf; 15540Sstevel@tonic-gate int i, j, nfc, nrv, blen, stat = LDAP_SUCCESS; 15550Sstevel@tonic-gate int n, numMatches; 15560Sstevel@tonic-gate char *myself = "objFromLDAP"; 15570Sstevel@tonic-gate 15580Sstevel@tonic-gate if (t == 0) 15590Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 15600Sstevel@tonic-gate 15610Sstevel@tonic-gate /* 15620Sstevel@tonic-gate * If there's nowhere to store the result, we might as 15630Sstevel@tonic-gate * well pretend all went well, and return right away. 15640Sstevel@tonic-gate */ 15650Sstevel@tonic-gate if (obj == 0) 15660Sstevel@tonic-gate return (LDAP_SUCCESS); 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate /* Prepare for the worst */ 15690Sstevel@tonic-gate *obj = 0; 15700Sstevel@tonic-gate 15710Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 15720Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 15730Sstevel@tonic-gate LOG_WARNING, 15740Sstevel@tonic-gate #else 15750Sstevel@tonic-gate LOG_INFO, 15760Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 15770Sstevel@tonic-gate "%s: %s", myself, NIL(t->objName)); 15780Sstevel@tonic-gate 15790Sstevel@tonic-gate tp = selectTableMapping(t, 0, 0, 1, 0, &numMatches); 15800Sstevel@tonic-gate if (tp == 0 || numMatches <= 0) { 15810Sstevel@tonic-gate sfree(tp); 15820Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 15830Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 15840Sstevel@tonic-gate LOG_WARNING, 15850Sstevel@tonic-gate #else 15860Sstevel@tonic-gate LOG_INFO, 15870Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 15880Sstevel@tonic-gate "%s: %s (no mapping)", myself, NIL(t->objName)); 15890Sstevel@tonic-gate return (LDAP_SUCCESS); 15900Sstevel@tonic-gate } 15910Sstevel@tonic-gate 15920Sstevel@tonic-gate for (n = 0; n < numMatches; n++) { 15930Sstevel@tonic-gate 15940Sstevel@tonic-gate t = tp[n]; 15950Sstevel@tonic-gate 15960Sstevel@tonic-gate filter = makeFilter(t->objectDN->read.attrs); 15970Sstevel@tonic-gate if (filter == 0 || (fc = makeFilterComp(filter, &nfc)) == 0 || 15980Sstevel@tonic-gate nfc <= 0) { 15990Sstevel@tonic-gate sfree(tp); 16000Sstevel@tonic-gate sfree(filter); 16010Sstevel@tonic-gate freeFilterComp(fc, nfc); 16020Sstevel@tonic-gate return ((t->objectDN->read.attrs != 0) ? 16030Sstevel@tonic-gate LDAP_NO_MEMORY : LDAP_PARAM_ERROR); 16040Sstevel@tonic-gate } 16050Sstevel@tonic-gate /* Don't need the filter, just the components */ 16060Sstevel@tonic-gate sfree(filter); 16070Sstevel@tonic-gate 16080Sstevel@tonic-gate /* 16090Sstevel@tonic-gate * Look for a "nisplusObject" attribute, and (if found) copy 16100Sstevel@tonic-gate * the value to attrs[0]. Also remove the "nisplusObject" 16110Sstevel@tonic-gate * attribute and value from the filter components. 16120Sstevel@tonic-gate */ 16130Sstevel@tonic-gate attrs[0] = sdup(myself, T, "nisplusObject"); 16140Sstevel@tonic-gate if (attrs[0] == 0) { 16150Sstevel@tonic-gate sfree(tp); 16160Sstevel@tonic-gate freeFilterComp(fc, nfc); 16170Sstevel@tonic-gate return (LDAP_NO_MEMORY); 16180Sstevel@tonic-gate } 16190Sstevel@tonic-gate attrs[1] = 0; 16200Sstevel@tonic-gate for (i = 0; i < nfc; i++) { 16210Sstevel@tonic-gate char *name, *value; 16220Sstevel@tonic-gate int compare; 16230Sstevel@tonic-gate 16240Sstevel@tonic-gate name = fc[i]; 16250Sstevel@tonic-gate /* Skip if not of attr=value form */ 16260Sstevel@tonic-gate if ((value = strchr(name, '=')) == 0) 16270Sstevel@tonic-gate continue; 16280Sstevel@tonic-gate 16290Sstevel@tonic-gate /* Temporarily overWrite the '=' with a '\0' */ 16300Sstevel@tonic-gate *value = '\0'; 16310Sstevel@tonic-gate 16320Sstevel@tonic-gate /* Compare with our target attribute name */ 16330Sstevel@tonic-gate compare = strcasecmp("nisplusObject", name); 16340Sstevel@tonic-gate 16350Sstevel@tonic-gate /* Put back the '=' */ 16360Sstevel@tonic-gate *value = '='; 16370Sstevel@tonic-gate 16380Sstevel@tonic-gate /* Is it the name we're looking for ? */ 16390Sstevel@tonic-gate if (compare == 0) { 16400Sstevel@tonic-gate sfree(attrs[0]); 16410Sstevel@tonic-gate attrs[0] = sdup(myself, T, value+1); 16420Sstevel@tonic-gate if (attrs[0] == 0) { 16430Sstevel@tonic-gate sfree(tp); 16440Sstevel@tonic-gate freeFilterComp(fc, nfc); 16450Sstevel@tonic-gate return (LDAP_NO_MEMORY); 16460Sstevel@tonic-gate } 16470Sstevel@tonic-gate sfree(fc[i]); 16480Sstevel@tonic-gate if (i < nfc-1) 16490Sstevel@tonic-gate (void) memmove(&fc[i], &fc[i+1], 16500Sstevel@tonic-gate (nfc-1-i) * sizeof (fc[i])); 16510Sstevel@tonic-gate nfc--; 16520Sstevel@tonic-gate break; 16530Sstevel@tonic-gate } 16540Sstevel@tonic-gate } 16550Sstevel@tonic-gate 16560Sstevel@tonic-gate ls = buildLdapSearch(t->objectDN->read.base, 16570Sstevel@tonic-gate t->objectDN->read.scope, 16580Sstevel@tonic-gate nfc, fc, 0, attrs, 0, 1); 16590Sstevel@tonic-gate sfree(attrs[0]); 16600Sstevel@tonic-gate freeFilterComp(fc, nfc); 16610Sstevel@tonic-gate if (ls == 0) { 16620Sstevel@tonic-gate sfree(tp); 16630Sstevel@tonic-gate return (LDAP_OPERATIONS_ERROR); 16640Sstevel@tonic-gate } 16650Sstevel@tonic-gate 16660Sstevel@tonic-gate nrv = 0; 16670Sstevel@tonic-gate rv = ldapSearch(ls, &nrv, 0, &stat); 16680Sstevel@tonic-gate if (rv == 0) { 16690Sstevel@tonic-gate sfree(tp); 16700Sstevel@tonic-gate freeLdapSearch(ls); 16710Sstevel@tonic-gate return (stat); 16720Sstevel@tonic-gate } 16730Sstevel@tonic-gate 16740Sstevel@tonic-gate for (i = 0, buf = 0; i < nrv && buf == 0; i++) { 16750Sstevel@tonic-gate for (j = 0; j < rv[i].numAttrs; j++) { 16760Sstevel@tonic-gate if (strcasecmp(ls->attrs[0], 16770Sstevel@tonic-gate rv[i].attrName[j]) == 0) { 16780Sstevel@tonic-gate if (rv[i].attrVal[j].numVals <= 0) 16790Sstevel@tonic-gate continue; 16800Sstevel@tonic-gate buf = rv[i].attrVal[j].val[0].value; 16810Sstevel@tonic-gate blen = rv[i].attrVal[j].val[0].length; 16820Sstevel@tonic-gate break; 16830Sstevel@tonic-gate } 16840Sstevel@tonic-gate } 16850Sstevel@tonic-gate } 16860Sstevel@tonic-gate 16870Sstevel@tonic-gate if (buf != 0) { 16880Sstevel@tonic-gate o = unXdrNisObject(buf, blen, eaP, numEaP); 16890Sstevel@tonic-gate if (o == 0) { 16900Sstevel@tonic-gate sfree(tp); 16910Sstevel@tonic-gate freeLdapSearch(ls); 16920Sstevel@tonic-gate freeRuleValue(rv, nrv); 16930Sstevel@tonic-gate return (LDAP_OPERATIONS_ERROR); 16940Sstevel@tonic-gate } 16950Sstevel@tonic-gate stat = LDAP_SUCCESS; 16960Sstevel@tonic-gate *obj = o; 16970Sstevel@tonic-gate } else { 16980Sstevel@tonic-gate stat = LDAP_NO_SUCH_OBJECT; 16990Sstevel@tonic-gate } 17000Sstevel@tonic-gate 17010Sstevel@tonic-gate freeLdapSearch(ls); 17020Sstevel@tonic-gate freeRuleValue(rv, nrv); 17030Sstevel@tonic-gate 17040Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 17050Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 17060Sstevel@tonic-gate LOG_WARNING, 17070Sstevel@tonic-gate #else 17080Sstevel@tonic-gate LOG_INFO, 17090Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 17100Sstevel@tonic-gate "%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat)); 17110Sstevel@tonic-gate 17120Sstevel@tonic-gate if (stat != LDAP_SUCCESS) 17130Sstevel@tonic-gate break; 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate } 17160Sstevel@tonic-gate 17170Sstevel@tonic-gate sfree(tp); 17180Sstevel@tonic-gate 17190Sstevel@tonic-gate return (stat); 17200Sstevel@tonic-gate } 17210Sstevel@tonic-gate 17220Sstevel@tonic-gate int 17230Sstevel@tonic-gate deleteLDAPobj(__nis_table_mapping_t *t) { 17240Sstevel@tonic-gate __nis_table_mapping_t **tp; 17250Sstevel@tonic-gate int n, stat, numMatches = 0; 17260Sstevel@tonic-gate char *myself = "deleteLDAPobj"; 17270Sstevel@tonic-gate 17280Sstevel@tonic-gate if (t == 0) 17290Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 17300Sstevel@tonic-gate 17310Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 17320Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 17330Sstevel@tonic-gate LOG_WARNING, 17340Sstevel@tonic-gate #else 17350Sstevel@tonic-gate LOG_INFO, 17360Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 17370Sstevel@tonic-gate "%s: %s", myself, NIL(t->objName)); 17380Sstevel@tonic-gate 17390Sstevel@tonic-gate tp = selectTableMapping(t, 0, 1, 1, 0, &numMatches); 17400Sstevel@tonic-gate if (tp == 0 || numMatches <= 0) { 17410Sstevel@tonic-gate sfree(tp); 17420Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 17430Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 17440Sstevel@tonic-gate LOG_WARNING, 17450Sstevel@tonic-gate #else 17460Sstevel@tonic-gate LOG_INFO, 17470Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 17480Sstevel@tonic-gate "%s: %s (no mapping)", myself, NIL(t->objName)); 17490Sstevel@tonic-gate return (LDAP_SUCCESS); 17500Sstevel@tonic-gate } 17510Sstevel@tonic-gate 17520Sstevel@tonic-gate for (n = 0; n < numMatches; n++) { 17530Sstevel@tonic-gate 17540Sstevel@tonic-gate t = tp[n]; 17550Sstevel@tonic-gate 17560Sstevel@tonic-gate if (t->objectDN->delDisp == dd_always) { 17570Sstevel@tonic-gate /* Delete entire entry */ 17580Sstevel@tonic-gate stat = ldapModify(t->objectDN->write.base, 0, 17590Sstevel@tonic-gate t->objectDN->write.attrs, 1); 17600Sstevel@tonic-gate } else if (t->objectDN->delDisp == dd_perDbId) { 17610Sstevel@tonic-gate /* 17620Sstevel@tonic-gate * Delete the attribute holding the object. 17630Sstevel@tonic-gate * First, determine what that attribute is called. 17640Sstevel@tonic-gate */ 17650Sstevel@tonic-gate char *attrName = 17660Sstevel@tonic-gate attrVal(myself, 17670Sstevel@tonic-gate "nisplusObject", 17680Sstevel@tonic-gate "nisplusObject", 17690Sstevel@tonic-gate t->objectDN->write.attrs); 17700Sstevel@tonic-gate __nis_rule_value_t rv; 17710Sstevel@tonic-gate __nis_value_t val; 17720Sstevel@tonic-gate 17730Sstevel@tonic-gate if (attrName == 0) { 17740Sstevel@tonic-gate sfree(tp); 17750Sstevel@tonic-gate return (LDAP_NO_MEMORY); 17760Sstevel@tonic-gate } 17770Sstevel@tonic-gate 17780Sstevel@tonic-gate /* 17790Sstevel@tonic-gate * Build a __nis_value_t with 'numVals' < 0 to 17800Sstevel@tonic-gate * indicate deletion. 17810Sstevel@tonic-gate */ 17820Sstevel@tonic-gate val.type = vt_ber; 17830Sstevel@tonic-gate val.numVals = -1; 17840Sstevel@tonic-gate val.val = 0; 17850Sstevel@tonic-gate 17860Sstevel@tonic-gate /* 17870Sstevel@tonic-gate * Build a rule-value with the name we determined 17880Sstevel@tonic-gate * above, and the deletion value. 17890Sstevel@tonic-gate */ 17900Sstevel@tonic-gate (void) memset(&rv, 0, sizeof (rv)); 17910Sstevel@tonic-gate rv.numAttrs = 1; 17920Sstevel@tonic-gate rv.attrName = &attrName; 17930Sstevel@tonic-gate rv.attrVal = &val; 17940Sstevel@tonic-gate 17950Sstevel@tonic-gate stat = ldapModify(t->objectDN->write.base, &rv, 17960Sstevel@tonic-gate t->objectDN->write.attrs, 0); 17970Sstevel@tonic-gate 17980Sstevel@tonic-gate sfree(attrName); 17990Sstevel@tonic-gate } else if (t->objectDN->delDisp == dd_never) { 18000Sstevel@tonic-gate /* Nothing to do, so we're trivially successful */ 18010Sstevel@tonic-gate stat = LDAP_SUCCESS; 18020Sstevel@tonic-gate } else { 18030Sstevel@tonic-gate stat = LDAP_PARAM_ERROR; 18040Sstevel@tonic-gate } 18050Sstevel@tonic-gate 18060Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 18070Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 18080Sstevel@tonic-gate LOG_WARNING, 18090Sstevel@tonic-gate #else 18100Sstevel@tonic-gate LOG_INFO, 18110Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 18120Sstevel@tonic-gate "%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat)); 18130Sstevel@tonic-gate 18140Sstevel@tonic-gate /* If there were no such object, we've trivially succeeded */ 18150Sstevel@tonic-gate if (stat == LDAP_NO_SUCH_OBJECT) 18160Sstevel@tonic-gate stat = LDAP_SUCCESS; 18170Sstevel@tonic-gate 18180Sstevel@tonic-gate if (stat != LDAP_SUCCESS) 18190Sstevel@tonic-gate break; 18200Sstevel@tonic-gate 18210Sstevel@tonic-gate } 18220Sstevel@tonic-gate 18230Sstevel@tonic-gate sfree(tp); 18240Sstevel@tonic-gate 18250Sstevel@tonic-gate return (stat); 18260Sstevel@tonic-gate } 1827