1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <strings.h> 30*0Sstevel@tonic-gate #include <string.h> 31*0Sstevel@tonic-gate #include <lber.h> 32*0Sstevel@tonic-gate #include <ldap.h> 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #include "db_item_c.h" 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate #include "nisdb_mt.h" 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #include "ldap_util.h" 39*0Sstevel@tonic-gate #include "ldap_structs.h" 40*0Sstevel@tonic-gate #include "ldap_val.h" 41*0Sstevel@tonic-gate #include "ldap_ruleval.h" 42*0Sstevel@tonic-gate #include "ldap_op.h" 43*0Sstevel@tonic-gate #include "ldap_nisdbquery.h" 44*0Sstevel@tonic-gate #include "ldap_attr.h" 45*0Sstevel@tonic-gate #include "ldap_nisplus.h" 46*0Sstevel@tonic-gate #include "ldap_xdr.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate item * 50*0Sstevel@tonic-gate buildItem(int len, void *value) { 51*0Sstevel@tonic-gate char *myself = "buildItem"; 52*0Sstevel@tonic-gate item *i = am(myself, sizeof (*i)); 53*0Sstevel@tonic-gate int mlen = len; 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate if (i == 0) 56*0Sstevel@tonic-gate return (0); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* 59*0Sstevel@tonic-gate * To this function, a NULL value, or a length less than or equal 60*0Sstevel@tonic-gate * zero means an item with no value. Hence, buildItem(0, 0) is 61*0Sstevel@tonic-gate * _not_ the right way to create index_value == 0 to indicate 62*0Sstevel@tonic-gate * deletion. 63*0Sstevel@tonic-gate */ 64*0Sstevel@tonic-gate if (value == 0 || len <= 0) { 65*0Sstevel@tonic-gate i->itemvalue.itemvalue_len = 0; 66*0Sstevel@tonic-gate i->itemvalue.itemvalue_val = 0; 67*0Sstevel@tonic-gate return (i); 68*0Sstevel@tonic-gate } 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate /* 71*0Sstevel@tonic-gate * NIS+ usually stores the terminating NUL for strings, so we add 72*0Sstevel@tonic-gate * it here just in case. This means we usually waste a byte for 73*0Sstevel@tonic-gate * binary column values... 74*0Sstevel@tonic-gate */ 75*0Sstevel@tonic-gate if (len > 0 && ((char *)value)[len-1] != '\0') 76*0Sstevel@tonic-gate mlen++; 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate i->itemvalue.itemvalue_len = len; 79*0Sstevel@tonic-gate i->itemvalue.itemvalue_val = am(myself, mlen); 80*0Sstevel@tonic-gate if (mlen > 0 && i->itemvalue.itemvalue_val == 0) { 81*0Sstevel@tonic-gate free(i); 82*0Sstevel@tonic-gate return (0); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate memcpy(i->itemvalue.itemvalue_val, value, len); 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate return (i); 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate void 90*0Sstevel@tonic-gate freeItem(item *i) { 91*0Sstevel@tonic-gate if (i != 0) { 92*0Sstevel@tonic-gate sfree(i->itemvalue.itemvalue_val); 93*0Sstevel@tonic-gate free(i); 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate void 98*0Sstevel@tonic-gate freeQcomp(db_qcomp *qc, int doFree) { 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate if (qc == 0) 101*0Sstevel@tonic-gate return; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate freeItem(qc->index_value); 104*0Sstevel@tonic-gate if (doFree) 105*0Sstevel@tonic-gate free(qc); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate db_query * 109*0Sstevel@tonic-gate buildQuery(int num_components, db_qcomp *components) { 110*0Sstevel@tonic-gate char *myself = "buildQuery"; 111*0Sstevel@tonic-gate db_query *q = am(myself, sizeof (*q)); 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate if (q == 0) 114*0Sstevel@tonic-gate return (0); 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate q->components.components_len = num_components; 117*0Sstevel@tonic-gate q->components.components_val = components; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate return (q); 120*0Sstevel@tonic-gate } 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate /* 123*0Sstevel@tonic-gate * Clone a db_query. The 'numComps' parameter can be used to specify 124*0Sstevel@tonic-gate * the number of db_qcomp's to allocate (in the 'components.components_val' 125*0Sstevel@tonic-gate * array), if 'components.components_len' hasn't yet reached its expected 126*0Sstevel@tonic-gate * maximum value. 127*0Sstevel@tonic-gate */ 128*0Sstevel@tonic-gate db_query * 129*0Sstevel@tonic-gate cloneQuery(db_query *old, int numComps) { 130*0Sstevel@tonic-gate db_query *new; 131*0Sstevel@tonic-gate int i; 132*0Sstevel@tonic-gate char *myself = "cloneQuery"; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate if (old == 0) 135*0Sstevel@tonic-gate return (0); 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate new = am(myself, sizeof (*new)); 138*0Sstevel@tonic-gate if (new == 0) 139*0Sstevel@tonic-gate return (0); 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate if (old->components.components_len > numComps) 142*0Sstevel@tonic-gate numComps = old->components.components_len; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate new->components.components_val = am(myself, 145*0Sstevel@tonic-gate sizeof (new->components.components_val[0]) * 146*0Sstevel@tonic-gate numComps); 147*0Sstevel@tonic-gate if (numComps > 0 && new->components.components_val == 0) { 148*0Sstevel@tonic-gate free(new); 149*0Sstevel@tonic-gate return (0); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate for (i = 0; i < old->components.components_len; i++) { 153*0Sstevel@tonic-gate item *it; 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate if (old->components.components_val[i].index_value == 0) { 156*0Sstevel@tonic-gate new->components.components_val[i].index_value = 0; 157*0Sstevel@tonic-gate new->components.components_val[i].which_index = 158*0Sstevel@tonic-gate old->components.components_val[i].which_index; 159*0Sstevel@tonic-gate continue; 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate it = buildItem(old->components.components_val[i].index_value-> 163*0Sstevel@tonic-gate itemvalue.itemvalue_len, 164*0Sstevel@tonic-gate old->components.components_val[i].index_value-> 165*0Sstevel@tonic-gate itemvalue.itemvalue_val); 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate if (it == 0) { 168*0Sstevel@tonic-gate new->components.components_len = i + 1; 169*0Sstevel@tonic-gate freeQuery(new); 170*0Sstevel@tonic-gate return (0); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate new->components.components_val[i].index_value = it; 174*0Sstevel@tonic-gate new->components.components_val[i].which_index = 175*0Sstevel@tonic-gate old->components.components_val[i].which_index; 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate new->components.components_len = old->components.components_len; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate return (new); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate void 184*0Sstevel@tonic-gate freeQuery(db_query *q) { 185*0Sstevel@tonic-gate int i; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate if (q == 0) 188*0Sstevel@tonic-gate return; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 191*0Sstevel@tonic-gate freeItem(q->components.components_val[i].index_value); 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate sfree(q->components.components_val); 195*0Sstevel@tonic-gate sfree(q); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate void 199*0Sstevel@tonic-gate freeQueries(db_query **q, int numQ) { 200*0Sstevel@tonic-gate int i; 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate if (q == 0) 203*0Sstevel@tonic-gate return; 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate for (i = 0; i < numQ; i++) 206*0Sstevel@tonic-gate freeQuery(q[i]); 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate sfree(q); 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate /* 212*0Sstevel@tonic-gate * Given an array index[0..num-1] of pointers to strings of the form 213*0Sstevel@tonic-gate * "name=value", create the corresponding db_queries. "name=" indicates 214*0Sstevel@tonic-gate * deletion, which results in a db_query component where index_value == 0. 215*0Sstevel@tonic-gate * 216*0Sstevel@tonic-gate * The __nis_table_mapping_t structure is used to translate column 217*0Sstevel@tonic-gate * names to indices. 218*0Sstevel@tonic-gate * 219*0Sstevel@tonic-gate * If 'rvP' is non-NULL, the searchable columns from the 'index' 220*0Sstevel@tonic-gate * name/value pairs are used to retrieve copies of the corresponding NIS+ 221*0Sstevel@tonic-gate * entries, and '*rvP' is initialized with the current entry values 222*0Sstevel@tonic-gate * and object attributes. Names/values supplied in 'index' override 223*0Sstevel@tonic-gate * those from existing NIS+ entries. 224*0Sstevel@tonic-gate */ 225*0Sstevel@tonic-gate db_query ** 226*0Sstevel@tonic-gate createQuery(int num, char **index, __nis_table_mapping_t *t, 227*0Sstevel@tonic-gate __nis_rule_value_t **rvP, int *numVals) { 228*0Sstevel@tonic-gate db_query **q; 229*0Sstevel@tonic-gate db_qcomp *qc; 230*0Sstevel@tonic-gate int i, j, n, a, nv, niv, stat, sinum; 231*0Sstevel@tonic-gate __nis_rule_value_t *rvq; 232*0Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 233*0Sstevel@tonic-gate nis_result *res = 0; 234*0Sstevel@tonic-gate char *table = 0; 235*0Sstevel@tonic-gate char *myself = "createQuery"; 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate rvq = initRuleValue(1, 0); 238*0Sstevel@tonic-gate if (rvq == 0) 239*0Sstevel@tonic-gate return (0); 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate if (numVals == 0) 242*0Sstevel@tonic-gate numVals = &nv; 243*0Sstevel@tonic-gate *numVals = 0; 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate if (rvP != 0) { 246*0Sstevel@tonic-gate /* 247*0Sstevel@tonic-gate * Try to obtain a copy of the table object, in order to 248*0Sstevel@tonic-gate * determine the searchable columns. A failure isn't 249*0Sstevel@tonic-gate * necessarily fatal; we just try to compose the entire 250*0Sstevel@tonic-gate * LDAP data from the col=val pairs. 251*0Sstevel@tonic-gate */ 252*0Sstevel@tonic-gate table = fullObjName(F, t->objName); 253*0Sstevel@tonic-gate if (table == 0) { 254*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 255*0Sstevel@tonic-gate "%s: Error converting \"%s\" to FQ object name", 256*0Sstevel@tonic-gate myself, NIL(t->objName)); 257*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 258*0Sstevel@tonic-gate return (0); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate stat = getNisPlusObj(table, myself, &res); 262*0Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 263*0Sstevel@tonic-gate if (res->objects.objects_val->zo_data.zo_type != 264*0Sstevel@tonic-gate NIS_TABLE_OBJ) { 265*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 266*0Sstevel@tonic-gate "%s: \"%s\" isn't a table object", 267*0Sstevel@tonic-gate myself, NIL(table)); 268*0Sstevel@tonic-gate nis_freeresult(res); 269*0Sstevel@tonic-gate res = 0; 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate } else { 272*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 273*0Sstevel@tonic-gate "%s: Unable to retrieve \"%s\" object: %s", 274*0Sstevel@tonic-gate myself, NIL(table), ldap_err2string(stat)); 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* Create a rule-value from the col=val pairs */ 279*0Sstevel@tonic-gate for (n = 0; n < num; n++) { 280*0Sstevel@tonic-gate char *name; 281*0Sstevel@tonic-gate char *value; 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate if ((value = strchr(index[n], '=')) == 0) { 284*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 285*0Sstevel@tonic-gate "%s: no '=' in \"%s\"", 286*0Sstevel@tonic-gate myself, index[n]); 287*0Sstevel@tonic-gate continue; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate *value = '\0'; 291*0Sstevel@tonic-gate value++; 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate for (a = 0; a < t->numColumns; a++) { 294*0Sstevel@tonic-gate if (strcmp(index[n], t->column[a]) == 0) { 295*0Sstevel@tonic-gate int i, len = slen(value)+1; 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate /* Add col=val pair to 'rvq' */ 298*0Sstevel@tonic-gate if (addSCol2RuleValue(index[n], value, rvq)) { 299*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 300*0Sstevel@tonic-gate sfree(table); 301*0Sstevel@tonic-gate if (res != 0) 302*0Sstevel@tonic-gate nis_freeresult(res); 303*0Sstevel@tonic-gate return (0); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate break; 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate } 309*0Sstevel@tonic-gate if (a >= t->numColumns) { 310*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 311*0Sstevel@tonic-gate "%s: Ignoring unknown column \"%s\"", 312*0Sstevel@tonic-gate myself, NIL(index[n])); 313*0Sstevel@tonic-gate } 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate /* 317*0Sstevel@tonic-gate * Find out if any of the columns specified via the 'index' 318*0Sstevel@tonic-gate * array are multi-valued. 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate for (n = 0, niv = 1; n < rvq->numColumns; n++) { 321*0Sstevel@tonic-gate if (rvq->colVal[n].numVals > 1) 322*0Sstevel@tonic-gate niv *= rvq->colVal[n].numVals; 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate /* 326*0Sstevel@tonic-gate * Generate a NIS+ query, provided that the following conditions 327*0Sstevel@tonic-gate * are satisfied: 328*0Sstevel@tonic-gate * 329*0Sstevel@tonic-gate * We were able to get information about the table, and 330*0Sstevel@tonic-gate * 331*0Sstevel@tonic-gate * The col=val pairs include at least one searchable 332*0Sstevel@tonic-gate * column, and 333*0Sstevel@tonic-gate * 334*0Sstevel@tonic-gate * At most one value was supplied for each searchable 335*0Sstevel@tonic-gate * column. 336*0Sstevel@tonic-gate */ 337*0Sstevel@tonic-gate if (res != 0 && rvq->numColumns > 0) { 338*0Sstevel@tonic-gate bp2buf(myself, &b, "["); 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate for (n = 0, sinum = 0; n < rvq->numColumns; n++) { 341*0Sstevel@tonic-gate table_obj *to = &(NIS_RES_OBJECT(res)->TA_data); 342*0Sstevel@tonic-gate table_col *tc; 343*0Sstevel@tonic-gate int si = -1; 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate for (i = 0; i < to->ta_cols.ta_cols_len; i++) { 346*0Sstevel@tonic-gate tc = &to->ta_cols.ta_cols_val[i]; 347*0Sstevel@tonic-gate if (strcmp(rvq->colName[n], tc->tc_name) == 0 && 348*0Sstevel@tonic-gate (tc->tc_flags & TA_SEARCHABLE) != 0) { 349*0Sstevel@tonic-gate si = i; 350*0Sstevel@tonic-gate break; 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate if (si >= 0) { 355*0Sstevel@tonic-gate if (rvq->colVal[n].numVals < 0) 356*0Sstevel@tonic-gate continue; 357*0Sstevel@tonic-gate if (rvq->colVal[n].numVals > 1) { 358*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 359*0Sstevel@tonic-gate "%s: Multi-valued column \"%s\" excluded from NIS+ search", 360*0Sstevel@tonic-gate myself, rvq->colName[n]); 361*0Sstevel@tonic-gate continue; 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate if (sinum == 0) 364*0Sstevel@tonic-gate bp2buf(myself, &b, "%s=%s", 365*0Sstevel@tonic-gate rvq->colName[n], 366*0Sstevel@tonic-gate rvq->colVal[n].val[0].value); 367*0Sstevel@tonic-gate else 368*0Sstevel@tonic-gate bp2buf(myself, &b, ",%s=%s", 369*0Sstevel@tonic-gate rvq->colName[n], 370*0Sstevel@tonic-gate rvq->colVal[n].val[0].value); 371*0Sstevel@tonic-gate sinum++; 372*0Sstevel@tonic-gate } else { 373*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 374*0Sstevel@tonic-gate "%s: \"%s\" not searchable; not included in NIS+ query", 375*0Sstevel@tonic-gate myself, index[n]); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate bp2buf(myself, &b, "]"); 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate if (strcmp(b.buf, "[]") == 0) { 381*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 382*0Sstevel@tonic-gate "%s: No searchable column specified; skipping NIS+ query", 383*0Sstevel@tonic-gate myself); 384*0Sstevel@tonic-gate nis_freeresult(res); 385*0Sstevel@tonic-gate res = 0; 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate } else if (res != 0) { 388*0Sstevel@tonic-gate nis_freeresult(res); 389*0Sstevel@tonic-gate res = 0; 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate /* Query NIS+ */ 393*0Sstevel@tonic-gate if (res != 0) { 394*0Sstevel@tonic-gate __nis_rule_value_t *rv; 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate bp2buf(myself, &b, "%s", table); 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 399*0Sstevel@tonic-gate "%s: NIS+ query: %s", myself, NIL(b.buf)); 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate rv = getNisPlusEntrySimple(b.buf, numVals); 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate /* 404*0Sstevel@tonic-gate * Add values from the NIS+ entry to the ones passed in by 405*0Sstevel@tonic-gate * our caller (in the form of col=value pairs). 406*0Sstevel@tonic-gate */ 407*0Sstevel@tonic-gate if (rv != 0 && *numVals > 1 && niv > 1) { 408*0Sstevel@tonic-gate /* 409*0Sstevel@tonic-gate * Since we have both multi-valued columns in the 410*0Sstevel@tonic-gate * 'index' array, _and_ multiple NIS+ matches, we 411*0Sstevel@tonic-gate * don't know how to combine the two in a meaningful 412*0Sstevel@tonic-gate * fashion. Ignore the NIS+ values, and use the 413*0Sstevel@tonic-gate * 'index' array only. 414*0Sstevel@tonic-gate */ 415*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 416*0Sstevel@tonic-gate "%s: At least one multi-valued input column, and multiple NIS+ matches", 417*0Sstevel@tonic-gate myself); 418*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 419*0Sstevel@tonic-gate "%s: Ignoring NIS+ lookup results", myself); 420*0Sstevel@tonic-gate freeRuleValue(rv, *numVals); 421*0Sstevel@tonic-gate rv = 0; 422*0Sstevel@tonic-gate *numVals = 1; 423*0Sstevel@tonic-gate } else if (rv != 0 && *numVals > 0) { 424*0Sstevel@tonic-gate /* 425*0Sstevel@tonic-gate * Since passed-in values override those from the 426*0Sstevel@tonic-gate * NIS+ entries, we first need to delete the passed-in 427*0Sstevel@tonic-gate * columns from the NIS+ data, and then add the 428*0Sstevel@tonic-gate * passed-in columns/values. 429*0Sstevel@tonic-gate */ 430*0Sstevel@tonic-gate for (i = 0; i < rvq->numColumns; i++) { 431*0Sstevel@tonic-gate for (n = 0; n < *numVals; n++) { 432*0Sstevel@tonic-gate delColFromRuleValue(&rv[n], 433*0Sstevel@tonic-gate rvq->colName[i]); 434*0Sstevel@tonic-gate for (j = 0; j < rvq->colVal[i].numVals; 435*0Sstevel@tonic-gate j++) { 436*0Sstevel@tonic-gate if (addCol2RuleValue( 437*0Sstevel@tonic-gate rvq->colVal[i].type, 438*0Sstevel@tonic-gate rvq->colName[i], 439*0Sstevel@tonic-gate rvq->colVal[i].val[j]. 440*0Sstevel@tonic-gate value, 441*0Sstevel@tonic-gate rvq->colVal[i].val[j]. 442*0Sstevel@tonic-gate length, 443*0Sstevel@tonic-gate &rv[n])) { 444*0Sstevel@tonic-gate freeRuleValue(rv, 445*0Sstevel@tonic-gate *numVals); 446*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 447*0Sstevel@tonic-gate sfree(b.buf); 448*0Sstevel@tonic-gate sfree(table); 449*0Sstevel@tonic-gate nis_freeresult(res); 450*0Sstevel@tonic-gate return (0); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate } 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 456*0Sstevel@tonic-gate rvq = rv; 457*0Sstevel@tonic-gate } else { 458*0Sstevel@tonic-gate if (rv != 0) { 459*0Sstevel@tonic-gate /* 460*0Sstevel@tonic-gate * Since we got here, '*numVals' <= 0, 461*0Sstevel@tonic-gate * so it's unclear if it's safe to call 462*0Sstevel@tonic-gate * freeRuleValue(). 463*0Sstevel@tonic-gate */ 464*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 465*0Sstevel@tonic-gate "%s: getNisPlusEntrySimple() => non-NULL, but %d elements", 466*0Sstevel@tonic-gate myself, *numVals); 467*0Sstevel@tonic-gate } else 468*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 469*0Sstevel@tonic-gate "%s: No NIS+ data for \"%s\"", 470*0Sstevel@tonic-gate myself, b.buf); 471*0Sstevel@tonic-gate *numVals = 1; 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate nis_freeresult(res); 474*0Sstevel@tonic-gate res = 0; 475*0Sstevel@tonic-gate } else { 476*0Sstevel@tonic-gate *numVals = 1; 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate sfree(b.buf); 480*0Sstevel@tonic-gate sfree(table); 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate if (rvq->numColumns <= 0) { 483*0Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 484*0Sstevel@tonic-gate *numVals = 0; 485*0Sstevel@tonic-gate return (0); 486*0Sstevel@tonic-gate } 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate /* 489*0Sstevel@tonic-gate * If any column name was repeated in the col=val pairs (but with 490*0Sstevel@tonic-gate * different values), 'rvq' will have one or more multi-valued 491*0Sstevel@tonic-gate * column values. We now convert those into an array of rule-values 492*0Sstevel@tonic-gate * where every column is single-valued. 493*0Sstevel@tonic-gate * 494*0Sstevel@tonic-gate * Since we want all combinations of column values, the number 495*0Sstevel@tonic-gate * of array elements is the product of all column value counts. 496*0Sstevel@tonic-gate * 497*0Sstevel@tonic-gate * There are four possible combinations of 'index' and NIS+ data: 498*0Sstevel@tonic-gate * 499*0Sstevel@tonic-gate * (1) Only single-valued 'index' columns, and at most one NIS+ 500*0Sstevel@tonic-gate * entry, so 'rvq' is complete, and '*numVals' == 1. 501*0Sstevel@tonic-gate * 502*0Sstevel@tonic-gate * (2) Single-valued 'index' columns, but multiple NIS+ entries. 503*0Sstevel@tonic-gate * '*numVals' reflects the number of NIS+ entries, and no 504*0Sstevel@tonic-gate * expansion of 'index' column values to array elements is 505*0Sstevel@tonic-gate * needed. 506*0Sstevel@tonic-gate * 507*0Sstevel@tonic-gate * (3) At least one multi-valued 'index', and multiple NIS+ 508*0Sstevel@tonic-gate * entries. We already rejected the NIS+ data for this case 509*0Sstevel@tonic-gate * above, so it is in fact equivalent to case (4). 510*0Sstevel@tonic-gate * 511*0Sstevel@tonic-gate * (4) At least one multi-valued 'index', but at most one NIS+ 512*0Sstevel@tonic-gate * entry. This is the case where we must expand the multi-valued 513*0Sstevel@tonic-gate * columns to multiple array elements. 514*0Sstevel@tonic-gate */ 515*0Sstevel@tonic-gate if (niv > 1 && *numVals == 1) { 516*0Sstevel@tonic-gate __nis_rule_value_t *rv; 517*0Sstevel@tonic-gate int repeat; 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate /* 520*0Sstevel@tonic-gate * By using initRuleValue() to create 'rv', and make each 521*0Sstevel@tonic-gate * element a clone of 'rvq', we save a lot of code. The 522*0Sstevel@tonic-gate * down side is that 'rv' only really needs one element 523*0Sstevel@tonic-gate * for each rv[].colVal[].val array, but we know that at 524*0Sstevel@tonic-gate * least one rvq->colVal[].val array has more than one 525*0Sstevel@tonic-gate * element. Hence, making 'rv' a clone of 'rvq' will waste 526*0Sstevel@tonic-gate * memory. 527*0Sstevel@tonic-gate * 528*0Sstevel@tonic-gate * However, we believe this waste is acceptable, because 529*0Sstevel@tonic-gate * we expect that 'niv' will be small. Also, we are executing 530*0Sstevel@tonic-gate * in the context of a utility command, not in a daemon. 531*0Sstevel@tonic-gate */ 532*0Sstevel@tonic-gate rv = initRuleValue(niv, rvq); 533*0Sstevel@tonic-gate if (rv == 0) { 534*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 535*0Sstevel@tonic-gate *numVals = 0; 536*0Sstevel@tonic-gate return (0); 537*0Sstevel@tonic-gate } 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate /* 540*0Sstevel@tonic-gate * For each column value in 'rvq', copy to the appropriate 541*0Sstevel@tonic-gate * place in 'rv', so that the end result is that all 542*0Sstevel@tonic-gate * combinations of values are enumerated, and each 543*0Sstevel@tonic-gate * 'rv[n].colVal[i]' is single-valued. 544*0Sstevel@tonic-gate * 545*0Sstevel@tonic-gate * We do this by traversing the rv[] array 'rvq->numColumns' 546*0Sstevel@tonic-gate * times, where each traversal 'i' works on the values 547*0Sstevel@tonic-gate * for rvq->colVal[i]. A repeat factor 'repeat' starts out 548*0Sstevel@tonic-gate * at '1', and is multiplied by 'rvq->colVal[i].numVals' 549*0Sstevel@tonic-gate * at the end of each traversal. Every value 550*0Sstevel@tonic-gate * rvq->colVal[i].val[j] is repeated 'repeat' times. 551*0Sstevel@tonic-gate * 552*0Sstevel@tonic-gate * This algorithm works by regarding the rv[] array as 553*0Sstevel@tonic-gate * an I-dimensional array (I = rvq->numColumns), where 554*0Sstevel@tonic-gate * each dimension 'i' corresponds to the values for 555*0Sstevel@tonic-gate * rvq->colVal[i]. The I-dimensional array is stored 556*0Sstevel@tonic-gate * in column-major order. 557*0Sstevel@tonic-gate * 558*0Sstevel@tonic-gate * Since the 'rv' elements start out as copies of 'rvq', 559*0Sstevel@tonic-gate * we achieve the "copy" of the 'rvq' column values by 560*0Sstevel@tonic-gate * deleting those we don't want from the 'rv' elements. 561*0Sstevel@tonic-gate */ 562*0Sstevel@tonic-gate for (i = 0, repeat = 1; i < rvq->numColumns; i++) { 563*0Sstevel@tonic-gate int r, k; 564*0Sstevel@tonic-gate for (n = 0, j = 0, r = 0; n < niv; n++) { 565*0Sstevel@tonic-gate /* 566*0Sstevel@tonic-gate * Free all but element 'j' of the 567*0Sstevel@tonic-gate * rv[n].colVal[i].val array. 568*0Sstevel@tonic-gate */ 569*0Sstevel@tonic-gate for (k = 0; k < rv[n].colVal[i].numVals; k++) { 570*0Sstevel@tonic-gate /* Leave element 'j' in place */ 571*0Sstevel@tonic-gate if (k == j) 572*0Sstevel@tonic-gate continue; 573*0Sstevel@tonic-gate sfree(rv[n].colVal[i].val[k]. 574*0Sstevel@tonic-gate value); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate rv[n].colVal[i].numVals = 1; 577*0Sstevel@tonic-gate /* Move element 'j' to zero */ 578*0Sstevel@tonic-gate if (j != 0) 579*0Sstevel@tonic-gate rv[n].colVal[i].val[0] = 580*0Sstevel@tonic-gate rv[n].colVal[i].val[j]; 581*0Sstevel@tonic-gate 582*0Sstevel@tonic-gate /* 583*0Sstevel@tonic-gate * Increment the repeat index 'r'. If >= 584*0Sstevel@tonic-gate * 'repeat', reset 'r' and increment the 585*0Sstevel@tonic-gate * value index 'j'. If 'j' >= 586*0Sstevel@tonic-gate * rvq->colVal[i].numVals, start over on 587*0Sstevel@tonic-gate * the column values for column 'i' (i.e., 588*0Sstevel@tonic-gate * reset 'j' to zero). 589*0Sstevel@tonic-gate */ 590*0Sstevel@tonic-gate r += 1; 591*0Sstevel@tonic-gate if (r >= repeat) { 592*0Sstevel@tonic-gate r = 0; 593*0Sstevel@tonic-gate j += 1; 594*0Sstevel@tonic-gate if (j >= rvq->colVal[i].numVals) 595*0Sstevel@tonic-gate j = 0; 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate } 598*0Sstevel@tonic-gate repeat *= rvq->colVal[i].numVals; 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate *numVals = niv; 602*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 603*0Sstevel@tonic-gate rvq = rv; 604*0Sstevel@tonic-gate rv = 0; 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate q = am(myself, *numVals * sizeof (q[0])); 608*0Sstevel@tonic-gate if (q == 0) { 609*0Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 610*0Sstevel@tonic-gate return (0); 611*0Sstevel@tonic-gate } 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate /* 614*0Sstevel@tonic-gate * Create queries from the rvq[] array. 615*0Sstevel@tonic-gate */ 616*0Sstevel@tonic-gate for (a = 0; a < *numVals; a++) { 617*0Sstevel@tonic-gate int nn, err = 0; 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate qc = am(myself, rvq[a].numColumns * sizeof (*qc)); 620*0Sstevel@tonic-gate if (qc != 0) { 621*0Sstevel@tonic-gate for (nn = 0, i = 0; i < rvq[a].numColumns; i++) { 622*0Sstevel@tonic-gate for (j = 0; j < t->numColumns; j++) { 623*0Sstevel@tonic-gate if (strcmp(rvq[a].colName[i], 624*0Sstevel@tonic-gate t->column[j]) == 0) { 625*0Sstevel@tonic-gate break; 626*0Sstevel@tonic-gate } 627*0Sstevel@tonic-gate } 628*0Sstevel@tonic-gate if (j >= t->numColumns) 629*0Sstevel@tonic-gate continue; 630*0Sstevel@tonic-gate qc[nn].which_index = j; 631*0Sstevel@tonic-gate if (rvq[a].colVal[i].numVals > 0) { 632*0Sstevel@tonic-gate qc[nn].index_value = buildItem( 633*0Sstevel@tonic-gate rvq[a].colVal[i].val[0].length, 634*0Sstevel@tonic-gate rvq[a].colVal[i].val[0].value); 635*0Sstevel@tonic-gate if (qc[nn].index_value == 0) 636*0Sstevel@tonic-gate err++; 637*0Sstevel@tonic-gate } else { 638*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 639*0Sstevel@tonic-gate "%s: No values for [%d]%s", 640*0Sstevel@tonic-gate myself, a, rvq[a].colName[i]); 641*0Sstevel@tonic-gate err++; 642*0Sstevel@tonic-gate } 643*0Sstevel@tonic-gate nn++; 644*0Sstevel@tonic-gate } 645*0Sstevel@tonic-gate if (err == 0) 646*0Sstevel@tonic-gate q[a] = buildQuery(nn, qc); 647*0Sstevel@tonic-gate } 648*0Sstevel@tonic-gate if (err > 0 || q[a] == 0) { 649*0Sstevel@tonic-gate freeQueries(q, a); 650*0Sstevel@tonic-gate for (a = 0; a < nn; a++) 651*0Sstevel@tonic-gate freeQcomp(&qc[a], F); 652*0Sstevel@tonic-gate sfree(qc); 653*0Sstevel@tonic-gate freeRuleValue(rvq, *numVals); 654*0Sstevel@tonic-gate return (0); 655*0Sstevel@tonic-gate } 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate if (rvP != 0) { 659*0Sstevel@tonic-gate *rvP = rvq; 660*0Sstevel@tonic-gate } else { 661*0Sstevel@tonic-gate freeRuleValue(rvq, 1); 662*0Sstevel@tonic-gate *numVals = 0; 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate return (q); 666*0Sstevel@tonic-gate } 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate void 669*0Sstevel@tonic-gate printQuery(db_query *q, __nis_table_mapping_t *t) { 670*0Sstevel@tonic-gate int i, mc = -1; 671*0Sstevel@tonic-gate char *myself = "printQuery"; 672*0Sstevel@tonic-gate char *val[NIS_MAXCOLUMNS]; 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate if (q == 0) 675*0Sstevel@tonic-gate return; 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate (void) memset(val, 0, sizeof (val)); 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate /* 680*0Sstevel@tonic-gate * Collect the values, which may be out of order in 'q'. 681*0Sstevel@tonic-gate * Remember the largest index. 682*0Sstevel@tonic-gate */ 683*0Sstevel@tonic-gate for (i = 0; i < q->components.components_len; i++) { 684*0Sstevel@tonic-gate int ix = q->components.components_val[i].which_index; 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate if (ix >= NIS_MAXCOLUMNS || 687*0Sstevel@tonic-gate (t != 0 && ix >= t->numColumns)) 688*0Sstevel@tonic-gate continue; 689*0Sstevel@tonic-gate if (ix > mc) 690*0Sstevel@tonic-gate mc = ix; 691*0Sstevel@tonic-gate val[ix] = q->components.components_val[i].index_value-> 692*0Sstevel@tonic-gate itemvalue.itemvalue_val; 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate /* Print the values we collected */ 696*0Sstevel@tonic-gate for (i = 0; i <= mc; i++) { 697*0Sstevel@tonic-gate p2buf(myself, "%s%s", (i != 0 ? " " : ""), 698*0Sstevel@tonic-gate (val[i] != 0 ? val[i] : "")); 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate /* If we printed anything, add a newline */ 701*0Sstevel@tonic-gate if (mc >= 0) 702*0Sstevel@tonic-gate p2buf(myself, "\n"); 703*0Sstevel@tonic-gate } 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate /* 706*0Sstevel@tonic-gate * Verify that the db_query's 'q' and 'fq' match, in the sense that if 707*0Sstevel@tonic-gate * they both have a value for a certain index, the values are the same. 708*0Sstevel@tonic-gate */ 709*0Sstevel@tonic-gate int 710*0Sstevel@tonic-gate verifyQueryMatch(db_query *q, db_query *fq) { 711*0Sstevel@tonic-gate int i, j, match; 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate if (fq == 0) 714*0Sstevel@tonic-gate return (1); 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate if (q == 0) 717*0Sstevel@tonic-gate return ((fq == 0) ? 1 : 0); 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate for (i = 0, match = 1; match && i < q->components.components_len; 720*0Sstevel@tonic-gate i++) { 721*0Sstevel@tonic-gate for (j = 0; j < fq->components.components_len; j++) { 722*0Sstevel@tonic-gate int len, flen; 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate /* Same index ? */ 725*0Sstevel@tonic-gate if (q->components.components_val[i].which_index != 726*0Sstevel@tonic-gate fq->components.components_val[j]. 727*0Sstevel@tonic-gate which_index) 728*0Sstevel@tonic-gate continue; 729*0Sstevel@tonic-gate /* 730*0Sstevel@tonic-gate * If one 'index_value' is NULL, the other one must 731*0Sstevel@tonic-gate * be NULL as well. 732*0Sstevel@tonic-gate */ 733*0Sstevel@tonic-gate if (q->components.components_val[i].index_value == 0) { 734*0Sstevel@tonic-gate if (fq->components.components_val[j]. 735*0Sstevel@tonic-gate index_value == 0) 736*0Sstevel@tonic-gate continue; 737*0Sstevel@tonic-gate else { 738*0Sstevel@tonic-gate match = 0; 739*0Sstevel@tonic-gate break; 740*0Sstevel@tonic-gate } 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate if (fq->components.components_val[j].index_value == 743*0Sstevel@tonic-gate 0) { 744*0Sstevel@tonic-gate match = 0; 745*0Sstevel@tonic-gate break; 746*0Sstevel@tonic-gate } 747*0Sstevel@tonic-gate /* Same value lengths ? */ 748*0Sstevel@tonic-gate len = q->components.components_val[i].index_value-> 749*0Sstevel@tonic-gate itemvalue.itemvalue_len; 750*0Sstevel@tonic-gate flen = fq->components.components_val[j].index_value-> 751*0Sstevel@tonic-gate itemvalue.itemvalue_len; 752*0Sstevel@tonic-gate if (len != flen) { 753*0Sstevel@tonic-gate /* 754*0Sstevel@tonic-gate * There's a twist here: the input query 755*0Sstevel@tonic-gate * may well _not_ count a concluding NUL 756*0Sstevel@tonic-gate * in a string value, while the output 757*0Sstevel@tonic-gate * usually will. So, if the difference in 758*0Sstevel@tonic-gate * length is one, and the "extra" byte is 759*0Sstevel@tonic-gate * a zero-valued one, we accept equality. 760*0Sstevel@tonic-gate * 'q' is assumed to be the output, and 761*0Sstevel@tonic-gate * 'fq' the input. 762*0Sstevel@tonic-gate */ 763*0Sstevel@tonic-gate if (!(len > 0 && len == (flen+1) && 764*0Sstevel@tonic-gate q->components.components_val[i]. 765*0Sstevel@tonic-gate index_value-> 766*0Sstevel@tonic-gate itemvalue.itemvalue_val[len-1] == 0)) { 767*0Sstevel@tonic-gate match = 0; 768*0Sstevel@tonic-gate break; 769*0Sstevel@tonic-gate } 770*0Sstevel@tonic-gate } 771*0Sstevel@tonic-gate /* Same value ? */ 772*0Sstevel@tonic-gate if (memcmp(q->components.components_val[i].index_value-> 773*0Sstevel@tonic-gate itemvalue.itemvalue_val, 774*0Sstevel@tonic-gate fq->components.components_val[j].index_value-> 775*0Sstevel@tonic-gate itemvalue.itemvalue_val, 776*0Sstevel@tonic-gate flen) != 0) { 777*0Sstevel@tonic-gate match = 0; 778*0Sstevel@tonic-gate break; 779*0Sstevel@tonic-gate } 780*0Sstevel@tonic-gate } 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate return (match); 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate /* 787*0Sstevel@tonic-gate * Remove those queries in 'q' that don't match t->index. 788*0Sstevel@tonic-gate * Returns a pointer to the filtered array, which could be 789*0Sstevel@tonic-gate * a compacted version of the original, or a new copy; in 790*0Sstevel@tonic-gate * the latter case, the original will have been freed. 791*0Sstevel@tonic-gate * 792*0Sstevel@tonic-gate * Filtered/removed db_query's are freed. 793*0Sstevel@tonic-gate */ 794*0Sstevel@tonic-gate db_query ** 795*0Sstevel@tonic-gate filterQuery(__nis_table_mapping_t *t, db_query **q, db_query *qin, 796*0Sstevel@tonic-gate __nis_obj_attr_t ***objAttr, int *numQueries) { 797*0Sstevel@tonic-gate db_query **new; 798*0Sstevel@tonic-gate __nis_obj_attr_t **attr; 799*0Sstevel@tonic-gate int i, nq, nn; 800*0Sstevel@tonic-gate char *myself = "filterQuery"; 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate if ((t == 0 && qin == 0) || q == 0 || 803*0Sstevel@tonic-gate numQueries == 0 || *numQueries <= 0) 804*0Sstevel@tonic-gate return (q); 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate nq = *numQueries; 807*0Sstevel@tonic-gate new = am(myself, nq * sizeof (new[0])); 808*0Sstevel@tonic-gate if (objAttr != 0) 809*0Sstevel@tonic-gate attr = am(myself, nq * sizeof (attr[0])); 810*0Sstevel@tonic-gate else 811*0Sstevel@tonic-gate attr = 0; 812*0Sstevel@tonic-gate if (new == 0 || (objAttr != 0 && attr == 0)) { 813*0Sstevel@tonic-gate sfree(new); 814*0Sstevel@tonic-gate freeQueries(q, nq); 815*0Sstevel@tonic-gate sfree(attr); 816*0Sstevel@tonic-gate if (objAttr != 0) { 817*0Sstevel@tonic-gate freeObjAttr(*objAttr, nq); 818*0Sstevel@tonic-gate *objAttr = 0; 819*0Sstevel@tonic-gate } 820*0Sstevel@tonic-gate *numQueries = -1; 821*0Sstevel@tonic-gate return (0); 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate for (i = 0, nn = 0; i < nq; i++) { 825*0Sstevel@tonic-gate int retain = 1; 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate if (t != 0) 828*0Sstevel@tonic-gate retain = verifyIndexMatch(t, q[i], 0, 0, 0); 829*0Sstevel@tonic-gate 830*0Sstevel@tonic-gate if (retain && qin != 0) 831*0Sstevel@tonic-gate retain = verifyQueryMatch(q[i], qin); 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate if (retain) { 834*0Sstevel@tonic-gate new[nn] = q[i]; 835*0Sstevel@tonic-gate if (objAttr != 0) 836*0Sstevel@tonic-gate attr[nn] = (*objAttr)[i]; 837*0Sstevel@tonic-gate nn++; 838*0Sstevel@tonic-gate } else { 839*0Sstevel@tonic-gate freeQuery(q[i]); 840*0Sstevel@tonic-gate q[i] = 0; 841*0Sstevel@tonic-gate if (objAttr != 0) { 842*0Sstevel@tonic-gate freeSingleObjAttr((*objAttr)[i]); 843*0Sstevel@tonic-gate (*objAttr)[i] = 0; 844*0Sstevel@tonic-gate } 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate } 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate /* All q[i]'s are either in 'new', or have been deleted */ 849*0Sstevel@tonic-gate free(q); 850*0Sstevel@tonic-gate if (objAttr != 0) { 851*0Sstevel@tonic-gate sfree(*objAttr); 852*0Sstevel@tonic-gate *objAttr = attr; 853*0Sstevel@tonic-gate } 854*0Sstevel@tonic-gate 855*0Sstevel@tonic-gate *numQueries = nn; 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate return (new); 858*0Sstevel@tonic-gate } 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate db_query ** 861*0Sstevel@tonic-gate createNisPlusEntry(__nis_table_mapping_t *t, __nis_rule_value_t *rv, 862*0Sstevel@tonic-gate db_query *qin, __nis_obj_attr_t ***objAttr, 863*0Sstevel@tonic-gate int *numQueries) { 864*0Sstevel@tonic-gate db_query **query = 0; 865*0Sstevel@tonic-gate int r, i, j, ir; 866*0Sstevel@tonic-gate __nis_value_t *rval, *lval; 867*0Sstevel@tonic-gate __nis_mapping_item_t *litem; 868*0Sstevel@tonic-gate int numItems; 869*0Sstevel@tonic-gate int nq, iqc; 870*0Sstevel@tonic-gate __nis_obj_attr_t **attr = 0; 871*0Sstevel@tonic-gate char **dn = 0; 872*0Sstevel@tonic-gate int numDN = 0; 873*0Sstevel@tonic-gate char *myself = "createNisPlusEntry"; 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate if (t == 0 || t->objectDN == 0 || rv == 0) 876*0Sstevel@tonic-gate return (0); 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate /* Establish default, per-thread, search base */ 879*0Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = t->objectDN->read.base; 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate for (r = 0, nq = 0; r < t->numRulesFromLDAP; r++) { 882*0Sstevel@tonic-gate int nrq, ntq, err; 883*0Sstevel@tonic-gate db_query **newq; 884*0Sstevel@tonic-gate __nis_obj_attr_t **newattr; 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate rval = buildRvalue(&t->ruleFromLDAP[r]->rhs, 887*0Sstevel@tonic-gate mit_ldap, rv, NULL); 888*0Sstevel@tonic-gate if (rval == 0) 889*0Sstevel@tonic-gate continue; 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate litem = buildLvalue(&t->ruleFromLDAP[r]->lhs, &rval, 892*0Sstevel@tonic-gate &numItems); 893*0Sstevel@tonic-gate if (litem == 0) { 894*0Sstevel@tonic-gate freeValue(rval, 1); 895*0Sstevel@tonic-gate /* XXX Should this be a fatal error ? */ 896*0Sstevel@tonic-gate continue; 897*0Sstevel@tonic-gate } 898*0Sstevel@tonic-gate 899*0Sstevel@tonic-gate lval = 0; 900*0Sstevel@tonic-gate for (i = 0; i < numItems; i++) { 901*0Sstevel@tonic-gate __nis_value_t *tmpval, *old; 902*0Sstevel@tonic-gate 903*0Sstevel@tonic-gate tmpval = getMappingItem(&litem[i], 904*0Sstevel@tonic-gate mit_nisplus, 0, 0, NULL); 905*0Sstevel@tonic-gate 906*0Sstevel@tonic-gate /* 907*0Sstevel@tonic-gate * If the LHS specifies an out-of-context LDAP or 908*0Sstevel@tonic-gate * NIS+ item, we do the update right here. We 909*0Sstevel@tonic-gate * don't add any values to 'lval'; instead, we 910*0Sstevel@tonic-gate * skip to the next item. (However, we still 911*0Sstevel@tonic-gate * get a string representation of the LHS in case 912*0Sstevel@tonic-gate * we need to report an error.) 913*0Sstevel@tonic-gate */ 914*0Sstevel@tonic-gate if (litem[i].type == mit_nisplus && 915*0Sstevel@tonic-gate litem[i].searchSpec.obj.index.numIndexes > 0) { 916*0Sstevel@tonic-gate int err; 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate err = storeNisPlus(&litem[i], i, numItems, 919*0Sstevel@tonic-gate rv, t->objName, rval); 920*0Sstevel@tonic-gate if (err != NIS_SUCCESS) { 921*0Sstevel@tonic-gate char *iname = "<unknown>"; 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate if (tmpval != 0 && 924*0Sstevel@tonic-gate tmpval->numVals == 1) 925*0Sstevel@tonic-gate iname = tmpval->val[0].value; 926*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 927*0Sstevel@tonic-gate "%s: NIS+ store \"%s\": %s", 928*0Sstevel@tonic-gate myself, iname, 929*0Sstevel@tonic-gate nis_sperrno(err)); 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate freeValue(tmpval, 1); 933*0Sstevel@tonic-gate continue; 934*0Sstevel@tonic-gate } else if (litem[i].type == mit_ldap) { 935*0Sstevel@tonic-gate int stat; 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate if (dn == 0) 938*0Sstevel@tonic-gate dn = findDNs(myself, rv, 1, 939*0Sstevel@tonic-gate t->objectDN->write.base, 940*0Sstevel@tonic-gate &numDN); 941*0Sstevel@tonic-gate 942*0Sstevel@tonic-gate stat = storeLDAP(&litem[i], i, numItems, rval, 943*0Sstevel@tonic-gate t->objectDN, dn, numDN); 944*0Sstevel@tonic-gate if (stat != LDAP_SUCCESS) { 945*0Sstevel@tonic-gate char *iname = "<unknown>"; 946*0Sstevel@tonic-gate 947*0Sstevel@tonic-gate if (tmpval != 0 && 948*0Sstevel@tonic-gate tmpval->numVals == 1) 949*0Sstevel@tonic-gate iname = tmpval->val[0].value; 950*0Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 951*0Sstevel@tonic-gate "%s: LDAP store \"%s\": %s", 952*0Sstevel@tonic-gate myself, iname, 953*0Sstevel@tonic-gate ldap_err2string(stat)); 954*0Sstevel@tonic-gate } 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate freeValue(tmpval, 1); 957*0Sstevel@tonic-gate continue; 958*0Sstevel@tonic-gate } 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate old = lval; 961*0Sstevel@tonic-gate lval = concatenateValues(old, tmpval); 962*0Sstevel@tonic-gate freeValue(tmpval, 1); 963*0Sstevel@tonic-gate freeValue(old, 1); 964*0Sstevel@tonic-gate } 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate freeMappingItem(litem, numItems); 967*0Sstevel@tonic-gate if (lval == 0 || lval->numVals <= 0 || rval->numVals <= 0) { 968*0Sstevel@tonic-gate freeValue(lval, 1); 969*0Sstevel@tonic-gate freeValue(rval, 1); 970*0Sstevel@tonic-gate continue; 971*0Sstevel@tonic-gate } 972*0Sstevel@tonic-gate 973*0Sstevel@tonic-gate /* 974*0Sstevel@tonic-gate * We now have a number of possible cases. The notation 975*0Sstevel@tonic-gate * used in the table is: 976*0Sstevel@tonic-gate * 977*0Sstevel@tonic-gate * single A single value (numVals == 1) 978*0Sstevel@tonic-gate * single/rep A single value with repeat == 1 979*0Sstevel@tonic-gate * multi[N] N values 980*0Sstevel@tonic-gate * multi[N]/rep M values with repeat == 1 981*0Sstevel@tonic-gate * (M) M resulting db_query's 982*0Sstevel@tonic-gate * 983*0Sstevel@tonic-gate * lval \ rval single single/rep multi[N] multi[N]/rep 984*0Sstevel@tonic-gate * single (1) (1) (1) (1) 985*0Sstevel@tonic-gate * single/rep (1) (1) (N) (N) 986*0Sstevel@tonic-gate * multi[M] (1) (1) (1) 1+(N-1)/M 987*0Sstevel@tonic-gate * multi[M]/rep (1) (1) (1) 1+(N-1)/M 988*0Sstevel@tonic-gate * 989*0Sstevel@tonic-gate * Of course, we already have 'nq' db_query's from previous 990*0Sstevel@tonic-gate * rules, so the resulting number of queries is max(1,nq) 991*0Sstevel@tonic-gate * times the numbers in the table above. 992*0Sstevel@tonic-gate */ 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate /* The number of queries resulting from the current rule */ 995*0Sstevel@tonic-gate if (rval->numVals > 1) { 996*0Sstevel@tonic-gate if (lval->numVals == 1 && lval->repeat) 997*0Sstevel@tonic-gate nrq = rval->numVals; 998*0Sstevel@tonic-gate else if (lval->numVals > 1 && rval->repeat) 999*0Sstevel@tonic-gate nrq = 1 + ((rval->numVals-1)/lval->numVals); 1000*0Sstevel@tonic-gate else 1001*0Sstevel@tonic-gate nrq = 1; 1002*0Sstevel@tonic-gate } else { 1003*0Sstevel@tonic-gate nrq = 1; 1004*0Sstevel@tonic-gate } 1005*0Sstevel@tonic-gate 1006*0Sstevel@tonic-gate /* Total number of queries after adding the current rule */ 1007*0Sstevel@tonic-gate if (nq <= 0) 1008*0Sstevel@tonic-gate ntq = nrq; 1009*0Sstevel@tonic-gate else 1010*0Sstevel@tonic-gate ntq = nq * nrq; 1011*0Sstevel@tonic-gate 1012*0Sstevel@tonic-gate if (ntq > nq) { 1013*0Sstevel@tonic-gate newq = realloc(query, ntq * sizeof (query[0])); 1014*0Sstevel@tonic-gate newattr = realloc(attr, ntq * sizeof (attr[0])); 1015*0Sstevel@tonic-gate if (newq == 0 || newattr == 0) { 1016*0Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, 1017*0Sstevel@tonic-gate "%s: realloc(%d) => NULL", 1018*0Sstevel@tonic-gate myself, ntq * sizeof (query[0])); 1019*0Sstevel@tonic-gate freeValue(lval, 1); 1020*0Sstevel@tonic-gate freeValue(rval, 1); 1021*0Sstevel@tonic-gate freeQueries(query, nq); 1022*0Sstevel@tonic-gate freeObjAttr(attr, nq); 1023*0Sstevel@tonic-gate sfree(newq); 1024*0Sstevel@tonic-gate freeDNs(dn, numDN); 1025*0Sstevel@tonic-gate return (0); 1026*0Sstevel@tonic-gate } 1027*0Sstevel@tonic-gate query = newq; 1028*0Sstevel@tonic-gate attr = newattr; 1029*0Sstevel@tonic-gate } 1030*0Sstevel@tonic-gate 1031*0Sstevel@tonic-gate /* 1032*0Sstevel@tonic-gate * Copy/clone the existing queries to the new array, 1033*0Sstevel@tonic-gate * remembering that realloc() has done the first 'nq' 1034*0Sstevel@tonic-gate * ones. 1035*0Sstevel@tonic-gate * 1036*0Sstevel@tonic-gate * If there's an error (probably memory allocation), we 1037*0Sstevel@tonic-gate * still go through the rest of the array, so that it's 1038*0Sstevel@tonic-gate * simple to free the elements when we clean up. 1039*0Sstevel@tonic-gate */ 1040*0Sstevel@tonic-gate for (i = 1, err = 0; i < nrq; i++) { 1041*0Sstevel@tonic-gate for (j = 0; j < nq; j++) { 1042*0Sstevel@tonic-gate query[(nq*i)+j] = cloneQuery(query[j], 1043*0Sstevel@tonic-gate t->numColumns); 1044*0Sstevel@tonic-gate if (query[(nq*i)+j] == 0 && 1045*0Sstevel@tonic-gate query[j] != 0) 1046*0Sstevel@tonic-gate err++; 1047*0Sstevel@tonic-gate attr[(nq*i)+j] = cloneObjAttr(attr[j]); 1048*0Sstevel@tonic-gate if (attr[(nq*i)+j] == 0 && 1049*0Sstevel@tonic-gate attr[j] != 0) 1050*0Sstevel@tonic-gate err++; 1051*0Sstevel@tonic-gate } 1052*0Sstevel@tonic-gate } 1053*0Sstevel@tonic-gate 1054*0Sstevel@tonic-gate if (err > 0) { 1055*0Sstevel@tonic-gate freeValue(lval, 1); 1056*0Sstevel@tonic-gate freeValue(rval, 1); 1057*0Sstevel@tonic-gate freeQueries(query, ntq); 1058*0Sstevel@tonic-gate freeObjAttr(attr, ntq); 1059*0Sstevel@tonic-gate freeDNs(dn, numDN); 1060*0Sstevel@tonic-gate return (0); 1061*0Sstevel@tonic-gate } 1062*0Sstevel@tonic-gate 1063*0Sstevel@tonic-gate /* 1064*0Sstevel@tonic-gate * Special case if nq == 0 (i.e., the first time we 1065*0Sstevel@tonic-gate * allocated db_query's). If so, we now allocate empty 1066*0Sstevel@tonic-gate * db_qcomp arrays, which simplifies subsequent 1067*0Sstevel@tonic-gate * copying of values. 1068*0Sstevel@tonic-gate */ 1069*0Sstevel@tonic-gate if (nq <= 0) { 1070*0Sstevel@tonic-gate (void) memset(query, 0, ntq * sizeof (query[0])); 1071*0Sstevel@tonic-gate (void) memset(attr, 0, ntq * sizeof (attr[0])); 1072*0Sstevel@tonic-gate for (i = 0, err = 0; i < ntq; i++) { 1073*0Sstevel@tonic-gate query[i] = am(myself, sizeof (*query[i])); 1074*0Sstevel@tonic-gate if (query[i] == 0) { 1075*0Sstevel@tonic-gate err++; 1076*0Sstevel@tonic-gate break; 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate query[i]->components.components_val = 1079*0Sstevel@tonic-gate am(myself, t->numColumns * 1080*0Sstevel@tonic-gate sizeof (query[i]->components.components_val[0])); 1081*0Sstevel@tonic-gate if (query[i]->components.components_val == 0) { 1082*0Sstevel@tonic-gate err++; 1083*0Sstevel@tonic-gate break; 1084*0Sstevel@tonic-gate } 1085*0Sstevel@tonic-gate query[i]->components.components_len = 0; 1086*0Sstevel@tonic-gate } 1087*0Sstevel@tonic-gate if (err > 0) { 1088*0Sstevel@tonic-gate freeValue(lval, 1); 1089*0Sstevel@tonic-gate freeValue(rval, 1); 1090*0Sstevel@tonic-gate freeQueries(query, ntq); 1091*0Sstevel@tonic-gate freeObjAttr(attr, ntq); 1092*0Sstevel@tonic-gate freeDNs(dn, numDN); 1093*0Sstevel@tonic-gate return (0); 1094*0Sstevel@tonic-gate } 1095*0Sstevel@tonic-gate } 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate /* Now we're ready to add the new values */ 1098*0Sstevel@tonic-gate for (i = 0, ir = 0; i < lval->numVals; i++) { 1099*0Sstevel@tonic-gate char *oaName = 0; 1100*0Sstevel@tonic-gate int index; 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate /* Find column index */ 1103*0Sstevel@tonic-gate for (index = 0; index < t->numColumns; 1104*0Sstevel@tonic-gate index++) { 1105*0Sstevel@tonic-gate if (strncmp(t->column[index], 1106*0Sstevel@tonic-gate lval->val[i].value, 1107*0Sstevel@tonic-gate lval->val[i].length) == 0) 1108*0Sstevel@tonic-gate break; 1109*0Sstevel@tonic-gate } 1110*0Sstevel@tonic-gate if (index >= t->numColumns) { 1111*0Sstevel@tonic-gate /* 1112*0Sstevel@tonic-gate * Could be one of the special object 1113*0Sstevel@tonic-gate * attributes. 1114*0Sstevel@tonic-gate */ 1115*0Sstevel@tonic-gate oaName = isObjAttr(&lval->val[i]); 1116*0Sstevel@tonic-gate if (oaName == 0) 1117*0Sstevel@tonic-gate continue; 1118*0Sstevel@tonic-gate } 1119*0Sstevel@tonic-gate 1120*0Sstevel@tonic-gate for (j = i*nrq; j < (i+1)*nrq; j++) { 1121*0Sstevel@tonic-gate int k; 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate /* If we're out of values, repeat last one */ 1124*0Sstevel@tonic-gate ir = (j < rval->numVals) ? 1125*0Sstevel@tonic-gate j : rval->numVals - 1; 1126*0Sstevel@tonic-gate 1127*0Sstevel@tonic-gate /* 1128*0Sstevel@tonic-gate * Step through the query array, adding 1129*0Sstevel@tonic-gate * the new value every 'nrq' queries, and 1130*0Sstevel@tonic-gate * starting at 'query[j % nrq]'. 1131*0Sstevel@tonic-gate */ 1132*0Sstevel@tonic-gate for (k = j % nrq, err = 0; k < ntq; k += nrq) { 1133*0Sstevel@tonic-gate int ic, c; 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate if (oaName != 0) { 1136*0Sstevel@tonic-gate int fail = setObjAttrField( 1137*0Sstevel@tonic-gate oaName, 1138*0Sstevel@tonic-gate &rval->val[ir], 1139*0Sstevel@tonic-gate &attr[k]); 1140*0Sstevel@tonic-gate if (fail) { 1141*0Sstevel@tonic-gate err++; 1142*0Sstevel@tonic-gate break; 1143*0Sstevel@tonic-gate } 1144*0Sstevel@tonic-gate continue; 1145*0Sstevel@tonic-gate } 1146*0Sstevel@tonic-gate 1147*0Sstevel@tonic-gate ic = query[k]->components. 1148*0Sstevel@tonic-gate components_len; 1149*0Sstevel@tonic-gate /* 1150*0Sstevel@tonic-gate * If we've already filled this 1151*0Sstevel@tonic-gate * query, the new value is a dup 1152*0Sstevel@tonic-gate * which we'll ignore. 1153*0Sstevel@tonic-gate */ 1154*0Sstevel@tonic-gate if (ic >= t->numColumns) 1155*0Sstevel@tonic-gate continue; 1156*0Sstevel@tonic-gate 1157*0Sstevel@tonic-gate /* 1158*0Sstevel@tonic-gate * Do we already have a value for 1159*0Sstevel@tonic-gate * this 'index' ? 1160*0Sstevel@tonic-gate */ 1161*0Sstevel@tonic-gate for (c = 0; c < ic; c++) { 1162*0Sstevel@tonic-gate if (query[k]->components. 1163*0Sstevel@tonic-gate components_val[c]. 1164*0Sstevel@tonic-gate which_index == index) 1165*0Sstevel@tonic-gate break; 1166*0Sstevel@tonic-gate } 1167*0Sstevel@tonic-gate 1168*0Sstevel@tonic-gate /* If no previous value, add it */ 1169*0Sstevel@tonic-gate if (c >= ic) { 1170*0Sstevel@tonic-gate int l; 1171*0Sstevel@tonic-gate char *v; 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate query[k]->components. 1174*0Sstevel@tonic-gate components_val[ic]. 1175*0Sstevel@tonic-gate which_index = index; 1176*0Sstevel@tonic-gate l = rval->val[ir].length; 1177*0Sstevel@tonic-gate v = rval->val[ir].value; 1178*0Sstevel@tonic-gate if (rval->type == vt_string && 1179*0Sstevel@tonic-gate l > 0 && 1180*0Sstevel@tonic-gate v[l-1] != '\0' && 1181*0Sstevel@tonic-gate v[l] == '\0') 1182*0Sstevel@tonic-gate l++; 1183*0Sstevel@tonic-gate query[k]->components. 1184*0Sstevel@tonic-gate components_val[ic]. 1185*0Sstevel@tonic-gate index_value = 1186*0Sstevel@tonic-gate buildItem(l, v); 1187*0Sstevel@tonic-gate if (query[k]-> 1188*0Sstevel@tonic-gate components. 1189*0Sstevel@tonic-gate components_val[ic]. 1190*0Sstevel@tonic-gate index_value == 0) { 1191*0Sstevel@tonic-gate err++; 1192*0Sstevel@tonic-gate break; 1193*0Sstevel@tonic-gate } 1194*0Sstevel@tonic-gate query[k]->components. 1195*0Sstevel@tonic-gate components_len++; 1196*0Sstevel@tonic-gate } 1197*0Sstevel@tonic-gate } 1198*0Sstevel@tonic-gate if (err > 0) { 1199*0Sstevel@tonic-gate freeValue(lval, 1); 1200*0Sstevel@tonic-gate freeValue(rval, 1); 1201*0Sstevel@tonic-gate freeQueries(query, ntq); 1202*0Sstevel@tonic-gate freeObjAttr(attr, ntq); 1203*0Sstevel@tonic-gate freeDNs(dn, numDN); 1204*0Sstevel@tonic-gate return (0); 1205*0Sstevel@tonic-gate } 1206*0Sstevel@tonic-gate } 1207*0Sstevel@tonic-gate } 1208*0Sstevel@tonic-gate freeValue(lval, 1); 1209*0Sstevel@tonic-gate freeValue(rval, 1); 1210*0Sstevel@tonic-gate 1211*0Sstevel@tonic-gate nq = ntq; 1212*0Sstevel@tonic-gate } 1213*0Sstevel@tonic-gate 1214*0Sstevel@tonic-gate freeDNs(dn, numDN); 1215*0Sstevel@tonic-gate 1216*0Sstevel@tonic-gate if (nq <= 0) { 1217*0Sstevel@tonic-gate sfree(query); 1218*0Sstevel@tonic-gate query = 0; 1219*0Sstevel@tonic-gate } 1220*0Sstevel@tonic-gate 1221*0Sstevel@tonic-gate /* Should we filter on index or input query ? */ 1222*0Sstevel@tonic-gate if (query != 0) { 1223*0Sstevel@tonic-gate if (t->index.numIndexes > 0) 1224*0Sstevel@tonic-gate query = filterQuery(t, query, qin, &attr, &nq); 1225*0Sstevel@tonic-gate else if (qin != 0) 1226*0Sstevel@tonic-gate query = filterQuery(0, query, qin, &attr, &nq); 1227*0Sstevel@tonic-gate } 1228*0Sstevel@tonic-gate 1229*0Sstevel@tonic-gate if (query != 0 && numQueries != 0) 1230*0Sstevel@tonic-gate *numQueries = nq; 1231*0Sstevel@tonic-gate 1232*0Sstevel@tonic-gate if (objAttr != 0) 1233*0Sstevel@tonic-gate *objAttr = attr; 1234*0Sstevel@tonic-gate else 1235*0Sstevel@tonic-gate freeObjAttr(attr, nq); 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate return (query); 1238*0Sstevel@tonic-gate } 1239*0Sstevel@tonic-gate /* 1240*0Sstevel@tonic-gate * Given a table mapping and a rule-value, convert to an array of 1241*0Sstevel@tonic-gate * (db_query *), using the fromLDAP ruleset. 1242*0Sstevel@tonic-gate * 1243*0Sstevel@tonic-gate * On entry, '*numQueries' holds the number of elements in the 'rv' 1244*0Sstevel@tonic-gate * array. On exit, it holds the number of (db_query *)'s in the return 1245*0Sstevel@tonic-gate * value array. 1246*0Sstevel@tonic-gate */ 1247*0Sstevel@tonic-gate db_query ** 1248*0Sstevel@tonic-gate ruleValue2Query(__nis_table_mapping_t *t, __nis_rule_value_t *rv, 1249*0Sstevel@tonic-gate db_query *qin, __nis_obj_attr_t ***objAttr, int *numQueries) { 1250*0Sstevel@tonic-gate db_query **q = 0, ***qp = 0; 1251*0Sstevel@tonic-gate int i, nqp, nq, *nnp = 0, nv; 1252*0Sstevel@tonic-gate __nis_obj_attr_t **attr = 0, ***atp = 0; 1253*0Sstevel@tonic-gate char *myself = "ruleValue2Query"; 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate 1256*0Sstevel@tonic-gate if (t == 0 || rv == 0 || numQueries == 0) 1257*0Sstevel@tonic-gate return (0); 1258*0Sstevel@tonic-gate 1259*0Sstevel@tonic-gate nv = *numQueries; 1260*0Sstevel@tonic-gate if (nv <= 0) 1261*0Sstevel@tonic-gate return (0); 1262*0Sstevel@tonic-gate 1263*0Sstevel@tonic-gate /* 1264*0Sstevel@tonic-gate * 'qp' is an array of (db_query **), and we get one element for 1265*0Sstevel@tonic-gate * each call to createNisPlusEntry(); i.e., one for each rule-value. 1266*0Sstevel@tonic-gate * 1267*0Sstevel@tonic-gate * 'nnp[i]' is the count of (db_query *) in each 'qp[i]'. 1268*0Sstevel@tonic-gate */ 1269*0Sstevel@tonic-gate qp = am(myself, nv * sizeof (*qp)); 1270*0Sstevel@tonic-gate nnp = am(myself, nv * sizeof (*nnp)); 1271*0Sstevel@tonic-gate atp = am(myself, nv * sizeof (*atp)); 1272*0Sstevel@tonic-gate if (qp == 0 || nnp == 0 || atp == 0) { 1273*0Sstevel@tonic-gate sfree(qp); 1274*0Sstevel@tonic-gate sfree(nnp); 1275*0Sstevel@tonic-gate sfree(atp); 1276*0Sstevel@tonic-gate return (0); 1277*0Sstevel@tonic-gate } 1278*0Sstevel@tonic-gate 1279*0Sstevel@tonic-gate for (i = 0, nq = 0, nqp = 0; i < nv; i++) { 1280*0Sstevel@tonic-gate qp[nqp] = createNisPlusEntry(t, &rv[i], qin, &atp[nqp], 1281*0Sstevel@tonic-gate &nnp[nqp]); 1282*0Sstevel@tonic-gate /* If we fail, abort (XXX??? or continue ???) */ 1283*0Sstevel@tonic-gate if (qp[nqp] == 0) 1284*0Sstevel@tonic-gate goto cleanup; 1285*0Sstevel@tonic-gate nq += nnp[nqp]; 1286*0Sstevel@tonic-gate nqp++; 1287*0Sstevel@tonic-gate } 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate /* If we didn't get any (db_query **)'s, return failure */ 1290*0Sstevel@tonic-gate if (nqp == 0 || nq <= 0) 1291*0Sstevel@tonic-gate goto cleanup; 1292*0Sstevel@tonic-gate 1293*0Sstevel@tonic-gate q = am(myself, nq * sizeof (q[0])); 1294*0Sstevel@tonic-gate attr = am(myself, nq * sizeof (attr[0])); 1295*0Sstevel@tonic-gate if (q == 0 || attr == 0) { 1296*0Sstevel@tonic-gate nq = 0; 1297*0Sstevel@tonic-gate goto cleanup; 1298*0Sstevel@tonic-gate } 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate /* Convert 'qp' to an array of (db_query *)'s */ 1301*0Sstevel@tonic-gate for (i = 0, nq = 0; i < nqp; i++) { 1302*0Sstevel@tonic-gate (void) memcpy(&q[nq], qp[i], nnp[i] * sizeof (qp[i][0])); 1303*0Sstevel@tonic-gate (void) memcpy(&attr[nq], atp[i], nnp[i] * sizeof (atp[i][0])); 1304*0Sstevel@tonic-gate nq += nnp[i]; 1305*0Sstevel@tonic-gate free(qp[i]); 1306*0Sstevel@tonic-gate free(atp[i]); 1307*0Sstevel@tonic-gate } 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate *numQueries = nq; 1310*0Sstevel@tonic-gate if (objAttr != 0) 1311*0Sstevel@tonic-gate *objAttr = attr; 1312*0Sstevel@tonic-gate else 1313*0Sstevel@tonic-gate freeObjAttr(attr, nq); 1314*0Sstevel@tonic-gate 1315*0Sstevel@tonic-gate /* Make sure 'cleanup' doesn't free the db_query pointers */ 1316*0Sstevel@tonic-gate nqp = 0; 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gate cleanup: 1319*0Sstevel@tonic-gate for (i = 0; i < nqp; i++) { 1320*0Sstevel@tonic-gate freeQueries(qp[i], nnp[i]); 1321*0Sstevel@tonic-gate sfree(atp[i]); 1322*0Sstevel@tonic-gate } 1323*0Sstevel@tonic-gate sfree(qp); 1324*0Sstevel@tonic-gate sfree(nnp); 1325*0Sstevel@tonic-gate sfree(atp); 1326*0Sstevel@tonic-gate 1327*0Sstevel@tonic-gate return (q); 1328*0Sstevel@tonic-gate } 1329*0Sstevel@tonic-gate 1330*0Sstevel@tonic-gate db_query * 1331*0Sstevel@tonic-gate pseudoEntryObj2Query(entry_obj *e, nis_object *tobj, __nis_rule_value_t *rv) { 1332*0Sstevel@tonic-gate db_query *qbuf; 1333*0Sstevel@tonic-gate db_qcomp *qcbuf; 1334*0Sstevel@tonic-gate int nc, i; 1335*0Sstevel@tonic-gate __nis_rule_value_t *rvt = 0; 1336*0Sstevel@tonic-gate char *myself = "pseudoEntryObj2Query"; 1337*0Sstevel@tonic-gate 1338*0Sstevel@tonic-gate nc = e->en_cols.en_cols_len - 1; 1339*0Sstevel@tonic-gate 1340*0Sstevel@tonic-gate if (e == 0 || nc < 0 || nc > NIS_MAXCOLUMNS) 1341*0Sstevel@tonic-gate return (0); 1342*0Sstevel@tonic-gate 1343*0Sstevel@tonic-gate /* 1344*0Sstevel@tonic-gate * If 'rvP' is non-NULL, build a rule value from the pseudo- 1345*0Sstevel@tonic-gate * nis_object in e->en_cols.en_cols_val[0]. 1346*0Sstevel@tonic-gate */ 1347*0Sstevel@tonic-gate if (rv != 0) { 1348*0Sstevel@tonic-gate nis_object *o; 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gate o = unmakePseudoEntryObj(e, tobj); 1351*0Sstevel@tonic-gate if (o == 0) 1352*0Sstevel@tonic-gate return (0); 1353*0Sstevel@tonic-gate rvt = addObjAttr2RuleValue(o, 0); 1354*0Sstevel@tonic-gate nis_destroy_object(o); 1355*0Sstevel@tonic-gate if (rvt == 0) 1356*0Sstevel@tonic-gate return (0); 1357*0Sstevel@tonic-gate } 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate qbuf = am(myself, sizeof (*qbuf)); 1360*0Sstevel@tonic-gate /* 1361*0Sstevel@tonic-gate * If there are no columns (other than the pseudo-entry object), 1362*0Sstevel@tonic-gate * we're done. 1363*0Sstevel@tonic-gate */ 1364*0Sstevel@tonic-gate if (nc == 0) 1365*0Sstevel@tonic-gate return (qbuf); 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate qcbuf = am(myself, nc * sizeof (*qcbuf)); 1368*0Sstevel@tonic-gate if (qcbuf == 0) { 1369*0Sstevel@tonic-gate sfree(qcbuf); 1370*0Sstevel@tonic-gate if (rvt != 0) 1371*0Sstevel@tonic-gate freeRuleValue(rvt, 1); 1372*0Sstevel@tonic-gate return (0); 1373*0Sstevel@tonic-gate } 1374*0Sstevel@tonic-gate 1375*0Sstevel@tonic-gate /* 1376*0Sstevel@tonic-gate * Build the db_query, remembering that e->en_cols.en_cols_val[0] 1377*0Sstevel@tonic-gate * is the pseudo-nis_object. 1378*0Sstevel@tonic-gate */ 1379*0Sstevel@tonic-gate qbuf->components.components_val = qcbuf; 1380*0Sstevel@tonic-gate qbuf->components.components_len = nc; 1381*0Sstevel@tonic-gate for (i = 0; i < nc; i++) { 1382*0Sstevel@tonic-gate qcbuf[i].which_index = i; 1383*0Sstevel@tonic-gate qcbuf[i].index_value = buildItem( 1384*0Sstevel@tonic-gate e->en_cols.en_cols_val[i+1].ec_value.ec_value_len, 1385*0Sstevel@tonic-gate e->en_cols.en_cols_val[i+1].ec_value.ec_value_val); 1386*0Sstevel@tonic-gate if (qcbuf[i].index_value == 0) { 1387*0Sstevel@tonic-gate freeQuery(qbuf); 1388*0Sstevel@tonic-gate if (rvt != 0) 1389*0Sstevel@tonic-gate freeRuleValue(rvt, 1); 1390*0Sstevel@tonic-gate return (0); 1391*0Sstevel@tonic-gate } 1392*0Sstevel@tonic-gate } 1393*0Sstevel@tonic-gate 1394*0Sstevel@tonic-gate if (rvt != 0) { 1395*0Sstevel@tonic-gate *rv = *rvt; 1396*0Sstevel@tonic-gate sfree(rvt); 1397*0Sstevel@tonic-gate } 1398*0Sstevel@tonic-gate 1399*0Sstevel@tonic-gate return (qbuf); 1400*0Sstevel@tonic-gate } 1401*0Sstevel@tonic-gate 1402*0Sstevel@tonic-gate /* 1403*0Sstevel@tonic-gate * Given an input query 'q', and a db_query work buffer 'qbuf', return 1404*0Sstevel@tonic-gate * a pointer to a query with one component corresponding to component 1405*0Sstevel@tonic-gate * 'index' in 'q'. 1406*0Sstevel@tonic-gate * 1407*0Sstevel@tonic-gate * Note that no memory is allocated, and that the returned query has 1408*0Sstevel@tonic-gate * pointers into 'q'. 1409*0Sstevel@tonic-gate */ 1410*0Sstevel@tonic-gate db_query * 1411*0Sstevel@tonic-gate queryFromComponent(db_query *q, int index, db_query *qbuf) { 1412*0Sstevel@tonic-gate 1413*0Sstevel@tonic-gate if (q == 0 || index < 0 || index >= q->components.components_len || 1414*0Sstevel@tonic-gate qbuf == 0) 1415*0Sstevel@tonic-gate return (0); 1416*0Sstevel@tonic-gate 1417*0Sstevel@tonic-gate qbuf->components.components_len = 1; 1418*0Sstevel@tonic-gate qbuf->components.components_val = &q->components.components_val[index]; 1419*0Sstevel@tonic-gate 1420*0Sstevel@tonic-gate return (qbuf); 1421*0Sstevel@tonic-gate } 1422