Print this page
5910 libnisdb won't build with modern GCC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libnisdb/yptol/dit_access_utils.c
+++ new/usr/src/lib/libnisdb/yptol/dit_access_utils.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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 24 */
24 25
25 26 /*
26 27 * DESCRIPTION: Contains dit_access interface support functions.
27 28 */
28 29 #include <sys/systeminfo.h>
29 30 #include <unistd.h>
30 31 #include <stdlib.h>
31 32 #include <sys/types.h>
32 33 #include <sys/stat.h>
33 34 #include <sys/systeminfo.h>
34 35 #include <unistd.h>
35 36 #include <stdlib.h>
36 37 #include <syslog.h>
37 38 #include <ndbm.h>
38 39 #include <strings.h>
39 40 #include <errno.h>
41 +#include <ctype.h>
40 42 #include "../ldap_util.h"
41 43 #include "../ldap_map.h"
42 44 #include "../ldap_parse.h"
43 45 #include "../ldap_structs.h"
44 46 #include "../ldap_val.h"
45 47 #include "../ldap_ruleval.h"
46 48 #include "../ldap_op.h"
47 49 #include "../ldap_attr.h"
48 50 #include "../ldap_nisdbquery.h"
49 51 #include "../nisdb_mt.h"
50 52 #include "shim.h"
51 53 #include "yptol.h"
52 54 #include "dit_access_utils.h"
53 55
54 56 #define YPMULTI "YP_MULTI_"
55 57 #define YPMULTISZ 9 /* == strlen(YPMULTI) */
56 58
57 59 /*
58 60 * Returns 'map,domain.'
59 61 */
60 62 char *
61 63 getFullMapName(char *map, char *domain) {
62 64 char *myself = "getFullMapName";
63 65 char *objPath;
64 66 if (map == 0 || domain == 0) {
65 67 return (0);
66 68 }
67 69 objPath = scat(myself, T, scat(myself, F, map, ","),
68 70 scat(myself, F, domain, "."));
69 71
70 72 return (objPath);
71 73 }
72 74
73 75 /*
74 76 * Convert string to __nis_value_t
75 77 */
76 78 __nis_value_t *stringToValue(char *dptr, int dsize) {
77 79 char *myself = "stringToValue";
78 80 char *emptystr = "";
79 81 __nis_value_t *val;
80 82
81 83 if ((val = am(myself, sizeof (*val))) == 0) {
82 84 return (0);
83 85 }
84 86
85 87 val->type = vt_string;
86 88 val->repeat = 0;
87 89 val->numVals = 1;
88 90 if ((val->val = am(myself, sizeof (val->val[0]))) == 0) {
89 91 sfree(val);
90 92 return (0);
91 93 }
92 94
93 95 /*
94 96 * Null strings or strings with length 0 are treated
95 97 * as empty strings with length 1
96 98 */
97 99 if (dptr == 0 || dsize <= 0) {
98 100 dptr = emptystr;
99 101 dsize = 1;
100 102 }
101 103
102 104 val->val->length = dsize;
103 105 if (dptr[dsize - 1] != '\0') {
104 106 val->val->length = dsize + 1;
105 107 }
106 108
107 109 val->val->value = am(myself, val->val->length);
108 110 if (val->val->value == 0) {
109 111 freeValue(val, 1);
110 112 return (0);
111 113 }
112 114 (void) memcpy(val->val->value, dptr, dsize);
113 115
114 116 return (val);
115 117 }
116 118
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
117 119 /*
118 120 * Returns an array of rule-values corresponding to the
119 121 * splitfields.
120 122 */
121 123 __nis_rule_value_t *
122 124 processSplitField(__nis_table_mapping_t *sf, __nis_value_t *inVal,
123 125 int *nv, int *statP) {
124 126
125 127 char *sepset;
126 128 __nis_rule_value_t *rvq;
127 - __nis_mapping_format_t *ftmp;
128 129 __nis_value_t **valA, *tempVal;
129 130 int i, j, res, numVals, oldlen, count;
130 131 char *str, *oldstr;
131 - char *myself = "processSplitField";
132 132
133 133 /* sf will be non NULL */
134 134
135 135 if (inVal == 0 || inVal->type != vt_string) {
136 136 *statP = MAP_PARAM_ERROR;
137 137 return (0);
138 138 }
139 139
140 140 /* Get the separator list */
141 141 sepset = sf->separatorStr;
142 142
143 143 /* Initialize rule-value */
144 144 rvq = 0;
145 145 count = 0;
146 146
147 147 if ((tempVal = stringToValue(inVal->val->value,
148 148 inVal->val->length)) == 0) {
149 149 *statP = MAP_NO_MEMORY;
150 150 return (0);
151 151 }
152 152
153 153 str = oldstr = tempVal->val->value;
154 154 oldlen = tempVal->val->length;
155 155
156 156 while (str) {
157 157 tempVal->val->value = str;
158 158 tempVal->val->length = strlen(str) + 1;
159 159
160 160 /* Loop to check which format matches str */
161 161 for (i = 0; i <= sf->numSplits; i++) {
162 162 valA = matchMappingItem(sf->e[i].element.match.fmt,
163 163 tempVal, &numVals, sepset, &str);
164 164 if (valA == 0) {
165 165 /* The format didn't match. Try the next one */
166 166 continue;
167 167 }
168 168
169 169 /*
170 170 * If we are here means we had a match.
171 171 * Each new set of values obtained from the match is
172 172 * added to a new rule-value. This is to preserve the
173 173 * the distinction between each set.
174 174 */
175 175 rvq = growRuleValue(count, count + 1, rvq, 0);
176 176 if (rvq == 0) {
177 177 *statP = MAP_INTERNAL_ERROR;
178 178 for (j = 0; j < numVals; j++)
179 179 freeValue(valA[j], 1);
180 180 sfree(valA);
181 181 tempVal->val->value = oldstr;
182 182 tempVal->val->length = oldlen;
183 183 freeValue(tempVal, 1);
184 184 return (0);
185 185 }
186 186 count++;
187 187
188 188 for (j = 0; j < numVals; j++) {
189 189 res = addCol2RuleValue(vt_string,
190 190 sf->e[i].element.match.item[j].name,
191 191 valA[j]->val->value,
192 192 valA[j]->val->length,
193 193 &rvq[count - 1]);
194 194 if (res == -1) {
195 195 *statP = MAP_INTERNAL_ERROR;
196 196 for (; j < numVals; j++)
197 197 freeValue(valA[j], 1);
198 198 sfree(valA);
199 199 tempVal->val->value = oldstr;
200 200 tempVal->val->length = oldlen;
201 201 freeValue(tempVal, 1);
202 202 freeRuleValue(rvq, count);
203 203 return (0);
204 204 }
205 205 freeValue(valA[j], 1);
206 206 }
207 207 sfree(valA);
208 208
209 209 /*
210 210 * Since we had a match, break out of this loop
211 211 * to parse remainder of str
212 212 */
213 213 break;
214 214 }
215 215
216 216 /* Didn't find any match, so get out of the loop */
217 217 if (i > sf->numSplits) {
218 218 str = 0;
219 219 break;
220 220 }
221 221
222 222 /* Skip the separators before looping back */
223 223 if (str) {
224 224 str = str + strspn(str, sepset);
225 225 if (*str == '\0')
226 226 break;
227 227 }
228 228 }
229 229
230 230 tempVal->val->value = oldstr;
231 231 tempVal->val->length = oldlen;
232 232 freeValue(tempVal, 1);
233 233
234 234 if (str == 0) {
235 235 freeRuleValue(rvq, count);
236 236 return (0);
237 237 }
238 238
239 239 if (nv != 0)
240 240 *nv = count;
241 241
242 242 return (rvq);
243 243 }
244 244
245 245 /*
246 246 * Convert the datum to an array of RuleValues
↓ open down ↓ |
105 lines elided |
↑ open up ↑ |
247 247 */
248 248 __nis_rule_value_t *
249 249 datumToRuleValue(datum *key, datum *value, __nis_table_mapping_t *t,
250 250 int *nv, char *domain, bool_t readonly, int *statP) {
251 251
252 252 __nis_rule_value_t *rvq, *subrvq, *newrvq;
253 253 __nis_value_t *val;
254 254 __nis_value_t **valA;
255 255 __nis_table_mapping_t *sf;
256 256 int valueLen, comLen, numVals, nr, count = 1;
257 - int i, j, k, l, af;
257 + int i, j, k, l;
258 258 char *ipaddr, *ipvalue;
259 259
260 260 /* At this point, 't' is always non NULL */
261 261
262 262 /* Initialize rule-value */
263 263 if ((rvq = initRuleValue(1, 0)) == 0) {
264 264 *statP = MAP_INTERNAL_ERROR;
265 265 return (0);
266 266 }
267 267
268 268 /* Add domainname to rule-value */
269 269 if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain),
270 270 rvq)) {
271 271 freeRuleValue(rvq, 1);
272 272 *statP = MAP_INTERNAL_ERROR;
273 273 return (0);
274 274 }
275 275
276 276 /* Handle key */
277 277 if (key != 0) {
278 278 /* Add field=value pair for N2LKEY */
279 279 i = addCol2RuleValue(vt_string, N2LKEY, key->dptr, key->dsize,
280 280 rvq);
281 281
282 282 /* For readonly, add field=value pair for N2LSEARCHKEY */
283 283 if (readonly == TRUE && i == 0) {
284 284 i = addCol2RuleValue(vt_string, N2LSEARCHKEY, key->dptr,
285 285 key->dsize, rvq);
286 286 }
287 287 if (i) {
288 288 freeRuleValue(rvq, 1);
289 289 *statP = MAP_INTERNAL_ERROR;
290 290 return (0);
291 291 }
292 292
293 293 /* Add field=value pairs for IP addresses */
294 294 if (checkIPaddress(key->dptr, key->dsize, &ipaddr) > 0) {
295 295 /* If key is IPaddress, use preferred format */
296 296 ipvalue = ipaddr;
297 297 valueLen = strlen(ipaddr);
298 298 i = addCol2RuleValue(vt_string, N2LIPKEY, ipvalue,
299 299 valueLen, rvq);
300 300 } else {
301 301 /* If not, use original value for N2LSEARCHIPKEY */
302 302 ipaddr = 0;
303 303 ipvalue = key->dptr;
304 304 valueLen = key->dsize;
305 305 i = 0;
306 306 }
307 307
308 308 if (readonly == TRUE && i == 0) {
309 309 i = addCol2RuleValue(vt_string, N2LSEARCHIPKEY, ipvalue,
310 310 valueLen, rvq);
311 311 }
312 312 sfree(ipaddr);
313 313 if (i) {
314 314 freeRuleValue(rvq, 1);
315 315 *statP = MAP_INTERNAL_ERROR;
316 316 return (0);
317 317 }
318 318 }
319 319
320 320 /* Handle datum value */
321 321 if (value != 0 && t->e) {
322 322 valueLen = value->dsize;
323 323 /*
324 324 * Extract the comment, if any, and add it to
325 325 * the rule-value.
326 326 */
327 327 if (t->commentChar != '\0') {
328 328 /*
329 329 * We loop on value->dsize because value->dptr
330 330 * may not be NULL-terminated.
331 331 */
332 332 for (i = 0; i < value->dsize; i++) {
333 333 if (value->dptr[i] == t->commentChar) {
334 334 valueLen = i;
335 335 comLen = value->dsize - i - 1;
336 336 if (comLen == 0)
337 337 break;
338 338 if (addCol2RuleValue(vt_string,
339 339 N2LCOMMENT, value->dptr + i + 1,
340 340 comLen, rvq)) {
341 341 freeRuleValue(rvq, 1);
342 342 *statP = MAP_INTERNAL_ERROR;
343 343 return (0);
344 344 }
345 345 break;
346 346 }
347 347 }
348 348 }
349 349
350 350 /* Skip trailing whitespaces */
351 351 for (; valueLen > 0 && (value->dptr[valueLen - 1] == ' ' ||
352 352 value->dptr[valueLen - 1] == '\t'); valueLen--);
353 353
354 354 /*
355 355 * At this point valueLen is the effective length of
356 356 * the data. Convert value into __nis_value_t so that
357 357 * we can use the matchMappingItem function to break it
358 358 * into fields.
359 359 */
360 360 if ((val = stringToValue(value->dptr, valueLen)) == 0) {
361 361 freeRuleValue(rvq, 1);
362 362 *statP = MAP_NO_MEMORY;
363 363 return (0);
364 364 }
365 365
366 366 /* Perform namefield match */
367 367 valA = matchMappingItem(t->e->element.match.fmt, val,
368 368 &numVals, 0, 0);
369 369 if (valA == 0) {
370 370 freeValue(val, 1);
371 371 freeRuleValue(rvq, 1);
372 372 *statP = MAP_NAMEFIELD_MATCH_ERROR;
373 373 return (0);
374 374 }
375 375
376 376 /* We don't need val anymore, so free it */
377 377 freeValue(val, 1);
378 378
379 379 /*
380 380 * Since matchMappingItem only returns us an array of
381 381 * __nis_value_t's, we need to associate each value
382 382 * in the array with the corresponding item name.
383 383 * This code assumes that numVals will be less than or
384 384 * equal to the number of item names associated with
385 385 * the format.
386 386 * These name=value pairs are added to rvq.
387 387 */
388 388 for (i = 0, *statP = SUCCESS; i < numVals; i++) {
389 389 for (j = 0; j < count; j++) {
390 390 if (addCol2RuleValue(vt_string,
391 391 t->e->element.match.item[i].name,
392 392 valA[i]->val->value,
393 393 valA[i]->val->length, &rvq[j])) {
394 394 *statP = MAP_INTERNAL_ERROR;
395 395 break;
396 396 }
397 397 }
398 398 if (*statP == MAP_INTERNAL_ERROR)
399 399 break;
400 400
401 401 /*
402 402 * Check if splitField exists for the field.
403 403 * Since splitfields are also stored as mapping
404 404 * structures, we need to get the hash table entry
405 405 * corresponding to the splitfield name
406 406 */
407 407 sf = mappingFromMap(t->e->element.match.item[i].name,
408 408 domain, statP);
409 409 if (*statP == MAP_NO_MEMORY)
410 410 break;
411 411 *statP = SUCCESS;
412 412 if (sf == 0)
413 413 continue;
414 414
415 415 /*
416 416 * Process and add splitFields to rule-value rvq
417 417 */
418 418 subrvq = processSplitField(sf, valA[i], &nr, statP);
419 419
420 420 if (subrvq == 0) {
421 421 /* statP would have been set */
422 422 break;
423 423 }
424 424
425 425 /*
426 426 * We merge 'count' rule-values in rvq with 'nr'
427 427 * rule-values from subrvq to give us a whopping
428 428 * 'count * nr' rule-values
429 429 */
430 430
431 431 /* Initialize the new rule-value array */
432 432 if ((newrvq = initRuleValue(count * nr, 0)) == 0) {
433 433 *statP = MAP_INTERNAL_ERROR;
434 434 freeRuleValue(subrvq, nr);
435 435 break;
436 436 }
437 437
438 438 for (j = 0, l = 0; j < nr; j++) {
439 439 for (k = 0; k < count; k++, l++) {
440 440 if ((mergeRuleValue(&newrvq[l],
441 441 &rvq[k]) == -1) ||
442 442 (mergeRuleValue(
443 443 &newrvq[l],
444 444 &subrvq[j]) == -1)) {
445 445 *statP = MAP_INTERNAL_ERROR;
446 446 for (i = 0; i < numVals; i++)
447 447 freeValue(valA[i], 1);
448 448 sfree(valA);
449 449 freeRuleValue(rvq, count);
450 450 freeRuleValue(newrvq,
451 451 count * nr);
452 452 freeRuleValue(subrvq, nr);
453 453 return (0);
454 454 }
455 455 }
456 456 }
457 457
458 458 freeRuleValue(rvq, count);
459 459 rvq = newrvq;
460 460 count = l;
461 461 freeRuleValue(subrvq, nr);
462 462
463 463 }
464 464
465 465 /* We don't need valA anymore, so free it */
466 466 for (i = 0; i < numVals; i++)
467 467 freeValue(valA[i], 1);
468 468 sfree(valA);
469 469
470 470 if (*statP != SUCCESS) {
471 471 freeRuleValue(rvq, count);
472 472 return (0);
473 473 }
474 474
475 475 } /* if value */
476 476
477 477 if (nv != 0)
478 478 *nv = count;
479 479 return (rvq);
480 480
481 481 }
482 482
483 483 /*
484 484 * Generate name=values pairs for splitfield names
485 485 *
486 486 * Consider Example:
487 487 * nisLDAPnameFields club:
488 488 * ("%s %s %s", name, code, members)
489 489 * nisLDAPsplitField members:
490 490 * ("(%s,%s,%s)", host, user, domain),
491 491 * ("%s", group)
492 492 * On entry,
493 493 * - rv is an array of numVals rule-values each containing
494 494 * name=value pairs for names occuring in nisLDAPsplitField.
495 495 * (i.e host, user, domain, group)
496 496 * - trv contains name=value pairs for names occuring in
497 497 * nisLDAPnameFields. (i.e name, code but not members)
498 498 *
499 499 * For every name in nisLDAPnamefields that is a splitfield,
500 500 * this function applies the data in rv to the corresponding
501 501 * splitfield formats (accessed thru t), to generate a single
502 502 * string value for the corresponding splitfield (members).
503 503 * This new name=value pair is then added to trv.
504 504 * Besides, any uninitialized namefield names are set to empty strings.
505 505 */
506 506 suc_code
507 507 addSplitFieldValues(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
508 508 __nis_rule_value_t *trv, int numVals, char *domain) {
509 509 __nis_table_mapping_t *sf;
510 510 __nis_value_t *val;
511 511 int i, j, k, nitems, res, statP;
512 512 char *str, *tempstr;
513 513 char delim[2] = {0, 0};
514 514 char *emptystr = "";
515 515 char *myself = "addSplitFieldValues";
516 516
517 517 if (trv == 0)
518 518 return (MAP_INTERNAL_ERROR);
519 519
520 520 if (t->e == 0)
521 521 return (SUCCESS);
522 522
523 523 nitems = t->e->element.match.numItems;
524 524
525 525 /*
526 526 * Procedure:
527 527 * - Check each name in nisLDAPnamefield
528 528 * - if it's a splifield, construct its value and add it to trv
529 529 * - if not, check if it has a value
530 530 * - if not, add empty string
531 531 */
532 532 for (i = 0, sf = 0; i < nitems; i++) {
533 533 if (rv) {
534 534 /*
535 535 * str will eventually contain the single string
536 536 * value for the corresponding splitfield.
537 537 * No point initializing str if rv == 0 because
538 538 * splitfield cannot be constructed without rv.
539 539 * So, only initialized here.
540 540 */
541 541 str = 0;
542 542
543 543 /* Check if it's a splitfield name */
544 544 sf = mappingFromMap(t->e->element.match.item[i].name,
545 545 domain, &statP);
546 546
547 547 /*
548 548 * Return only incase of memory allocation failure.
549 549 * The other error case (MAP_NO_MAPPING_EXISTS),
550 550 * indicates that the item name is not a splitfieldname
551 551 * i.e it's a namefieldname. This case is handled by
552 552 * the following if (sf == 0)
553 553 */
554 554 if (statP == MAP_NO_MEMORY)
555 555 return (statP);
556 556 }
557 557
558 558 if (sf == 0) {
559 559 /*
560 560 * Not a splitfield name. Verify if it has a value
561 561 */
562 562 if (findVal(t->e->element.match.item[i].name,
563 563 trv, mit_nisplus) == 0) {
564 564 /* if not, use empty string */
565 565 res = addCol2RuleValue(vt_string,
566 566 t->e->element.match.item[i].name,
567 567 emptystr, 0, trv);
568 568 if (res == -1) {
569 569 return (MAP_INTERNAL_ERROR);
570 570 }
571 571 }
572 572 /*
573 573 * If rv == 0 then sf == 0 so we will continue here
574 574 * i.e. does not matter that str is not yet set up.
575 575 */
576 576 continue;
577 577 }
578 578
579 579 /* Code to construct a single value */
580 580
581 581 /* Use the first separator character as the delimiter */
582 582 delim[0] = sf->separatorStr[0];
583 583
584 584 for (j = 0; j < numVals; j++) {
585 585 /* sf->numSplits is zero-based */
586 586 for (k = 0; k <= sf->numSplits; k++) {
587 587 val = getMappingFormatArray(
588 588 sf->e[k].element.match.fmt, &rv[j],
589 589 fa_item,
590 590 sf->e[k].element.match.numItems,
591 591 sf->e[k].element.match.item);
592 592 if (val == 0)
593 593 continue;
594 594 if (val->numVals > 0) {
595 595 if (str) {
596 596 tempstr = scat(myself,
597 597 0, str, delim);
598 598 sfree(str);
599 599 if (tempstr)
600 600 str = tempstr;
601 601 else {
602 602 freeValue(val, 1);
603 603 return (MAP_NO_MEMORY);
604 604 }
605 605 }
606 606 tempstr = scat(myself, 0, str,
607 607 val->val->value);
608 608 sfree(str);
609 609 if (tempstr)
610 610 str = tempstr;
611 611 else {
612 612 freeValue(val, 1);
613 613 return (MAP_NO_MEMORY);
614 614 }
615 615 }
616 616 freeValue(val, 1);
617 617 }
618 618 }
619 619 if (str == 0)
620 620 str = emptystr;
621 621
622 622 res = addCol2RuleValue(vt_string,
623 623 t->e->element.match.item[i].name,
624 624 str, strlen(str), trv);
625 625
626 626 if (str != emptystr)
627 627 sfree(str);
628 628
629 629 if (res == -1) {
630 630 return (MAP_INTERNAL_ERROR);
631 631 }
632 632 }
633 633
634 634 return (SUCCESS);
635 635 }
636 636
637 637 /*
↓ open down ↓ |
370 lines elided |
↑ open up ↑ |
638 638 * Updates 'rv' with NIS name=value pairs suitable to
639 639 * construct datum from namefield information.
640 640 * Some part based on createNisPlusEntry (from ldap_nisdbquery.c)
641 641 * This code assumes that from a given LDAP entry, applying the
642 642 * mapping rules, would give us one or more NIS entries, differing
643 643 * only in key.
644 644 */
645 645 suc_code
646 646 buildNISRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
647 647 char *domain) {
648 - int r, i, j, k, l, index, nrq, res, len;
648 + int r, i, j, k, l, nrq, res, len;
649 649 int numItems, splitname, count, statP;
650 650 __nis_value_t *rval;
651 651 __nis_mapping_item_t *litem;
652 652 __nis_mapping_rule_t *rl;
653 653 __nis_rule_value_t *rvq;
654 654 char *value, *emptystr = "";
655 655
656 656 statP = SUCCESS;
657 657
658 658 /* Initialize default base */
659 659 __nisdb_get_tsd()->searchBase = t->objectDN->read.base;
660 660
661 661 /* Initialize rule-value rvq */
662 662 rvq = 0;
663 663 count = 0;
664 664
665 665 /* Add domainname to rule-value */
666 666 if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain),
667 667 rv)) {
668 668 return (MAP_INTERNAL_ERROR);
669 669 }
670 670
671 671 for (r = 0; r < t->numRulesFromLDAP; r++) {
672 672 rl = t->ruleFromLDAP[r];
673 673
674 674 /* Set escapeFlag if RHS is "dn" to remove escape chars */
675 675 if (rl->rhs.numElements == 1 &&
676 676 rl->rhs.element->type == me_item &&
677 677 rl->rhs.element->element.item.type == mit_ldap &&
678 678 strcasecmp(rl->rhs.element->element.item.name, "dn")
679 679 == 0) {
680 680 __nisdb_get_tsd()->escapeFlag = '2';
681 681 }
682 682
683 683 rval = buildRvalue(&rl->rhs, mit_ldap, rv, NULL);
684 684
685 685 /* Reset escapeFlag */
686 686 __nisdb_get_tsd()->escapeFlag = '\0';
687 687
688 688 if (rval == 0) {
689 689 continue;
690 690 }
691 691
692 692 if (rval->numVals <= 0) {
693 693 /* Treat as invalid */
694 694 freeValue(rval, 1);
695 695 continue;
696 696 }
697 697
698 698 litem = buildLvalue(&rl->lhs, &rval, &numItems);
699 699 if (litem == 0) {
700 700 /* This will take care of numItems == 0 */
701 701 freeValue(rval, 1);
702 702 continue;
703 703 }
704 704
705 705 if (rval->numVals > 1) {
706 706 if (numItems == 1 && litem->repeat)
707 707 nrq = rval->numVals;
708 708 else if (numItems > 1 && rval->repeat)
709 709 nrq = 1 + ((rval->numVals-1)/numItems);
710 710 else
711 711 nrq = 1;
712 712 } else
713 713 nrq = 1;
714 714
715 715 /* Set splitname if splitfield names are specified */
716 716 for (i = 0; i < numItems; i++) {
717 717 if (strcasecmp(litem[i].name, N2LKEY) == 0 ||
718 718 strcasecmp(litem[i].name, N2LIPKEY) == 0 ||
719 719 strcasecmp(litem[i].name, N2LCOMMENT) == 0)
720 720 continue;
721 721 for (j = 0; j < t->numColumns; j++) {
722 722 if (strcmp(litem[i].name, t->column[j]) == 0)
723 723 break;
724 724 }
725 725 if (j == t->numColumns)
726 726 break;
727 727 }
728 728
729 729 splitname = (i < numItems)?1:0;
730 730
731 731 for (j = 0; j < nrq; j++) {
732 732 if (splitname == 1) {
733 733 /*
734 734 * Put every value of splitfieldname in a new
735 735 * rule-value. Helps generating splitfields.
736 736 */
737 737 rvq = growRuleValue(count, count + 1, rvq, 0);
738 738 if (rvq == 0) {
739 739 freeRuleValue(rvq, count);
740 740 freeValue(rval, 1);
741 741 freeMappingItem(litem, numItems);
742 742 return (MAP_INTERNAL_ERROR);
743 743 }
744 744 count++;
745 745 }
746 746
747 747 for (k = j % nrq, l = 0; l < numItems; k += nrq, l++) {
748 748 /* If we run out of values, use empty strings */
749 749 if (k >= rval->numVals) {
750 750 value = emptystr;
751 751 len = 0;
752 752 } else {
753 753 value = rval->val[k].value;
754 754 len = rval->val[k].length;
755 755 }
756 756 res = (splitname == 1)?addCol2RuleValue(
757 757 vt_string, litem[l].name, value,
758 758 len, &rvq[count - 1]):0;
759 759 if (res != -1)
760 760 res = addCol2RuleValue(vt_string,
761 761 litem[l].name, value, len, rv);
762 762 if (res == -1) {
763 763 freeRuleValue(rvq, count);
764 764 freeValue(rval, 1);
765 765 freeMappingItem(litem, numItems);
766 766 return (MAP_INTERNAL_ERROR);
767 767 }
768 768 }
769 769 }
770 770 freeValue(rval, 1);
771 771 rval = 0;
772 772 freeMappingItem(litem, numItems);
773 773 litem = 0;
774 774 numItems = 0;
775 775 } /* for r < t->numRulesFromLDAP */
776 776
777 777 statP = addSplitFieldValues(t, rvq, rv, count, domain);
778 778
779 779 if (rvq)
780 780 freeRuleValue(rvq, count);
781 781
782 782 if (verifyIndexMatch(t, 0, rv, 0, 0) == 0)
783 783 return (MAP_INDEXLIST_ERROR);
784 784 return (statP);
785 785
786 786 } /* end of buildNISRuleValue */
787 787
788 788 /*
789 789 * Convert rule-value to datum using namefield information
790 790 */
791 791 datum *
792 792 ruleValueToDatum(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *statP) {
793 793 __nis_value_t *val;
794 794 datum *value;
795 795 char *str, *cstr, commentSep[3] = {' ', 0, 0};
796 796 char *myself = "ruleValueToDatum";
797 797
798 798 /* No error yet */
799 799 *statP = 0;
800 800
801 801 /* Return empty datum if no namefield information available */
802 802 if (t->e == 0) {
803 803 if ((value = am(myself, sizeof (*value))) == 0)
804 804 *statP = MAP_NO_MEMORY;
805 805 return (value);
806 806 }
807 807
808 808 val = getMappingFormatArray(t->e->element.match.fmt, rv,
809 809 fa_item, t->e->element.match.numItems,
810 810 t->e->element.match.item);
811 811
812 812 if (val && val->val && val->val->value) {
813 813 if ((value = am(myself, sizeof (*value))) == 0) {
814 814 *statP = MAP_NO_MEMORY;
815 815 freeValue(val, 1);
816 816 return (0);
817 817 }
818 818
819 819 /* Strip trailing whitespaces */
820 820 cstr = (char *)val->val->value + val->val->length;
821 821 for (; cstr >= (char *)val->val->value &&
822 822 (*cstr == ' ' || *cstr == '\t'); *cstr-- = '\0');
823 823
824 824 if (t->commentChar != '\0' &&
825 825 (str = findVal(N2LCOMMENT, rv, mit_nisplus)) != 0 &&
826 826 *str != '\0') {
827 827 commentSep[1] = t->commentChar;
828 828 cstr = scat(myself, F, commentSep, str);
829 829 if (cstr) {
830 830 value->dptr = scat(myself, F,
831 831 val->val->value, cstr);
832 832 sfree(cstr);
833 833 }
834 834 } else {
835 835 value->dptr = sdup(myself, T, val->val->value);
836 836 }
837 837 freeValue(val, 1);
838 838 if (value->dptr) {
839 839 value->dsize = strlen(value->dptr);
840 840 return (value);
841 841 } else {
842 842 *statP = MAP_NO_MEMORY;
843 843 sfree(value);
844 844 return (0);
845 845 }
846 846 }
847 847
848 848 *statP = MAP_NAMEFIELD_MATCH_ERROR;
849 849 return (0);
850 850 }
851 851
852 852 datum *
853 853 getKeyFromRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *nv,
854 854 int *statP, bool_t xlate_to_lcase)
855 855 {
856 856 int i, j, k;
857 857 datum *key = 0;
858 858 char *str;
859 859 char *myself = "getKeyFromRuleValue";
860 860
861 861 /* No error yet */
862 862 *statP = 0;
863 863
864 864 if (rv == 0 || nv == 0)
865 865 return (0);
866 866
867 867 for (i = 0; i < rv->numColumns; i++) {
868 868 if (rv->colName[i] == 0)
869 869 continue;
870 870 if (strcasecmp(N2LKEY, rv->colName[i]) == 0 ||
871 871 strcasecmp(N2LIPKEY, rv->colName[i]) == 0) {
872 872 if ((*nv = rv->colVal[i].numVals) == 0)
873 873 return (0);
874 874 if ((key = am(myself, sizeof (key[0]) * *nv)) == 0) {
875 875 *statP = MAP_NO_MEMORY;
876 876 return (0);
877 877 }
878 878 for (j = 0; j < *nv; j++) {
879 879 if ((str = rv->colVal[i].val[j].value) == 0) {
880 880 key[j].dsize = 0;
881 881 key[j].dptr = 0;
882 882 } else {
883 883 if (verifyIndexMatch(t, 0, 0,
884 884 rv->colName[i], str) == 0) {
885 885 key[j].dsize = 0;
886 886 key[j].dptr = 0;
887 887 continue;
888 888 }
889 889
890 890 key[j].dsize = strlen(str);
891 891 key[j].dptr = am(myself,
892 892 key[j].dsize + 1);
893 893 if (key[j].dptr == 0) {
894 894 *statP = MAP_NO_MEMORY;
895 895 for (--j; j >= 0; j--)
896 896 sfree(key[j].dptr);
897 897 sfree(key);
898 898 return (0);
899 899 }
900 900
901 901 /* transliterate key to lowercase */
902 902 if (xlate_to_lcase == TRUE) {
903 903
904 904 /*
905 905 * For multi-homed
906 906 * entries, skip over
907 907 * "YP_MULTI_" prefix.
908 908 */
909 909 k = 0;
910 910 if (strncmp(YPMULTI, str,
911 911 YPMULTISZ) == 0) {
912 912 k = YPMULTISZ;
913 913 bcopy(str, key[j].dptr,
914 914 YPMULTISZ);
915 915 }
916 916 while (k < key[j].dsize) {
917 917 key[j].dptr[k] =
918 918 (char)tolower(
919 919 (int)(uchar_t)
920 920 str[k]);
921 921 k++;
922 922 }
923 923 } else {
924 924 bcopy(str, key[j].dptr,
925 925 key[j].dsize);
926 926 }
927 927 }
928 928 }
929 929 return (key);
930 930 }
931 931 }
932 932 return (0);
933 933 }
934 934
935 935 /*
936 936 * Get the mapping structure corresponding to `map,domain.'
937 937 */
938 938 __nis_table_mapping_t *
939 939 mappingFromMap(char *map, char *domain, int *statP) {
940 940 char *mapPath;
941 941 __nis_table_mapping_t *t;
942 942
943 943 /* No error yet */
944 944 *statP = 0;
945 945
946 946 /* Construct map,domain. */
947 947 if ((mapPath = getFullMapName(map, domain)) == 0) {
948 948 *statP = MAP_NO_MEMORY;
949 949 return (0);
950 950 }
951 951
952 952 /* Get the hash table entry for the mapPath */
953 953 if ((t = __nis_find_item_mt(mapPath, &ldapMappingList, 1, 0))
954 954 == 0) {
955 955 *statP = MAP_NO_MAPPING_EXISTS;
956 956 }
957 957 sfree(mapPath);
958 958 return (t);
959 959 }
960 960
961 961 /*
962 962 * Verify at least one key value obtained from DIT matches the search key
963 963 * RETURNS: 1 MATCH
964 964 * 0 NO MATCH
965 965 * -1 NO KEY FOUND
966 966 */
967 967 static int
968 968 verifyKey(char *key, __nis_rule_value_t *rv) {
969 969 int i, j;
970 970 char *sipkey, *str;
971 971
972 972 for (i = 0; i < rv->numColumns; i++) {
973 973 if (rv->colName[i] == 0)
974 974 continue;
975 975 if (strcasecmp(N2LKEY, rv->colName[i]) == 0) {
976 976 if (rv->colVal[i].val == 0)
977 977 return (0);
978 978 for (j = 0; j < rv->colVal[i].numVals; j++) {
979 979 str = (char *)rv->colVal[i].val[j].value;
980 980 if (str && strcmp(str, key) == 0)
981 981 return (1);
982 982 }
983 983 return (0);
984 984 } else if (strcasecmp(N2LIPKEY, rv->colName[i]) == 0) {
985 985 if (checkIPaddress(key, strlen(key), &sipkey) > 0) {
986 986 if (rv->colVal[i].val == 0)
987 987 return (0);
988 988 for (j = 0; j < rv->colVal[i].numVals; j++) {
989 989 str = rv->colVal[i].val[j].value;
990 990 if (str && strcmp(str, sipkey) == 0) {
991 991 sfree(sipkey);
992 992 return (1);
993 993 }
994 994 }
995 995 sfree(sipkey);
996 996 }
997 997 return (0);
998 998 }
999 999 }
1000 1000 return (-1);
1001 1001 }
1002 1002
↓ open down ↓ |
344 lines elided |
↑ open up ↑ |
1003 1003 /*
1004 1004 * Read (i.e get and map) a single NIS entry from the LDAP DIT
1005 1005 */
1006 1006 bool_t
1007 1007 singleReadFromDIT(char *map, char *domain, datum *key, datum *value,
1008 1008 int *statP) {
1009 1009 __nis_table_mapping_t *t;
1010 1010 __nis_rule_value_t *rv_request = 0, *rv_result = 0;
1011 1011 __nis_ldap_search_t *ls;
1012 1012 __nis_object_dn_t *objectDN = NULL;
1013 - int i, rc, nr = 0, nv = 0;
1013 + int i, rc, nr = 0;
1014 1014 datum *datval = 0;
1015 - char *skey, *str, *sipkey;
1015 + char *skey, *str;
1016 1016 char *myself = "singleReadFromDIT";
1017 1017
1018 1018 *statP = SUCCESS;
1019 1019
1020 1020 if (!map || !domain || !key || !value) {
1021 1021 *statP = MAP_PARAM_ERROR;
1022 1022 return (FALSE);
1023 1023 }
1024 1024
1025 1025
1026 1026 /* Get the mapping information for the map */
1027 1027 if ((t = mappingFromMap(map, domain, statP)) == 0) {
1028 1028 /*
1029 1029 * No problem. We don't handle this map and domain. Maybe it's
1030 1030 * handled by a service other than NIS.
1031 1031 */
1032 1032 return (FALSE);
1033 1033 }
1034 1034
1035 1035 /* NULL-terminated version of datum key for logging */
1036 1036 if ((skey = am(myself, key->dsize + 1)) == 0) {
1037 1037 *statP = MAP_NO_MEMORY;
1038 1038 return (FALSE);
1039 1039 }
1040 1040 (void) memcpy(skey, key->dptr, key->dsize);
1041 1041
1042 1042 if ((str = getFullMapName(map, domain)) == 0) {
1043 1043 *statP = MAP_NO_MEMORY;
1044 1044 return (FALSE);
1045 1045 }
1046 1046
1047 1047 /* For each alternate mapping */
1048 1048 for (; t != 0; t = t->next) {
1049 1049 /* Verify objName */
1050 1050 if (strcmp(str, t->objName) != 0) {
1051 1051 continue;
1052 1052 }
1053 1053
1054 1054 /* Verify if key matches the index */
1055 1055 if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 ||
1056 1056 verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0)
1057 1057 continue;
1058 1058
1059 1059 /* Check if rulesFromLDAP are provided */
1060 1060 if (t->numRulesFromLDAP == 0) {
1061 1061 logmsg(MSG_NOTIMECHECK, LOG_INFO,
1062 1062 "%s: No rulesFromLDAP information available "
1063 1063 "for %s (%s)", myself, t->dbId, map);
1064 1064 continue;
1065 1065 }
1066 1066
1067 1067 /* Convert key into rule-value */
1068 1068 if ((rv_request = datumToRuleValue(key, 0, t, 0, domain, TRUE,
1069 1069 statP)) == 0) {
1070 1070 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1071 1071 "%s: Conversion error %d (NIS to name=value "
1072 1072 "pairs) for NIS key (%s) for %s (%s)",
1073 1073 myself, *statP, skey, t->dbId, map);
1074 1074 continue;
1075 1075 }
1076 1076 /* Convert rule-value into ldap request */
1077 1077 for (objectDN = t->objectDN; objectDN &&
1078 1078 objectDN->read.base;
1079 1079 objectDN = objectDN->next) {
1080 1080 ls = createLdapRequest(t, rv_request, 0, 1, NULL,
1081 1081 objectDN);
1082 1082 if (ls == 0) {
1083 1083 *statP = MAP_CREATE_LDAP_REQUEST_ERROR;
1084 1084 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1085 1085 "%s: Failed to create ldapSearch "
1086 1086 "request for "
1087 1087 "NIS key (%s) for %s (%s) "
1088 1088 "for base %s",
1089 1089 myself, skey, t->dbId, map,
1090 1090 objectDN->read.base);
1091 1091 continue;
1092 1092 }
1093 1093 ls->timeout.tv_sec = SINGLE_ACCESS_TIMEOUT_SEC;
1094 1094 ls->timeout.tv_usec = SINGLE_ACCESS_TIMEOUT_USEC;
1095 1095 /* Query LDAP */
1096 1096 nr = (ls->isDN)?0:-1;
1097 1097 rv_result = ldapSearch(ls, &nr, 0, statP);
1098 1098 freeLdapSearch(ls);
1099 1099 if (rv_result == 0) {
1100 1100 if (*statP == LDAP_NO_SUCH_OBJECT) {
1101 1101 /* Entry does not exist in */
1102 1102 /* the ldap server */
1103 1103 }
1104 1104 continue;
1105 1105 }
1106 1106 freeRuleValue(rv_request, 1);
1107 1107 rv_request = 0;
1108 1108
1109 1109 /* if result > 1, first match will be returned */
1110 1110 if (nr > 1) {
1111 1111 logmsg(MSG_NOTIMECHECK, LOG_INFO,
1112 1112 "%s: %d ldapSearch results "
1113 1113 "for NIS key (%s) "
1114 1114 "for %s (%s) for base %s. "
1115 1115 "First match will be returned ",
1116 1116 myself, nr, skey, t->dbId, map,
1117 1117 objectDN->read.base);
1118 1118 }
1119 1119
1120 1120 for (i = 0; i < nr; i++) {
1121 1121 /* Convert LDAP data to NIS equivalents */
1122 1122 *statP = buildNISRuleValue(t, &rv_result[i],
1123 1123 domain);
1124 1124 if (*statP == MAP_INDEXLIST_ERROR)
1125 1125 continue;
1126 1126
1127 1127 if (*statP != SUCCESS) {
1128 1128 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1129 1129 "%s: Conversion error %d (LDAP to "
1130 1130 "name=value pairs) for NIS key (%s) "
1131 1131 "for %s (%s) for base %s", myself,
1132 1132 *statP, skey,
1133 1133 t->dbId, map, objectDN->read.base);
1134 1134 continue;
1135 1135 }
1136 1136
1137 1137 /*
1138 1138 * Check if 'key' from the ldap result matches the key
1139 1139 * provided by our caller
1140 1140 */
1141 1141 if ((rc = verifyKey(skey, &rv_result[i]))
1142 1142 == -1) {
1143 1143 logmsg(MSG_NOTIMECHECK, LOG_INFO,
1144 1144 "%s: Cannot verify key from ldap "
1145 1145 "result for NIS key (%s) for %s (%s) "
1146 1146 "for base %s",
1147 1147 myself, skey, t->dbId, map,
1148 1148 objectDN->read.base);
1149 1149 continue;
1150 1150 }
1151 1151
1152 1152 if (rc == 1) {
1153 1153 datval = ruleValueToDatum(t,
1154 1154 &rv_result[i], statP);
1155 1155 if (datval == 0) {
1156 1156 logmsg(MSG_NOTIMECHECK,
1157 1157 LOG_WARNING,
1158 1158 "%s: Conversion error %d "
1159 1159 "(name=value pairs to NIS) "
1160 1160 "for NIS key (%s) for %s (%s)"
1161 1161 " for base %s",
1162 1162 myself,
1163 1163 *statP, skey, t->dbId, map,
1164 1164 objectDN->read.base);
1165 1165 continue;
1166 1166 }
1167 1167 if (value) {
1168 1168 value->dptr = datval->dptr;
1169 1169 value->dsize = datval->dsize;
1170 1170 }
1171 1171 sfree(datval);
1172 1172 sfree(skey);
1173 1173 freeRuleValue(rv_result, nr);
1174 1174 rv_result = 0;
1175 1175 *statP = SUCCESS;
1176 1176
1177 1177 /* Free full map name */
1178 1178 sfree(str);
1179 1179
1180 1180 return (TRUE);
1181 1181 }
1182 1182 }
1183 1183 freeRuleValue(rv_result, nr);
1184 1184 rv_result = 0;
1185 1185 } /* end of for over objectDN */
1186 1186
1187 1187 if (rv_request != 0) {
1188 1188 freeRuleValue(rv_request, 1);
1189 1189 rv_request = 0;
1190 1190 }
1191 1191 if (rv_result != 0) {
1192 1192 freeRuleValue(rv_result, nr);
1193 1193 rv_result = 0;
1194 1194 }
1195 1195 }
1196 1196 sfree(skey);
1197 1197 *statP = MAP_NO_MATCHING_KEY;
1198 1198
1199 1199 /* Free full map name */
1200 1200 sfree(str);
1201 1201
1202 1202 return (FALSE);
1203 1203 }
1204 1204
1205 1205
1206 1206 /*
1207 1207 * Maps and writes a single NIS entry to the LDAP DIT
1208 1208 */
1209 1209 int
1210 1210 singleWriteToDIT(char *map, char *domain, datum *key, datum *value,
1211 1211 bool_t replace) {
1212 1212 __nis_table_mapping_t *t;
1213 1213 __nis_rule_value_t *rv, *frv;
1214 1214 __nis_ldap_search_t *ls;
1215 1215 int statP = SUCCESS, flag;
1216 1216 int nv, nr, i, rc, collapse;
1217 1217 char *dn = 0, *skey, *svalue, *str;
1218 1218 char *myself = "singleWriteToDIT";
1219 1219
1220 1220 if (!map || !domain || !key || !value) {
1221 1221 return (MAP_PARAM_ERROR);
1222 1222 }
1223 1223
1224 1224 /* Return SUCCESS for empty or whitespace key */
1225 1225 for (i = 0; i < key->dsize && (key->dptr[i] == 0 ||
1226 1226 key->dptr[i] == ' ' || key->dptr[i] == '\t'); i++);
1227 1227 if (i >= key->dsize)
1228 1228 return (SUCCESS);
1229 1229
1230 1230 /* Get the mapping information for the map */
1231 1231 if ((t = mappingFromMap(map, domain, &statP)) == 0) {
1232 1232 /*
1233 1233 * No problem. We don't handle this map and domain. Maybe it's
1234 1234 * handled by a service other than NIS.
1235 1235 */
1236 1236 return (statP);
1237 1237 }
1238 1238
1239 1239 /* NULL-terminated version of key and value for logging */
1240 1240 if ((skey = am(myself, key->dsize + 1)) == 0)
1241 1241 return (MAP_NO_MEMORY);
1242 1242 (void) memcpy(skey, key->dptr, key->dsize);
1243 1243
1244 1244 if ((svalue = am(myself, value->dsize + 1)) == 0) {
1245 1245 sfree(skey);
1246 1246 return (MAP_NO_MEMORY);
1247 1247 }
1248 1248 (void) memcpy(svalue, value->dptr, value->dsize);
1249 1249
1250 1250 if ((str = getFullMapName(map, domain)) == 0) {
1251 1251 sfree(skey);
1252 1252 sfree(svalue);
1253 1253 return (MAP_NO_MEMORY);
1254 1254 }
1255 1255
1256 1256 /* For each alternate mapping */
1257 1257 for (flag = 0; t != 0; t = t->next) {
1258 1258 /* Verify objName */
1259 1259 if (strcmp(str, t->objName) != 0) {
1260 1260 continue;
1261 1261 }
1262 1262
1263 1263 /* Verify if key matches the index */
1264 1264 if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 ||
1265 1265 verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0)
1266 1266 continue;
1267 1267
1268 1268 /* Check the writespecs */
1269 1269 if (t->objectDN->write.base == 0) {
1270 1270 logmsg(MSG_NOTIMECHECK, LOG_INFO,
1271 1271 "%s: No baseDN in writespec. Write disabled "
1272 1272 "for %s (%s)", myself, t->dbId, map);
1273 1273 continue;
1274 1274 }
1275 1275
1276 1276 /* Check if rulesToLDAP are provided */
1277 1277 if (t->numRulesToLDAP == 0) {
1278 1278 logmsg(MSG_NOTIMECHECK, LOG_INFO,
1279 1279 "%s: No rulesToLDAP. Write disabled for "
1280 1280 "%s (%s)", myself, t->dbId, map);
1281 1281 continue;
1282 1282 }
1283 1283
1284 1284 /* Set flag to indicate write is enabled */
1285 1285 flag = 1;
1286 1286
1287 1287 /* Convert key and value into an array of rule-values */
1288 1288 if ((rv = datumToRuleValue(key, value, t, &nv, domain, FALSE,
1289 1289 &statP)) == 0) {
1290 1290 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1291 1291 "%s: Conversion error %d (NIS to name=value "
1292 1292 "pairs) for NIS data (key=%s, value=%s) "
1293 1293 "for %s (%s)",
1294 1294 myself, statP, skey, svalue, t->dbId, map);
1295 1295 sfree(skey);
1296 1296 sfree(svalue);
1297 1297
1298 1298 /* Free full map name */
1299 1299 sfree(str);
1300 1300
1301 1301 return (statP);
1302 1302 }
1303 1303
1304 1304 /* Convert NIS data to LDAP equivalents for each rule-value */
1305 1305 for (i = 0; i < nv; i++) {
1306 1306 /* Verify indexlist with name=value pairs */
1307 1307 if (verifyIndexMatch(t, 0, &rv[i], 0, 0) == 0)
1308 1308 break;
1309 1309
1310 1310 /* Create LDAP request and LDAP name=value pairs */
1311 1311 if ((ls = createLdapRequest(t, &rv[i],
1312 1312 0, 0, NULL, NULL)) == 0) {
1313 1313 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1314 1314 "%s: Conversion error (name=value pairs"
1315 1315 " to LDAP) for NIS data "
1316 1316 "(key=%s, value=%s) for %s (%s)",
1317 1317 myself, skey, svalue, t->dbId, map);
1318 1318 freeRuleValue(rv, nv);
1319 1319 sfree(skey);
1320 1320 sfree(svalue);
1321 1321
1322 1322 /* Free full map name */
1323 1323 sfree(str);
1324 1324
1325 1325 return (MAP_CREATE_LDAP_REQUEST_ERROR);
1326 1326 }
1327 1327 freeLdapSearch(ls);
1328 1328 /* printRuleValue(&rv[i]); */
1329 1329 }
1330 1330
1331 1331 /* If i < nv then this alternate mapping isn't the one */
1332 1332 if (i < nv)
1333 1333 continue;
1334 1334
1335 1335 /*
1336 1336 * Merge rule-values with the same DN so that we have
1337 1337 * one ldap write request for each DN
1338 1338 */
1339 1339 nr = nv;
1340 1340 frv = mergeRuleValueWithSameDN(rv, &nr);
1341 1341 freeRuleValue(rv, nv);
1342 1342 if (frv == 0) {
1343 1343 if (nr == -1) {
1344 1344 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1345 1345 "%s: Unable to merge LDAP write "
1346 1346 "requests to same DN for NIS data "
1347 1347 "(key=%s, value=%s) for %s (%s)",
1348 1348 myself, skey, svalue, t->dbId, map);
1349 1349 statP = MAP_INTERNAL_ERROR;
1350 1350 } else if (nr == 0) {
1351 1351 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1352 1352 "%s: Cannot generate write DN due to "
1353 1353 "missing information for NIS data "
1354 1354 "(key=%s, value=%s) for %s (%s)",
1355 1355 myself, skey, svalue, t->dbId, map);
1356 1356 statP = MAP_NO_DN;
1357 1357 }
1358 1358 sfree(skey);
1359 1359 sfree(svalue);
1360 1360
1361 1361 /* Free full map name */
1362 1362 sfree(str);
1363 1363
1364 1364 return (statP);
1365 1365 }
1366 1366
1367 1367 /* Write to the LDAP server */
1368 1368 for (collapse = 0, i = 0; i < nr; i++) {
1369 1369 if ((dn = findVal("dn", &frv[i], mit_ldap)) != 0) {
1370 1370 if (replace == FALSE) {
1371 1371 /* ldap add */
1372 1372 rc = ldapAdd(dn, &frv[i],
1373 1373 t->objectDN->write.attrs, 0);
1374 1374 } else {
1375 1375 /* ldap modify with addFirst set */
1376 1376 rc = ldapModify(dn, &frv[i],
1377 1377 t->objectDN->write.attrs, 1);
1378 1378 }
1379 1379
1380 1380 /* if we get err=20, collapse and try again */
1381 1381 if (!collapse &&
1382 1382 (rc == LDAP_TYPE_OR_VALUE_EXISTS) &&
1383 1383 (collapseRuleValue(&frv[i]) == 1)) {
1384 1384 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1385 1385 "%s: Ignoring values differing "
1386 1386 "in case from NIS data (key=%s,"
1387 1387 " value=%s) for (dn: %s) for "
1388 1388 "%s (%s)", myself, skey,
1389 1389 svalue, dn, t->dbId, map);
1390 1390 collapse = 1;
1391 1391 i--;
1392 1392 continue;
1393 1393 }
1394 1394
1395 1395 collapse = 0;
1396 1396 if (rc != LDAP_SUCCESS) {
1397 1397 /* Log error */
1398 1398 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1399 1399 "%s: %s error %d (%s) for "
1400 1400 "(dn: %s) for NIS data "
1401 1401 "(key=%s, value=%s) "
1402 1402 "for %s (%s)",
1403 1403 myself, (replace == TRUE) ?
1404 1404 "ldapModify" : "ldapAdd", rc,
1405 1405 ldap_err2string(rc), dn, skey,
1406 1406 svalue, t->dbId, map);
1407 1407
1408 1408 /* Dumping failed call may be useful */
1409 1409 /* printRuleValue(&frv[i]); */
1410 1410
1411 1411 /*
1412 1412 * Return the error code and let wrapper
1413 1413 * sort out if mapping should continue
1414 1414 * or abort.
1415 1415 */
1416 1416 statP = rc;
1417 1417 sfree(skey);
1418 1418 sfree(svalue);
1419 1419 freeRuleValue(frv, nr);
1420 1420
1421 1421 /* Free full map name */
1422 1422 sfree(str);
1423 1423
1424 1424 return (statP);
1425 1425 }
1426 1426 }
1427 1427 }
1428 1428
1429 1429 freeRuleValue(frv, nr);
1430 1430 }
1431 1431
1432 1432 sfree(skey);
1433 1433 sfree(svalue);
1434 1434
1435 1435 /* Free full map name */
1436 1436 sfree(str);
1437 1437
1438 1438 return ((flag)?SUCCESS:MAP_WRITE_DISABLED);
1439 1439 }
1440 1440
1441 1441 suc_code
1442 1442 collapseRuleValue(__nis_rule_value_t *rv) {
1443 1443 int i, j, k, flag;
1444 1444
1445 1445 /* Using 'val' to appease cstyle's 80 chars/line limit */
1446 1446 __nis_value_t *val;
1447 1447
1448 1448 for (i = 0, flag = 0; i < rv->numAttrs; i++) {
1449 1449 val = &rv->attrVal[i];
1450 1450 for (j = 1; j < val->numVals; j++) {
1451 1451 for (k = 0; k < j; k++) {
1452 1452 if (val->val[j].length != val->val[k].length)
1453 1453 continue;
1454 1454 if (val->val[k].length == 0)
1455 1455 continue;
1456 1456 if (strncasecmp(val->val[j].value,
1457 1457 val->val[k].value,
1458 1458 val->val[j].length) != 0)
1459 1459 continue;
1460 1460 flag = 1;
1461 1461 sfree(val->val[j].value);
1462 1462
1463 1463 #ifdef ORDER_NOT_IMPORTANT
1464 1464 val->val[j--] = val->val[--val->numVals];
1465 1465 #else
1466 1466 /* Order needs to be maintained */
1467 1467 for (k = j + 1; k < val->numVals; k++)
1468 1468 val->val[k - 1] = val->val[k];
1469 1469 j--;
1470 1470 val->numVals--;
1471 1471 #endif
1472 1472 break;
1473 1473 }
1474 1474 }
1475 1475 }
1476 1476 return (flag);
1477 1477 }
1478 1478
1479 1479 /* ObjectClass lookup table */
1480 1480 static struct {
1481 1481 const char *attrType;
1482 1482 const char *objectClass;
1483 1483 } oc_lookup[] = {
1484 1484 { "o", "objectclass=organization"},
1485 1485 { "organizationname", "objectclass=organization"},
1486 1486 { "2.5.4.10", "objectclass=organization"},
1487 1487 { "ou", "objectclass=organizationalunit"},
1488 1488 { "organizationalunitname", "objectclass=organizationalunit"},
1489 1489 { "2.5.4.11", "objectclass=organizationalunit"},
1490 1490 { "c", "objectclass=country"},
1491 1491 { "countryname", "objectclass=country"},
1492 1492 { "2.5.4.6", "objectclass=country"},
1493 1493 { "dc", "objectclass=domain"},
1494 1494 { "domaincomponent", "objectclass=domain"},
1495 1495 { "0.9.2342.19200300.100.1.25", "objectclass=domain"},
1496 1496 { "nismapname", "objectclass=nismap"},
1497 1497 { "1.3.6.1.1.1.1.26", "objectclass=nismap"},
1498 1498 { "automountmapname", "objectclass=automountmap"},
1499 1499 { "1.3.6.1.1.1.1.31", "objectclass=automountmap"},
1500 1500 { 0, 0}
1501 1501 };
1502 1502
1503 1503 /*
1504 1504 * Returns the name of the objectclass to which the object
1505 1505 * represented by the given 'rdn' will most likely belong to.
1506 1506 * The return value is in static memory so it should not be
1507 1507 * freed
1508 1508 */
1509 1509 const char *
1510 1510 getObjectClass(char *rdn) {
1511 1511
1512 1512 char *attrtype, *p;
1513 1513 int len, i;
1514 1514
1515 1515 /* Skip leading whitespaces */
1516 1516 for (p = rdn; *p == ' ' || *p == '\t'; p++);
1517 1517 if (*p == '\0')
1518 1518 return (0);
1519 1519 attrtype = p;
1520 1520
1521 1521 /* Find '=' */
1522 1522 if ((p = strchr(attrtype, '=')) == 0 || p == attrtype ||
1523 1523 *(p - 1) == '\\')
1524 1524 return (0);
1525 1525
1526 1526 /*
1527 1527 * Skip trailing whitespaces in attrtype
1528 1528 * Don't worry, p won't decrease beyond attrtype
1529 1529 */
1530 1530 for (--p; *p == ' ' || *p == '\t'; p--);
1531 1531 len = p - attrtype + 1;
1532 1532
1533 1533 for (i = 0; oc_lookup[i].attrType; i++)
1534 1534 if (!strncasecmp(oc_lookup[i].attrType, attrtype, len))
1535 1535 /* Check length is right */
1536 1536 if (len == strlen(oc_lookup[i].attrType))
1537 1537 return (oc_lookup[i].objectClass);
1538 1538
1539 1539 return (0);
1540 1540 }
1541 1541
1542 1542 /*
1543 1543 * Split 'dn' into rdn and parentdn based on the first
1544 1544 * occurrence of unescaped 'comma' or 'semicolon'. rdn
1545 1545 * lies on the LHS while parentdn lies on the RHS of the
1546 1546 * split. If none found, then an empty string ("") is
1547 1547 * assigned to parentdn
1548 1548 */
1549 1549 int
1550 1550 splitDN(char *dn, char **rdn, char **parentdn) {
1551 1551 char *value, *name;
1552 1552 char *myself = "splitDN";
1553 1553
1554 1554 if ((name = sdup(myself, T, dn)) == 0)
1555 1555 return (-1);
1556 1556
1557 1557 for (value = name; *value != '\0'; value++) {
1558 1558 if (*value == ',' || *value == ';')
1559 1559 if (value == name || *(value - 1) != '\\')
1560 1560 break;
1561 1561 }
1562 1562
1563 1563 if (*value != '\0') {
1564 1564 *value = '\0';
1565 1565 value++;
1566 1566 } else
1567 1567 value = 0;
1568 1568
1569 1569 if (parentdn) {
1570 1570 if ((*parentdn = sdup(myself, T, value)) == 0) {
1571 1571 sfree(name);
1572 1572 return (-1);
1573 1573 }
1574 1574 }
1575 1575 if (rdn)
1576 1576 *rdn = name;
1577 1577 else
1578 1578 sfree(name);
1579 1579
1580 1580 return (1);
1581 1581 }
1582 1582
1583 1583 /*
1584 1584 * FUNCTION : makeNISObject()
1585 1585 *
1586 1586 * DESCRIPTION: Sets up a nis Object in the DIT.
1587 1587 *
1588 1588 * GIVEN :
1589 1589 * Case 1: Both 'domain' and 'dn' are non-NULL
1590 1590 * Create nisDomainObject with the given information
1591 1591 * Case 2: Only 'domain' is non-NULL
1592 1592 * Obtain the 'dn' from the nisLDAPdomainContext list
1593 1593 * Create nisDomainObject with the above information
1594 1594 * Case 3: Only 'dn' is non-NULL
1595 1595 * Create an object with the 'dn'
1596 1596 * Here we guess the objectclass attribute, based on
1597 1597 * oc_lookup table
1598 1598 * Case 4: Both 'domain' and 'dn' are NULL
1599 1599 * Error
1600 1600 *
1601 1601 * RETURNS : SUCCESS = It worked
1602 1602 * FAILURE = There was a problem.
1603 1603 */
1604 1604 suc_code
1605 1605 makeNISObject(char *domain, char *dn) {
1606 1606 __nis_rule_value_t *rv;
1607 1607 __nis_ldap_search_t *ls;
1608 1608 int i, rc, nr, add_rc;
1609 1609 char *val;
1610 1610 char *myself = "makeNISObject";
1611 1611
1612 1612 if (!dn && !domain)
1613 1613 return (FAILURE);
1614 1614
1615 1615 /*
1616 1616 * If only 'domain' name is provided, then
1617 1617 * try to find dn from the nisLDAPdomainContext
1618 1618 * list generated by the parser
1619 1619 */
1620 1620 if (!dn) {
1621 1621 for (i = 0; i < ypDomains.numDomains; i++) {
1622 1622 if (ypDomains.domainLabels[i] == 0)
1623 1623 continue;
1624 1624 if (strcasecmp(domain, ypDomains.domainLabels[i])
1625 1625 == 0) {
1626 1626 dn = ypDomains.domains[i];
1627 1627 break;
1628 1628 }
1629 1629 }
1630 1630 if (!dn)
1631 1631 return (FAILURE);
1632 1632 }
1633 1633
1634 1634 /*
1635 1635 * If only 'dn' is given, then it means that the
1636 1636 * caller simply wants to a create an entry for
1637 1637 * that 'dn'.
1638 1638 *
1639 1639 * If 'domain' is given, then check if the 'dn'
1640 1640 * has already been set up as a nis domain object.
1641 1641 * If not, see if we can make it become one.
1642 1642 */
1643 1643 if (domain) {
1644 1644 /*
1645 1645 * Check to see if the nis domain object has
1646 1646 * already been set up
1647 1647 */
1648 1648 ls = buildLdapSearch(dn, LDAP_SCOPE_BASE, 0, 0,
1649 1649 "objectclass=*", 0, 0, 0);
1650 1650 if (ls == 0) {
1651 1651 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1652 1652 "%s: Unable to create ldapSearch "
1653 1653 "request for dn: %s", myself, dn);
1654 1654 return (FAILURE);
1655 1655 }
1656 1656 nr = -1;
1657 1657 rv = ldapSearch(ls, &nr, 0, &rc);
1658 1658 freeLdapSearch(ls);
1659 1659 if (rc == LDAP_SUCCESS) {
1660 1660 val = findVal("nisDomain", rv, mit_ldap);
1661 1661 if (val != NULL) {
1662 1662 /*
1663 1663 * Yes, nis domain object found. Check
1664 1664 * to see if the domain names match.
1665 1665 * If so, we are done. If not, log
1666 1666 * a warning message, and return SUCCESS.
1667 1667 */
1668 1668 if (strcasecmp(val, domain) == 0) {
1669 1669 freeRuleValue(rv, nr);
1670 1670 return (SUCCESS);
1671 1671 } else {
1672 1672 logmsg(MSG_NOTIMECHECK,
1673 1673 LOG_WARNING,
1674 1674 "%s: Entry (dn: %s) already "
1675 1675 "contains a nis domain name "
1676 1676 "(%s). The domain name (%s) "
1677 1677 "is not added.",
1678 1678 myself, dn, val, domain);
1679 1679 freeRuleValue(rv, nr);
1680 1680 return (SUCCESS);
1681 1681 }
1682 1682 } else {
1683 1683 freeRuleValue(rv, nr);
1684 1684 /*
1685 1685 * Entry for the 'dn' exists, but it
1686 1686 * is not a nis domain object yet.
1687 1687 * Add the nisDoamin attribute and
1688 1688 * the nisDomainObject objectclass to
1689 1689 * the entry.
1690 1690 */
1691 1691 if ((rv = initRuleValue(1, 0)) == 0)
1692 1692 return (FAILURE);
1693 1693
1694 1694 if (addSAttr2RuleValue("nisDomain",
1695 1695 domain, rv) == -1) {
1696 1696 freeRuleValue(rv, 1);
1697 1697 return (FAILURE);
1698 1698 }
1699 1699 rc = ldapModify(dn, rv,
1700 1700 "objectclass=nisDomainObject",
1701 1701 0);
1702 1702 freeRuleValue(rv, 1);
1703 1703 if (rc == LDAP_SUCCESS) {
1704 1704 logmsg(MSG_NOTIMECHECK,
1705 1705 LOG_INFO,
1706 1706 "%s: entry (dn: %s) "
1707 1707 "modified to be an "
1708 1708 "nis domain object",
1709 1709 myself, dn);
1710 1710 return (SUCCESS);
1711 1711 } else {
1712 1712 logmsg(MSG_NOTIMECHECK,
1713 1713 LOG_ERR,
1714 1714 "%s: unable to modify "
1715 1715 "entry (dn: %s) to be "
1716 1716 "a nis domain object: "
1717 1717 "ldapModify error %d (%s)",
1718 1718 myself, dn, rc,
1719 1719 ldap_err2string(rc));
1720 1720 return (FAILURE);
1721 1721 }
1722 1722 }
1723 1723 } else { /* search for 'dn' failed */
1724 1724 freeRuleValue(rv, nr);
1725 1725
1726 1726 /*
1727 1727 * It is OK if no such object, otherwise
1728 1728 * log an error.
1729 1729 */
1730 1730 if (rc != LDAP_NO_SUCH_OBJECT) {
1731 1731 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1732 1732 "%s: unable to retrieve "
1733 1733 "entry (dn: %s): "
1734 1734 "ldapSearch error %d (%s)",
1735 1735 myself, dn, rc,
1736 1736 ldap_err2string(rc));
1737 1737 return (FAILURE);
1738 1738 }
1739 1739 }
1740 1740
1741 1741 /*
1742 1742 * If the 'dn' is actually the naming context of
1743 1743 * the DIT, we should be able to make it a nis domain
1744 1744 * object without worrying about missing parent
1745 1745 * entries. If unable to add the entry for the 'dn'
1746 1746 * due to missing parent entries, fall through
1747 1747 * to create them and then add the nis domain object.
1748 1748 */
1749 1749 if (addNISObject(domain, dn, &add_rc) == SUCCESS)
1750 1750 return (SUCCESS);
1751 1751 else if (add_rc != LDAP_NO_SUCH_OBJECT)
1752 1752 return (FAILURE);
1753 1753 }
1754 1754
1755 1755 /* Create parent */
1756 1756 if (addParent(dn, NULL) == FAILURE)
1757 1757 return (FAILURE);
1758 1758
1759 1759 if (addNISObject(domain, dn, NULL) == FAILURE)
1760 1760 return (FAILURE);
1761 1761
1762 1762 return (SUCCESS);
1763 1763 }
1764 1764
1765 1765 suc_code
1766 1766 addParent(char *dn, char **attr) {
1767 1767 __nis_rule_value_t *rv;
1768 1768 __nis_ldap_search_t *ls;
1769 1769 int rc, nr;
1770 1770 char *parentdn = 0, *rdn = 0;
1771 1771 char *myself = "addParent";
1772 1772
1773 1773 /* Obtain parentdn */
1774 1774 if (splitDN(dn, &rdn, &parentdn) == -1)
1775 1775 return (FAILURE);
1776 1776 if (!parentdn) {
1777 1777 sfree(rdn);
1778 1778 return (FAILURE);
1779 1779 }
1780 1780
1781 1781 /* Check if parentdn exists */
1782 1782 ls = buildLdapSearch(parentdn, LDAP_SCOPE_BASE, 0, 0,
1783 1783 "objectclass=*", 0, 0, 0);
1784 1784 if (ls == 0) {
1785 1785 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1786 1786 "%s: Unable to create ldapSearch request for "
1787 1787 "parent (dn: %s) of (dn: %s)",
1788 1788 myself, parentdn, dn);
1789 1789 sfree(parentdn);
1790 1790 sfree(rdn);
1791 1791 return (FAILURE);
1792 1792 }
1793 1793 nr = -1;
1794 1794 rv = ldapSearch(ls, &nr, 0, &rc);
1795 1795 freeLdapSearch(ls);
1796 1796 freeRuleValue(rv, nr);
1797 1797
1798 1798 /* Create parent if it doesn't exists */
1799 1799 if (rc == LDAP_NO_SUCH_OBJECT) {
1800 1800 if (makeNISObject(0, parentdn) == FAILURE) {
1801 1801 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1802 1802 "%s: Unable to create parent (dn: %s) of "
1803 1803 "(dn: %s) in the DIT", myself, parentdn, dn);
1804 1804 sfree(parentdn);
1805 1805 sfree(rdn);
1806 1806 return (FAILURE);
1807 1807 }
1808 1808 }
1809 1809 sfree(parentdn);
1810 1810
1811 1811 if (attr && rdn)
1812 1812 *attr = (char *)getObjectClass(rdn);
1813 1813 sfree(rdn);
1814 1814
1815 1815 return (SUCCESS);
1816 1816 }
1817 1817
1818 1818
1819 1819
1820 1820 /*
1821 1821 * FUNCTION : is_fatal_error()
1822 1822 *
1823 1823 * DESCRIPTION: Works out if a failed mapping operation should be retried.
1824 1824 *
1825 1825 * INPUTS : Result code from operation
1826 1826 *
1827 1827 * OUTPUTS : TRUE = Fatal error, don't retry.
1828 1828 * FALSE = Temporary error, retry.
1829 1829 */
1830 1830 bool_t
1831 1831 is_fatal_error(int res)
1832 1832 {
1833 1833
1834 1834 if (0 > res)
1835 1835 /* An internal mapping error. Not going to go away. */
1836 1836 return (TRUE);
1837 1837
1838 1838 switch (res) {
1839 1839 case (LDAP_PROTOCOL_ERROR):
1840 1840 case (LDAP_TIMELIMIT_EXCEEDED):
1841 1841 case (LDAP_PARTIAL_RESULTS):
1842 1842 case (LDAP_BUSY):
1843 1843 case (LDAP_UNAVAILABLE):
1844 1844 case (LDAP_UNWILLING_TO_PERFORM):
1845 1845 case (LDAP_OTHER):
1846 1846 case (LDAP_SERVER_DOWN):
1847 1847 case (LDAP_LOCAL_ERROR):
1848 1848 case (LDAP_TIMEOUT):
1849 1849 case (LDAP_NO_MEMORY):
1850 1850 /* Probably worth a retry */
1851 1851 return (FALSE);
1852 1852
1853 1853 default:
1854 1854 return (TRUE);
1855 1855 }
1856 1856 }
1857 1857
1858 1858 /*
1859 1859 * FUNCTION : addNISObject()
1860 1860 *
1861 1861 * DESCRIPTION: Add a nis Object in the DIT.
1862 1862 *
1863 1863 * GIVEN :
1864 1864 * Case 1: 'dn' is NULL
1865 1865 * Error
1866 1866 * Case 2: 'domain' is non-NULL
1867 1867 * Create nisDomainObject with the given information
1868 1868 * Case 3: 'domain' is NULL
1869 1869 * Create an object with the 'dn'
1870 1870 * Here we guess the objectclass attribute, based on
1871 1871 * oc_lookup table
1872 1872 *
1873 1873 * RETURNS : SUCCESS = It worked
1874 1874 * FAILURE = There was a problem. If the ldap add
1875 1875 * operation failed, ldap_rc will be set
1876 1876 * to the ldap error code.
1877 1877 */
1878 1878 suc_code
1879 1879 addNISObject(char *domain, char *dn, int *ldap_rc) {
1880 1880 __nis_rule_value_t *rv;
1881 1881 int rc;
1882 1882 char *objClassAttrs = NULL, *attrs;
1883 1883 char *value, *svalue, *rdn = NULL;
1884 1884 char *myself = "addNISObject";
1885 1885
1886 1886 if (!dn)
1887 1887 return (FAILURE);
1888 1888
1889 1889 if ((rv = initRuleValue(1, 0)) == 0)
1890 1890 return (FAILURE);
1891 1891
1892 1892 if (ldap_rc)
1893 1893 *ldap_rc = -1;
1894 1894
1895 1895 /*
1896 1896 * Add name=value pairs from RDN. Although this is not required
1897 1897 * for SunOne Directory Server, during openldap interoperabilty
1898 1898 * tests, it was found out that openldap server returned object
1899 1899 * class violation errors if MUST attributes were not specified
1900 1900 * explicitly.
1901 1901 */
1902 1902 if (splitDN(dn, &rdn, 0) == -1)
1903 1903 return (FAILURE);
1904 1904 if (rdn != NULL) {
1905 1905 objClassAttrs = (char *)getObjectClass(rdn);
1906 1906 if (objClassAttrs == NULL) {
1907 1907 sfree(rdn);
1908 1908 return (FAILURE);
1909 1909 }
1910 1910
1911 1911 /*
1912 1912 * RDN can be composed of multiple name=value pairs
1913 1913 * concatenated by '+'. Hence, we need to determine each
1914 1914 * pair and add it to 'rv'
1915 1915 */
1916 1916 for (value = rdn, svalue = NULL; *value != '\0'; value++) {
1917 1917 if (*value == '+') {
1918 1918 /* Make sure it's not escaped */
1919 1919 if (value == rdn || *(value - 1) != '\\') {
1920 1920 /*
1921 1921 * We are at the start of the new
1922 1922 * pair. 'svalue' now contains the
1923 1923 * value for the previous pair. Add
1924 1924 * the previous pair to 'rv'
1925 1925 */
1926 1926 *value = '\0';
1927 1927 if (svalue &&
1928 1928 addSAttr2RuleValue(rdn, svalue, rv)
1929 1929 == -1) {
1930 1930 sfree(rdn);
1931 1931 freeRuleValue(rv, 1);
1932 1932 return (FAILURE);
1933 1933 }
1934 1934 svalue = NULL;
1935 1935 rdn = value + 1;
1936 1936 continue;
1937 1937 }
1938 1938 }
1939 1939
1940 1940 if (*value == '=') {
1941 1941 if (value == rdn || *(value - 1) != '\\') {
1942 1942 /*
1943 1943 * 'rdn' now contains the name.
1944 1944 * Whatever follows till the next
1945 1945 * unescaped '+' or '\0' is the
1946 1946 * value for this pair.
1947 1947 */
1948 1948 *value = '\0';
1949 1949 svalue = value + 1;
1950 1950 continue;
1951 1951 }
1952 1952 }
1953 1953 }
1954 1954
1955 1955 /*
1956 1956 * End of String. Add the previous name=value pair to 'rv'
1957 1957 */
1958 1958 if (svalue && addSAttr2RuleValue(rdn, svalue, rv) == -1) {
1959 1959 sfree(rdn);
1960 1960 freeRuleValue(rv, 1);
1961 1961 return (FAILURE);
1962 1962 }
1963 1963 sfree(rdn);
1964 1964 } else /* rdn == NULL */
1965 1965 return (FAILURE);
1966 1966
1967 1967 /* Create the entry */
1968 1968 if (domain) {
1969 1969 if (addSAttr2RuleValue("nisDomain", domain, rv) == -1) {
1970 1970 freeRuleValue(rv, 1);
1971 1971 return (FAILURE);
1972 1972 }
1973 1973 attrs = scat(myself, F, "objectclass=nisdomainobject,",
1974 1974 objClassAttrs);
1975 1975 if (!attrs) {
1976 1976 freeRuleValue(rv, 1);
1977 1977 return (FAILURE);
1978 1978 }
1979 1979 rc = ldapAdd(dn, rv, attrs, 0);
1980 1980 sfree(attrs);
1981 1981 } else {
1982 1982 rc = ldapAdd(dn, rv, objClassAttrs, 0);
1983 1983 }
1984 1984
1985 1985 if (rc == LDAP_SUCCESS)
1986 1986 logmsg(MSG_NOTIMECHECK, LOG_INFO,
1987 1987 "%s: Entry (dn: %s) added to DIT",
1988 1988 myself, dn);
1989 1989 else if (rc == LDAP_ALREADY_EXISTS)
1990 1990 /* Treat this as success */
1991 1991 rc = LDAP_SUCCESS;
1992 1992 else
1993 1993 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1994 1994 "%s: ldapAdd error %d (%s) for (dn: %s)",
1995 1995 myself, rc, ldap_err2string(rc), dn);
1996 1996
1997 1997 freeRuleValue(rv, 1);
1998 1998 if (ldap_rc)
1999 1999 *ldap_rc = rc;
2000 2000 return ((rc == LDAP_SUCCESS)?SUCCESS:FAILURE);
2001 2001 }
↓ open down ↓ |
976 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX