Print this page
5910 libnisdb won't build with modern GCC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libnisdb/ldap_map.c
+++ new/usr/src/lib/libnisdb/ldap_map.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 + * Copyright 2015 Gary Mills
22 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 24 * Use is subject to license terms.
24 25 */
25 26
26 27 #include <strings.h>
27 28 #include <sys/types.h>
28 29 #include <sys/stat.h>
29 30 #include <errno.h>
30 31 #include <stdio.h>
31 32 #include <rpcsvc/nis.h>
32 33 #include <rpc/xdr.h>
33 34
34 35 #include "ldap_util.h"
35 36 #include "ldap_attr.h"
36 37 #include "ldap_ruleval.h"
37 38 #include "ldap_op.h"
38 39 #include "ldap_map.h"
39 40 #include "ldap_glob.h"
40 41 #include "ldap_xdr.h"
41 42 #include "ldap_val.h"
42 43
43 44 /* From yptol/dit_access_utils.h */
44 45 #define N2LKEY "rf_key"
45 46 #define N2LIPKEY "rf_ipkey"
46 47
47 48 __nis_hash_table_mt ldapMappingList = NIS_HASH_TABLE_MT_INIT;
48 49 extern int yp2ldap;
49 50
50 51
51 52 int
52 53 setColumnNames(__nis_table_mapping_t *t) {
53 54 int i, j, nic, noc;
54 55 char **col;
55 56 zotypes type;
56 57 char *myself = "setColumnNames";
57 58
58 59 if (t == 0)
59 60 return (0);
60 61
61 62 type = t->objType;
62 63 col = t->column;
63 64 nic = (col != 0) ? t->numColumns : -1;
64 65
65 66 t->objType = NIS_BOGUS_OBJ;
66 67 t->obj = 0;
67 68
68 69 /*
69 70 * If it's a table object, but there are no translation rules,
70 71 * this mapping is for the table object itself. In that case,
71 72 * we throw away the column names (if any).
72 73 */
73 74 if (t->objType == NIS_TABLE_OBJ && t->numRulesFromLDAP == 0 &&
74 75 t->numRulesToLDAP == 0) {
75 76 for (i = 0; i < t->numColumns; i++)
76 77 sfree(t->column[i]);
77 78 sfree(t->column);
78 79 t->column = 0;
79 80 t->numColumns = 0;
80 81 noc = 0;
81 82 }
82 83
83 84 /*
84 85 * Verify that all column names found by the parser
85 86 * are present in the actual column list.
86 87 */
87 88 if (verbose) {
88 89 for (i = 0, noc = 0; i < nic; i++) {
89 90 int found = 0;
90 91
91 92 if (col[i] == 0)
92 93 continue;
93 94 /* Skip the 'zo_*' special column names */
94 95 if (isObjAttrString(col[i]))
95 96 continue;
96 97 for (j = 0; j < t->numColumns; j++) {
97 98 if (strcmp(col[i], t->column[j]) == 0) {
98 99 noc++;
99 100 found = 1;
100 101 break;
101 102 }
102 103 }
103 104 if (!found) {
104 105 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
105 106 "%s: No column \"%s\" in \"%s\"",
106 107 myself, NIL(col[i]), NIL(t->objName));
107 108 }
108 109 }
109 110 }
110 111
111 112 /* Remove any setup by the parser */
112 113 for (i = 0; i < nic; i++) {
113 114 sfree(col[i]);
114 115 }
115 116 sfree(col);
116 117
117 118 return (0);
118 119 }
119 120
120 121 void
121 122 freeSingleObjAttr(__nis_obj_attr_t *attr) {
122 123 if (attr == 0)
123 124 return;
124 125
125 126 sfree(attr->zo_owner);
126 127 sfree(attr->zo_group);
127 128 sfree(attr->zo_domain);
128 129 sfree(attr);
129 130 }
130 131
131 132 void
132 133 freeObjAttr(__nis_obj_attr_t **attr, int numAttr) {
133 134 int i;
134 135
135 136 if (attr == 0)
136 137 return;
137 138
138 139 for (i = 0; i < numAttr; i++) {
139 140 freeSingleObjAttr(attr[i]);
140 141 }
141 142
142 143 sfree(attr);
143 144 }
144 145
145 146 __nis_obj_attr_t *
146 147 cloneObjAttr(__nis_obj_attr_t *old) {
147 148 __nis_obj_attr_t *new;
148 149 char *myself = "cloneObjAttr";
149 150
150 151 if (old == 0)
151 152 return (0);
152 153
153 154 new = am(myself, sizeof (*new));
154 155 if (new == 0)
155 156 return (0);
156 157
157 158 new->zo_owner = sdup(myself, T, old->zo_owner);
158 159 if (new->zo_owner == 0 && old->zo_owner != 0)
159 160 goto cleanup;
160 161
161 162 new->zo_group = sdup(myself, T, old->zo_group);
162 163 if (new->zo_group == 0 && old->zo_group != 0)
163 164 goto cleanup;
164 165
165 166 new->zo_domain = sdup(myself, T, old->zo_domain);
166 167 if (new->zo_domain == 0 && old->zo_domain != 0)
167 168 goto cleanup;
168 169
169 170 new->zo_access = old->zo_access;
170 171 new->zo_ttl = old->zo_ttl;
171 172
172 173 return (new);
173 174
174 175 cleanup:
175 176 freeSingleObjAttr(new);
176 177
177 178 return (0);
178 179 }
179 180
180 181
181 182 /*
182 183 * Obtain NIS+ entries (in the form of db_query's) from the supplied table
183 184 * mapping and db_query.
184 185 *
185 186 * If 'qin' is NULL, enumeration is desired.
186 187 *
187 188 * On exit, '*numQueries' contains the number of (db_query *)'s in the
188 189 * return array, '*ldapStat' the LDAP operation status, and '*objAttr'
189 190 * a pointer to an array (of '*numQueries elements) of object attributes
190 191 * (zo_owner, etc.). If no object attributes were retrieved, '*objAttr'
191 192 * is NULL; any and all of the (*objAttr)[i]'s may be NULL.
192 193 */
193 194 db_query **
194 195 mapFromLDAP(__nis_table_mapping_t *t, db_query *qin, int *numQueries,
195 196 char *dbId, int *ldapStat, __nis_obj_attr_t ***objAttr) {
196 197 __nis_table_mapping_t **tp;
197 198 db_query **q;
198 199 __nis_rule_value_t *rv;
199 200 __nis_ldap_search_t *ls;
200 201 int n, numVals, numMatches = 0;
201 202 int stat;
202 203 __nis_obj_attr_t **attr;
203 204 char *myself = "mapFromLDAP";
204 205
205 206 if (ldapStat == 0)
206 207 ldapStat = &stat;
207 208
208 209 if (t == 0 || numQueries == 0) {
209 210 *ldapStat = LDAP_PARAM_ERROR;
210 211 return (0);
211 212 }
212 213
213 214 /* Select the correct table mapping(s) */
214 215 tp = selectTableMapping(t, qin, 0, 0, dbId, &numMatches);
215 216 if (tp == 0 || numMatches <= 0) {
216 217 /*
217 218 * Not really an error; just no matching mapping
218 219 * for the query.
219 220 */
220 221 *ldapStat = LDAP_SUCCESS;
221 222 return (0);
222 223 }
223 224
224 225 q = 0;
225 226 attr = 0;
226 227
227 228 /* For each mapping */
228 229 for (numVals = 0, n = 0; n < numMatches; n++) {
229 230 db_query **qt;
230 231 int i, nqt = 0, filterOnQin, res = 0;
231 232
232 233 t = tp[n];
233 234
234 235 if (qin != 0) {
235 236 rv = buildNisPlusRuleValue(t, qin, 0);
236 237 if (rv != 0) {
237 238 /*
238 239 * Depending on the value of res, we shall
239 240 * proceed to next table mapping.
240 241 */
241 242 ls = createLdapRequest(t, rv, 0, 1, &res, NULL);
242 243 }
243 244 else
244 245 ls = 0;
245 246 } else {
246 247 /* Build enumeration request */
247 248 rv = 0;
248 249 ls = createLdapRequest(t, 0, 0, 1, NULL, NULL);
249 250 }
250 251
251 252 freeRuleValue(rv, 1);
252 253
253 254 if (ls == 0) {
254 255 /*
255 256 * if the res is NP_LDAP_RULES_NO_VALUE, that means we
256 257 * have enough NIS+ columns for the rules to produce
257 258 * values, but none of them did, so continue to the
258 259 * next table mapping. Otherwise do cleanup and return
259 260 * error.
260 261 */
261 262 if (res == NP_LDAP_RULES_NO_VALUE)
262 263 continue;
263 264 for (i = 0; i < numVals; i++)
264 265 freeQuery(q[i]);
265 266 sfree(q);
266 267 free(tp);
267 268 *ldapStat = LDAP_OPERATIONS_ERROR;
268 269 return (0);
269 270 }
270 271
271 272 /* Query LDAP */
272 273 nqt = (ls->isDN || qin != 0) ? 0 : -1;
273 274 rv = ldapSearch(ls, &nqt, 0, ldapStat);
274 275
275 276 /*
276 277 * If qin != 0, then we need to make sure that the
277 278 * LDAP search is filtered so that only entries that
278 279 * are compatible with 'qin' are retained. This will
279 280 * happen automatically if we do a DN search (in which
280 281 * case, no need to filter on 'qin').
281 282 */
282 283 if (ls->isDN || qin == 0)
283 284 filterOnQin = 0;
284 285 else
285 286 filterOnQin = 1;
286 287
287 288 freeLdapSearch(ls);
288 289
289 290 /* Convert rule-values to db_query's */
290 291 if (rv != 0 && nqt > 0) {
291 292 int nrv = nqt;
292 293 __nis_obj_attr_t **at = 0;
293 294
294 295 qt = ruleValue2Query(t, rv,
295 296 (filterOnQin) ? qin : 0, &at, &nqt);
296 297 freeRuleValue(rv, nrv);
297 298
298 299 if (qt != 0 && q == 0) {
299 300 q = qt;
300 301 attr = at;
301 302 numVals = nqt;
302 303 } else if (qt != 0) {
303 304 db_query **tmp;
304 305 __nis_obj_attr_t **atmp;
305 306
306 307 /* Extend the 'q' array */
307 308 tmp = realloc(q,
308 309 (numVals+nqt) * sizeof (q[0]));
309 310 /* ... and the 'attr' array */
310 311 atmp = realloc(attr,
311 312 (numVals+nqt) * sizeof (attr[0]));
312 313 if (tmp == 0 || atmp == 0) {
313 314 logmsg(MSG_NOMEM, LOG_ERR,
314 315 "%s: realloc(%d) => NULL",
315 316 myself,
316 317 (numVals+nqt) * sizeof (q[0]));
317 318 for (i = 0; i < numVals; i++)
318 319 freeQuery(q[i]);
319 320 for (i = 0; i < nqt; i++)
320 321 freeQuery(qt[i]);
321 322 sfree(tmp);
322 323 sfree(atmp);
323 324 sfree(q);
324 325 sfree(qt);
325 326 sfree(tp);
326 327 freeObjAttr(at, nqt);
327 328 freeObjAttr(attr, numVals);
328 329 *ldapStat = LDAP_NO_MEMORY;
329 330 return (0);
330 331 }
331 332 q = tmp;
332 333 attr = atmp;
333 334 /* Add the results for this 't' */
334 335 (void) memcpy(&q[numVals], qt,
335 336 nqt * sizeof (qt[0]));
336 337 (void) memcpy(&attr[numVals], at,
337 338 nqt * sizeof (at[0]));
338 339 numVals += nqt;
339 340
340 341 sfree(qt);
341 342 sfree(at);
342 343 }
343 344 }
344 345 }
345 346
346 347 *numQueries = numVals;
347 348 if (objAttr != 0)
348 349 *objAttr = attr;
349 350 else
350 351 freeObjAttr(attr, numVals);
351 352 sfree(tp);
352 353
353 354 return (q);
354 355 }
355 356
356 357 /*
357 358 * Add the object attributes (zo_owner, etc.) to the rule-value 'rv'.
358 359 * Returns a pointer to the (possibly newly allocated) rule-value,
359 360 * or NULL in case of failure. If not returning 'rvIn', the latter
360 361 * will have been freed.
361 362 */
362 363 __nis_rule_value_t *
363 364 addObjAttr2RuleValue(nis_object *obj, __nis_rule_value_t *rvIn) {
364 365 __nis_rule_value_t *rv;
365 366 char abuf[2 * sizeof (obj->zo_access) + 1];
366 367 char tbuf[2 * sizeof (obj->zo_ttl) + 1];
367 368
368 369 if (obj == 0)
369 370 return (0);
370 371
371 372 if (rvIn != 0) {
372 373 rv = rvIn;
373 374 } else {
374 375 rv = initRuleValue(1, 0);
375 376 if (rv == 0)
376 377 return (0);
377 378 }
378 379
379 380 if (obj->zo_owner != 0) {
380 381 if (addSCol2RuleValue("zo_owner", obj->zo_owner, rv) != 0) {
381 382 freeRuleValue(rv, 1);
382 383 return (0);
383 384 }
384 385 }
385 386
386 387 if (obj->zo_group != 0) {
387 388 if (addSCol2RuleValue("zo_group", obj->zo_group, rv) != 0) {
388 389 freeRuleValue(rv, 1);
389 390 return (0);
390 391 }
391 392 }
392 393
393 394 if (obj->zo_domain != 0) {
394 395 if (addSCol2RuleValue("zo_domain", obj->zo_domain, rv) != 0) {
395 396 freeRuleValue(rv, 1);
396 397 return (0);
397 398 }
398 399 }
399 400
400 401 (void) memset(abuf, 0, sizeof (abuf));
401 402 (void) memset(tbuf, 0, sizeof (tbuf));
402 403
403 404 sprintf(abuf, "%x", obj->zo_access);
404 405 sprintf(tbuf, "%x", obj->zo_ttl);
405 406
406 407 if (addSCol2RuleValue("zo_access", abuf, rv) != 0) {
407 408 freeRuleValue(rv, 1);
408 409 return (0);
409 410 }
410 411 if (addSCol2RuleValue("zo_ttl", tbuf, rv) != 0) {
411 412 freeRuleValue(rv, 1);
412 413 return (0);
413 414 }
414 415
415 416 return (rv);
416 417 }
417 418
418 419 /*
419 420 * Returns a pointer to (NOT a copy of) the value for the specified
420 421 * column 'col' in the rule-value 'rv'.
421 422 */
422 423 __nis_value_t *
423 424 findColValue(char *col, __nis_rule_value_t *rv) {
424 425 int i;
425 426
426 427 if (col == 0 || rv == 0 || rv->numColumns <= 0)
427 428 return (0);
428 429
429 430 for (i = 0; i < rv->numColumns; i++) {
430 431 if (strcmp(col, rv->colName[i]) == 0)
431 432 return (&rv->colVal[i]);
432 433 }
433 434
434 435 return (0);
435 436 }
436 437
437 438 /*
438 439 * Return the NIS+ object attributes (if any) in the rule-value 'rv'.
439 440 */
440 441 __nis_obj_attr_t *
441 442 ruleValue2ObjAttr(__nis_rule_value_t *rv) {
442 443 __nis_obj_attr_t *attr;
443 444 __nis_value_t *val;
444 445 char *myself = "ruleValue2ObjAttr";
445 446
446 447 if (rv == 0 || rv->numColumns <= 0)
447 448 return (0);
448 449
449 450 attr = am(myself, sizeof (*attr));
450 451
451 452 if ((val = findColValue("zo_owner", rv)) != 0 &&
452 453 val->type == vt_string && val->numVals == 1 &&
453 454 val->val[0].value != 0) {
454 455 attr->zo_owner = sdup(myself, T, val->val[0].value);
455 456 if (attr->zo_owner == 0) {
456 457 freeSingleObjAttr(attr);
457 458 return (0);
458 459 }
459 460 }
460 461
461 462 if ((val = findColValue("zo_group", rv)) != 0 &&
462 463 val->type == vt_string && val->numVals == 1 &&
463 464 val->val[0].value != 0) {
464 465 attr->zo_group = sdup(myself, T, val->val[0].value);
465 466 if (attr->zo_group == 0) {
466 467 freeSingleObjAttr(attr);
467 468 return (0);
468 469 }
469 470 }
470 471
471 472 if ((val = findColValue("zo_domain", rv)) != 0 &&
472 473 val->type == vt_string && val->numVals == 1 &&
473 474 val->val[0].value != 0) {
474 475 attr->zo_domain = sdup(myself, T, val->val[0].value);
475 476 if (attr->zo_domain == 0) {
476 477 freeSingleObjAttr(attr);
477 478 return (0);
478 479 }
479 480 }
480 481
481 482 if ((val = findColValue("zo_access", rv)) != 0 &&
482 483 val->type == vt_string && val->numVals == 1 &&
483 484 val->val[0].value != 0) {
484 485 if (sscanf(val->val[0].value, "%x", &attr->zo_access) != 1) {
485 486 freeSingleObjAttr(attr);
486 487 return (0);
487 488 }
488 489 }
489 490
490 491 if ((val = findColValue("zo_ttl", rv)) != 0 &&
491 492 val->type == vt_string && val->numVals == 1 &&
492 493 val->val[0].value != 0) {
493 494 if (sscanf(val->val[0].value, "%x", &attr->zo_ttl) != 1) {
494 495 freeSingleObjAttr(attr);
495 496 return (0);
496 497 }
497 498 }
498 499
499 500 return (attr);
500 501 }
501 502
502 503 /*
503 504 * If the supplied string is one of the object attributes, return one.
504 505 * Otherwise, return zero.
505 506 */
506 507 int
507 508 isObjAttrString(char *str) {
508 509 if (str == 0)
509 510 return (0);
510 511
511 512 if (strcmp("zo_owner", str) == 0 ||
512 513 strcmp("zo_group", str) == 0 ||
513 514 strcmp("zo_domain", str) == 0 ||
514 515 strcmp("zo_access", str) == 0 ||
515 516 strcmp("zo_ttl", str) == 0)
516 517 return (1);
517 518 else
518 519 return (0);
519 520 }
520 521
521 522
522 523 /*
523 524 * If the supplied value is one of the object attribute strings, return
524 525 * a pointer to the string. Otherwise, return NULL.
525 526 */
526 527 char *
527 528 isObjAttr(__nis_single_value_t *val) {
528 529 if (val == 0 || val->length <= 0 || val->value == 0)
529 530 return (0);
530 531
531 532 if (isObjAttrString(val->value))
532 533 return (val->value);
533 534 else
534 535 return (0);
535 536 }
536 537
537 538 int
538 539 setObjAttrField(char *attrName, __nis_single_value_t *val,
539 540 __nis_obj_attr_t **objAttr) {
540 541 __nis_obj_attr_t *attr;
541 542 char *myself = "setObjAttrField";
542 543
543 544 if (attrName == 0 || val == 0 || objAttr == 0 ||
544 545 val->value == 0 || val->length <= 0)
545 546 return (-1);
546 547
547 548 if (*objAttr != 0) {
548 549 attr = *objAttr;
549 550 } else {
550 551 attr = am(myself, sizeof (*attr));
551 552 if (attr == 0)
552 553 return (-2);
553 554 *objAttr = attr;
554 555 }
555 556
556 557 if (strcmp("zo_owner", attrName) == 0) {
557 558 if (attr->zo_owner == 0) {
558 559 attr->zo_owner = sdup(myself, T, val->value);
559 560 if (attr->zo_owner == 0)
560 561 return (-11);
561 562 }
562 563 } else if (strcmp("zo_group", attrName) == 0) {
563 564 if (attr->zo_group == 0) {
564 565 attr->zo_group = sdup(myself, T, val->value);
565 566 if (attr->zo_group == 0)
566 567 return (-12);
567 568 }
568 569 } else if (strcmp("zo_domain", attrName) == 0) {
569 570 if (attr->zo_domain == 0) {
570 571 attr->zo_domain = sdup(myself, T, val->value);
571 572 if (attr->zo_domain == 0)
572 573 return (-13);
573 574 }
574 575 } else if (strcmp("zo_access", attrName) == 0) {
575 576 if (attr->zo_access == 0) {
576 577 if (sscanf(val->value, "%x", &attr->zo_access) != 1)
577 578 return (-14);
578 579 }
579 580 } else if (strcmp("zo_ttl", attrName) == 0) {
580 581 if (attr->zo_ttl == 0) {
581 582 if (sscanf(val->value, "%x", &attr->zo_ttl) != 1)
582 583 return (-15);
583 584 }
584 585 }
585 586
586 587 return (0);
587 588 }
588 589
589 590 /*
590 591 * Return a DN and rule-value for the supplied mapping, db_query's, and
591 592 * input rule-value. This function only works on a single mapping. See
592 593 * mapToLDAP() below for a description of the action depending on the
593 594 * values of 'old' and 'new'.
594 595 *
595 596 * If both 'old' and 'new' are supplied, and the modify would result
596 597 * in a change to the DN, '*oldDN' will contain the old DN. Otherwise
597 598 * (and normally), '*oldDN' will be NULL.
598 599 */
599 600 char *
600 601 map1qToLDAP(__nis_table_mapping_t *t, db_query *old, db_query *new,
601 602 __nis_rule_value_t *rvIn, __nis_rule_value_t **rvOutP,
602 603 char **oldDnP) {
603 604
604 605 __nis_rule_value_t *rv, *rvt;
605 606 __nis_ldap_search_t *ls;
606 607 char *dn = 0, *oldDn = 0;
607 608 __nis_table_mapping_t del;
608 609 char *myself = "map1qToLDAP";
609 610
610 611 if (t == 0 || (old == 0 && new == 0) || rvOutP == 0)
611 612 return (0);
612 613
613 614 /*
614 615 * If entry should be deleted, we look at the delete
615 616 * policy in the table mapping. Should it specify a
616 617 * rule set, we use that rule set to build a rule-
617 618 * value, and the delete actually becomes a modify
618 619 * operation.
619 620 */
620 621 if (old != 0 && new == 0) {
621 622 if (t->objectDN->delDisp == dd_perDbId) {
622 623 /*
623 624 * The functions that build a rule-value from a
624 625 * rule set expect a __nis_table_mapping_t, but the
625 626 * rule set in the __nis_object_dn_t isn't of that
626 627 * form. So, build a pseudo-__nis_table_mapping_t that
627 628 * borrows heavily from 't'.
628 629 */
629 630 del = *t;
630 631
631 632 del.numRulesToLDAP = del.objectDN->numDbIds;
632 633 del.ruleToLDAP = del.objectDN->dbId;
633 634
634 635 /*
635 636 * Do a modify with the pseudo-table
636 637 * mapping, and the 'old' db_query
637 638 * supplying input to the delete rule
638 639 * set.
639 640 */
640 641 t = &del;
641 642 new = old;
642 643 } else if (t->objectDN->delDisp == dd_always) {
643 644
644 645 /* Nothing to do here; all handled below */
645 646
646 647 } else if (t->objectDN->delDisp == dd_never) {
647 648
648 649 return (0);
649 650
650 651 } else {
651 652
652 653 logmsg(MSG_INVALIDDELDISP, LOG_WARNING,
653 654 "%s: Invalid delete disposition %d for \"%s\"",
654 655 myself, t->objectDN->delDisp,
655 656 NIL(t->dbId));
656 657 return (0);
657 658
658 659 }
659 660 }
660 661
661 662 /* Make a copy of the input rule-value */
662 663 if (rvIn != 0) {
663 664 rv = initRuleValue(1, rvIn);
664 665 if (rv == 0)
665 666 return (0);
666 667 } else {
667 668 rv = 0;
668 669 }
669 670
670 671 /* First get a rule-value from the supplied NIS+ entry. */
671 672 rvt = rv;
672 673 rv = buildNisPlusRuleValue(t, ((old != 0) ? old : new), rvt);
673 674 freeRuleValue(rvt, 1);
674 675 if (rv == 0) {
675 676 logmsg(MSG_NORULEVALUE, LOG_WARNING,
676 677 "%s: No in-query rule-value derived for \"%s\"",
677 678 myself, NIL(t->dbId));
678 679 return (0);
679 680 }
680 681
681 682 /*
682 683 * Create a request (really only care about the DN) from the
683 684 * supplied NIS+ entry data.
684 685 */
685 686 ls = createLdapRequest(t, rv, &dn, 0, NULL, NULL);
686 687 if (ls == 0 || dn == 0) {
687 688 logmsg(MSG_NOTIMECHECK, LOG_ERR,
688 689 "%s: Unable to create LDAP request for %s: %s",
689 690 myself, NIL(t->dbId),
690 691 (dn != 0) ? dn : rvId(rv, mit_nisplus));
691 692 sfree(dn);
692 693 freeLdapSearch(ls);
693 694 freeRuleValue(rv, 1);
694 695 return (0);
695 696 }
696 697
697 698 freeLdapSearch(ls);
698 699
699 700 if (new != 0) {
700 701 /*
701 702 * Create a rule-value from the new NIS+ entry.
702 703 * Don't want to mix in the rule-value derived
703 704 * from 'old', so delete it. However, we still
704 705 * want the owner, group, etc., from 'rvIn'.
705 706 */
706 707 if (old != 0) {
707 708 freeRuleValue(rv, 1);
708 709 if (rvIn != 0) {
709 710 rv = initRuleValue(1, rvIn);
710 711 if (rv == 0) {
711 712 sfree(dn);
712 713 return (0);
713 714 }
714 715 } else {
715 716 rv = 0;
716 717 }
717 718 }
718 719 rvt = rv;
719 720 rv = buildNisPlusRuleValue(t, new, rvt);
720 721 freeRuleValue(rvt, 1);
721 722 if (rv == 0) {
722 723 logmsg(MSG_NORULEVALUE, LOG_WARNING,
723 724 "%s: No new rule-value derived for \"%s: %s\"",
724 725 myself, NIL(t->dbId), dn);
725 726 sfree(dn);
726 727 return (0);
727 728 }
728 729 /*
729 730 * Check if the proposed modification would result in a
730 731 * a change to the DN.
731 732 */
732 733 if (old != 0) {
733 734 oldDn = dn;
734 735 dn = 0;
735 736 ls = createLdapRequest(t, rv, &dn, 0, NULL, NULL);
736 737 if (ls == 0 || dn == 0) {
737 738 logmsg(MSG_NOTIMECHECK, LOG_ERR,
738 739 "%s: Unable to create new DN for \"%s: %s\"",
739 740 myself, NIL(t->dbId), oldDn);
740 741 sfree(oldDn);
741 742 freeLdapSearch(ls);
742 743 freeRuleValue(rv, 1);
743 744 return (0);
744 745 }
745 746 freeLdapSearch(ls);
746 747 if (strcasecmp(oldDn, dn) == 0) {
747 748 sfree(oldDn);
748 749 oldDn = 0;
749 750 }
750 751 }
751 752 }
752 753
753 754
754 755 *rvOutP = rv;
755 756 if (oldDnP != 0)
756 757 *oldDnP = oldDn;
757 758
758 759 return (dn);
759 760 }
760 761
761 762 /*
762 763 * Since the DN hash list is an automatic variable, there's no need for
763 764 * locking, and we remove the locking overhead by using the libnsl
764 765 * hash functions.
765 766 */
766 767 #undef NIS_HASH_ITEM
767 768 #undef NIS_HASH_TABLE
768 769
769 770 typedef struct {
770 771 NIS_HASH_ITEM item;
771 772 int index;
772 773 char *oldDn;
773 774 } __dn_item_t;
774 775
775 776 /*
776 777 * Update LDAP per the supplied table mapping and db_query's.
777 778 *
778 779 * 'nq' is the number of elements in the 'old', 'new', and 'rvIn'
779 780 * arrays. mapToLDAP() generally performs one update for each
780 781 * element; however, if one or more of the individual queries
781 782 * produce the same DN, they're merged into a single update.
782 783 *
783 784 * There are four cases, depending on the values of 'old[iq]' and
784 785 * 'new[iq]':
785 786 *
786 787 * (1) old[iq] == 0 && new[iq] == 0
787 788 * No action; skip to next query
788 789 *
789 790 * (2) old[iq] == 0 && new[iq] != 0
790 791 * Attempt to use the 'new' db_query to get a DN, and try to create
791 792 * the corresponding LDAP entry.
792 793 *
793 794 * (3) old[iq] != 0 && new[iq] == 0
794 795 * Use the 'old' db_query to get a DN, and try to delete the LDAP
795 796 * entry per the table mapping.
796 797 *
797 798 * (4) old[iq] != 0 && new[iq] != 0
798 799 * Use the 'old' db_query to get a DN, and update (possibly create)
799 800 * the corresponding LDAP entry per the 'new' db_query.
800 801 *
801 802 * If 'rvIn' is non-NULL, it is expected to contain the object attributes
802 803 * (zo_owner, etc.) to be written to LDAP. 'rvIn' is an array with 'nq'
803 804 * elements.
804 805 *
805 806 * If 'firstOnly' is set, only the first old[iq]/new[iq] pair is used
806 807 * to perform the actual update. Any additional queries specified will
807 808 * have their values folded in, but are not used to derive update targets.
808 809 * This mode is inteded to support the case where multiple NIS+ entries
809 810 * map to one and the same LDAP entry. Note that 'rvIn' must still be
810 811 * an array of 'nq' elements, though if 'firstOnly' is set, it should be
811 812 * OK to leave all but 'rvIn[0]' empty.
812 813 *
813 814 * 'dbId' is used to further narow down the selection of mapping candidates
814 815 * to those matching the 'dbId' value.
815 816 */
816 817 int
817 818 mapToLDAP(__nis_table_mapping_t *tm, int nq, db_query **old, db_query **new,
818 819 __nis_rule_value_t *rvIn, int firstOnly, char *dbId) {
819 820 __nis_table_mapping_t **tp, **tpa;
820 821 int i, n, rnq, iq, r, ret = LDAP_SUCCESS;
821 822 int maxMatches, numMatches = 0;
822 823 __nis_ldap_search_t *ls;
823 824 char **dn = 0, **odn = 0;
824 825 __nis_rule_value_t **rv;
825 826 __dn_item_t *dni;
826 827 char *myself = "mapToLDAP";
827 828
828 829
829 830 if (tm == 0 || (old == 0 && new == 0) || nq <= 0)
830 831 return (LDAP_PARAM_ERROR);
831 832
832 833 /* Determine maximum number of table mapping matches */
833 834 if (nq == 1) {
834 835 tp = selectTableMapping(tm,
835 836 (old != 0 && old[0] != 0) ? old[0] : new[0], 1, 0,
836 837 dbId, &maxMatches);
837 838 numMatches = maxMatches;
838 839 } else {
839 840 tp = selectTableMapping(tm, 0, 1, 0, dbId, &maxMatches);
840 841 }
841 842
842 843 /*
843 844 * If no matching mapping, we're not mapping to LDAP in this
844 845 * particular case.
845 846 */
846 847 if (tp == 0 || maxMatches == 0) {
847 848 sfree(tp);
848 849 return (LDAP_SUCCESS);
849 850 }
850 851
851 852 /*
852 853 * Allocate the 'rv', 'dn', and 'tpa' arrays. Worst case is that
853 854 * we need nq * maxMatches elements in each array. However, if
854 855 * 'firstOnly' is set, we only need one element per matching
855 856 * mapping in each.
856 857 */
857 858 dn = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (dn[0]));
858 859 odn = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (odn[0]));
859 860 rv = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (rv[0]));
860 861 tpa = am(myself, (firstOnly ? 1 : nq) * maxMatches * sizeof (tpa[0]));
861 862 if (dn == 0 || odn == 0 || rv == 0 || tpa == 0) {
862 863 sfree(tp);
863 864 sfree(dn);
864 865 sfree(odn);
865 866 sfree(rv);
866 867 sfree(tpa);
867 868 return (LDAP_NO_MEMORY);
868 869 }
869 870
870 871 /* Unless nq == 1, we don't need the 'tp' value */
871 872 if (nq != 1)
872 873 sfree(tp);
873 874
874 875 logmsg(MSG_NOTIMECHECK,
875 876 #ifdef NISDB_LDAP_DEBUG
876 877 LOG_WARNING,
877 878 #else
878 879 LOG_INFO,
879 880 #endif /* NISDB_LDAP_DEBUG */
880 881 "%s: %s: %d * %d potential updates",
881 882 myself, NIL(tm->objName), nq, maxMatches);
882 883
883 884 /*
884 885 * Create DNs, column and attribute values, and merge duplicate DNs.
885 886 */
886 887 for (iq = 0, rnq = 0; iq < nq; iq++) {
887 888 int idx;
888 889
889 890 if ((old == 0 || old[iq] == 0) &&
890 891 (new == 0 || new[iq] == 0))
891 892 continue;
892 893
893 894 /*
894 895 * Select matching table mappings; if nq == 1, we've already
895 896 * got the 'tp' array from above. We expect this to be the
896 897 * most common case, so it's worth special treatment.
897 898 */
898 899 if (nq != 1)
899 900 tp = selectTableMapping(tm,
900 901 (old != 0 && old[iq] != 0) ? old[iq] : new[iq], 1, 0,
901 902 dbId, &numMatches);
902 903 if (tp == 0)
903 904 continue;
904 905 else if (numMatches <= 0) {
905 906 sfree(tp);
906 907 continue;
907 908 }
908 909
909 910 idx = iq * maxMatches;
910 911
911 912 if (idx == 0 || !firstOnly)
912 913 (void) memcpy(&tpa[idx], tp,
913 914 numMatches * sizeof (tpa[idx]));
914 915
915 916 for (n = 0; n < numMatches; n++) {
916 917 char *dnt, *odnt;
917 918 __nis_rule_value_t *rvt = 0;
918 919
919 920 if (tp[n] == 0)
920 921 continue;
921 922
922 923 dnt = map1qToLDAP(tp[n],
923 924 (old != 0) ? old[iq] : 0,
924 925 (new != 0) ? new[iq] : 0,
925 926 (rvIn != 0) ? &rvIn[iq] : 0,
926 927 &rvt, &odnt);
927 928
928 929 if (dnt == 0)
929 930 continue;
930 931 if (rvt == 0) {
931 932 #ifdef NISDB_LDAP_DEBUG
932 933 abort();
933 934 #else
934 935 sfree(dnt);
935 936 sfree(odnt);
936 937 continue;
937 938 #endif /* NISDB_LDAP_DEBUG */
938 939 }
939 940
940 941 /*
941 942 * Create a request to get a rule-value with
942 943 * NIS+ data translated to LDAP equivalents.
943 944 */
944 945 ls = createLdapRequest(tp[n], rvt, 0, 0, NULL, NULL);
945 946 if (ls == 0) {
946 947 if (ret == LDAP_SUCCESS)
947 948 ret = LDAP_OPERATIONS_ERROR;
948 949 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
949 950 "%s: Unable to map to LDAP attrs for %s:dn=%s",
950 951 myself, NIL(tp[n]->dbId), dnt);
951 952 sfree(dnt);
952 953 freeRuleValue(rvt, 1);
953 954 continue;
954 955 }
955 956 freeLdapSearch(ls);
956 957
957 958 /*
958 959 * If the DN is the same as one we already know
959 960 * about, merge the rule-values.
960 961 */
961 962
962 963 if ((iq == 0 || !firstOnly) && dnt != 0) {
963 964 dni = am(myself, sizeof (*dni));
964 965 if (dni != 0) {
965 966 dni->item.name = dnt;
966 967 dni->index = idx + n;
967 968 dni->oldDn = odnt;
968 969 } else {
969 970 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
970 971 "%s: Skipping update for dn=\"%s\"",
971 972 myself, dnt);
972 973 sfree(dnt);
973 974 dnt = 0;
974 975 }
975 976 if (dnt != 0) {
976 977 dn[idx+n] = dnt;
977 978 odn[idx+n] = odnt;
978 979 rv[idx+n] = rvt;
979 980 rnq++;
980 981 } else {
981 982 freeRuleValue(rvt, 1);
982 983 rvt = 0;
983 984 }
984 985 } else if (dnt != 0) {
985 986 sfree(dnt);
986 987 sfree(odnt);
987 988 freeRuleValue(rvt, 1);
988 989 }
989 990 }
990 991 sfree(tp);
991 992 }
992 993
993 994 logmsg(MSG_NOTIMECHECK,
994 995 #ifdef NISDB_LDAP_DEBUG
995 996 LOG_WARNING,
996 997 #else
997 998 LOG_INFO,
998 999 #endif /* NISDB_LDAP_DEBUG */
999 1000 "%s: %s: %d update%s requested",
1000 1001 myself, NIL(tm->objName), rnq, rnq != 1 ? "s" : "");
1001 1002
1002 1003 /* Perform the updates */
1003 1004 for (i = rnq = 0; i < (firstOnly ? maxMatches : nq*maxMatches); i++) {
1004 1005 int delPerDbId;
1005 1006
1006 1007 if (dn[i] == 0)
1007 1008 continue;
1008 1009
1009 1010 #ifdef NISDB_LDAP_DEBUG
1010 1011 logmsg(MSG_NOTIMECHECK, LOG_INFO,
1011 1012 "%s: %s %s:dn=%s",
1012 1013 myself,
1013 1014 (new != 0 && new[i/maxMatches] != 0) ?
1014 1015 "modify" : "delete",
1015 1016 NIL(tpa[i]->dbId), dn[i]);
1016 1017 #endif /* NISDB_LDAP_DEBUG */
1017 1018
1018 1019 delPerDbId = (tpa[i]->objectDN->delDisp == dd_perDbId);
1019 1020 if ((new != 0 && new[i/maxMatches] != 0) || delPerDbId) {
1020 1021 /*
1021 1022 * Try to modify/create the specified DN. First,
1022 1023 * however, if the update changes the DN, make
1023 1024 * that change.
1024 1025 */
1025 1026 if (odn[i] == 0 || (r = ldapChangeDN(odn[i], dn[i])) ==
1026 1027 LDAP_SUCCESS) {
1027 1028 int addFirst;
1028 1029
1029 1030 addFirst = (new != 0 &&
1030 1031 new[i/maxMatches] != 0 &&
1031 1032 !delPerDbId);
1032 1033 r = ldapModify(dn[i], rv[i],
1033 1034 tpa[i]->objectDN->write.attrs,
1034 1035 addFirst);
1035 1036 }
1036 1037 } else {
1037 1038 /* Try to delete the specified DN */
1038 1039 r = ldapModify(dn[i], 0,
1039 1040 tpa[i]->objectDN->write.attrs, 0);
1040 1041 }
1041 1042
1042 1043 if (r == LDAP_SUCCESS) {
1043 1044 rnq++;
1044 1045 } else {
1045 1046 if (ret == LDAP_SUCCESS)
1046 1047 ret = r;
1047 1048 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1048 1049 "%s: LDAP %s request error %d for %s:dn=%s",
1049 1050 myself,
1050 1051 (new != 0 && new[i/maxMatches] != 0) ?
1051 1052 "modify" : "delete",
1052 1053 r, NIL(tpa[i]->dbId), dn[i]);
1053 1054 }
1054 1055
1055 1056 sfree(dn[i]);
1056 1057 dn[i] = 0;
1057 1058 freeRuleValue(rv[i], 1);
1058 1059 rv[i] = 0;
1059 1060 }
1060 1061
1061 1062 sfree(dn);
1062 1063 sfree(odn);
1063 1064 sfree(rv);
1064 1065 sfree(tpa);
1065 1066
1066 1067 logmsg(MSG_NOTIMECHECK,
1067 1068 #ifdef NISDB_LDAP_DEBUG
1068 1069 LOG_WARNING,
1069 1070 #else
1070 1071 LOG_INFO,
1071 1072 #endif /* NISDB_LDAP_DEBUG */
1072 1073 "%s: %s: %d update%s performed",
1073 1074 myself, NIL(tm->objName), rnq, rnq != 1 ? "s" : "");
1074 1075
1075 1076 return (ret);
1076 1077 }
1077 1078
1078 1079 /*
1079 1080 * In nis+2ldap, check if the query 'q' matches the selector index 'x->index'.
1080 1081 *
1081 1082 * In nis2ldap, if 'name' is provided then check if its value in 'val'
1082 1083 * matches the selector index. If 'name' is NULL, then check if rule-value 'rv'
1083 1084 * matches the index.
1084 1085 * To match the selector index, all fieldspecs in the indexlist should match
1085 1086 * (AND). In nis2ldap, an exception is, if there are multiple fieldspecs with
1086 1087 * the same fieldname then only one of them needs to match (OR).
1087 1088 * Example:
1088 1089 * Indexlist = [host="H*", host="I*", user="U*", domain="D*"]
1089 1090 * Then,
1090 1091 * host = "H1", user="U1", domain="D1" ==> pass
1091 1092 * host = "I1", user="U1", domain="D1" ==> pass
1092 1093 * host = "X1", user="U1", domain="D1" ==> fail
1093 1094 * host = "H1", user="X1", domain="D1" ==> fail
1094 1095 * host = "H1", user="U1" ==> fail
1095 1096 *
1096 1097 * Return 1 in case of a match, 0 otherwise.
1097 1098 */
1098 1099 int
1099 1100 verifyIndexMatch(__nis_table_mapping_t *x, db_query *q,
1100 1101 __nis_rule_value_t *rv, char *name, char *val) {
1101 1102 int i, j, k, match = 1;
1102 1103 char *myself = "verifyIndexMatch";
1103 1104
1104 1105 /*
1105 1106 * The pass and fail arrays are used by N2L to keep track of
1106 1107 * index matches. This saves us from having matches in a
1107 1108 * nested loop to decide OR or AND.
1108 1109 */
1109 1110 int ppos, fpos;
1110 1111 char **pass, **fail;
1111 1112
1112 1113 if (x == 0)
1113 1114 return (0);
1114 1115
1115 1116 /* Trivial match */
1116 1117 if (x->index.numIndexes <= 0 || (!yp2ldap && q == 0))
1117 1118 return (1);
1118 1119
1119 1120 if (yp2ldap) {
1120 1121 if (!(pass = am(myself, x->index.numIndexes * sizeof (char *))))
1121 1122 return (0);
1122 1123 if (!(fail = am(myself,
1123 1124 x->index.numIndexes * sizeof (char *)))) {
1124 1125 sfree(pass);
1125 1126 return (0);
1126 1127 }
1127 1128 ppos = fpos = 0;
1128 1129 }
1129 1130
1130 1131 /* Check each index */
1131 1132 for (i = 0; i < x->index.numIndexes; i++) {
1132 1133 int len = 0;
1133 1134 char *value = 0;
1134 1135
1135 1136 /* Skip NULL index names */
1136 1137 if (x->index.name[i] == 0)
1137 1138 continue;
1138 1139
1139 1140 /* Check N2L values */
1140 1141 if (yp2ldap) {
1141 1142 if (name) {
1142 1143 if (strcasecmp(x->index.name[i], name) == 0)
1143 1144 value = val;
1144 1145 else
1145 1146 continue;
1146 1147 } else if (rv) {
1147 1148 if (strcasecmp(x->index.name[i], N2LKEY) == 0 ||
1148 1149 strcasecmp(x->index.name[i], N2LIPKEY)
1149 1150 == 0)
1150 1151 continue;
1151 1152 value = findVal(x->index.name[i], rv,
1152 1153 mit_nisplus);
1153 1154 }
1154 1155
1155 1156 if (value && verifyMappingMatch(x->index.value[i],
1156 1157 value))
1157 1158 pass[ppos++] = x->index.name[i];
1158 1159 else
1159 1160 fail[fpos++] = x->index.name[i];
1160 1161 continue;
1161 1162 }
1162 1163
1163 1164 /* If here, means nis+2ldap */
1164 1165
1165 1166 /* Is the index name a known column ? */
1166 1167 for (j = 0; j < x->numColumns; j++) {
1167 1168 if (strcmp(x->index.name[i], x->column[j]) == 0) {
1168 1169 /*
1169 1170 * Do we have a value for the column ?
1170 1171 */
1171 1172 for (k = 0; k < q->components.components_len;
1172 1173 k++) {
1173 1174 if (q->components.components_val[k].
1174 1175 which_index == j) {
1175 1176 value = q->components.
1176 1177 components_val[k].
1177 1178 index_value->
1178 1179 itemvalue.
1179 1180 itemvalue_val;
1180 1181 len = q->components.
1181 1182 components_val[k].
1182 1183 index_value->
1183 1184 itemvalue.
1184 1185 itemvalue_len;
1185 1186 break;
1186 1187 }
1187 1188 }
1188 1189 if (value != 0)
1189 1190 break;
1190 1191 }
1191 1192 }
1192 1193
1193 1194 /*
1194 1195 * If we found a value, check if it matches the
1195 1196 * format. If no value found or no match, this
1196 1197 * mapping is _not_ an alternative. Otherwise,
1197 1198 * we continue checking any other indexes.
1198 1199 */
1199 1200 if (value == 0 ||
1200 1201 !verifyMappingMatch(x->index.value[i],
1201 1202 value)) {
1202 1203 match = 0;
1203 1204 break;
1204 1205 }
1205 1206 }
1206 1207
1207 1208 if (yp2ldap) {
1208 1209 for (--fpos; fpos >= 0; fpos--) {
1209 1210 for (i = 0; i < ppos; i++) {
1210 1211 if (strcmp(pass[i], fail[fpos]) == 0)
1211 1212 break;
1212 1213 }
1213 1214 if (i == ppos) {
1214 1215 match = 0;
1215 1216 break;
1216 1217 }
1217 1218 }
1218 1219 sfree(pass);
1219 1220 sfree(fail);
1220 1221 }
1221 1222
1222 1223 return (match);
1223 1224 }
1224 1225
1225 1226 /*
1226 1227 * Return all table mappings that match the column values in 'q'.
1227 1228 * If there's no match, return those alternative mappings that don't
1228 1229 * have an index; if no such mapping exists, return NULL.
1229 1230 *
1230 1231 * If 'wantWrite' is set, we want mappings for writing (i.e., data
1231 1232 * to LDAP); otherwise, we want mappings for reading.
1232 1233 *
↓ open down ↓ |
1201 lines elided |
↑ open up ↑ |
1233 1234 * If 'wantObj' is set, we want object mappings only (i.e., _not_
1234 1235 * those used to map entries in tables).
1235 1236 *
1236 1237 * If 'dbId' is non-NULL, we select mappings with a matching dbId field.
1237 1238 */
1238 1239 __nis_table_mapping_t **
1239 1240 selectTableMapping(__nis_table_mapping_t *t, db_query *q,
1240 1241 int wantWrite, int wantObj, char *dbId,
1241 1242 int *numMatches) {
1242 1243 __nis_table_mapping_t *r, *x, **tp;
1243 - int i, j, k, nm, numap;
1244 + int i, nm, numap;
1244 1245 char *myself = "selectTableMapping";
1245 1246
1246 1247 if (numMatches == 0)
1247 1248 numMatches = &nm;
1248 1249
1249 1250 /*
1250 1251 * Count the number of possible mappings, so that we can
1251 1252 * allocate the 'tp' array up front.
1252 1253 */
1253 1254 for (numap = 0, x = t; x != 0; numap++, x = x->next);
1254 1255
1255 1256 if (numap == 0) {
1256 1257 *numMatches = 0;
1257 1258 return (0);
1258 1259 }
1259 1260
1260 1261 tp = am(myself, numap * sizeof (tp[0]));
1261 1262 if (tp == 0) {
1262 1263 *numMatches = -1;
1263 1264 return (0);
1264 1265 }
1265 1266
1266 1267 /*
1267 1268 * Special cases:
1268 1269 *
1269 1270 * q == 0 trivially matches any 't' of the correct object type
1270 1271 *
1271 1272 * wantObj != 0 means we ignore 'q'
1272 1273 */
1273 1274 if (q == 0 || wantObj) {
1274 1275 for (i = 0, x = t, nm = 0; i < numap; i++, x = x->next) {
1275 1276 if (x->objectDN == 0)
1276 1277 continue;
1277 1278 if (wantWrite) {
1278 1279 if (x->objectDN->write.scope ==
1279 1280 LDAP_SCOPE_UNKNOWN)
1280 1281 continue;
1281 1282 } else {
1282 1283 if (x->objectDN->read.scope ==
1283 1284 LDAP_SCOPE_UNKNOWN)
1284 1285 continue;
1285 1286 }
1286 1287 if (wantObj) {
1287 1288 if (x->numColumns > 0)
1288 1289 continue;
1289 1290 } else {
1290 1291 if (x->numColumns <= 0)
1291 1292 continue;
1292 1293 }
1293 1294 if (dbId != 0 && x->dbId != 0 &&
1294 1295 strcmp(dbId, x->dbId) != 0)
1295 1296 continue;
1296 1297 tp[nm] = x;
1297 1298 nm++;
1298 1299 }
1299 1300 *numMatches = nm;
1300 1301 if (nm == 0) {
1301 1302 sfree(tp);
1302 1303 tp = 0;
1303 1304 }
1304 1305 return (tp);
1305 1306 }
1306 1307
1307 1308 /* Scan all mappings, and collect candidates */
1308 1309 for (nm = 0, r = 0, x = t; x != 0; x = x->next) {
1309 1310 if (x->objectDN == 0)
1310 1311 continue;
1311 1312 if (wantWrite) {
1312 1313 if (x->objectDN->write.scope == LDAP_SCOPE_UNKNOWN)
1313 1314 continue;
1314 1315 } else {
1315 1316 if (x->objectDN->read.scope == LDAP_SCOPE_UNKNOWN)
1316 1317 continue;
1317 1318 }
1318 1319 /* Only want table/entry mappings */
1319 1320 if (x->numColumns <= 0)
1320 1321 continue;
1321 1322 if (dbId != 0 && x->dbId != 0 &&
1322 1323 strcmp(dbId, x->dbId) != 0)
1323 1324 continue;
1324 1325 /*
1325 1326 * It's a match if: there are no indexes, or we actually
1326 1327 * match the query with the indexes.
1327 1328 */
1328 1329 if (x->index.numIndexes <= 0 ||
1329 1330 verifyIndexMatch(x, q, 0, 0, 0)) {
1330 1331 tp[nm] = x;
1331 1332 nm++;
1332 1333 }
1333 1334 }
1334 1335
1335 1336 if (nm == 0) {
1336 1337 free(tp);
1337 1338 tp = 0;
1338 1339 }
1339 1340
1340 1341 *numMatches = nm;
1341 1342
1342 1343 return (tp);
1343 1344 }
1344 1345
1345 1346 /*
1346 1347 * Return 1 if there's an indexed mapping, 0 otherwise.
1347 1348 */
1348 1349 int
1349 1350 haveIndexedMapping(__nis_table_mapping_t *t) {
1350 1351 __nis_table_mapping_t *x;
1351 1352
1352 1353 for (x = t; x != 0; x = x->next) {
1353 1354 if (x->index.numIndexes > 0)
1354 1355 return (1);
1355 1356 }
1356 1357
1357 1358 return (0);
1358 1359 }
1359 1360
1360 1361 /*
1361 1362 * Given an input string 'attrs' of the form "attr1=val1,attr2=val2,...",
1362 1363 * or a filter, return the value associated with the attribute 'attrName'.
1363 1364 * If no instance of 'attrName' is found, return 'default'. In all cases,
1364 1365 * the return value is a copy, and must be freed by the caller.
1365 1366 *
1366 1367 * Of course, return NULL in case of failure.
1367 1368 */
1368 1369 static char *
1369 1370 attrVal(char *msg, char *attrName, char *def, char *attrs) {
1370 1371 char *val, *filter, **fc = 0;
1371 1372 int i, nfc;
1372 1373 char *myself = "attrVal";
1373 1374
1374 1375 if (attrName == 0 || attrs == 0)
1375 1376 return (0);
1376 1377
1377 1378 if (msg == 0)
1378 1379 msg = myself;
1379 1380
1380 1381 val = def;
1381 1382
1382 1383 filter = makeFilter(attrs);
1383 1384 if (filter != 0 && (fc = makeFilterComp(filter, &nfc)) != 0 &&
1384 1385 nfc > 0) {
1385 1386 for (i = 0; i < nfc; i++) {
1386 1387 char *name, *value;
1387 1388
1388 1389 name = fc[i];
1389 1390 /* Skip if not of attr=value form */
1390 1391 if ((value = strchr(name, '=')) == 0)
1391 1392 continue;
1392 1393
1393 1394 *value = '\0';
1394 1395 value++;
1395 1396
1396 1397 if (strcasecmp(attrName, name) == 0) {
1397 1398 val = value;
1398 1399 break;
1399 1400 }
1400 1401 }
1401 1402 }
1402 1403
1403 1404 if (val != 0)
1404 1405 val = sdup(msg, T, val);
1405 1406
1406 1407 sfree(filter);
1407 1408 freeFilterComp(fc, nfc);
1408 1409
1409 1410 return (val);
1410 1411 }
1411 1412
↓ open down ↓ |
158 lines elided |
↑ open up ↑ |
1412 1413 extern bool_t xdr_nis_object(register XDR *xdrs, nis_object *objp);
1413 1414
1414 1415 /*
1415 1416 * Copy an XDR:ed version of the NIS+ object 'o' (or the one indicated
1416 1417 * by 't->objName' if 'o' is NULL) to the place indicated by
1417 1418 * 't->objectDN->write'. Return an appropriate LDAP status code.
1418 1419 */
1419 1420 int
1420 1421 objToLDAP(__nis_table_mapping_t *t, nis_object *o, entry_obj **ea, int numEa) {
1421 1422 __nis_table_mapping_t **tp;
1422 - XDR xdr;
1423 - char *objName;
1424 1423 int stat, osize, n, numMatches = 0;
1425 1424 void *buf;
1426 1425 __nis_rule_value_t *rv;
1427 1426 __nis_value_t *val;
1428 1427 __nis_single_value_t *sv;
1429 1428 char **attrName, *dn;
1430 1429 char *myself = "objToLDAP";
1431 1430
1432 1431 if (t == 0)
1433 1432 return (LDAP_PARAM_ERROR);
1434 1433
1435 1434 logmsg(MSG_NOTIMECHECK,
1436 1435 #ifdef NISDB_LDAP_DEBUG
1437 1436 LOG_WARNING,
1438 1437 #else
1439 1438 LOG_INFO,
1440 1439 #endif /* NISDB_LDAP_DEBUG */
1441 1440 "%s: %s", myself, NIL(t->objName));
1442 1441
1443 1442 tp = selectTableMapping(t, 0, 1, 1, 0, &numMatches);
1444 1443 if (tp == 0 || numMatches <= 0) {
1445 1444 sfree(tp);
1446 1445 logmsg(MSG_NOTIMECHECK,
1447 1446 #ifdef NISDB_LDAP_DEBUG
1448 1447 LOG_WARNING,
1449 1448 #else
1450 1449 LOG_INFO,
1451 1450 #endif /* NISDB_LDAP_DEBUG */
1452 1451 "%s: %s (no mapping)", myself, NIL(t->objName));
1453 1452 return (LDAP_SUCCESS);
1454 1453 }
1455 1454
1456 1455 for (n = 0; n < numMatches; n++) {
1457 1456
1458 1457 t = tp[n];
1459 1458
1460 1459 if (o == 0) {
1461 1460 sfree(tp);
1462 1461 return (LDAP_OPERATIONS_ERROR);
1463 1462 }
1464 1463
1465 1464 buf = (char *)xdrNisObject(o, ea, numEa, &osize);
1466 1465 if (buf == 0) {
1467 1466 sfree(tp);
1468 1467 return (LDAP_OPERATIONS_ERROR);
1469 1468 }
1470 1469
1471 1470 /*
1472 1471 * Prepare to build a rule-value containing the XDR:ed
1473 1472 * object
1474 1473 */
1475 1474 rv = am(myself, sizeof (*rv));
1476 1475 sv = am(myself, sizeof (*sv));
1477 1476 val = am(myself, sizeof (*val));
1478 1477 attrName = am(myself, sizeof (attrName[0]));
1479 1478 if (attrName != 0)
1480 1479 attrName[0] = attrVal(myself, "nisplusObject",
1481 1480 "nisplusObject",
1482 1481 t->objectDN->write.attrs);
1483 1482 if (rv == 0 || sv == 0 || val == 0 || attrName == 0 ||
1484 1483 attrName[0] == 0) {
1485 1484 sfree(tp);
1486 1485 sfree(buf);
1487 1486 sfree(rv);
1488 1487 sfree(sv);
1489 1488 sfree(val);
1490 1489 sfree(attrName);
1491 1490 return (LDAP_NO_MEMORY);
1492 1491 }
1493 1492
1494 1493 sv->length = osize;
1495 1494 sv->value = buf;
1496 1495
1497 1496 /* 'vt_ber' just means "not a NUL-terminated string" */
1498 1497 val->type = vt_ber;
1499 1498 val->repeat = 0;
1500 1499 val->numVals = 1;
1501 1500 val->val = sv;
1502 1501
1503 1502 rv->numAttrs = 1;
1504 1503 rv->attrName = attrName;
1505 1504 rv->attrVal = val;
1506 1505
1507 1506 /*
1508 1507 * The 'write.base' is the actual DN of the entry (and the
1509 1508 * scope had better be 'base', but we don't check that).
1510 1509 */
1511 1510 dn = t->objectDN->write.base;
1512 1511
1513 1512 stat = ldapModify(dn, rv, t->objectDN->write.attrs, 1);
1514 1513
1515 1514 freeRuleValue(rv, 1);
1516 1515
1517 1516 logmsg(MSG_NOTIMECHECK,
1518 1517 #ifdef NISDB_LDAP_DEBUG
1519 1518 LOG_WARNING,
1520 1519 #else
1521 1520 LOG_INFO,
1522 1521 #endif /* NISDB_LDAP_DEBUG */
1523 1522 "%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
1524 1523
1525 1524 if (stat != LDAP_SUCCESS)
1526 1525 break;
1527 1526
1528 1527 }
1529 1528
1530 1529 sfree(tp);
1531 1530
1532 1531 return (stat);
1533 1532 }
1534 1533
1535 1534 /*
1536 1535 * Retrieve a copy of the 't->objName' object from LDAP, where it's
1537 1536 * stored in XDR:ed form in the place indicated by 't->objectDN->read'.
↓ open down ↓ |
104 lines elided |
↑ open up ↑ |
1538 1537 * Un-XDR the object, and return a pointer to it in '*obj'; it's the
1539 1538 * responsibility of the caller to free the object when it's no
1540 1539 * longer needed.
1541 1540 *
1542 1541 * Returns an appropriate LDAP status.
1543 1542 */
1544 1543 int
1545 1544 objFromLDAP(__nis_table_mapping_t *t, nis_object **obj,
1546 1545 entry_obj ***eaP, int *numEaP) {
1547 1546 __nis_table_mapping_t **tp;
1548 - XDR xdr;
1549 1547 nis_object *o;
1550 1548 __nis_rule_value_t *rv;
1551 1549 __nis_ldap_search_t *ls;
1552 1550 char *attrs[2], *filter, **fc = 0;
1553 1551 void *buf;
1554 1552 int i, j, nfc, nrv, blen, stat = LDAP_SUCCESS;
1555 1553 int n, numMatches;
1556 1554 char *myself = "objFromLDAP";
1557 1555
1558 1556 if (t == 0)
1559 1557 return (LDAP_PARAM_ERROR);
1560 1558
1561 1559 /*
1562 1560 * If there's nowhere to store the result, we might as
1563 1561 * well pretend all went well, and return right away.
1564 1562 */
1565 1563 if (obj == 0)
1566 1564 return (LDAP_SUCCESS);
1567 1565
1568 1566 /* Prepare for the worst */
1569 1567 *obj = 0;
1570 1568
1571 1569 logmsg(MSG_NOTIMECHECK,
1572 1570 #ifdef NISDB_LDAP_DEBUG
1573 1571 LOG_WARNING,
1574 1572 #else
1575 1573 LOG_INFO,
1576 1574 #endif /* NISDB_LDAP_DEBUG */
1577 1575 "%s: %s", myself, NIL(t->objName));
1578 1576
1579 1577 tp = selectTableMapping(t, 0, 0, 1, 0, &numMatches);
1580 1578 if (tp == 0 || numMatches <= 0) {
1581 1579 sfree(tp);
1582 1580 logmsg(MSG_NOTIMECHECK,
1583 1581 #ifdef NISDB_LDAP_DEBUG
1584 1582 LOG_WARNING,
1585 1583 #else
1586 1584 LOG_INFO,
1587 1585 #endif /* NISDB_LDAP_DEBUG */
1588 1586 "%s: %s (no mapping)", myself, NIL(t->objName));
1589 1587 return (LDAP_SUCCESS);
1590 1588 }
1591 1589
1592 1590 for (n = 0; n < numMatches; n++) {
1593 1591
1594 1592 t = tp[n];
1595 1593
1596 1594 filter = makeFilter(t->objectDN->read.attrs);
1597 1595 if (filter == 0 || (fc = makeFilterComp(filter, &nfc)) == 0 ||
1598 1596 nfc <= 0) {
1599 1597 sfree(tp);
1600 1598 sfree(filter);
1601 1599 freeFilterComp(fc, nfc);
1602 1600 return ((t->objectDN->read.attrs != 0) ?
1603 1601 LDAP_NO_MEMORY : LDAP_PARAM_ERROR);
1604 1602 }
1605 1603 /* Don't need the filter, just the components */
1606 1604 sfree(filter);
1607 1605
1608 1606 /*
1609 1607 * Look for a "nisplusObject" attribute, and (if found) copy
1610 1608 * the value to attrs[0]. Also remove the "nisplusObject"
1611 1609 * attribute and value from the filter components.
1612 1610 */
1613 1611 attrs[0] = sdup(myself, T, "nisplusObject");
1614 1612 if (attrs[0] == 0) {
1615 1613 sfree(tp);
1616 1614 freeFilterComp(fc, nfc);
1617 1615 return (LDAP_NO_MEMORY);
1618 1616 }
1619 1617 attrs[1] = 0;
1620 1618 for (i = 0; i < nfc; i++) {
1621 1619 char *name, *value;
1622 1620 int compare;
1623 1621
1624 1622 name = fc[i];
1625 1623 /* Skip if not of attr=value form */
1626 1624 if ((value = strchr(name, '=')) == 0)
1627 1625 continue;
1628 1626
1629 1627 /* Temporarily overWrite the '=' with a '\0' */
1630 1628 *value = '\0';
1631 1629
1632 1630 /* Compare with our target attribute name */
1633 1631 compare = strcasecmp("nisplusObject", name);
1634 1632
1635 1633 /* Put back the '=' */
1636 1634 *value = '=';
1637 1635
1638 1636 /* Is it the name we're looking for ? */
1639 1637 if (compare == 0) {
1640 1638 sfree(attrs[0]);
1641 1639 attrs[0] = sdup(myself, T, value+1);
1642 1640 if (attrs[0] == 0) {
1643 1641 sfree(tp);
1644 1642 freeFilterComp(fc, nfc);
1645 1643 return (LDAP_NO_MEMORY);
1646 1644 }
1647 1645 sfree(fc[i]);
1648 1646 if (i < nfc-1)
1649 1647 (void) memmove(&fc[i], &fc[i+1],
1650 1648 (nfc-1-i) * sizeof (fc[i]));
1651 1649 nfc--;
1652 1650 break;
1653 1651 }
1654 1652 }
1655 1653
1656 1654 ls = buildLdapSearch(t->objectDN->read.base,
1657 1655 t->objectDN->read.scope,
1658 1656 nfc, fc, 0, attrs, 0, 1);
1659 1657 sfree(attrs[0]);
1660 1658 freeFilterComp(fc, nfc);
1661 1659 if (ls == 0) {
1662 1660 sfree(tp);
1663 1661 return (LDAP_OPERATIONS_ERROR);
1664 1662 }
1665 1663
1666 1664 nrv = 0;
1667 1665 rv = ldapSearch(ls, &nrv, 0, &stat);
1668 1666 if (rv == 0) {
1669 1667 sfree(tp);
1670 1668 freeLdapSearch(ls);
1671 1669 return (stat);
1672 1670 }
1673 1671
1674 1672 for (i = 0, buf = 0; i < nrv && buf == 0; i++) {
1675 1673 for (j = 0; j < rv[i].numAttrs; j++) {
1676 1674 if (strcasecmp(ls->attrs[0],
1677 1675 rv[i].attrName[j]) == 0) {
1678 1676 if (rv[i].attrVal[j].numVals <= 0)
1679 1677 continue;
1680 1678 buf = rv[i].attrVal[j].val[0].value;
1681 1679 blen = rv[i].attrVal[j].val[0].length;
1682 1680 break;
1683 1681 }
1684 1682 }
1685 1683 }
1686 1684
1687 1685 if (buf != 0) {
1688 1686 o = unXdrNisObject(buf, blen, eaP, numEaP);
1689 1687 if (o == 0) {
1690 1688 sfree(tp);
1691 1689 freeLdapSearch(ls);
1692 1690 freeRuleValue(rv, nrv);
1693 1691 return (LDAP_OPERATIONS_ERROR);
1694 1692 }
1695 1693 stat = LDAP_SUCCESS;
1696 1694 *obj = o;
1697 1695 } else {
1698 1696 stat = LDAP_NO_SUCH_OBJECT;
1699 1697 }
1700 1698
1701 1699 freeLdapSearch(ls);
1702 1700 freeRuleValue(rv, nrv);
1703 1701
1704 1702 logmsg(MSG_NOTIMECHECK,
1705 1703 #ifdef NISDB_LDAP_DEBUG
1706 1704 LOG_WARNING,
1707 1705 #else
1708 1706 LOG_INFO,
1709 1707 #endif /* NISDB_LDAP_DEBUG */
1710 1708 "%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
1711 1709
1712 1710 if (stat != LDAP_SUCCESS)
1713 1711 break;
1714 1712
1715 1713 }
1716 1714
1717 1715 sfree(tp);
1718 1716
1719 1717 return (stat);
1720 1718 }
1721 1719
1722 1720 int
1723 1721 deleteLDAPobj(__nis_table_mapping_t *t) {
1724 1722 __nis_table_mapping_t **tp;
1725 1723 int n, stat, numMatches = 0;
1726 1724 char *myself = "deleteLDAPobj";
1727 1725
1728 1726 if (t == 0)
1729 1727 return (LDAP_PARAM_ERROR);
1730 1728
1731 1729 logmsg(MSG_NOTIMECHECK,
1732 1730 #ifdef NISDB_LDAP_DEBUG
1733 1731 LOG_WARNING,
1734 1732 #else
1735 1733 LOG_INFO,
1736 1734 #endif /* NISDB_LDAP_DEBUG */
1737 1735 "%s: %s", myself, NIL(t->objName));
1738 1736
1739 1737 tp = selectTableMapping(t, 0, 1, 1, 0, &numMatches);
1740 1738 if (tp == 0 || numMatches <= 0) {
1741 1739 sfree(tp);
1742 1740 logmsg(MSG_NOTIMECHECK,
1743 1741 #ifdef NISDB_LDAP_DEBUG
1744 1742 LOG_WARNING,
1745 1743 #else
1746 1744 LOG_INFO,
1747 1745 #endif /* NISDB_LDAP_DEBUG */
1748 1746 "%s: %s (no mapping)", myself, NIL(t->objName));
1749 1747 return (LDAP_SUCCESS);
1750 1748 }
1751 1749
1752 1750 for (n = 0; n < numMatches; n++) {
1753 1751
1754 1752 t = tp[n];
1755 1753
1756 1754 if (t->objectDN->delDisp == dd_always) {
1757 1755 /* Delete entire entry */
1758 1756 stat = ldapModify(t->objectDN->write.base, 0,
1759 1757 t->objectDN->write.attrs, 1);
1760 1758 } else if (t->objectDN->delDisp == dd_perDbId) {
1761 1759 /*
1762 1760 * Delete the attribute holding the object.
1763 1761 * First, determine what that attribute is called.
1764 1762 */
1765 1763 char *attrName =
1766 1764 attrVal(myself,
1767 1765 "nisplusObject",
1768 1766 "nisplusObject",
1769 1767 t->objectDN->write.attrs);
1770 1768 __nis_rule_value_t rv;
1771 1769 __nis_value_t val;
1772 1770
1773 1771 if (attrName == 0) {
1774 1772 sfree(tp);
1775 1773 return (LDAP_NO_MEMORY);
1776 1774 }
1777 1775
1778 1776 /*
1779 1777 * Build a __nis_value_t with 'numVals' < 0 to
1780 1778 * indicate deletion.
1781 1779 */
1782 1780 val.type = vt_ber;
1783 1781 val.numVals = -1;
1784 1782 val.val = 0;
1785 1783
1786 1784 /*
1787 1785 * Build a rule-value with the name we determined
1788 1786 * above, and the deletion value.
1789 1787 */
1790 1788 (void) memset(&rv, 0, sizeof (rv));
1791 1789 rv.numAttrs = 1;
1792 1790 rv.attrName = &attrName;
1793 1791 rv.attrVal = &val;
1794 1792
1795 1793 stat = ldapModify(t->objectDN->write.base, &rv,
1796 1794 t->objectDN->write.attrs, 0);
1797 1795
1798 1796 sfree(attrName);
1799 1797 } else if (t->objectDN->delDisp == dd_never) {
1800 1798 /* Nothing to do, so we're trivially successful */
1801 1799 stat = LDAP_SUCCESS;
1802 1800 } else {
1803 1801 stat = LDAP_PARAM_ERROR;
1804 1802 }
1805 1803
1806 1804 logmsg(MSG_NOTIMECHECK,
1807 1805 #ifdef NISDB_LDAP_DEBUG
1808 1806 LOG_WARNING,
1809 1807 #else
1810 1808 LOG_INFO,
1811 1809 #endif /* NISDB_LDAP_DEBUG */
1812 1810 "%s: %s (%s)", myself, NIL(t->objName), ldap_err2string(stat));
1813 1811
1814 1812 /* If there were no such object, we've trivially succeeded */
1815 1813 if (stat == LDAP_NO_SUCH_OBJECT)
1816 1814 stat = LDAP_SUCCESS;
1817 1815
1818 1816 if (stat != LDAP_SUCCESS)
1819 1817 break;
1820 1818
1821 1819 }
1822 1820
1823 1821 sfree(tp);
1824 1822
1825 1823 return (stat);
1826 1824 }
↓ open down ↓ |
268 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX