Print this page
5910 libnisdb won't build with modern GCC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libnisdb/ldap_val.c
+++ new/usr/src/lib/libnisdb/ldap_val.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
27 28 #include <lber.h>
28 29 #include <ldap.h>
29 30 #include <strings.h>
30 31 #include <errno.h>
31 32
32 33 #include "nisdb_mt.h"
33 34
34 35 #include "ldap_util.h"
35 36 #include "ldap_op.h"
36 37 #include "ldap_ruleval.h"
37 38 #include "ldap_attr.h"
38 39 #include "ldap_val.h"
39 40 #include "ldap_ldap.h"
40 41
41 42 extern int yp2ldap;
42 43
43 44
44 45 __nis_mapping_format_t *
45 46 cloneMappingFormat(__nis_mapping_format_t *m) {
46 47 __nis_mapping_format_t *new;
47 48 int i, nf, err;
48 49 char *myself = "cloneMappingFormat";
49 50
50 51 if (m == 0)
51 52 return (0);
52 53
53 54 for (nf = 0; m[nf].type != mmt_end; nf++);
54 55 nf++;
55 56
56 57 new = am(myself, nf * sizeof (new[0]));
57 58 if (new == 0)
58 59 return (0);
59 60
60 61 /* Copy the whole array */
61 62 memcpy(new, m, nf * sizeof (new[0]));
62 63
63 64 /* Make copies of allocated stuff */
64 65 for (i = 0, err = 0; i < nf; i++) {
65 66 switch (m[i].type) {
66 67 case mmt_string:
67 68 new[i].match.string = sdup(myself, T,
68 69 m[i].match.string);
69 70 if (new[i].match.string == 0 && m[i].match.string != 0)
70 71 err++;
71 72 break;
72 73 case mmt_single:
73 74 new[i].match.single.lo =
74 75 am(myself, m[i].match.single.numRange *
75 76 sizeof (new[i].match.single.lo[0]));
76 77 new[i].match.single.hi =
77 78 am(myself, m[i].match.single.numRange *
78 79 sizeof (new[i].match.single.hi[0]));
79 80 if (new[i].match.single.lo != 0)
80 81 memcpy(new[i].match.single.lo,
81 82 m[i].match.single.lo,
82 83 m[i].match.single.numRange);
83 84 else if (m[i].match.single.lo != 0)
84 85 err++;
85 86 if (new[i].match.single.hi != 0)
86 87 memcpy(new[i].match.single.hi,
87 88 m[i].match.single.hi,
88 89 m[i].match.single.numRange);
89 90 else if (m[i].match.single.hi != 0)
90 91 err++;
91 92 break;
92 93 case mmt_berstring:
93 94 new[i].match.berString = sdup(myself, T,
94 95 m[i].match.berString);
95 96 if (new[i].match.berString == 0 &&
96 97 m[i].match.berString != 0)
97 98 err++;
98 99 break;
99 100 case mmt_item:
100 101 case mmt_limit:
101 102 case mmt_any:
102 103 case mmt_begin:
103 104 case mmt_end:
104 105 default:
105 106 break;
106 107 }
107 108 }
108 109
109 110 /* If there were memory allocation errors, free the copy */
110 111 if (err > 0) {
111 112 freeMappingFormat(new);
112 113 new = 0;
113 114 }
114 115
115 116 return (new);
116 117 }
117 118
118 119 void
119 120 freeMappingFormat(__nis_mapping_format_t *m) {
120 121 int i;
121 122
122 123 if (m == 0)
123 124 return;
124 125
125 126 for (i = 0; m[i].type != mmt_end; i++) {
126 127 switch (m[i].type) {
127 128 case mmt_string:
128 129 sfree(m[i].match.string);
129 130 break;
130 131 case mmt_single:
131 132 sfree(m[i].match.single.lo);
132 133 sfree(m[i].match.single.hi);
133 134 break;
134 135 case mmt_berstring:
135 136 sfree(m[i].match.berString);
136 137 break;
137 138 case mmt_item:
138 139 case mmt_limit:
139 140 case mmt_any:
140 141 case mmt_begin:
141 142 case mmt_end:
142 143 default:
143 144 break;
144 145 }
145 146 }
146 147
147 148 free(m);
148 149 }
149 150
150 151
151 152 void
152 153 copyIndex(__nis_index_t *old, __nis_index_t *new, int *err) {
153 154 int i;
154 155 char *myself = "copyIndex";
155 156
156 157 if (old == 0 || new == 0) {
157 158 *err = EINVAL;
158 159 return;
159 160 }
160 161
161 162 for (i = 0; i < old->numIndexes; i++) {
162 163 new->name[i] = sdup(myself, T, old->name[i]);
163 164 if (new->name[i] == 0 && old->name[i] != 0) {
164 165 *err = ENOMEM;
165 166 return;
166 167 }
167 168 new->value[i] = cloneMappingFormat(old->value[i]);
168 169 if (new->value[i] == 0 && old->value[i] != 0) {
169 170 *err = ENOMEM;
170 171 return;
171 172 }
172 173 }
173 174
174 175 new->numIndexes = old->numIndexes;
175 176 }
176 177
177 178 __nis_index_t *
178 179 cloneIndex(__nis_index_t *old) {
179 180 char *myself = "cloneIndex";
180 181 int err = 0;
181 182 __nis_index_t *new = am(myself, sizeof (*new));
182 183
183 184 if (old == 0)
184 185 return (0);
185 186
186 187 if (new != 0) {
187 188 copyIndex(old, new, &err);
188 189 if (err != 0) {
189 190 freeIndex(new, 1);
190 191 new = 0;
191 192 }
192 193 }
193 194
194 195 return (new);
195 196 }
196 197
197 198 void
198 199 freeIndex(__nis_index_t *old, bool_t doFree) {
199 200 int i;
200 201
201 202 if (old == 0)
202 203 return;
203 204
204 205 for (i = 0; i < old->numIndexes; i++) {
205 206 sfree(old->name[i]);
206 207 freeMappingFormat(old->value[i]);
207 208 }
208 209
209 210 if (doFree)
210 211 free(old);
211 212 }
212 213
213 214 char **
214 215 cloneName(char **name, int numNames) {
215 216 char **new;
216 217 int i;
217 218 char *myself = "cloneName";
218 219
219 220 if (name == 0 || numNames <= 0)
220 221 return (0);
221 222
222 223 new = am(myself, numNames * sizeof (new[0]));
223 224 if (new == 0)
224 225 return (0);
225 226
226 227 for (i = 0; i < numNames; i++) {
227 228 if (name[i] != 0) {
228 229 new[i] = sdup(myself, T, name[i]);
229 230 if (new[i] == 0) {
230 231 for (i--; i >= 0; i--) {
231 232 sfree(new[i]);
232 233 }
233 234 sfree(new);
234 235 return (0);
235 236 }
236 237 } else {
237 238 new[i] = 0;
238 239 }
239 240 }
240 241
241 242 return (new);
242 243 }
243 244
244 245 void
245 246 freeValue(__nis_value_t *val, int count) {
246 247 int c, i;
247 248
248 249 if (val == 0)
249 250 return;
250 251
251 252 for (c = 0; c < count; c++) {
252 253 if (val[c].val != 0) {
253 254 for (i = 0; i < val[c].numVals; i++) {
254 255 sfree(val[c].val[i].value);
255 256 }
256 257 free(val[c].val);
257 258 }
258 259 }
259 260
260 261 free(val);
261 262 }
262 263
263 264 __nis_value_t *
264 265 cloneValue(__nis_value_t *val, int count) {
265 266 __nis_value_t *n;
266 267 int c, i;
267 268 char *myself = "cloneValue";
268 269
269 270 if (count <= 0 || val == 0)
270 271 return (0);
271 272
272 273 n = am(myself, count * sizeof (*n));
273 274 if (n == 0)
274 275 return (0);
275 276
276 277 for (c = 0; c < count; c++) {
277 278 n[c].type = val[c].type;
278 279 n[c].repeat = val[c].repeat;
279 280 n[c].numVals = val[c].numVals;
280 281 if (n[c].numVals > 0) {
281 282 n[c].val = am(myself, n[c].numVals *
282 283 sizeof (n[c].val[0]));
283 284 if (n[c].val == 0) {
284 285 freeValue(n, c);
285 286 return (0);
286 287 }
287 288 } else {
288 289 n[c].val = 0;
289 290 }
290 291 for (i = 0; i < n[c].numVals; i++) {
291 292 int amlen = val[c].val[i].length;
292 293
293 294 /*
294 295 * The functions that create string values try to
295 296 * make sure that there's a NUL at the end. However,
296 297 * both NIS+ and LDAP have a tendency to store strings
297 298 * without a NUL, so the value length may not include
298 299 * the NUL (even though it's there). In order to
299 300 * preserve that NUL, we add a byte to the length if
300 301 * the type is vt_string, and there isn't already a
301 302 * NUL at the end. The memory allocation function
302 303 * (am()) will take care of actually putting the NUL
303 304 * in place, since it allocates zero-initialized
304 305 * memory.
305 306 */
306 307 n[c].val[i].length = val[c].val[i].length;
307 308 if (n[c].type == vt_string && amlen > 0 &&
308 309 ((char *)val[c].val[i].value)[amlen-1] !=
309 310 '\0') {
310 311 amlen++;
311 312 }
312 313 n[c].val[i].value = am(myself, amlen);
313 314 if (amlen > 0 && n[c].val[i].value == 0) {
314 315 freeValue(n, c);
315 316 return (0);
316 317 }
317 318 memcpy(n[c].val[i].value, val[c].val[i].value,
318 319 n[c].val[i].length);
319 320 }
320 321 }
321 322
322 323 return (n);
323 324 }
324 325
325 326 /* Define LBER_USE_DER per ber_decode(3LDAP) */
326 327 #ifndef LBER_USE_DER
327 328 #define LBER_USE_DER 0x01
328 329 #endif /* LBER_USE_DER */
329 330
330 331 /*
331 332 * Return a copy of 'valIn' where each value has been replaced by the
332 333 * BER encoded equivalent specified by 'berstring'. 'valIn' is unchanged.
333 334 */
334 335 __nis_value_t *
335 336 berEncode(__nis_value_t *valIn, char *berstring) {
336 337 char *myself = "berEncode";
337 338 __nis_value_t *val;
338 339 int i;
339 340
340 341 if (valIn == 0 || berstring == 0)
341 342 return (0);
342 343
343 344 val = cloneValue(valIn, 1);
344 345 if (val == 0)
345 346 return (0);
346 347
347 348 for (i = 0; i < val->numVals; i++) {
348 349 BerElement *ber = ber_alloc();
349 350 struct berval *bv = 0;
350 351 int ret;
351 352
352 353 if (ber == 0) {
353 354 logmsg(MSG_NOMEM, LOG_ERR, "%s: ber_alloc() => NULL",
354 355 myself);
355 356 freeValue(val, 1);
356 357 return (0);
357 358 }
358 359
359 360 if ((strcmp("b", berstring) == 0 ||
360 361 strcmp("i", berstring) == 0)) {
361 362 if (val->val[i].length >= sizeof (int)) {
362 363 ret = ber_printf(ber, berstring,
363 364 *((int *)(val->val[i].value)));
364 365 } else {
365 366 ret = -1;
366 367 }
367 368 } else if (strcmp("B", berstring) == 0) {
368 369 ret = ber_printf(ber, berstring,
369 370 val->val[i].value,
370 371 val->val[i].length * 8);
371 372 } else if (strcmp("n", berstring) == 0) {
372 373 ret = ber_printf(ber, berstring);
373 374 } else if (strcmp("o", berstring) == 0) {
374 375 ret = ber_printf(ber, berstring,
375 376 val->val[i].value, val->val[i].length);
376 377 } else if (strcmp("s", berstring) == 0) {
377 378 char *str = am(myself, val->val[i].length + 1);
378 379
379 380 if (str != 0) {
380 381 ret = ber_printf(ber, berstring, str);
381 382 free(str);
382 383 } else {
383 384 ret = -1;
384 385 }
385 386 } else {
386 387 ret = -1;
387 388 }
388 389
389 390 if (ret == -1) {
390 391 reportError(NPL_BERENCODE, "%s: BER encoding error",
391 392 myself);
392 393 ber_free(ber, 1);
393 394 freeValue(val, 1);
394 395 return (0);
395 396 }
396 397
397 398 if (ber_flatten(ber, &bv) != 0 || bv == 0) {
398 399 reportError(NPL_BERENCODE, "%s: ber_flatten() error",
399 400 myself);
400 401 ber_free(ber, 1);
401 402 freeValue(val, 1);
402 403 return (0);
403 404 }
404 405
405 406 sfree(val->val[i].value);
406 407 val->val[i].length = bv->bv_len;
407 408 val->val[i].value = bv->bv_val;
408 409
409 410 ber_free(ber, 1);
410 411 }
411 412
412 413 val->type = vt_ber;
413 414
414 415 return (val);
415 416 }
416 417
417 418 __nis_value_t *
418 419 berDecode(__nis_value_t *valIn, char *berstring) {
419 420 __nis_value_t *val;
420 421 int i;
421 422 char *myself = "berDecode";
422 423
423 424 if (valIn == 0 || berstring == 0)
424 425 return (0);
425 426
426 427 val = cloneValue(valIn, 1);
427 428 if (val == 0)
428 429 return (0);
429 430
430 431 for (i = 0; i < val->numVals; i++) {
431 432 void *v = 0;
432 433 int ret, len = 0;
433 434 struct berval bv;
434 435 BerElement *ber;
435 436
436 437 if (val->val[i].value == 0 || val->val[i].length <= 0)
437 438 continue;
438 439
439 440 bv.bv_val = val->val[i].value;
440 441 bv.bv_len = val->val[i].length;
441 442 ber = ber_init(&bv);
442 443 if (ber == 0) {
443 444 reportError(NPL_BERDECODE, "%s: ber_init() error",
444 445 myself);
445 446 freeValue(val, 1);
446 447 return (0);
447 448 }
448 449
449 450 if ((strcmp("b", berstring) == 0 ||
450 451 strcmp("i", berstring) == 0)) {
451 452 len = sizeof (int);
452 453 v = am(myself, len);
453 454 if (v != 0) {
454 455 ret = ber_scanf(ber, berstring, v);
455 456 } else {
456 457 ret = -1;
457 458 }
458 459 } else if (strcmp("B", berstring) == 0) {
459 460 long llen;
460 461
461 462 ret = ber_scanf(ber, berstring, &v, &llen);
462 463 if (ret != -1) {
463 464 len = llen/8;
464 465 }
465 466 } else if (strcmp("n", berstring) == 0) {
466 467 ret = 0;
467 468 } else if (strcmp("o", berstring) == 0) {
468 469 struct berval *bv = am(myself, sizeof (*bv));
469 470
470 471 if (bv != 0) {
471 472 ret = ber_scanf(ber, "O", &bv);
472 473 if (ret != -1 && bv != 0) {
473 474 v = bv->bv_val;
474 475 len = bv->bv_len;
475 476 } else {
476 477 ret = -1;
477 478 }
478 479 /* Only free 'bv' itself */
479 480 free(bv);
480 481 } else {
481 482 ret = -1;
482 483 }
483 484 } else if (strcmp("s", berstring) == 0) {
484 485 ret = ber_scanf(ber, "a", &v);
485 486 if (ret != -1) {
486 487 len = slen(v);
487 488 }
488 489 } else {
489 490 ret = -1;
490 491 }
491 492
492 493 if (ret == -1) {
493 494 reportError(NPL_BERDECODE, "%s: BER decoding error",
494 495 myself);
495 496 freeValue(val, 1);
496 497 return (0);
497 498 }
498 499
499 500 /* Free the old value, and replace it with the decoded one */
500 501 sfree(val->val[i].value);
501 502 val->val[i].value = v;
502 503 val->val[i].length = len;
503 504 }
504 505
505 506 return (val);
506 507 }
507 508
508 509 /*
509 510 * Return the value of the specified item.
510 511 */
511 512 __nis_value_t *
512 513 getMappingItemVal(__nis_mapping_item_t *item, __nis_mapping_item_type_t native,
513 514 __nis_rule_value_t *rv, char *berstring, int *np_ldap_stat) {
514 515 __nis_value_t *val = 0, *nameVal, *exVal = 0;
515 516 int numName, caseInsens, cmp;
516 517 int i, j, k;
517 518 char **name;
518 519 enum {rvOnly, rvThenLookup, lookupOnly} check;
519 520 unsigned char fromldap = '\0';
520 521
521 522 if (item == 0)
522 523 return (0);
523 524
524 525 /*
525 526 * First, we decide if we should look for the value in 'rv',
526 527 * directly from NIS+/LDAP, or both.
527 528 */
528 529 switch (item->type) {
529 530 case mit_nisplus:
530 531 /* Do we have a valid index/object spec ? */
531 532 if (item->searchSpec.obj.index.numIndexes <= 0 &&
532 533 item->searchSpec.obj.name == 0) {
533 534 /*
534 535 * No valid index/object. If we have a rule-value,
535 536 * use it. Otherwise, return error.
536 537 */
537 538 if (rv != 0) {
538 539 name = rv->colName;
539 540 nameVal = rv->colVal;
540 541 numName = rv->numColumns;
541 542 caseInsens = 0;
542 543 check = rvOnly;
543 544 } else {
544 545 return (0);
545 546 }
546 547 } else {
547 548 /*
548 549 * Valid index, so skip the rule-value and do
549 550 * a direct NIS+ lookup.
550 551 */
551 552 check = lookupOnly;
552 553 }
553 554 break;
554 555 case mit_ldap:
555 556 if (rv != 0) {
556 557 name = rv->attrName;
557 558 nameVal = rv->attrVal;
558 559 numName = rv->numAttrs;
559 560 caseInsens = 1;
560 561 fromldap = '1';
561 562 }
562 563 /* Do we have a valid triple ? */
563 564 if (item->searchSpec.triple.scope == LDAP_SCOPE_UNKNOWN) {
564 565 /*
565 566 * No valid triple. If we have a rule-value, use it.
566 567 * Otherwise, return error.
567 568 */
568 569 if (rv != 0) {
569 570 check = rvOnly;
570 571 } else {
571 572 return (0);
572 573 }
573 574 } else if (item->searchSpec.triple.base == 0 &&
574 575 item->searchSpec.triple.scope ==
575 576 LDAP_SCOPE_ONELEVEL &&
576 577 item->searchSpec.triple.attrs == 0 &&
577 578 item->searchSpec.triple.element == 0) {
578 579 /*
579 580 * We have a valid triple, but it points to the
580 581 * current LDAP container. Thus, first look in
581 582 * the rule-value; if that fails, perform a direct
582 583 * LDAP lookup.
583 584 */
584 585 if (rv != 0) {
585 586 check = rvThenLookup;
586 587 } else {
587 588 check = lookupOnly;
588 589 }
589 590 } else {
590 591 /*
591 592 * Valid triple, and it's not the current container
592 593 * (at least not in the trivial sense). Hence, do
593 594 * a direct LDAP lookup.
594 595 */
595 596 check = lookupOnly;
596 597 }
597 598 break;
598 599 default:
599 600 return (0);
600 601 }
601 602
602 603 /* Check the rule-value */
603 604 if (check == rvOnly || check == rvThenLookup) {
604 605 for (i = 0; i < numName; i++) {
605 606 if (caseInsens)
606 607 cmp = strcasecmp(item->name, name[i]);
607 608 else
608 609 cmp = strcmp(item->name, name[i]);
609 610 if (cmp == 0) {
610 611 if (nameVal[i].numVals <= 0)
611 612 break;
612 613 if (berstring == 0) {
613 614 val = cloneValue(&nameVal[i], 1);
614 615 } else if (yp2ldap && berstring[0] == 'a') {
615 616 val = cloneValue(&nameVal[i], 1);
616 617 } else {
617 618 val = berDecode(&nameVal[i],
618 619 berstring);
619 620 }
620 621 if (val != 0) {
621 622 val->repeat = item->repeat;
622 623 /*
623 624 * If value for nis+ column is
624 625 * passed with value, val is
625 626 * manipulated in cloneValue().
626 627 * To decide whether there are
627 628 * enough nis+ column values
628 629 * for rule to produce a value,
629 630 * we need nis+ column values
630 631 * as well as nis_mapping_element
631 632 * from the rule. If we are here,
632 633 * it indicates that the 'val has
633 634 * an valid value for the column
634 635 * item-> name. So set
635 636 * NP_LDAP_MAP_SUCCESS
636 637 * to np_ldap-stat.
637 638 */
638 639
639 640 if (np_ldap_stat != NULL)
640 641 *np_ldap_stat =
641 642 NP_LDAP_MAP_SUCCESS;
642 643 }
643 644 break;
644 645 }
645 646 }
646 647 }
647 648
648 649 /* Do a direct lookup ? */
649 650 if (val == 0 && (check == rvThenLookup || check == lookupOnly)) {
650 651 if (item->type == mit_ldap) {
651 652 int err = 0;
652 653 __nis_search_triple_t triple;
653 654 char *baseDN;
654 655
655 656 /*
656 657 * If item->searchSpec.triple.base is NULL, or ends
657 658 * in a comma, append the current search base from
658 659 * the TSD (put there by an upper layer).
659 660 *
660 661 * Special case for N2L mode:
661 662 * if item->searchSpec.triple.base ends in a comma,
662 663 * the current domain Context is used.
663 664 */
664 665 if (yp2ldap && item->searchSpec.triple.base &&
665 666 strlen(item->searchSpec.triple.base) > 0) {
666 667 baseDN = __nisdb_get_tsd()->domainContext;
667 668 } else {
668 669 baseDN = __nisdb_get_tsd()->searchBase;
669 670 }
670 671 triple.base = appendBase(item->searchSpec.triple.base,
671 672 baseDN, &err, 0);
672 673 if (err == 0) {
673 674 triple.scope = item->searchSpec.triple.scope;
674 675 triple.attrs = item->searchSpec.triple.attrs;
675 676 triple.element =
676 677 item->searchSpec.triple.element;
677 678 val = lookupLDAP(&triple, item->name, rv, 0,
678 679 np_ldap_stat);
679 680 fromldap = '1';
680 681 } else {
681 682 val = 0;
682 683 }
683 684 sfree(triple.base);
684 685 }
685 686 }
686 687
687 688
688 689 /* Special processing for NIS to LDAP mode */
689 690 if (yp2ldap && val != 0) {
690 691
691 692 /*
692 693 * Escape special chars from dn before sending to DIT,
693 694 * provided val is not ldap-based
694 695 */
695 696 if (fromldap == '\0' && __nisdb_get_tsd()->escapeFlag == '1') {
696 697 if (escapeSpecialChars(val) < 0) {
697 698 freeValue(val, 1);
698 699 return (0);
699 700 }
700 701 } else if (__nisdb_get_tsd()->escapeFlag == '2') {
701 702 /* Remove escape chars from data received from DIT */
702 703 (void) removeEscapeChars(val);
703 704 }
704 705
705 706 /*
706 707 * Remove from 'val', any values obtained using
707 708 * the 'removespec' syntax
708 709 */
709 710
710 711 /* Obtain exVal */
711 712 if (item->exItem)
712 713 exVal = getMappingItemVal(item->exItem, native, rv,
713 714 berstring, NULL);
714 715
715 716 /* delete */
716 717 if (exVal != 0) {
717 718 for (i = 0; i < val->numVals; ) {
718 719 for (j = 0; j < exVal->numVals; j++) {
719 720 if (sstrncmp(val->val[i].value,
720 721 exVal->val[j].value,
721 722 MAX(val->val[i].length,
722 723 exVal->val[j].length))
723 724 == 0)
724 725 break;
725 726 }
726 727 if (j < exVal->numVals) {
727 728 sfree(val->val[i].value);
728 729 val->val[i].value = 0;
729 730 val->val[i].length = 0;
730 731 for (k = i; k < val->numVals - 1; k++) {
731 732 val->val[k] = val->val[k + 1];
732 733 val->val[k + 1].value = 0;
733 734 val->val[k + 1].length = 0;
734 735 }
735 736 val->numVals--;
736 737 } else
737 738 i++;
738 739 }
739 740
740 741 freeValue(exVal, 1);
741 742
742 743 /*
743 744 * If val->numVals <= 0, then we have no val to
744 745 * return. So free up stuff.
745 746 */
746 747 if (val->numVals <= 0) {
747 748 free(val->val);
748 749 val->val = 0;
749 750 free(val);
750 751 return (0);
751 752 }
752 753 }
753 754 }
754 755
755 756 return (val);
756 757 }
757 758
758 759 __nis_value_t *
759 760 getMappingFormat(__nis_mapping_format_t *f, __nis_rule_value_t *rv,
760 761 __nis_format_arg_t at, void *a, int *numArg) {
761 762 char *myself = "getMappingFormat";
762 763 __nis_value_t *val = 0;
763 764 __nis_buffer_t b = {0, 0};
764 765 int i;
765 766
766 767 if (f == 0)
767 768 return (0);
768 769
769 770 if (rv == 0) {
770 771 val = am(myself, sizeof (*val));
771 772 if (val == 0)
772 773 return (0);
773 774
774 775 switch (f->type) {
775 776 case mmt_item:
776 777 bp2buf(myself, &b, "%%s");
777 778 break;
778 779 case mmt_string:
779 780 bp2buf(myself, &b, "%s", NIL(f->match.string));
780 781 break;
781 782 case mmt_single:
782 783 bp2buf(myself, &b, "[");
783 784 for (i = 0; i < f->match.single.numRange; i++) {
784 785 if (f->match.single.lo[i] ==
785 786 f->match.single.hi[i])
786 787 bp2buf(myself, &b, "%c",
787 788 f->match.single.lo[i]);
788 789 else
789 790 bp2buf(myself, &b, "%c-%c",
790 791 f->match.single.lo[i],
791 792 f->match.single.hi[i]);
792 793 }
793 794 bp2buf(myself, &b, "]");
794 795 break;
795 796 case mmt_limit:
796 797 break;
797 798 case mmt_any:
798 799 bp2buf(myself, &b, "*");
799 800 break;
800 801 case mmt_berstring:
801 802 bp2buf(myself, &b, "%s", NIL(f->match.berString));
802 803 break;
803 804 case mmt_begin:
804 805 case mmt_end:
805 806 bp2buf(myself, &b, "\"");
806 807 break;
807 808 default:
808 809 bp2buf(myself, &b, "<unknown>");
809 810 }
810 811 val->type = vt_string;
811 812 val->numVals = 1;
812 813 val->val = am(myself, sizeof (val->val[0]));
813 814 if (val->val == 0) {
814 815 sfree(val);
815 816 return (0);
816 817 }
817 818 val->val[0].value = b.buf;
818 819 val->val[0].length = b.len;
819 820 } else {
820 821 switch (f->type) {
821 822 case mmt_item:
822 823 case mmt_berstring:
823 824 if (a != 0) {
824 825 if (at == fa_item) {
825 826 val = getMappingItemVal(
826 827 (__nis_mapping_item_t *)a,
827 828 mit_any, rv,
828 829 (f->type == mmt_berstring) ? f->match.berString : 0, NULL);
829 830 if (numArg != 0)
830 831 (*numArg)++;
831 832 } else {
832 833 val = cloneValue(
833 834 (__nis_value_t *)a, 1);
834 835 if (numArg != 0)
835 836 (*numArg)++;
836 837 }
837 838 }
838 839 break;
839 840 case mmt_string:
840 841 val = am(myself, sizeof (*val));
841 842 if (val == 0)
842 843 return (0);
843 844 val->type = vt_string;
844 845 val->numVals = 1;
845 846 val->val = am(myself, sizeof (val->val[0]));
846 847 if (val->val == 0) {
847 848 sfree(val);
848 849 return (0);
849 850 }
850 851 val->val[0].value = sdup(myself, T, f->match.string);
851 852 val->val[0].length = strlen(val->val[0].value);
852 853 break;
853 854 case mmt_single:
854 855 case mmt_limit:
855 856 case mmt_any:
856 857 case mmt_begin:
857 858 case mmt_end:
858 859 /* Not an error, so return an empty value */
859 860 val = am(myself, sizeof (*val));
860 861 if (val == 0)
861 862 return (0);
862 863 val->type = vt_string;
863 864 val->numVals = 0;
864 865 val->val = 0;
865 866 break;
866 867 default:
867 868 /* Do nothing */
868 869 val = 0;
869 870 break;
870 871 }
871 872 }
872 873 return (val);
873 874 }
874 875
875 876 /*
876 877 * Used when evaluating an expression. Typically, the value of the
877 878 * expression so far will be kept in 'v1', and 'v2' is the value
878 879 * of the current component of the expression. In the general case,
879 880 * both will be multi-valued, and the result is an "explosion"
880 881 * resulting in N*M new values (if 'v1' had N values, and 'v2'
881 882 * M ditto).
882 883 *
883 884 * For example, if v1 = {"ab", "cd", "ef"}, and v2 = {"gh", "ij", "kl"},
884 885 * the result will be {"abgh", "abij", "abkl", "cdgh", "cdij", "cdkl",
885 886 * "efgh", "efij", "efkl"}.
886 887 *
887 888 * There are special cases when v1->repeat and/or v2->repeat are set.
888 889 * Repeat mostly makes sense with single values; for example, if
889 890 * v1 = {"x="} with repeat on, and v2 = {"1", "2", "3"}, the result
890 891 * is {"x=1", "x=2", "x=3"}.
891 892 *
892 893 * The result if v2 also had repeat on would be {"x=1x=2x=3"}. It's
893 894 * not clear if there's a useful application for this, but the code's
894 895 * there for the sake of orthogonality.
895 896 */
896 897 __nis_value_t *
897 898 explodeValues(__nis_value_t *v1, __nis_value_t *v2) {
898 899 int i1, i2, n, nv;
899 900 __nis_value_t *v;
900 901 __nis_buffer_t b = {0, 0};
901 902 char *myself = "explodeValues";
902 903
903 904 if (v1 == 0 || v1->numVals <= 0)
904 905 return (cloneValue(v2, 1));
905 906 if (v2 == 0 || v2->numVals <= 0)
906 907 return (cloneValue(v1, 1));
907 908
908 909 /*
909 910 * XXX What should we do if (v1->type != v2->type) ?
910 911 * Policy: Just explode anyway, even though the result is
911 912 * unlikely to be very useful.
912 913 */
913 914
914 915 v = am(myself, sizeof (*v));
915 916 if (v == 0)
916 917 return (0);
917 918
918 919 if (!v1->repeat && !v2->repeat)
919 920 nv = v1->numVals * v2->numVals;
920 921 else if (v1->repeat && !v2->repeat)
921 922 nv = v2->numVals;
922 923 else if (!v1->repeat && v2->repeat)
923 924 nv = v1->numVals;
924 925 else /* v1->repeat && v2->repeat */
925 926 nv = 1;
926 927
927 928 v->val = am(myself, nv * sizeof (v->val[0]));
928 929 if (v->val == 0) {
929 930 free(v);
930 931 return (0);
931 932 }
932 933
933 934 /*
934 935 * Four different cases, depending on the 'repeat' flags.
935 936 */
936 937 if (!v1->repeat && !v2->repeat) {
937 938 for (i1 = 0, n = 0; i1 < v1->numVals; i1++) {
938 939 for (i2 = 0; i2 < v2->numVals; i2++) {
939 940 if (v1->type == vt_string)
940 941 sbc2buf(myself, v1->val[i1].value,
941 942 v1->val[i1].length,
942 943 &b);
943 944 else
944 945 bc2buf(myself, v1->val[i1].value,
945 946 v1->val[i1].length,
946 947 &b);
947 948 if (v2->type == vt_string)
948 949 sbc2buf(myself, v2->val[i2].value,
949 950 v2->val[i2].length,
950 951 &b);
951 952 else
952 953 bc2buf(myself, v2->val[i2].value,
953 954 v2->val[i2].length,
954 955 &b);
955 956 v->val[n].value = b.buf;
956 957 v->val[n].length = b.len;
957 958 n++;
958 959 b.buf = 0;
959 960 b.len = 0;
960 961 }
961 962 }
962 963 } else if (v1->repeat && !v2->repeat) {
963 964 for (i2 = 0; i2 < v2->numVals; i2++) {
964 965 for (i1 = 0, n = 0; i1 < v1->numVals; i1++) {
965 966 if (v1->type == vt_string)
966 967 sbc2buf(myself, v1->val[i1].value,
967 968 v1->val[i1].length,
968 969 &b);
969 970 else
970 971 bc2buf(myself, v1->val[i1].value,
971 972 v1->val[i1].length,
972 973 &b);
973 974 if (v2->type == vt_string)
974 975 sbc2buf(myself, v2->val[i2].value,
975 976 v2->val[i2].length,
976 977 &b);
977 978 else
978 979 bc2buf(myself, v2->val[i2].value,
979 980 v2->val[i2].length,
980 981 &b);
981 982 }
982 983 v->val[n].value = b.buf;
983 984 v->val[n].length = b.len;
984 985 n++;
985 986 b.buf = 0;
986 987 b.len = 0;
987 988 }
988 989 } else if (!v1->repeat && v2->repeat) {
989 990 for (i1 = 0, n = 0; i1 < v1->numVals; i1++) {
990 991 for (i2 = 0; i2 < v2->numVals; i2++) {
991 992 if (v1->type == vt_string)
992 993 sbc2buf(myself, v1->val[i1].value,
993 994 v1->val[i1].length,
994 995 &b);
995 996 else
996 997 bc2buf(myself, v1->val[i1].value,
997 998 v1->val[i1].length,
998 999 &b);
999 1000 if (v2->type == vt_string)
1000 1001 sbc2buf(myself, v2->val[i2].value,
1001 1002 v2->val[i2].length,
1002 1003 &b);
1003 1004 else
1004 1005 bc2buf(myself, v2->val[i2].value,
1005 1006 v2->val[i2].length,
1006 1007 &b);
1007 1008 }
1008 1009 v->val[n].value = b.buf;
1009 1010 v->val[n].length = b.len;
1010 1011 n++;
1011 1012 b.buf = 0;
1012 1013 b.len = 0;
1013 1014 }
1014 1015 } else { /* v1->repeat && v2->repeat */
1015 1016 for (i1 = 0, n = 0; i1 < v1->numVals; i1++) {
1016 1017 for (i2 = 0; i2 < v2->numVals; i2++) {
1017 1018 if (v1->type == vt_string)
1018 1019 sbc2buf(myself, v1->val[i1].value,
1019 1020 v1->val[i1].length,
1020 1021 &b);
1021 1022 else
1022 1023 bc2buf(myself, v1->val[i1].value,
1023 1024 v1->val[i1].length,
1024 1025 &b);
1025 1026 if (v2->type == vt_string)
1026 1027 sbc2buf(myself, v2->val[i2].value,
1027 1028 v2->val[i2].length,
1028 1029 &b);
1029 1030 else
1030 1031 bc2buf(myself, v2->val[i2].value,
1031 1032 v2->val[i2].length,
1032 1033 &b);
1033 1034 }
1034 1035 }
1035 1036 v->val[n].value = b.buf;
1036 1037 v->val[n].length = b.len;
1037 1038 n++;
1038 1039 b.buf = 0;
1039 1040 b.len = 0;
1040 1041 }
1041 1042
1042 1043 #ifdef NISDB_LDAP_DEBUG
1043 1044 /* Sanity check */
1044 1045 if (n != nv)
1045 1046 abort();
1046 1047 #endif /* NISD__LDAP_DEBUG */
1047 1048
1048 1049 v->type = (v1->type == vt_string) ?
1049 1050 ((v2->type == vt_string) ?
1050 1051 vt_string : vt_ber) : vt_ber;
1051 1052 v->repeat = 0;
1052 1053 v->numVals = n;
1053 1054
1054 1055 return (v);
1055 1056 }
1056 1057
1057 1058 __nis_value_t *
1058 1059 getMappingFormatArray(__nis_mapping_format_t *a, __nis_rule_value_t *rv,
1059 1060 __nis_format_arg_t at, int numArgs, void *arg) {
1060 1061 int i, ia = 0;
1061 1062 __nis_value_t *val, *v = 0;
1062 1063 bool_t moreFormat = (a != 0);
1063 1064 bool_t moreArgs = (numArgs > 0);
1064 1065
1065 1066 while (moreFormat && (arg == 0 || ia < numArgs)) {
1066 1067 for (i = 0; moreFormat; i++) {
1067 1068 moreFormat = (a[i].type != mmt_end);
1068 1069 if (at == fa_item) {
1069 1070 __nis_mapping_item_t *item = arg;
1070 1071 val = getMappingFormat(&a[i], rv, at,
1071 1072 ((item != 0) ? &item[ia] : 0), &ia);
1072 1073 } else {
1073 1074 __nis_value_t **ival = arg;
1074 1075 val = getMappingFormat(&a[i], rv, at,
1075 1076 ((ival != 0) ? ival[ia] : 0), &ia);
1076 1077 }
1077 1078 if (val != 0) {
1078 1079 __nis_value_t *new = explodeValues(v, val);
1079 1080
1080 1081 freeValue(v, 1);
1081 1082 freeValue(val, 1);
1082 1083 if (new == 0)
1083 1084 return (0);
1084 1085
1085 1086 v = new;
1086 1087 } else {
1087 1088 freeValue(v, 1);
1088 1089 return (0);
1089 1090 }
1090 1091 /*
1091 1092 * If we run out of arguments, but still have format
1092 1093 * remaining, repeat the last argument. Keep track of
1093 1094 * the fact that we've really consumed all arguments.
1094 1095 */
1095 1096 if (moreFormat && ia >= numArgs) {
1096 1097 ia = (numArgs > 0) ? numArgs - 1 : 0;
1097 1098 moreArgs = FALSE;
1098 1099 }
1099 1100 }
1100 1101 /*
1101 1102 * We've run out of format, so if we still have arguments
1102 1103 * left, start over on the format.
1103 1104 */
1104 1105 if (ia < numArgs && moreArgs) {
1105 1106 /*
1106 1107 * However, if we didn't consume any arguments going
1107 1108 * through the format once, abort to avoid an infinite
1108 1109 * loop.
1109 1110 */
1110 1111 if (numArgs > 0 && ia <= 0) {
1111 1112 freeValue(v, 1);
1112 1113 return (0);
1113 1114 }
1114 1115 moreFormat = 1;
1115 1116 }
1116 1117 }
1117 1118
1118 1119 return (v);
1119 1120 }
1120 1121
1121 1122 /*
1122 1123 * Returns a string representation (such as "[name=foo, value=bar]")
1123 1124 * of a nis_index_t.
1124 1125 */
1125 1126 char *
1126 1127 getIndex(__nis_index_t *i, int *len) {
1127 1128 int n;
1128 1129 __nis_buffer_t b = {0, 0};
1129 1130 char *myself = "getIndex";
1130 1131
1131 1132 if (i == 0)
1132 1133 return (0);
1133 1134
1134 1135 if (i->numIndexes > 0) {
1135 1136 bp2buf(myself, &b, "[");
1136 1137 for (n = 0; n < i->numIndexes; n++) {
1137 1138 __nis_value_t *val;
1138 1139 int j;
1139 1140
1140 1141 val = getMappingFormatArray(i->value[n],
1141 1142 0, fa_any, 0, 0);
1142 1143 if (n > 0)
1143 1144 bp2buf(myself, &b, ", ");
1144 1145 bp2buf(myself, &b, "%s=", i->name[n]);
1145 1146 if (val != 0) {
1146 1147 for (j = 0; j < val->numVals; j++) {
1147 1148 bc2buf(myself, val->val[j].value,
1148 1149 val->val[j].length, &b);
1149 1150 }
1150 1151 } else {
1151 1152 bp2buf(myself, &b, "<no-vals>");
1152 1153 }
1153 1154 freeValue(val, 1);
1154 1155 }
1155 1156 bp2buf(myself, &b, "]");
1156 1157 }
1157 1158 if (len != 0)
1158 1159 *len = b.len;
1159 1160 return (b.buf);
1160 1161 }
1161 1162
1162 1163 char *
1163 1164 getObjSpec(__nis_obj_spec_t *o, int *len) {
1164 1165 __nis_buffer_t b = {0, 0};
1165 1166 char *myself = "getObjSpec";
1166 1167
1167 1168 if (o == 0)
1168 1169 return (0);
1169 1170
1170 1171 b.buf = getIndex(&o->index, &b.len);
1171 1172 sbc2buf(myself, o->name, slen(o->name), &b);
1172 1173 if (len != 0)
1173 1174 *len = b.len;
1174 1175 return (b.buf);
1175 1176 }
1176 1177
1177 1178 /*
1178 1179 * Returns a string representation of the LDAP scope. Note that the
1179 1180 * returned value is a static entity, and must be copied by the
1180 1181 * caller (but, obviously, must not be freed).
1181 1182 */
1182 1183 char *
1183 1184 getScope(int scope) {
1184 1185 switch (scope) {
1185 1186 case LDAP_SCOPE_BASE:
1186 1187 return ("base");
1187 1188 case LDAP_SCOPE_ONELEVEL:
1188 1189 return ("one");
1189 1190 case LDAP_SCOPE_SUBTREE:
1190 1191 return ("sub");
1191 1192 default:
1192 1193 return ("one");
1193 1194 }
1194 1195 }
1195 1196
1196 1197 /*
1197 1198 * Return a string representation of an LDAP search triple (such as
1198 1199 * "ou=Hosts,dc=eng,dc=sun,dc=com?one?cn=xyzzy").
1199 1200 */
1200 1201 char *
1201 1202 getSearchTriple(__nis_search_triple_t *s, int *len) {
1202 1203 __nis_buffer_t b = {0, 0};
1203 1204 char *a;
1204 1205 int l;
1205 1206 char *myself = "getSearchTriple";
1206 1207
1207 1208 /* If the scope is LDAP_SCOPE_UNKNOWN, the search triple is unused */
1208 1209 if (s == 0 || s->scope == LDAP_SCOPE_UNKNOWN) {
1209 1210 if (len != 0)
1210 1211 *len = 0;
1211 1212 return (0);
1212 1213 }
1213 1214
1214 1215 if (s->base != 0)
1215 1216 sbc2buf(myself, s->base, slen(s->base), &b);
1216 1217 if (!(s->scope == LDAP_SCOPE_ONELEVEL &&
1217 1218 (s->base == 0 || s->base[0] == '\0'))) {
1218 1219 bp2buf(myself, &b, "?%s?", getScope(s->scope));
1219 1220 }
1220 1221 if ((l = slen(s->attrs)) > 0) {
1221 1222 /*
1222 1223 * Remove white space from the filter/attribute list.
1223 1224 * The parser usually keeps any white space from the
1224 1225 * config file (or LDAP/command line), but we don't
1225 1226 * want it.
1226 1227 */
1227 1228 a = am(myself, l+1);
1228 1229 if (a != 0) {
1229 1230 int i, la;
1230 1231
1231 1232 for (i = 0, la = 0; i < l; i++) {
1232 1233 if (s->attrs[i] != ' ' &&
1233 1234 s->attrs[i] != '\t')
1234 1235 a[la++] = s->attrs[i];
1235 1236 }
1236 1237 sbc2buf(myself, a, la, &b);
1237 1238 sfree(a);
1238 1239 } else {
1239 1240 sbc2buf(myself, s->attrs, slen(s->attrs), &b);
1240 1241 }
1241 1242 }
1242 1243
1243 1244 if (len != 0)
1244 1245 *len = b.len;
1245 1246 return (b.buf);
1246 1247 }
1247 1248
1248 1249 __nis_value_t *
1249 1250 getMappingItem(__nis_mapping_item_t *i, __nis_mapping_item_type_t native,
1250 1251 __nis_rule_value_t *rv, char *berstring, int *np_ldap_stat) {
1251 1252 char *myself = "getMappingItem";
1252 1253 __nis_value_t *val = 0;
1253 1254 __nis_buffer_t b = {0, 0};
1254 1255 int len = 0;
1255 1256 char *buf;
1256 1257
1257 1258 if (i == 0)
1258 1259 return (0);
1259 1260
1260 1261 if (rv != 0)
1261 1262 return (getMappingItemVal(i, native, rv, berstring,
1262 1263 np_ldap_stat));
1263 1264
1264 1265 val = am(myself, sizeof (*val));
1265 1266 if (val == 0)
1266 1267 return (0);
1267 1268
1268 1269 switch (i->type) {
1269 1270 case mit_nisplus:
1270 1271 if (native != mit_nisplus)
1271 1272 bp2buf(myself, &b, "nis+:");
1272 1273 bp2buf(myself, &b, "%s", NIL(i->name));
1273 1274 buf = getObjSpec(&i->searchSpec.obj, &len);
1274 1275 if (buf != 0 && len > 0) {
1275 1276 bc2buf(myself, ":", 1, &b);
1276 1277 sbc2buf(myself, buf, len, &b);
1277 1278 }
1278 1279 sfree(buf);
1279 1280 val->type = vt_string;
1280 1281 val->repeat = i->repeat;
1281 1282 val->numVals = 1;
1282 1283 val->val = am(myself, sizeof (val->val[0]));
1283 1284 if (val->val == 0) {
1284 1285 sfree(b.buf);
1285 1286 free(val);
1286 1287 return (0);
1287 1288 }
1288 1289 val->val[0].value = b.buf;
1289 1290 val->val[0].length = b.len;
1290 1291 break;
1291 1292 case mit_ldap:
1292 1293 if (native != mit_ldap)
1293 1294 bp2buf(myself, &b, "ldap:");
1294 1295 bp2buf(myself, &b, "%s", NIL(i->name));
1295 1296 buf = getSearchTriple(&i->searchSpec.triple, &len);
1296 1297 if (buf != 0 && len > 0) {
1297 1298 bc2buf(myself, ":", 1, &b);
1298 1299 sbc2buf(myself, buf, len, &b);
1299 1300 }
1300 1301 sfree(buf);
1301 1302 val->type = vt_string;
1302 1303 val->repeat = i->repeat;
1303 1304 val->numVals = 1;
1304 1305 val->val = am(myself, sizeof (val->val[0]));
1305 1306 if (val->val == 0) {
1306 1307 sfree(b.buf);
1307 1308 free(val);
1308 1309 return (0);
1309 1310 }
1310 1311 val->val[0].value = b.buf;
1311 1312 val->val[0].length = b.len;
1312 1313 break;
1313 1314 default:
1314 1315 p2buf(myself, "<unknown>:");
1315 1316 p2buf(myself, "%s", NIL(i->name));
1316 1317 break;
1317 1318 }
1318 1319
1319 1320 return (val);
1320 1321 }
1321 1322
1322 1323 void
1323 1324 copyObjSpec(__nis_obj_spec_t *old, __nis_obj_spec_t *new, int *err) {
1324 1325 char *myself = "copyObjSpec";
1325 1326
1326 1327 if (old == 0 || new == 0) {
1327 1328 *err = EINVAL;
1328 1329 return;
1329 1330 }
1330 1331
1331 1332 if (new->index.name == 0) {
1332 1333 new->index.name = am(myself, old->index.numIndexes *
1333 1334 sizeof (new->index.name[0]));
1334 1335 if (old->index.numIndexes > 0 && new->index.name == 0) {
1335 1336 *err = ENOMEM;
1336 1337 return;
1337 1338 }
1338 1339 new->index.value = am(myself, old->index.numIndexes *
1339 1340 sizeof (new->index.value[0]));
1340 1341 if (old->index.numIndexes > 0 && new->index.value == 0) {
1341 1342 *err = ENOMEM;
1342 1343 return;
1343 1344 }
1344 1345 }
1345 1346 new->name = sdup(myself, T, old->name);
1346 1347 if (new->name == 0 && old->name != 0) {
1347 1348 *err = ENOMEM;
1348 1349 return;
1349 1350 }
1350 1351 copyIndex(&old->index, &new->index, err);
1351 1352 }
1352 1353
1353 1354 __nis_obj_spec_t *
1354 1355 cloneObjSpec(__nis_obj_spec_t *old) {
1355 1356 char *myself = "cloneObjSpec";
1356 1357 int err = 0;
1357 1358 __nis_obj_spec_t *new = am(myself, sizeof (*new));
1358 1359
1359 1360 if (new != 0) {
1360 1361 copyObjSpec(old, new, &err);
1361 1362 if (err != 0) {
1362 1363 freeObjSpec(new, 1);
1363 1364 new = 0;
1364 1365 }
1365 1366 }
1366 1367
1367 1368 return (new);
1368 1369 }
1369 1370
1370 1371 void
1371 1372 freeObjSpec(__nis_obj_spec_t *old, bool_t doFree) {
1372 1373
1373 1374 if (old == 0)
1374 1375 return;
1375 1376
1376 1377 sfree(old->name);
1377 1378 freeIndex(&old->index, FALSE);
1378 1379 if (doFree)
1379 1380 free(old);
1380 1381 }
1381 1382
1382 1383 void
1383 1384 copySearchTriple(__nis_search_triple_t *old, __nis_search_triple_t *new,
1384 1385 int *err) {
1385 1386 char *myself = "copySearchTriple";
1386 1387
1387 1388 *err = 0;
1388 1389
1389 1390 if (old == 0 || new == 0) {
1390 1391 *err = EINVAL;
1391 1392 return;
1392 1393 }
1393 1394
1394 1395 if (old->base != NULL)
1395 1396 new->base = sdup(myself, T, old->base);
1396 1397 else
1397 1398 new->base = NULL;
1398 1399 if (old->attrs != NULL)
1399 1400 new->attrs = sdup(myself, T, old->attrs);
1400 1401 else
1401 1402 new->attrs = NULL;
1402 1403 if ((new->base == 0 && old->base != 0) ||
1403 1404 (new->attrs == 0 && old->attrs != 0)) {
1404 1405 sfree(new->base);
1405 1406 new->base = 0;
1406 1407 sfree(new->attrs);
1407 1408 new->attrs = 0;
1408 1409 *err = ENOMEM;
1409 1410 return;
1410 1411 }
1411 1412 new->scope = old->scope;
1412 1413 /*
1413 1414 * XXX Really should have a cloneMappingElement() function.
1414 1415 * However, since whatever the 'element' field points to
1415 1416 * is allocated at parse time, and never is freed or modified,
1416 1417 * it's sufficient to copy the pointer value.
1417 1418 */
1418 1419 new->element = old->element;
1419 1420 }
1420 1421
1421 1422 __nis_search_triple_t *
1422 1423 cloneSearchTriple(__nis_search_triple_t *old) {
1423 1424 char *myself = "cloneSearchTriple";
1424 1425 int err = 0;
1425 1426 __nis_search_triple_t *new = am(myself, sizeof (*new));
1426 1427
1427 1428 if (new != 0) {
1428 1429 copySearchTriple(old, new, &err);
1429 1430 if (err != 0) {
1430 1431 freeSearchTriple(new, 1);
1431 1432 new = 0;
1432 1433 }
1433 1434 }
1434 1435
1435 1436 return (new);
1436 1437 }
1437 1438
1438 1439 void
1439 1440 freeSearchTriple(__nis_search_triple_t *old, bool_t doFree) {
1440 1441
1441 1442 if (old == 0)
1442 1443 return;
1443 1444
1444 1445 sfree(old->base);
1445 1446 sfree(old->attrs);
1446 1447 /*
1447 1448 * Since we only copied the element pointer when this structure
1448 1449 * was created, we don't free old->element.
1449 1450 */
1450 1451 if (doFree)
1451 1452 free(old);
1452 1453 }
1453 1454
1454 1455 void
1455 1456 copyTripleOrObj(__nis_mapping_item_type_t type,
1456 1457 __nis_triple_or_obj_t *old, __nis_triple_or_obj_t *new,
1457 1458 int *err) {
1458 1459
1459 1460 *err = 0;
1460 1461
1461 1462 if (old == 0 || new == 0) {
1462 1463 *err = EINVAL;
1463 1464 return;
1464 1465 }
1465 1466
1466 1467 if (type == mit_nisplus) {
1467 1468 copyObjSpec(&old->obj, &new->obj, err);
1468 1469 } else if (type == mit_ldap) {
1469 1470 copySearchTriple(&old->triple, &new->triple, err);
1470 1471 }
1471 1472 }
1472 1473
1473 1474 __nis_triple_or_obj_t *
1474 1475 cloneTripleOrObj(__nis_mapping_item_type_t type, __nis_triple_or_obj_t *old) {
1475 1476 char *myself = "cloneTripleOrObj";
1476 1477 int err = 0;
1477 1478 __nis_triple_or_obj_t *new = am(myself, sizeof (*new));
1478 1479
1479 1480 if (new != 0) {
1480 1481 copyTripleOrObj(type, old, new, &err);
1481 1482 if (err != 0) {
1482 1483 freeTripleOrObj(type, new, 1);
1483 1484 new = 0;
1484 1485 }
1485 1486 }
1486 1487
1487 1488 return (new);
1488 1489 }
1489 1490
1490 1491 void
1491 1492 freeTripleOrObj(__nis_mapping_item_type_t type, __nis_triple_or_obj_t *old,
1492 1493 bool_t doFree) {
1493 1494
1494 1495 if (old == 0)
1495 1496 return;
1496 1497
1497 1498 if (type == mit_nisplus)
1498 1499 freeObjSpec(&old->obj, doFree);
1499 1500 else if (type == mit_ldap)
1500 1501 freeSearchTriple(&old->triple, doFree);
1501 1502
1502 1503 if (doFree)
1503 1504 free(old);
1504 1505 }
1505 1506
1506 1507 void
1507 1508 copyItem(__nis_mapping_item_t *old, __nis_mapping_item_t *new, int *err) {
1508 1509
1509 1510 *err = 0;
1510 1511
1511 1512 if (old == 0 || new == 0) {
1512 1513 *err = EINVAL;
1513 1514 return;
1514 1515 }
1515 1516
1516 1517 new->type = old->type;
1517 1518 new->repeat = old->repeat;
1518 1519 if (old->name != 0) {
1519 1520 new->name = strdup(old->name);
1520 1521 if (new->name == 0) {
1521 1522 *err = ENOMEM;
1522 1523 return;
1523 1524 }
1524 1525 } else {
1525 1526 new->name = 0;
1526 1527 }
1527 1528 if (old->type == mit_nisplus || old->type == mit_ldap)
1528 1529 copyTripleOrObj(old->type, &old->searchSpec, &new->searchSpec,
1529 1530 err);
1530 1531 else
1531 1532 memset(&new->searchSpec, 0, sizeof (new->searchSpec));
1532 1533 }
1533 1534
1534 1535 __nis_mapping_item_t *
1535 1536 cloneItem(__nis_mapping_item_t *old) {
1536 1537 __nis_mapping_item_t *new;
1537 1538 int err = 0;
1538 1539 char *myself = "cloneItem";
1539 1540
1540 1541 if (old == 0)
1541 1542 return (0);
1542 1543
1543 1544 new = am(myself, sizeof (*new));
1544 1545 if (new == 0)
1545 1546 return (0);
1546 1547
1547 1548 copyItem(old, new, &err);
1548 1549 if (err != 0) {
1549 1550 freeMappingItem(new, 1);
1550 1551 return (0);
1551 1552 }
1552 1553
1553 1554 return (new);
1554 1555 }
1555 1556
1556 1557 void
1557 1558 freeMappingItem(__nis_mapping_item_t *item, int numItems) {
1558 1559 int i;
1559 1560
1560 1561 if (item == 0)
1561 1562 return;
1562 1563
1563 1564 for (i = 0; i < numItems; i++) {
1564 1565 sfree(item[i].name);
1565 1566 freeTripleOrObj(item[i].type, &item[i].searchSpec, FALSE);
1566 1567 }
1567 1568 sfree(item);
1568 1569 }
1569 1570
1570 1571 __nis_mapping_item_t *
1571 1572 concatenateMappingItem(__nis_mapping_item_t *old, int numItems,
1572 1573 __nis_mapping_item_t *cat) {
1573 1574 __nis_mapping_item_t *new;
1574 1575 int i, err = 0;
1575 1576 char *myself = "concatenateMappingItem";
1576 1577
1577 1578 if (old == 0 || numItems < 1)
1578 1579 return (cloneItem(cat));
1579 1580
1580 1581 new = am(myself, (numItems + 1) * sizeof (*new));
1581 1582 if (new == 0)
1582 1583 return (0);
1583 1584
1584 1585 for (i = 0; i < numItems; i++) {
1585 1586 copyItem(&old[i], &new[i], &err);
1586 1587 if (err != 0) {
1587 1588 freeMappingItem(new, i);
1588 1589 return (0);
1589 1590 }
1590 1591 }
1591 1592 copyItem(cat, &new[numItems], &err);
1592 1593 if (err != 0) {
1593 1594 freeMappingItem(new, numItems);
1594 1595 new = 0;
1595 1596 }
1596 1597
1597 1598 return (new);
1598 1599 }
1599 1600
1600 1601 __nis_value_t *
1601 1602 concatenateValues(__nis_value_t *v1, __nis_value_t *v2) {
1602 1603 int i, n, a;
1603 1604 __nis_value_t *v;
1604 1605 char *myself = "concatenateValues";
1605 1606
1606 1607 if (v1 == 0 || v1->numVals <= 0)
1607 1608 return (cloneValue(v2, 1));
1608 1609 if (v2 == 0 || v2->numVals <= 0)
1609 1610 return (cloneValue(v1, 1));
1610 1611
1611 1612 if (v1->type != v2->type)
1612 1613 return (0);
1613 1614
1614 1615 n = v1->numVals + v2->numVals;
1615 1616 v = am(myself, sizeof (*v));
1616 1617 if (v == 0)
1617 1618 return (0);
1618 1619 v->val = am(myself, n * sizeof (v->val[0]));
1619 1620 if (v->val == 0) {
1620 1621 free(v);
1621 1622 return (0);
1622 1623 }
1623 1624 v->type = v1->type;
1624 1625 v->numVals = 0;
1625 1626
1626 1627 for (a = 0; a < 2; a++) {
1627 1628 __nis_single_value_t *val = (a == 0) ? v1->val : v2->val;
1628 1629 int numv = (a == 0) ? v1->numVals :
1629 1630 v2->numVals;
1630 1631 for (i = 0; i < numv; i++) {
1631 1632 int clen, alen = val[i].length;
1632 1633
1633 1634 clen = alen;
1634 1635
1635 1636 /*
1636 1637 * Make sure there's a NUL at the end of a string,
1637 1638 * but avoid adding to the allocated length if there's
1638 1639 * already a NUL at the end.
1639 1640 */
1640 1641 if (alen > 0 && v->type == vt_string &&
1641 1642 ((char *)val[i].value)[alen-1] != '\0')
1642 1643 alen += 1;
1643 1644 v->val[v->numVals].value = am(myself, alen);
1644 1645 if (v->val[v->numVals].value == 0) {
1645 1646 freeValue(v, 1);
1646 1647 return (0);
1647 1648 }
1648 1649 memcpy(v->val[v->numVals].value, val[i].value, clen);
1649 1650 v->val[v->numVals].length = val[i].length;
1650 1651 v->numVals++;
1651 1652 }
1652 1653 }
1653 1654
1654 1655 return (v);
1655 1656 }
1656 1657
1657 1658 __nis_value_t *
1658 1659 splitMappingItem(__nis_mapping_item_t *item, char delim,
1659 1660 __nis_rule_value_t *rv) {
1660 1661 __nis_value_t *val = getMappingItem(item, mit_any,
1661 1662 rv, 0, NULL);
1662 1663 __nis_single_value_t *nval;
1663 1664 int i, n, nv;
1664 1665
1665 1666 if (val == 0)
1666 1667 return (0);
1667 1668 else if (delim == 0 || val->val == 0 || val->numVals <= 0 ||
1668 1669 val->type != vt_string) {
1669 1670 freeValue(val, 1);
1670 1671 return (0);
1671 1672 }
1672 1673
1673 1674 nval = val->val;
1674 1675 nv = val->numVals;
1675 1676 val->repeat = FALSE;
1676 1677 val->val = 0;
1677 1678 val->numVals = 0;
1678 1679
1679 1680 /* In N2L, space and tab delimiters are treated the same */
1680 1681 if (yp2ldap && delim == '\t')
1681 1682 delim = ' ';
1682 1683
1683 1684 /* If the item has multiple values, we split each one independently */
1684 1685 for (i = 0; i < nv; i++) {
1685 1686 char *str;
1686 1687 int s, e;
1687 1688 char *newstr;
1688 1689 __nis_single_value_t *newval;
1689 1690
1690 1691 if (yp2ldap && delim == ' ')
1691 1692 nval[i].value = trimWhiteSpaces(nval[i].value,
1692 1693 &nval[i].length, 1);
1693 1694
1694 1695 str = nval[i].value;
1695 1696
1696 1697 if (nval[i].value == 0)
1697 1698 continue;
1698 1699
1699 1700 for (s = 0; s < nval[i].length; s = e+1) {
1700 1701 /* Find the next delimiter, or end-of-string */
1701 1702 for (e = s; str[e] != '\0' && str[e] != delim; e++);
1702 1703 /*
1703 1704 * 'str[e]' is either a delimiter, or the concluding
1704 1705 * NUL. Make sure it's NUL.
1705 1706 */
1706 1707 str[e] = '\0';
1707 1708 /* Add to val->val */
1708 1709 newstr = strdup(&str[s]);
1709 1710 newval = realloc(val->val,
1710 1711 (val->numVals+1) *
1711 1712 sizeof (val->val[0]));
1712 1713 if (newval != 0)
1713 1714 val->val = newval;
1714 1715 if (newstr == 0 || newval == 0) {
1715 1716 freeValue(val, 1);
1716 1717 for (n = i; n < nv; n++) {
1717 1718 sfree(nval[n].value);
1718 1719 }
1719 1720 free(nval);
1720 1721 sfree(newstr);
1721 1722 return (0);
1722 1723 }
1723 1724 val->val[val->numVals].value = newstr;
1724 1725 val->val[val->numVals].length = strlen(newstr) + 1;
1725 1726 val->numVals++;
1726 1727 }
1727 1728 free(nval[i].value);
1728 1729 nval[i].value = 0;
1729 1730 }
1730 1731 /* Already freed the nval[i].value's as we traversed nval */
1731 1732 free(nval);
1732 1733
1733 1734 return (val);
1734 1735 }
1735 1736
1736 1737 /*
1737 1738 * Match the format spec 'f[curf]' to the input value string 'str'.
1738 1739 *
1739 1740 * If successful, returns the updated position in the value string 'str'.
1740 1741 * Otherwise, NULL is returned.
1741 1742 *
1742 1743 * curf Current index (i.e., the one we should look at) in 'f'
1743 1744 * nf Number of elements in 'f', including 'mmt_end'
1744 1745 * str The value string we're scanning
1745 1746 * val Pointer to where an item value (if any) should be returned
1746 1747 * Set to NULL if not an 'mmt_item'.
1747 1748 * fmtstart If non-zero on entry, skip characters in 'str' until we find
1748 1749 * the f[curf].type data, if doing so makes any sense. On exit,
1749 1750 * set to the start of the fmt element data (which will be 'str',
1750 1751 * unless we did skip characters)
1751 1752 * sepset List of separators
1752 1753 */
1753 1754 char *
1754 1755 scanMappingFormat(__nis_mapping_format_t *f, int curf, int nf, char *str,
1755 1756 char **val, char **fmtstart, char *sepset) {
1756 1757 char *mstr, *next, *start = 0, *tmpstr;
1757 1758 int i, len;
1758 1759 bool_t match;
1759 1760 char *myself = "scanMappingFormat";
1760 1761 /* N2L variables */
1761 1762 int af, skipspaces = 0;
1762 1763 bool_t ipaddr = FALSE;
1763 1764 char *spacestr = " ", *emptystr = "";
1764 1765
1765 1766
1766 1767 if (f == 0 || curf < 0 || nf <= 0 || str == 0)
1767 1768 return (0);
1768 1769
1769 1770 /*
1770 1771 * If separator list is NULL (which will be the case for
1771 1772 * nis+2ldap), then simply use empty string
1772 1773 */
1773 1774 if (sepset == 0)
1774 1775 sepset = emptystr;
1775 1776
1776 1777 if (curf >= nf) {
1777 1778 /* OK if the string also is exhausted */
1778 1779 if (strchr(sepset, *str) != 0)
1779 1780 return (str);
1780 1781 else
1781 1782 return (0);
1782 1783 }
1783 1784
1784 1785 switch (f[curf].type) {
1785 1786 case mmt_berstring:
1786 1787 if (f[curf].match.berString[0] != 'a') {
1787 1788 /* Not a matchable element */
1788 1789 return (0);
1789 1790 }
1790 1791
1791 1792 /*
1792 1793 * If here, it means it's an IP address (N2L case)
1793 1794 * So continue processing as if it was mmt_item
1794 1795 */
1795 1796 ipaddr = TRUE;
1796 1797
1797 1798 case mmt_item:
1798 1799 /*
1799 1800 * In order to find the end of the item value, we must look
1800 1801 * ahead and determine the start of the next formatting element.
1801 1802 * If successful, 'next' will be the start of the fmt element
1802 1803 * after the next one; we don't care about that, other than to
1803 1804 * check for error.
1804 1805 *
1805 1806 * Since an item match is somewhat like an any match, in that
1806 1807 * we don't know a priori if the first occurence of the next
1807 1808 * element really is the one we want, we have to scan ahead
1808 1809 * until we've reached the end.
1809 1810 */
1810 1811 tmpstr = str;
1811 1812 while ((next = scanMappingFormat(f, curf+1, nf, tmpstr, 0,
1812 1813 &start, sepset)) != 0) {
1813 1814 char *tmp = next;
1814 1815 int cf;
1815 1816
1816 1817 for (cf = curf+2; cf < nf; cf++) {
1817 1818 tmp = scanMappingFormat(f, cf, nf, tmp, 0,
1818 1819 0, sepset);
1819 1820 if (tmp == 0)
1820 1821 break;
1821 1822 }
1822 1823 if (tmp == 0) {
1823 1824 tmpstr = next;
1824 1825 } else if (strchr(sepset, *tmp) != 0) {
1825 1826 break;
1826 1827 } else {
1827 1828 return (0);
1828 1829 }
1829 1830
1830 1831 }
1831 1832 if (next == 0 || start == 0)
1832 1833 return (0);
1833 1834
1834 1835 if (val != 0) {
1835 1836 len = (int)((long)start - (long)str);
1836 1837 *val = am(myself, len + 1);
1837 1838 if (*val == 0)
1838 1839 return (0);
1839 1840 memcpy(*val, str, len);
1840 1841 (*val)[len] = '\0';
1841 1842
1842 1843 if (ipaddr == TRUE) {
1843 1844 /*
1844 1845 * In N2L, we need to check if *val is truly an
1845 1846 * IP address
1846 1847 */
1847 1848 af = checkIPaddress(*val, len, &tmpstr);
1848 1849
1849 1850 if (af == -2) {
1850 1851 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1851 1852 "%s:Internal error while "
1852 1853 "processing IPaddress %s",
1853 1854 myself, *val);
1854 1855 sfree(*val);
1855 1856 return (0);
1856 1857 } else if (af == -1) {
1857 1858 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1858 1859 "%s:%s is not an IP address",
1859 1860 myself, *val);
1860 1861 sfree(*val);
1861 1862 return (0);
1862 1863 } else if (af == 0) {
1863 1864 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1864 1865 "%s:IP address %s is not "
1865 1866 "supported by rfc2307bis",
1866 1867 myself, *val);
1867 1868 sfree(*val);
1868 1869 return (0);
1869 1870 } else if (sstrncmp(*val, tmpstr, len) != 0) {
1870 1871 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1871 1872 "%s:IPaddress %s converted "
1872 1873 "to %s", myself, *val, tmpstr);
1873 1874 }
1874 1875
1875 1876 sfree(*val);
1876 1877 *val = tmpstr;
1877 1878 }
1878 1879 }
1879 1880
1880 1881 if (fmtstart != 0)
1881 1882 *fmtstart = str;
1882 1883
1883 1884 return (start);
1884 1885
1885 1886 case mmt_string:
1886 1887 if ((mstr = f[curf].match.string) == 0 || *mstr == '\0') {
1887 1888 /*
1888 1889 * Count this as a successful match of an empty
1889 1890 * string.
1890 1891 */
1891 1892 if (fmtstart != 0)
1892 1893 *fmtstart = str;
1893 1894 return (str);
1894 1895 }
1895 1896
1896 1897 /*
1897 1898 * In N2L, if the format string 'mstr' contains only
1898 1899 * whitespaces (spaces and tabs), then it should
1899 1900 * match one or more whitespaces from the input
1900 1901 * string 'str'.
1901 1902 */
1902 1903 if (yp2ldap && strspn(mstr, " \t") == strlen(mstr)) {
1903 1904 mstr = spacestr;
1904 1905 skipspaces = 1;
1905 1906 next = str + strcspn(str, " \t");
1906 1907 /*
1907 1908 * Even if there is no whitespace in 'str',
1908 1909 * it's OK. This is to allow formats like
1909 1910 * "%s %s %s" to match inputs like "foo bar".
1910 1911 */
1911 1912 if (*next == '\0')
1912 1913 mstr = emptystr;
1913 1914 } else {
1914 1915 /* No match string in 'str' => failure */
1915 1916 if ((next = strstr(str, mstr)) == 0)
1916 1917 return (0);
1917 1918 }
1918 1919
1919 1920 /* If 'fmtstart' == 0, we require 'next' == 'str' */
1920 1921 if (fmtstart == 0 && next != str)
1921 1922 return (0);
1922 1923 /* Success; save start of match string if requested */
1923 1924 if (fmtstart != 0)
1924 1925 *fmtstart = next;
1925 1926 /* Update position in the value string */
1926 1927 str = (char *)((long)next + (long)strlen(mstr));
1927 1928
1928 1929 /* Skip whitespaces for N2L */
1929 1930 if (skipspaces == 1)
1930 1931 for (; *str == ' ' || *str == '\t'; str++);
1931 1932
1932 1933 return (str);
1933 1934
1934 1935 case mmt_single:
1935 1936 if (fmtstart != 0) {
1936 1937 match = FALSE;
1937 1938 /* Skip ahead until we match */
1938 1939 for (next = str; *next != '\0'; next++) {
1939 1940 unsigned char *lo = f[curf].match.single.lo;
1940 1941 unsigned char *hi = f[curf].match.single.hi;
1941 1942
1942 1943 for (i = 0; i < f[curf].match.single.numRange;
1943 1944 i++) {
1944 1945 if (*next >= lo[i] && *next <= hi[i]) {
1945 1946 match = TRUE;
1946 1947 break;
1947 1948 }
1948 1949 }
1949 1950 if (match)
1950 1951 break;
1951 1952 }
1952 1953 if (!match)
1953 1954 return (0);
1954 1955 *fmtstart = next;
1955 1956 str = next;
1956 1957 } else {
1957 1958 match = FALSE;
1958 1959 for (i = 0; i < f[curf].match.single.numRange; i++) {
1959 1960 if (*str >= f[curf].match.single.lo[i] &&
1960 1961 *str <= f[curf].match.single.hi[i]) {
1961 1962 match = TRUE;
1962 1963 break;
1963 1964 }
1964 1965 }
1965 1966 if (!match)
1966 1967 return (0);
1967 1968 }
1968 1969 /* Step over the matched character */
1969 1970 str++;
1970 1971 return (str);
1971 1972
1972 1973 case mmt_any:
1973 1974 /*
1974 1975 * Look ahead to find the beginning of the next element.
1975 1976 * Because a wildcard-match isn't necessarily uniquely
1976 1977 * determined until we've reached the end, we then continue
1977 1978 * to scan ahead.
1978 1979 */
1979 1980 while ((next = scanMappingFormat(f, curf+1, nf, str, 0,
1980 1981 &start, sepset)) != 0) {
1981 1982 char *tmp = next;
1982 1983 int cf;
1983 1984
1984 1985 for (cf = curf+2; cf < nf; cf++) {
1985 1986 tmp = scanMappingFormat(f, cf, nf, tmp, 0,
1986 1987 0, sepset);
1987 1988 if (tmp == 0)
1988 1989 break;
1989 1990 }
1990 1991 if (tmp == 0) {
1991 1992 str = next;
1992 1993 } else if (*tmp == '\0') {
1993 1994 break;
1994 1995 } else {
1995 1996 return (0);
1996 1997 }
1997 1998 }
1998 1999 if (next == 0 || start == 0)
1999 2000 return (0);
2000 2001
2001 2002 if (fmtstart != 0)
2002 2003 *fmtstart = str;
2003 2004
2004 2005 return (start);
2005 2006
2006 2007 case mmt_limit:
2007 2008 if (f[curf].match.limit == eos) {
2008 2009 if (fmtstart != 0) {
2009 2010 /* Skip to the end */
2010 2011 str = str + strcspn(str, sepset);
2011 2012 *fmtstart = str;
2012 2013 } else if (strchr(sepset, *str) == 0) {
2013 2014 return (0);
2014 2015 }
2015 2016 }
2016 2017 return (str);
2017 2018
2018 2019 case mmt_begin:
2019 2020 if (fmtstart != 0)
2020 2021 *fmtstart = str;
2021 2022 return (str);
2022 2023
2023 2024 case mmt_end:
2024 2025 if (fmtstart != 0) {
2025 2026 /* Skip to the end */
2026 2027 str = str + strcspn(str, sepset);
2027 2028 *fmtstart = str;
2028 2029 return (str);
2029 2030 }
2030 2031 /* No skipping, so we must be at the end of the value */
2031 2032 if (strchr(sepset, *str) == 0)
2032 2033 return (0);
2033 2034 return (str);
2034 2035
2035 2036 default:
2036 2037 break;
2037 2038 }
2038 2039
2039 2040 return (0);
2040 2041 }
2041 2042
2042 2043 /*
2043 2044 * Verify that the string 'str' matches the mapping format array 'f'.
2044 2045 * Returns 1 in case of a match, 0 otherwise.
2045 2046 */
2046 2047 int
2047 2048 verifyMappingMatch(__nis_mapping_format_t *f, char *str) {
2048 2049 int n, nf;
2049 2050 __nis_mapping_format_t *ftmp;
2050 2051
2051 2052 /* Count the number of format elements in the format */
2052 2053 for (nf = 0, ftmp = f; ftmp->type != mmt_end; ftmp++) {
2053 2054 nf++;
2054 2055 }
2055 2056 /* Count the mmt_end as well */
2056 2057 nf++;
2057 2058
2058 2059 for (n = 0; n < nf; n++) {
2059 2060 str = scanMappingFormat(f, n, nf, str, 0, 0, 0);
2060 2061 if (str == 0)
2061 2062 break;
2062 2063 }
2063 2064
2064 2065 return ((str != 0) ? 1 : 0);
2065 2066 }
2066 2067
2067 2068 /*
2068 2069 * Perform a match operation. For example, given the rule
2069 2070 * ("{%s}%s", auth_name, public_data)=nisPublicKey
2070 2071 * and assuming that 'nisPublicKey' has the value "{dh640-0}abcdef12345",
2071 2072 * assign "dh640-0" to 'auth_name' and "abcdef12345" to 'public_data'.
2072 2073 *
2073 2074 * Note that this function doesn't perform the actual assignment. Rather,
2074 2075 * it returns an array of __nis_value_t's, with element zero of the value
2075 2076 * array being the new value of the first matched item, element one the
2076 2077 * value of the second matched item, etc. In the example above, we'd
2077 2078 * return a value array with two elements.
2078 2079 *
2079 2080 * If there is more than one input value (inVal->numVals > 1), the
2080 2081 * output array elements will also be multi-valued.
2081 2082 *
2082 2083 * f The match format
↓ open down ↓ |
2051 lines elided |
↑ open up ↑ |
2083 2084 * inVal Input value(s)
2084 2085 * numVal Number of elements in the output value array
2085 2086 * sepset List of separators
2086 2087 * outstr Points to the updated position upto which the
2087 2088 * input string has been matched
2088 2089 */
2089 2090 __nis_value_t **
2090 2091 matchMappingItem(__nis_mapping_format_t *f, __nis_value_t *inVal,
2091 2092 int *numVals, char *sepset, char **outstr) {
2092 2093 __nis_value_t **v = 0;
2093 - int i, n, ni, numItems, nf, nv = 0;
2094 + int i, n, ni, numItems, nf;
2094 2095 char *str, *valstr;
2095 2096 __nis_mapping_format_t *ftmp;
2096 2097 char *myself = "matchMappingItem";
2097 2098
2098 2099 if (f == 0 ||
2099 2100 inVal == 0 || inVal->numVals < 1 || inVal->type != vt_string)
2100 2101 return (0);
2101 2102
2102 2103 /* Count the number of format elements and items in the format */
2103 2104 for (nf = numItems = 0, ftmp = f; ftmp->type != mmt_end; ftmp++) {
2104 2105 nf++;
2105 2106
2106 2107 /*
2107 2108 * Count mmt_item and mmt_berstring (used by N2L to
2108 2109 * represent address %a)
2109 2110 */
2110 2111 if (ftmp->type == mmt_item)
2111 2112 numItems++;
2112 2113 else if (ftmp->type == mmt_berstring && ftmp->match.berString &&
2113 2114 ftmp->match.berString[0] == 'a')
2114 2115 numItems++;
2115 2116 }
2116 2117 /* Count the mmt_end as well */
2117 2118 nf++;
2118 2119
2119 2120 /*
2120 2121 * If no items, there will be no values. This isn't exactly an error
2121 2122 * from the limited point of view of this function, so we return a
2122 2123 * __nis_value_t with zero values.
2123 2124 */
2124 2125 if (numItems <= 0) {
2125 2126 v = am(myself, sizeof (v[0]));
2126 2127 if (v == 0)
2127 2128 return (0);
2128 2129 v[0] = am(myself, sizeof (*v[0]));
2129 2130 if (v[0] == 0) {
2130 2131 sfree(v);
2131 2132 return (0);
2132 2133 }
2133 2134 v[0]->type = vt_string;
2134 2135 v[0]->numVals = 0;
2135 2136 v[0]->val = 0;
2136 2137 if (numVals != 0)
2137 2138 *numVals = 1;
2138 2139 return (v);
2139 2140 }
2140 2141
2141 2142 /* Allocate and initialize the return array */
2142 2143 v = am(myself, numItems * sizeof (v[0]));
2143 2144 if (v == 0)
2144 2145 return (0);
2145 2146 for (n = 0; n < numItems; n++) {
2146 2147 v[n] = am(myself, sizeof (*v[n]));
2147 2148 if (v[n] == 0) {
2148 2149 int j;
2149 2150
2150 2151 for (j = 0; j < n; j++)
2151 2152 freeValue(v[j], 1);
2152 2153 sfree(v);
2153 2154 return (0);
2154 2155 }
2155 2156 v[n]->type = vt_string;
2156 2157 v[n]->numVals = 0;
2157 2158 v[n]->val = am(myself, inVal->numVals * sizeof (v[n]->val[0]));
2158 2159 if (v[n]->val == 0) {
2159 2160 int j;
2160 2161
2161 2162 for (j = 0; j < n; j++)
2162 2163 freeValue(v[j], 1);
2163 2164 sfree(v);
2164 2165 return (0);
2165 2166 }
2166 2167 for (i = 0; i < inVal->numVals; i++) {
2167 2168 v[n]->val[i].length = 0;
2168 2169 v[n]->val[i].value = 0;
2169 2170 }
2170 2171 }
2171 2172
2172 2173 /* For each input value, perform the match operation */
2173 2174 for (i = 0; i < inVal->numVals; i++) {
2174 2175 str = inVal->val[i].value;
2175 2176 if (str == 0)
2176 2177 continue;
2177 2178 for (n = 0, ni = 0; n < nf; n++) {
2178 2179 valstr = 0;
2179 2180 str = scanMappingFormat(f, n, nf, str, &valstr,
2180 2181 0, sepset);
2181 2182 if (str == 0)
2182 2183 break;
2183 2184 if (valstr != 0 && ni < numItems &&
2184 2185 v[ni]->numVals < inVal->numVals) {
2185 2186 v[ni]->val[v[ni]->numVals].value = valstr;
2186 2187 v[ni]->val[v[ni]->numVals].length =
2187 2188 strlen(valstr) + 1;
2188 2189 v[ni]->numVals++;
2189 2190 ni++;
2190 2191 } else if (valstr != 0) {
2191 2192 sfree(valstr);
2192 2193 }
2193 2194 }
2194 2195 if (str == 0) {
2195 2196 for (n = 0; n < numItems; n++)
2196 2197 freeValue(v[n], 1);
2197 2198 sfree(v);
2198 2199 return (0);
2199 2200 }
2200 2201 }
2201 2202
2202 2203 if (numVals != 0)
2203 2204 *numVals = numItems;
2204 2205
2205 2206 /*
2206 2207 * Update the return string upto the point it has been matched
2207 2208 * This string will be used by the N2L code in its next call
2208 2209 * to this function
2209 2210 */
2210 2211 if (outstr != 0)
2211 2212 *outstr = str;
2212 2213
2213 2214 return (v);
2214 2215 }
2215 2216
2216 2217 /*
2217 2218 * Perform an extract operation. For example, given the expression
2218 2219 * (name, "%s.*")
2219 2220 * and assuming 'name' is an item with the value "some.thing", the
2220 2221 * value returned by the extract is "some".
2221 2222 */
2222 2223 __nis_value_t *
2223 2224 extractMappingItem(__nis_mapping_item_t *item, __nis_mapping_format_t *f,
2224 2225 __nis_rule_value_t *rv, int *stat) {
2225 2226 __nis_value_t *val = getMappingItem(item, mit_any,
2226 2227 rv, 0, stat);
2227 2228 __nis_single_value_t *nval;
2228 2229 int i, n, nv, nf;
2229 2230 __nis_mapping_format_t *ftmp;
2230 2231
2231 2232 if (val == 0)
2232 2233 return (0);
2233 2234 else if (f == 0 || rv == 0 || val->val == 0 ||
2234 2235 val->numVals <= 0 || val->type != vt_string) {
2235 2236 freeValue(val, 1);
2236 2237 return (0);
2237 2238 }
2238 2239
2239 2240 /* Sanity check the format; it must have one and only one mmt_item */
2240 2241 {
2241 2242 int numitem;
2242 2243
2243 2244 for (nf = numitem = 0, ftmp = f; ftmp->type != mmt_end;
2244 2245 ftmp++) {
2245 2246 nf++;
2246 2247 if (ftmp->type == mmt_item)
2247 2248 numitem++;
2248 2249 }
2249 2250 /* Count the mmt_end as well */
2250 2251 nf++;
2251 2252 if (numitem != 1) {
2252 2253 freeValue(val, 1);
2253 2254 return (0);
2254 2255 }
2255 2256 }
2256 2257
2257 2258 nval = val->val;
2258 2259 nv = val->numVals;
2259 2260 val->repeat = FALSE;
2260 2261 val->val = 0;
2261 2262 val->numVals = 0;
2262 2263
2263 2264 /* If the item has multiple values, we extract each one independently */
2264 2265 for (i = 0; i < nv; i++) {
2265 2266 char *str = nval[i].value;
2266 2267 char *newstr = 0;
2267 2268 __nis_single_value_t *newval;
2268 2269
2269 2270 if (nval[i].value == 0)
2270 2271 continue;
2271 2272
2272 2273 /*
2273 2274 * We match the whole string, even if we find a value for
2274 2275 * the item before exhausting all format elements. By doing
2275 2276 * this, we ensure that the string really matches the complete
2276 2277 * format specification.
2277 2278 */
2278 2279 for (n = 0; n < nf; n++) {
2279 2280 str = scanMappingFormat(f, n, nf, str, &newstr, 0, 0);
2280 2281 if (str == 0)
2281 2282 break;
2282 2283 }
2283 2284
2284 2285 /*
2285 2286 * *str should now be NUL, meaning we've reached the end of
2286 2287 * the string (value), and it completely matched the format.
2287 2288 * If 'str' is NULL, there was an error, and if 'newstr' is
2288 2289 * 0, we somehow failed to obtain a value.
2289 2290 */
2290 2291 if (str == 0 || *str != '\0' || newstr == 0 ||
2291 2292 (newval = realloc(val->val,
2292 2293 (val->numVals+1) *
2293 2294 sizeof (val->val[0]))) == 0) {
2294 2295 freeValue(val, 1);
2295 2296 for (n = 0; n < nv; n++) {
2296 2297 sfree(nval[n].value);
2297 2298 }
2298 2299 free(nval);
2299 2300 sfree(newstr);
2300 2301 return (0);
2301 2302 }
2302 2303
2303 2304 val->val = newval;
2304 2305 val->val[val->numVals].value = newstr;
2305 2306 val->val[val->numVals].length = strlen(newstr) + 1;
2306 2307 val->numVals++;
2307 2308
2308 2309 free(nval[i].value);
2309 2310 nval[i].value = 0;
2310 2311 }
2311 2312 free(nval);
2312 2313
2313 2314 return (val);
2314 2315 }
2315 2316
2316 2317 /*
2317 2318 * For each value in 'val', remove the last character, provided that
2318 2319 * it matches 'elide'.
2319 2320 */
2320 2321 void
2321 2322 stringElide(__nis_value_t *val, char elide) {
2322 2323
2323 2324 if (val != 0 && val->type == vt_string) {
2324 2325 int i;
2325 2326
2326 2327 for (i = 0; i < val->numVals; i++) {
2327 2328 int end = val->val[i].length;
2328 2329 char *str = val->val[i].value;
2329 2330
2330 2331 if (str == 0 || end <= 0)
2331 2332 continue;
2332 2333
2333 2334 /*
2334 2335 * If the NUL was counted in the length, step back
2335 2336 * over it.
2336 2337 */
2337 2338 if (str[end-1] == '\0')
2338 2339 end--;
2339 2340 if (end > 0 && str[end-1] == elide) {
2340 2341 str[end-1] = '\0';
2341 2342 val->val[i].length--;
2342 2343 }
2343 2344 }
2344 2345 }
2345 2346 }
2346 2347
2347 2348 /*
2348 2349 * Obtain the value for the mapping sub-element 'e', given the input
2349 2350 * rule-value 'rv'.
2350 2351 */
2351 2352 __nis_value_t *
2352 2353 getMappingSubElement(__nis_mapping_sub_element_t *e,
2353 2354 __nis_rule_value_t *rv, int *np_ldap_stat) {
2354 2355 __nis_value_t *val;
2355 2356
2356 2357 if (e == 0)
2357 2358 return (0);
2358 2359
2359 2360 switch (e->type) {
2360 2361 case me_item:
2361 2362 val = getMappingItem(&e->element.item, mit_any, rv, 0,
2362 2363 np_ldap_stat);
2363 2364 break;
2364 2365 case me_print:
2365 2366 val = getMappingFormatArray(e->element.print.fmt, rv,
2366 2367 fa_item,
2367 2368 e->element.print.numItems,
2368 2369 e->element.print.item);
2369 2370 if (e->element.print.doElide)
2370 2371 stringElide(val, e->element.print.elide);
2371 2372 break;
2372 2373 case me_split:
2373 2374 val = splitMappingItem(&e->element.split.item,
2374 2375 e->element.split.delim,
2375 2376 rv);
2376 2377 break;
2377 2378 case me_extract:
2378 2379 val = extractMappingItem(&e->element.extract.item,
2379 2380 e->element.extract.fmt,
2380 2381 rv, np_ldap_stat);
2381 2382 break;
2382 2383 case me_match:
2383 2384 default:
2384 2385 val = 0;
2385 2386 break;
2386 2387 }
2387 2388
2388 2389 return (val);
2389 2390 }
2390 2391
2391 2392 /*
2392 2393 * Obtain the value of the mapping element 'e', given the input rule-
2393 2394 * value 'rv'. The 'native' mapping type is used when 'rv' is NULL,
2394 2395 * and the result is a string representation of the mapping element;
2395 2396 * in that case, items of the 'native' type are printed without their
2396 2397 * type designation ("nis+" or "ldap").
2397 2398 */
2398 2399 __nis_value_t *
2399 2400 getMappingElement(__nis_mapping_element_t *e, __nis_mapping_item_type_t native,
2400 2401 __nis_rule_value_t *rv, int *stat) {
2401 2402 __nis_value_t *val, **tv;
2402 2403 int i, success = 0, novalue = 0;
2403 2404 int *np_ldap_stat;
2404 2405 char *myself = "getMappingElement";
2405 2406
2406 2407 switch (e->type) {
2407 2408 case me_item:
2408 2409 val = getMappingItem(&e->element.item, native, rv, 0, NULL);
2409 2410 break;
2410 2411 case me_print:
2411 2412 tv = am(myself, e->element.print.numSubElements *
2412 2413 sizeof (tv[0]));
2413 2414 np_ldap_stat = am(myself,
2414 2415 e->element.print.numSubElements * sizeof (int));
2415 2416 if ((e->element.print.numSubElements > 0) &&
2416 2417 (tv == 0 || np_ldap_stat == 0)) {
2417 2418 val = 0;
2418 2419 sfree(tv);
2419 2420 sfree(np_ldap_stat);
2420 2421 break;
2421 2422 }
2422 2423 for (i = 0; i < e->element.print.numSubElements; i++) {
2423 2424 np_ldap_stat[i] = 0;
2424 2425 tv[i] = getMappingSubElement(
2425 2426 &e->element.print.subElement[i],
2426 2427 rv, &np_ldap_stat[i]);
2427 2428 }
2428 2429 /*
2429 2430 * if we get NP_LDAP_NO_VALUE to any of the subelement
2430 2431 * and we get NP_LDAP_MAP_SUCCESS to all other subelement
2431 2432 * then we had enough nis+ column values which can
2432 2433 * produce value for this rule, but didn't. So return
2433 2434 * NP_LDAP_RULES_NO_VALUE to indicate to proceed to
2434 2435 * next database id.
2435 2436 */
2436 2437 for (i = 0; i < e->element.print.numSubElements; i++) {
2437 2438 if (np_ldap_stat[i] == NP_LDAP_MAP_SUCCESS)
2438 2439 success++;
2439 2440 if (np_ldap_stat[i] == NP_LDAP_NO_VALUE)
2440 2441 novalue++;
2441 2442 }
2442 2443 if (stat != NULL && novalue > 0 &&
2443 2444 ((novalue+success) ==
2444 2445 e->element.print.numSubElements))
2445 2446 *stat = NP_LDAP_RULES_NO_VALUE;
2446 2447 val = getMappingFormatArray(e->element.print.fmt, rv,
2447 2448 fa_value,
2448 2449 e->element.print.numSubElements,
2449 2450 tv);
2450 2451 for (i = 0; i < e->element.print.numSubElements; i++) {
2451 2452 freeValue(tv[i], 1);
2452 2453 }
2453 2454 sfree(tv);
2454 2455 sfree(np_ldap_stat);
2455 2456 if (e->element.print.doElide)
2456 2457 stringElide(val, e->element.print.elide);
2457 2458 break;
2458 2459 case me_split:
2459 2460 val = splitMappingItem(&e->element.split.item,
2460 2461 e->element.split.delim,
2461 2462 rv);
2462 2463 break;
2463 2464 case me_match:
2464 2465 /*
2465 2466 * A match doesn't produce an assignable value per se,
2466 2467 * so we shouldn't get one here.
2467 2468 */
2468 2469 val = 0;
2469 2470 break;
2470 2471 case me_extract:
2471 2472 val = extractMappingItem(&e->element.extract.item,
2472 2473 e->element.extract.fmt,
2473 2474 rv, NULL);
2474 2475 break;
2475 2476 default:
2476 2477 val = 0;
2477 2478 break;
2478 2479 }
2479 2480
2480 2481 return (val);
2481 2482 }
↓ open down ↓ |
378 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX