1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <syslog.h>
36
37 #include "ldap_parse.h"
38 #include "nis_parse_ldap_conf.h"
39 #include "nis_parse_ldap_err.h"
40 #include "ldap_util.h"
41
42 extern __nis_mapping_rule_t **dup_mapping_rules(
43 __nis_mapping_rule_t **rules, int n_rules);
44 extern __nis_mapping_rule_t *dup_mapping_rule(
45 __nis_mapping_rule_t *in);
46
47 static int merge_table_mapping(__nis_table_mapping_t *in,
48 __nis_table_mapping_t *out);
49 __nis_table_mapping_t *new_merged_mapping(const char *,
50 __nis_table_mapping_t *intbl);
51 static int append_mapping_rule(__nis_mapping_rule_t *src_rule,
52 __nis_table_mapping_t *tbl, int flag);
53
54
55 static int copy_object_dn(__nis_object_dn_t *in,
56 __nis_object_dn_t *newdn);
57
58 /*
59 * FUNCTION: initialize_table_mapping
60 *
61 * Initialize the __nis_table_mapping_t structure.
62 *
63 * INPUT: __nis_table_mapping_t
64 *
65 */
66 void
initialize_table_mapping(__nis_table_mapping_t * mapping)67 initialize_table_mapping(
68 __nis_table_mapping_t *mapping)
69 {
70 if (mapping != NULL) {
71 mapping->dbId = NULL;
72
73 mapping->index.numIndexes = 0;
74 mapping->index.name = NULL;
75 mapping->index.value = NULL;
76
77 mapping->numColumns = 0;
78 mapping->column = NULL;
79
80 mapping->initTtlLo = (time_t)NO_VALUE_SET;
81 mapping->initTtlHi = (time_t)NO_VALUE_SET;
82 mapping->ttl = (time_t)NO_VALUE_SET;
83
84 mapping->usedns_flag = 0;
85 mapping->securemap_flag = 0;
86 mapping->commentChar = DEFAULT_COMMENT_CHAR;
87 mapping->numSplits = 0;
88
89 mapping->objectDN = NULL;
90
91 mapping->separatorStr = DEFAULT_SEP_STRING;
92
93 mapping->numRulesFromLDAP = 0;
94 mapping->numRulesToLDAP = 0;
95
96 mapping->ruleFromLDAP = NULL;
97 mapping->ruleToLDAP = NULL;
98
99 mapping->e = NULL;
100 mapping->objName = NULL;
101 mapping->objPath = NULL;
102 mapping->obj = NULL;
103 mapping->isMaster = 0;
104 mapping->seq_num = NO_VALUE_SET;
105 }
106 }
107
108 /*
109 * FUNCTION: initialize_yp_parse_structs
110 *
111 * Initialize the __yp_domain_context_t structure.
112 *
113 * INPUT: __yp_domain_context_t
114 *
115 */
116 void
initialize_yp_parse_structs(__yp_domain_context_t * ypDomains)117 initialize_yp_parse_structs(
118 __yp_domain_context_t *ypDomains)
119 {
120 ypDomains->numDomains = 0;
121 ypDomains->domainLabels = NULL;
122 ypDomains->domains = NULL;
123 ypDomains->numYppasswdd = 0;
124 ypDomains->yppasswddDomainLabels = NULL;
125 }
126
127 /*
128 * FUNCTION: merge_table_mapping
129 *
130 * Merges information from one table_mapping struct
131 * into another
132 *
133 * INPUT: Source and Destination table_mapping structs.
134 * RETURN: 0 on success and > 0 on error.
135 */
136
137 static int
merge_table_mapping(__nis_table_mapping_t * in,__nis_table_mapping_t * out)138 merge_table_mapping(
139 __nis_table_mapping_t *in,
140 __nis_table_mapping_t *out)
141 {
142 int i;
143 int len;
144 int orig_num_rules;
145 int append;
146
147 if (in == NULL)
148 return (1);
149
150 if (in->dbId == NULL)
151 return (1);
152
153 /*
154 * If 'in' is generic (non-expanded) and 'out' is domain-specific,
155 * then rules from 'in' should not be appended to those in 'out'.
156 */
157 if (!strchr(in->dbId, COMMA_CHAR) && strchr(out->dbId, COMMA_CHAR))
158 append = 0;
159 else
160 append = 1;
161
162
163 if (!out->index.numIndexes && in->index.numIndexes > 0) {
164 if (!dup_index(&in->index, &out->index))
165 return (1);
166 }
167
168 /* add_column() increments numColumns, so we don't */
169 if (!out->numColumns && in->numColumns > 0) {
170 for (i = 0; i < in->numColumns; i++) {
171 if (!add_column(out, in->column[i]))
172 return (1);
173 }
174 }
175
176 if (out->commentChar == DEFAULT_COMMENT_CHAR &&
177 in->commentChar != DEFAULT_COMMENT_CHAR)
178 out->commentChar = in->commentChar;
179
180 if (out->usedns_flag == 0)
181 out->usedns_flag = in->usedns_flag;
182
183 if (out->securemap_flag == 0)
184 out->securemap_flag = in->securemap_flag;
185
186 if (out->separatorStr == DEFAULT_SEP_STRING &&
187 in->separatorStr != DEFAULT_SEP_STRING) {
188 out->separatorStr = s_strdup(in->separatorStr);
189 if (!out->separatorStr)
190 return (2);
191 }
192
193 if (!out->numSplits && !out->e && in->e) {
194 out->numSplits = in->numSplits;
195 out->e = (__nis_mapping_element_t *)
196 s_calloc(1, (in->numSplits+1) *
197 sizeof (__nis_mapping_element_t));
198 if (!out->e)
199 return (2);
200 for (i = 0; i <= in->numSplits; i++) {
201 if (!dup_mapping_element(&in->e[i], &out->e[i])) {
202 for (; i > 0; i--) {
203 free_mapping_element(&out->e[i - 1]);
204 }
205 out->e = NULL;
206 return (1);
207 }
208 }
209 }
210
211 if (out->initTtlLo == (time_t)NO_VALUE_SET &&
212 in->initTtlLo != (time_t)NO_VALUE_SET)
213 out->initTtlLo = in->initTtlLo;
214
215 if (out->initTtlHi == (time_t)NO_VALUE_SET &&
216 in->initTtlHi != (time_t)NO_VALUE_SET)
217 out->initTtlHi = in->initTtlHi;
218
219 if (out->ttl == (time_t)NO_VALUE_SET &&
220 in->ttl != (time_t)NO_VALUE_SET)
221 out->ttl = in->ttl;
222
223 if (!out->numRulesFromLDAP && in->numRulesFromLDAP) {
224 out->ruleFromLDAP = dup_mapping_rules(in->ruleFromLDAP,
225 in->numRulesFromLDAP);
226 if (!out->ruleFromLDAP)
227 return (1);
228 out->numRulesFromLDAP = in->numRulesFromLDAP;
229 } else if (append && out->numRulesFromLDAP && in->numRulesFromLDAP) {
230 orig_num_rules = out->numRulesFromLDAP;
231 for (i = 0; i < in->numRulesFromLDAP; i++) {
232 if (append_mapping_rule(in->ruleFromLDAP[i], out, 0)) {
233 for (i = out->numRulesFromLDAP;
234 i > orig_num_rules; i--) {
235 free_mapping_rule(out->ruleFromLDAP[i]);
236 out->ruleFromLDAP[i] = NULL;
237 }
238 return (1);
239
240 }
241 }
242 }
243
244 if (!out->numRulesToLDAP && in->numRulesToLDAP) {
245 out->ruleToLDAP = dup_mapping_rules(in->ruleToLDAP,
246 in->numRulesToLDAP);
247 if (!out->ruleToLDAP)
248 return (1);
249 out->numRulesToLDAP = in->numRulesToLDAP;
250 } else if (append && out->numRulesToLDAP && in->numRulesToLDAP) {
251 orig_num_rules = out->numRulesToLDAP;
252 for (i = 0; i < in->numRulesToLDAP; i++) {
253 if (append_mapping_rule(in->ruleToLDAP[i], out, 1)) {
254 for (i = out->numRulesToLDAP;
255 i > orig_num_rules; i--) {
256 free_mapping_rule(out->ruleToLDAP[i]);
257 out->ruleToLDAP[i] = NULL;
258 }
259 return (1);
260 }
261 }
262 }
263 if (!out->objectDN && in->objectDN) {
264 out->objectDN = (__nis_object_dn_t *)
265 s_calloc(1, sizeof (__nis_object_dn_t));
266 if (!out->objectDN)
267 return (2);
268 if (copy_object_dn(in->objectDN, out->objectDN)) {
269 free_object_dn(out->objectDN);
270 out->objectDN = NULL;
271 return (1);
272 }
273 }
274
275 if (!out->objName && in->objName) {
276 if (!strchr(in->objName, SPACE_CHAR)) {
277 /* objName has no space- a single map dbIdMapping */
278 out->objName = s_strndup(in->objName,
279 strlen(in->objName));
280 if (!out->objName)
281 return (2);
282 }
283 }
284
285 if (!out->objName && out->dbId) {
286 out->objName = s_strndup(out->dbId, strlen(out->dbId));
287 if (!out->objName)
288 return (2);
289 }
290
291 if (out->seq_num == NO_VALUE_SET && in->seq_num >= 0)
292 out->seq_num = in->seq_num;
293
294 return (p_error == no_parse_error ? 0 : 1);
295 }
296
297 /*
298 * FUNCTION: copy_object_dn
299 *
300 * Copies a __nis_object_dn_t structure.
301 *
302 * RETURN: 0 on success, > 0 on failure.
303 *
304 * NOTE: The caller MUST free newdn using
305 * free_object_dn() if return value != 0 (error condition)
306 */
307
308 static int
copy_object_dn(__nis_object_dn_t * in,__nis_object_dn_t * newdn)309 copy_object_dn(
310 __nis_object_dn_t *in,
311 __nis_object_dn_t *newdn)
312 {
313 if (in == NULL) {
314 p_error = parse_no_object_dn;
315 return (1);
316 }
317 while (in != NULL) {
318 if (in->read.base == NULL) {
319 newdn->read.base = NULL;
320 } else {
321 newdn->read.base = s_strndup(
322 in->read.base,
323 strlen(in->read.base));
324 if (newdn->read.base == NULL)
325 return (2);
326 }
327 newdn->read.scope = in->read.scope;
328 if (in->read.attrs) {
329 newdn->read.attrs = s_strndup(
330 in->read.attrs,
331 strlen(in->read.attrs));
332 if (newdn->read.attrs == NULL) {
333 return (2);
334 }
335 } else {
336 newdn->read.attrs = NULL;
337 }
338 newdn->read.element = in->read.element;
339 if (in->write.base != NULL) {
340 newdn->write.base = s_strndup(
341 in->write.base,
342 strlen(in->write.base));
343 if (newdn->write.base == NULL)
344 return (2);
345 } else {
346 newdn->write.base = NULL;
347 }
348 newdn->write.scope = in->write.scope;
349 if (in->write.attrs != NULL) {
350 newdn->write.attrs = s_strndup(
351 in->write.attrs,
352 strlen(in->write.attrs));
353 if (newdn->write.attrs == NULL) {
354 return (2);
355 }
356 } else {
357 newdn->write.attrs = NULL;
358 }
359 newdn->write.element = in->write.element;
360 if (in->dbIdName) {
361 newdn->dbIdName = s_strndup(in->dbIdName,
362 strlen(in->dbIdName));
363 if (newdn->dbIdName == NULL)
364 return (2);
365 }
366
367 if (in->delDisp)
368 newdn->delDisp = in->delDisp;
369
370 if (in->dbId && in->numDbIds > 0) {
371 newdn->dbId = dup_mapping_rules(in->dbId,
372 in->numDbIds);
373 if (!newdn->dbId)
374 return (1);
375 newdn->numDbIds = in->numDbIds;
376 }
377 if (in->next != NULL) {
378 newdn->next = (__nis_object_dn_t *)s_calloc(1,
379 sizeof (__nis_object_dn_t));
380 if (newdn->next == NULL)
381 return (1);
382 newdn = newdn->next;
383 in = in->next;
384 } else {
385 return (0);
386 }
387 } /* End of while on in */
388
389 return (0);
390 }
391
392 /*
393 * FUNCTION: free_yp_domain_context
394 *
395 * Frees __yp_domain_context_t
396 *
397 * INPUT: __yp_domain_context_t
398 */
399 void
free_yp_domain_context(__yp_domain_context_t * domains)400 free_yp_domain_context(__yp_domain_context_t *domains)
401 {
402 int i;
403
404 if (domains != NULL) {
405 for (i = 0; i < domains->numDomains; i++) {
406 if (domains->domains[i] != NULL) {
407 free(domains->domains[i]);
408 domains->domains[i] = NULL;
409 }
410 if (domains->domainLabels[i] != NULL) {
411 free(domains->domainLabels[i]);
412 domains->domainLabels[i] = NULL;
413 }
414 }
415 domains->domains = NULL;
416 domains->domainLabels = NULL;
417 for (i = 0; i < domains->numYppasswdd; i++) {
418 if (domains->yppasswddDomainLabels[i] != NULL) {
419 free(domains->yppasswddDomainLabels[i]);
420 domains->yppasswddDomainLabels[i]
421 = NULL;
422 }
423 }
424 domains->yppasswddDomainLabels = NULL;
425 domains->numDomains = 0;
426 domains = NULL;
427 }
428 }
429
430 /*
431 * FUNCTION: second_parser_pass
432 *
433 * Prepares the linked list of table_mappings for processing
434 * by finish_parse(), adding, merging and deleting structures
435 * as necessary. Also adds dummy objectDN info. for splitField's.
436 *
437 * RETURN VALUE: 0 on success, > 0 on failure.
438 */
439 int
second_parser_pass(__nis_table_mapping_t ** table_mapping)440 second_parser_pass(
441 __nis_table_mapping_t **table_mapping)
442 {
443 __nis_table_mapping_t *t, *t2;
444 __nis_table_mapping_t *t_new = NULL, *tg;
445 __nis_table_mapping_t *prev = NULL;
446 __nis_object_dn_t *objectDN;
447 char *objs, *dom;
448 char *objName = NULL;
449 char *lasts;
450 char *tobj, *alias, *dupalias, *tmp;
451 char *myself = "second_parser_pass";
452 int i = 0, len;
453 int remove_t = 0;
454 int add_t = 0;
455
456 prev = NULL;
457 for (t = *table_mapping; t != NULL; ) {
458 /*
459 * Temporarily using this field to flag deletion.
460 * 0 : don't delete
461 * 1 : delete
462 * The mapping structure will be deleted in final_parser_pass
463 */
464 t->isMaster = 0;
465
466 if (!t->dbId) {
467 p_error = parse_bad_map_error;
468 logmsg(MSG_NOTIMECHECK, LOG_ERR,
469 "%s: no dbId field", myself);
470 return (1);
471 }
472 tg = NULL;
473 dom = strchr(t->dbId, COMMA_CHAR);
474 if (t->objName != NULL) {
475 objName = strdup(t->objName);
476 if (objName == NULL) {
477 p_error = parse_no_mem_error;
478 logmsg(MSG_NOMEM, LOG_ERR,
479 "%s: Cannot allocate memory for objName", myself);
480 return (1);
481 }
482 objs = (char *)strtok_r(objName, " ", &lasts);
483 /* Get the generic mapping */
484 if (dom != NULL) {
485 tg = find_table_mapping(t->dbId, dom - t->dbId,
486 *table_mapping);
487 }
488 } else {
489 objs = NULL;
490 if (dom == NULL) {
491 t->objName = s_strndup(t->dbId,
492 strlen(t->dbId));
493 if (!t->objName) {
494 logmsg(MSG_NOMEM, LOG_ERR,
495 "%s: Cannot allocate memory for t->objName",
496 myself);
497 objs = NULL;
498 return (2);
499 }
500 } else {
501 /* Force relationship for domain specific */
502
503 /* Get the generic mapping */
504 tg = find_table_mapping(t->dbId, dom - t->dbId,
505 *table_mapping);
506 if (tg == NULL || tg->objName == NULL) {
507 /* If not found, use dbId for objName */
508 t->objName = s_strndup(t->dbId,
509 strlen(t->dbId));
510 if (t->objName == NULL) {
511 logmsg(MSG_NOMEM, LOG_ERR,
512 "%s: Cannot allocate memory for t->objName",
513 myself);
514 return (2);
515 }
516 } else {
517 dom++;
518 tobj = s_strndup(tg->objName,
519 strlen(tg->objName));
520 if (tobj == NULL) {
521 logmsg(MSG_NOMEM, LOG_ERR,
522 "%s: Cannot allocate memory for t->objName",
523 myself);
524 return (2);
525 }
526 alias = (char *)strtok_r(tobj, " ",
527 &lasts);
528
529 /* Loop 'breaks' on errors */
530 while (alias) {
531 tmp = NULL;
532 dupalias = s_strndup(alias,
533 strlen(alias));
534 if (!dupalias)
535 break;
536 if (getfullmapname(&dupalias,
537 dom)) {
538 i = 1;
539 break;
540 }
541 if (t->objName == NULL)
542 t->objName = dupalias;
543 else {
544 len = strlen(t->objName)
545 + strlen(dupalias) + 2;
546 tmp = s_calloc(1, len);
547 if (tmp == NULL)
548 break;
549 snprintf(tmp, len,
550 "%s %s",
551 t->objName,
552 dupalias);
553 free(dupalias);
554 dupalias = NULL;
555 free(t->objName);
556 t->objName = tmp;
557 }
558 alias = (char *)strtok_r(NULL,
559 " ", &lasts);
560 }
561
562 if (tobj)
563 free(tobj);
564
565 if (alias ||
566 (objName = s_strdup(t->objName))
567 == NULL) {
568 if (i)
569 logmsg(MSG_NOTIMECHECK,
570 LOG_ERR,
571 "%s: getfullmapname failed for %s for domain \"%s\"",
572 myself, dupalias, dom);
573 else {
574 p_error =
575 parse_no_mem_error;
576 logmsg(MSG_NOMEM,
577 LOG_ERR,
578 "%s: Cannot allocate memory",
579 myself);
580 }
581 if (dupalias)
582 free(dupalias);
583 if (t->objName)
584 free(t->objName);
585 return (2);
586
587 }
588 objs = (char *)strtok_r(objName, " ",
589 &lasts);
590 }
591 }
592 }
593
594 if (tg != NULL) {
595 if (merge_table_mapping(tg, t)) {
596 logmsg(MSG_NOTIMECHECK, LOG_ERR,
597 "Error merging information from the %s to the %s mapping structure",
598 tg->dbId, t->dbId);
599 objs = NULL;
600 if (objName)
601 free(objName);
602 return (1);
603 }
604 }
605
606 /*
607 * If objName is "map1 map2" then do the second pass.
608 * If it is just "map1" however skip the expansion.
609 * Also skip it if t->objName is null.
610 */
611 if (objs && strncasecmp(objs, t->objName,
612 strlen(t->objName))) {
613 t2 = find_table_mapping(objs, strlen(objs),
614 *table_mapping);
615 if (t2) {
616 if (merge_table_mapping(t, t2)) {
617 logmsg(MSG_NOTIMECHECK, LOG_ERR,
618 "Error merging information from the %s to the %s mapping structure",
619 t->dbId, t2->dbId);
620 objs = NULL;
621 if (objName)
622 free(objName);
623 return (1);
624 }
625 t->isMaster = 1;
626 } else {
627 t_new = new_merged_mapping(objs, t);
628 if (t_new) {
629 t->isMaster = 1;
630 if (prev != NULL)
631 prev->next = t_new;
632 else
633 *table_mapping = t_new;
634 prev = t_new;
635 prev->next = t;
636 } else {
637 logmsg(MSG_NOTIMECHECK, LOG_ERR,
638 "Error creating a new mapping structure %s",
639 objs);
640 objs = NULL;
641 if (objName)
642 free(objName);
643 return (1);
644 }
645 }
646 while ((objs = (char *)strtok_r(NULL, " ", &lasts))
647 != NULL) {
648 t2 = find_table_mapping(objs, strlen(objs),
649 *table_mapping);
650 if (t2) {
651 if (merge_table_mapping(t, t2)) {
652 logmsg(MSG_NOTIMECHECK, LOG_ERR,
653 "Error merging information from the %s to the %s mapping structure",
654 t->dbId, t2->dbId);
655 objs = NULL;
656 if (objName)
657 free(objName);
658 return (1);
659 }
660 t->isMaster = 1;
661 } else {
662 /*
663 * create a new t_map with dbId = objs
664 * and copy t->* into new t_map
665 */
666 t_new = new_merged_mapping(objs, t);
667 if (t_new) {
668 t->isMaster = 1;
669 if (prev != NULL)
670 prev->next = t_new;
671 else
672 *table_mapping = t_new;
673 prev = t_new;
674 prev->next = t;
675 } else {
676 logmsg(MSG_NOTIMECHECK, LOG_ERR,
677 "Error creating a new mapping structure %s",
678 objs);
679 objs = NULL;
680 if (objName)
681 free(objName);
682 return (1);
683 }
684 }
685 }
686 } /* if objs!= NULL */
687
688 prev = t;
689 t = t->next;
690
691 if (objName) {
692 free(objName);
693 objName = NULL;
694 objs = NULL;
695 }
696 } /* for t = table_mapping loop */
697 return (0);
698 }
699
700 __nis_table_mapping_t *
new_merged_mapping(const char * match,__nis_table_mapping_t * intbl)701 new_merged_mapping(const char *match,
702 __nis_table_mapping_t *intbl)
703 {
704
705 __nis_table_mapping_t *outtable = NULL;
706
707 outtable = (__nis_table_mapping_t *)
708 s_calloc(1, sizeof (__nis_table_mapping_t));
709 if (outtable == NULL)
710 return (NULL);
711 initialize_table_mapping(outtable);
712 outtable->dbId = s_strndup(match, strlen(match));
713 if (outtable->dbId == NULL) {
714 free_table_mapping(outtable);
715 outtable = NULL;
716 return (NULL);
717 }
718 if (merge_table_mapping(intbl, outtable)) {
719 free_table_mapping(outtable);
720 outtable = NULL;
721 }
722 return (outtable);
723 }
724
725 /*
726 * FUNCTION: final_parser_pass
727 *
728 * completes the final expansion of t_map structures linked list.
729 * all structures will have a non-null objPath as well as a objName
730 * in the form of "mapname . domainname ." or "splitfieldname .
731 * domainname .".
732 *
733 * RETURN VALUE: 0 on success, -1 on failure, -2 on fatal error.
734 */
735 int
final_parser_pass(__nis_table_mapping_t ** table_mapping,__yp_domain_context_t * ypDomains)736 final_parser_pass(
737 __nis_table_mapping_t **table_mapping,
738 __yp_domain_context_t *ypDomains)
739 {
740 __nis_table_mapping_t *t;
741 __nis_table_mapping_t *t1, *returned_map;
742 __nis_table_mapping_t *prev = NULL;
743 int i;
744 char *myself = "final_parser_pass";
745 int nm;
746 bool_t r;
747 int del_tbl_flag = 0;
748
749 if (ypDomains) {
750 if (!ypDomains->numDomains) {
751 p_error = parse_internal_error;
752 logmsg(MSG_NOTIMECHECK, LOG_ERR,
753 "%s:No domains specified.", myself);
754 return (-1);
755 }
756 } else {
757 p_error = parse_internal_error;
758 logmsg(MSG_NOTIMECHECK, LOG_ERR,
759 "%s:No domain structure supplied.", myself);
760 return (-1);
761 }
762 prev = NULL;
763
764 for (t = *table_mapping; t != NULL; ) {
765
766 /* Delete if marked for deletion by second_parser_pass */
767 if (t->isMaster == 1) {
768 if (prev != NULL)
769 prev->next = t->next;
770 else
771 *table_mapping = t->next;
772 t1 = t;
773 t = t->next;
774 free_table_mapping(t1);
775 continue;
776 }
777
778 if (!t->objName && t->dbId) {
779 t->objName = s_strndup(t->dbId, strlen(t->dbId));
780 if (!t->objName) {
781 logmsg(MSG_NOMEM, LOG_ERR,
782 "%s:Could not allocate.", myself);
783 return (-1);
784 }
785 }
786 i = ypDomains->numDomains;
787 while (i > 0) {
788 if (i == 1) {
789 /* modify existing table_mapping's */
790 nm = checkfullmapname(t->dbId,
791 ypDomains->domainLabels[0],
792 table_mapping, &returned_map);
793 if (nm == 1) {
794 /* delete this mapping structure */
795 logmsg(MSG_NOTIMECHECK,
796 LOG_WARNING,
797 "Mapping structure %s,%s "
798 "already exists.",
799 t->dbId,
800 ypDomains->domainLabels[0]);
801 if (merge_table_mapping(t,
802 returned_map)) {
803 logmsg(MSG_NOTIMECHECK, LOG_ERR,
804 "Error merging information "
805 "from the %s to the %s "
806 "mapping structure.",
807 t->dbId, returned_map->dbId);
808 return (-1);
809 }
810 if (del_tbl_flag == 0)
811 del_tbl_flag = 1;
812 } else if (nm == -1) {
813 logmsg(MSG_NOTIMECHECK, LOG_ERR,
814 "Error searching for %s,%s structure",
815 t->dbId, ypDomains->domainLabels[0]);
816 return (-1);
817 } else if (nm == 0 || nm == 2) {
818 if ((append_domainContext(&t,
819 ypDomains->domainLabels[0],
820 ypDomains->domains[0])) != 0) {
821 logmsg(MSG_NOTIMECHECK, LOG_ERR,
822 "Error appending domainContext %s",
823 ypDomains->domainLabels[0]);
824 return (-1);
825 }
826 del_tbl_flag = 0;
827 }
828 } else { /* if (i > 1) */
829 /* need to create new table_mapping's */
830 nm = checkfullmapname(t->dbId,
831 ypDomains->domainLabels[i - 1],
832 table_mapping, &returned_map);
833 if (nm == -1) {
834 logmsg(MSG_NOTIMECHECK, LOG_ERR,
835 "Error searching for %s,%s structure",
836 t->dbId, ypDomains->domainLabels[i - 1]);
837 return (-1);
838 } else if (nm == 0) {
839 t1 = new_merged_mapping(t->dbId, t);
840 /* we clone ourselves */
841 if (t1) {
842 if ((append_domainContext(&t1,
843 ypDomains->domainLabels[i - 1],
844 ypDomains->domains[i - 1])) != 0) {
845 logmsg(MSG_NOTIMECHECK, LOG_ERR,
846 "Error appending domainContext %s",
847 ypDomains->domainLabels[i - 1]);
848 free(t1);
849 return (-1);
850 }
851 if (prev != NULL) {
852 t1->next = prev->next;
853 prev->next = t1;
854 prev = prev->next;
855 } else {
856 t1->next =
857 *table_mapping;
858 *table_mapping = t1;
859 prev = t1;
860 }
861 } else { /* if !t1 */
862 p_error = parse_internal_error;
863 logmsg(MSG_NOTIMECHECK, LOG_ERR,
864 "%s:Could not create new table -"
865 " check all instances of %s for errors",
866 myself, t->dbId);
867 return (-1);
868 }
869 } else if (nm == 1) {
870 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
871 "Mapping structure %s,%s already exists.",
872 t->dbId,
873 ypDomains->domainLabels[i - 1]);
874 /*
875 * We should be deleting this, but can't
876 * really do it here, because we need to
877 * match with the domainLabels[0] case
878 * too. So we will just flag it for now.
879 */
880 if (merge_table_mapping(t,
881 returned_map)) {
882 logmsg(MSG_NOTIMECHECK, LOG_ERR,
883 "Error merging information from the %s to the %s mapping structure.",
884 t->dbId,
885 returned_map->dbId);
886 return (-1);
887 }
888 del_tbl_flag = 1;
889 } else if (nm == 2) {
890 if ((append_domainContext(&t,
891 ypDomains->domainLabels[i - 1],
892 ypDomains->domains[i - 1]))
893 != 0) {
894 logmsg(MSG_NOTIMECHECK, LOG_ERR,
895 "Error appending domainContext %s",
896 ypDomains->domainLabels[i - 1]);
897 return (-1);
898 }
899 } /* end of "if (nm == 0)" */
900 } /* end of else if (i > 1) */
901
902
903 /*
904 * 'merge_table_mapping' only copies unexpanded
905 * objectDN values into returned_map. Hence,
906 * read.base and write.base in returned_map
907 * needs to be expanded.
908 */
909 if (nm == 1 && returned_map && returned_map->objectDN) {
910 r = make_fqdn(
911 returned_map->objectDN,
912 ypDomains->domains[i - 1]);
913 if (r == TRUE &&
914 returned_map->objectDN->write.base) {
915 r = make_full_dn(
916 &returned_map->objectDN->write.base,
917 ypDomains->domains[i - 1]);
918 }
919
920 if (r == FALSE) {
921 logmsg(MSG_NOTIMECHECK, LOG_ERR,
922 "Error appending domainContext "
923 "%s to %s",
924 ypDomains->domainLabels[i - 1],
925 returned_map->dbId);
926 return (-2);
927 }
928 }
929 i--;
930 } /* end of while i > 0 loop */
931
932 if (del_tbl_flag == 1) {
933 if (prev != NULL) {
934 prev->next = t->next;
935 free_table_mapping(t);
936 t = prev->next;
937 } else {
938 *table_mapping = t->next;
939 free_table_mapping(t);
940 t = *table_mapping;
941 }
942 del_tbl_flag = 0;
943 } else {
944 prev = t;
945 t = t->next;
946 }
947 } /* end of table mapping loop */
948
949 for (t = *table_mapping; t != NULL; t = t->next) {
950 if (!t->dbId) {
951 logmsg(MSG_NOTIMECHECK, LOG_ERR,
952 "%s:Fatal error: structure with no dbId found.",
953 myself);
954 return (-2);
955 }
956 append_dot(&t->dbId);
957 if (!t->objectDN) {
958 p_error = parse_internal_error;
959 logmsg(MSG_NOTIMECHECK, LOG_ERR,
960 "%s:No objectDN for %s.", myself, t->dbId);
961 return (-1);
962 }
963 }
964
965 return (0);
966 }
967
968 /*
969 * FUNCTION: append_mapping_rule
970 *
971 * Appends mapping rules to a table_mapping structure
972 * with previously existing rules. flag controls whether
973 * the functions works on the rules From or To LDAP.
974 *
975 * RETURN VALUE: 0 on success, >= 1 on failure.
976 */
977
978 static int
append_mapping_rule(__nis_mapping_rule_t * src_rule,__nis_table_mapping_t * dst,int flag)979 append_mapping_rule(__nis_mapping_rule_t *src_rule,
980 __nis_table_mapping_t *dst, int flag)
981 {
982 __nis_mapping_rule_t **rules = NULL;
983
984 if (flag == 0) {
985 if (dst->ruleFromLDAP == NULL) {
986 p_error = parse_internal_error;
987 return (1);
988 }
989 rules = (__nis_mapping_rule_t **)
990 s_realloc(dst->ruleFromLDAP,
991 (dst->numRulesFromLDAP + 1) *
992 sizeof (__nis_mapping_rule_t *));
993 if (rules == NULL)
994 return (2);
995 dst->ruleFromLDAP = rules;
996 rules[dst->numRulesFromLDAP] = dup_mapping_rule(src_rule);
997 if (rules[dst->numRulesFromLDAP] == NULL) {
998 p_error = parse_no_mem_error;
999 return (2);
1000 }
1001 dst->numRulesFromLDAP++;
1002 } else if (flag == 1) {
1003 if (dst->ruleToLDAP == NULL) {
1004 p_error = parse_internal_error;
1005 return (1);
1006 }
1007 rules = (__nis_mapping_rule_t **)
1008 s_realloc(dst->ruleToLDAP,
1009 (dst->numRulesToLDAP + 1) *
1010 sizeof (__nis_mapping_rule_t *));
1011 if (rules == NULL)
1012 return (2);
1013 dst->ruleToLDAP = rules;
1014 rules[dst->numRulesToLDAP] = dup_mapping_rule(src_rule);
1015 if (rules[dst->numRulesToLDAP] == NULL) {
1016 p_error = parse_no_mem_error;
1017 return (2);
1018 }
1019 dst->numRulesToLDAP++;
1020 } else
1021 return (1);
1022
1023 return (0);
1024 }
1025
1026 /*
1027 * FUNCTION: check_domain_specific_order
1028 *
1029 * Makes sure that an attribute with explicitly specified
1030 * nisLDAPdomainContext is found before its non-domain
1031 * specific counterpart.
1032 *
1033 * RETURN VALUE: 0 normal exit
1034 * 1 if domain specific attribute found
1035 * after non-domain specific one.
1036 * -1 some error condition
1037 */
1038
1039 int
check_domain_specific_order(const char * sd,config_key attrib_num,__nis_table_mapping_t * table_mapping,__yp_domain_context_t * ypDomains)1040 check_domain_specific_order(const char *sd,
1041 config_key attrib_num,
1042 __nis_table_mapping_t *table_mapping,
1043 __yp_domain_context_t *ypDomains)
1044 {
1045 __nis_table_mapping_t *t;
1046 char *myself = "check_domain_specific_order";
1047 char *type;
1048 char *dbId = 0;
1049 int i, len;
1050 int match = 0;
1051
1052 if (ypDomains) {
1053 if (!ypDomains->numDomains) {
1054 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1055 "%s:No domains specified.", myself);
1056 return (-1);
1057 }
1058 } else {
1059 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1060 "%s:No domain structure supplied.", myself);
1061 return (-1);
1062 }
1063
1064 for (i = 0; i < ypDomains->numDomains; i++) {
1065 for (t = table_mapping; t != NULL; t = t->next) {
1066 len = strlen(sd);
1067 if ((strcasecmp(t->dbId, sd) == 0) && (len ==
1068 strlen(t->dbId)))
1069 /* prevent from matching against itself */
1070 continue;
1071 dbId = s_strndup(t->dbId, strlen(t->dbId));
1072 if (dbId == NULL) {
1073 logmsg(MSG_NOMEM, LOG_ERR,
1074 "%s:Memory allocation error.", myself);
1075 return (-1);
1076 }
1077
1078 if (getfullmapname(&dbId,
1079 ypDomains->domainLabels[i])) {
1080 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1081 "Error getting fully qualified name for %s",
1082 dbId);
1083 free(dbId);
1084 return (-1);
1085 }
1086 if ((strcasecmp(dbId, sd) == 0) && (len ==
1087 strlen(dbId))) {
1088 match = 0;
1089 switch (attrib_num) {
1090 case key_yp_map_flags:
1091 if (t->usedns_flag != 0 ||
1092 t->securemap_flag != 0)
1093 match = 1;
1094 type = YP_MAP_FLAGS;
1095 break;
1096 case key_yp_comment_char:
1097 if (t->commentChar !=
1098 DEFAULT_COMMENT_CHAR)
1099 match = 1;
1100 type = YP_COMMENT_CHAR;
1101 break;
1102 case key_yp_repeated_field_separators:
1103 if (t->separatorStr !=
1104 DEFAULT_SEP_STRING)
1105 match = 1;
1106 type =
1107 YP_REPEATED_FIELD_SEPARATORS;
1108 break;
1109 case key_yp_name_fields:
1110 if (t->e && t->numColumns)
1111 match = 1;
1112 type = YP_NAME_FIELDS;
1113 case key_yp_split_field:
1114 if (t->e && t->numColumns)
1115 match = 1;
1116 type = YP_SPLIT_FIELD;
1117 break;
1118 case key_yp_db_id_map:
1119 if (t->objName)
1120 match = 1;
1121 type = YP_DB_ID_MAP;
1122 break;
1123 case key_yp_entry_ttl:
1124 if (t->initTtlLo !=
1125 (time_t)NO_VALUE_SET)
1126 match = 1;
1127 type = YP_ENTRY_TTL;
1128 break;
1129 case key_yp_ldap_object_dn:
1130 if (t->objectDN)
1131 match = 1;
1132 type = YP_LDAP_OBJECT_DN;
1133 break;
1134 case key_nis_to_ldap_map:
1135 if (t->ruleToLDAP)
1136 match = 1;
1137 type = NIS_TO_LDAP_MAP;
1138 break;
1139 case key_ldap_to_nis_map:
1140 if (t->ruleFromLDAP)
1141 match = 1;
1142 type = LDAP_TO_NIS_MAP;
1143 break;
1144 default:
1145 type = "unknown";
1146 match = 0;
1147 break;
1148 } /* end of switch */
1149 if (match) {
1150 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1151 "Relative attribute '%s' of type '%s' found before fully qualified one '%s'",
1152 t->dbId, type, sd);
1153 free(dbId);
1154 dbId = NULL;
1155 return (1);
1156 }
1157 } /* end of strncasecmp */
1158 free(dbId);
1159 dbId = NULL;
1160 } /* end of t loop */
1161 } /* end of i loop */
1162 if (dbId)
1163 free(dbId);
1164 dbId = NULL;
1165 return (0);
1166 }
1167
1168 int
getfullmapname(char ** mapname,const char * domainname)1169 getfullmapname(char **mapname, const char *domainname)
1170 {
1171 char *maps = *mapname;
1172 int maplen = strlen(maps);
1173 int domainlen = strlen(domainname);
1174
1175 if (!maplen || !domainlen ||
1176 maps[maplen - 1] == PERIOD_CHAR)
1177 return (1);
1178 else if (strchr(maps, COMMA_CHAR)) {
1179 /* map already has a domain part, do nothing */
1180 return (0);
1181 } else {
1182 append_comma(&maps);
1183 maplen = strlen(maps);
1184 maps = realloc(maps, (maplen + domainlen + 1));
1185 if (maps != NULL) {
1186 if (strlcat(maps, domainname, (maplen + domainlen + 1))
1187 >= (maplen + domainlen + 1))
1188 return (1);
1189 *mapname = maps;
1190 return (0);
1191 } else
1192 return (1);
1193 }
1194 }
1195
1196 /*
1197 * FUNCTION: checkfullmapname
1198 *
1199 * Tries to find out if by appending the table mapping structures
1200 * with each of the provided nisLDAPdomainContexts, an already
1201 * existing fqdn table mapping structure results. That would be the
1202 * case when a full qualified domain specific attribute was present.
1203 *
1204 * Note that per NISLDAPmapping(4) such an attribute MUST be listed
1205 * in the mapping file BEFORE its non-fqdn counterpart.
1206 *
1207 * RETURNS: 0 normal exit, 1 if an existing structure found, -1 for all
1208 * errors, 2 if already fqdn. If returning 1 the existing structure is
1209 * in found_map.
1210 */
1211
1212 int
checkfullmapname(const char * mapname,const char * domainname,__nis_table_mapping_t ** table_mapping,__nis_table_mapping_t ** found_map)1213 checkfullmapname(const char *mapname, const char *domainname,
1214 __nis_table_mapping_t **table_mapping,
1215 __nis_table_mapping_t **found_map)
1216 {
1217 char *map;
1218
1219 *found_map = NULL;
1220
1221 /* This function does not alter mapname */
1222
1223 if (!mapname || !domainname || *table_mapping == NULL)
1224 return (-1);
1225
1226 if (strchr(mapname, COMMA_CHAR))
1227 return (2);
1228
1229 if ((map = s_strndup(mapname, strlen(mapname))) == 0)
1230 return (-1);
1231
1232 if (getfullmapname(&map, domainname)) {
1233 free(map);
1234 return (-1);
1235 }
1236
1237 *found_map = find_table_mapping(map, strlen(map), *table_mapping);
1238 if (*found_map) {
1239 free(map);
1240 return (1);
1241 }
1242
1243 free(map);
1244 return (0);
1245 }
1246
1247 /*
1248 * FUNCTION: append_domainContext
1249 *
1250 * Higher level function to append the domains to the appropriate
1251 * fields in a table mapping structure. Calls either getfullmapname()
1252 * or make_full_dn() to do the actual append.
1253 *
1254 * RETURNS: 0 on success, -1 on any error.
1255 */
1256
1257 int
append_domainContext(__nis_table_mapping_t ** table_map,char * DomainLabel,char * Domain)1258 append_domainContext(__nis_table_mapping_t **table_map,
1259 char *DomainLabel, char *Domain)
1260 {
1261 __nis_table_mapping_t *tmp_map = *table_map;
1262 char *lasts;
1263 char *tmp_dbId = NULL;
1264 char *id = NULL;
1265 int domain_specific = 0;
1266 char *myself = "append_domainContext";
1267
1268 if (!DomainLabel || !Domain || !tmp_map)
1269 return (-1);
1270 if (tmp_map->dbId == NULL || tmp_map->objName == NULL) {
1271 p_error = parse_bad_map_error;
1272 return (-1);
1273 }
1274 tmp_dbId = s_strndup(tmp_map->dbId, strlen(tmp_map->dbId));
1275 if (!tmp_dbId)
1276 return (-1);
1277 if (strchr(tmp_map->dbId, COMMA_CHAR)) {
1278 domain_specific = 1;
1279 id = (char *)strtok_r(tmp_dbId, COMMA_STRING, &lasts);
1280 if (id)
1281 id = (char *)strtok_r(NULL, COMMA_STRING, &lasts);
1282 else {
1283 free(tmp_dbId);
1284 return (-1);
1285 }
1286 if (!id) {
1287 free(tmp_dbId);
1288 return (-1);
1289 }
1290 if (strcasecmp(id, DomainLabel)) {
1291 free(tmp_dbId);
1292 return (0);
1293 }
1294 } else {
1295 if (getfullmapname(&tmp_map->dbId, DomainLabel)) {
1296 free(tmp_dbId);
1297 return (-1);
1298 }
1299 append_dot(&tmp_map->dbId);
1300 }
1301 if (tmp_dbId)
1302 free(tmp_dbId);
1303 tmp_dbId = NULL;
1304
1305 if (getfullmapname(&tmp_map->objName, DomainLabel))
1306 return (-1);
1307 append_dot(&tmp_map->objName);
1308
1309 /*
1310 * If domain specific mapping doesn't have objectDN,
1311 * then don't touch. Most probably, pass for the generic mapping
1312 * will handle this by coping over it's own objectDN
1313 */
1314 if (domain_specific && tmp_map->objectDN == NULL)
1315 return (0);
1316
1317 if (tmp_map->objectDN == NULL) {
1318 /* Allocate memory to objectDN */
1319 tmp_map->objectDN = (__nis_object_dn_t *)
1320 s_calloc(1, sizeof (__nis_object_dn_t));
1321 if (tmp_map->objectDN == NULL) {
1322 logmsg(MSG_NOMEM, LOG_ERR,
1323 "%s: Cannot allocate memory for objectDN",
1324 myself);
1325 return (2);
1326 }
1327 tmp_map->objectDN->read.base = NULL;
1328 tmp_map->objectDN->write.base = NULL;
1329 tmp_map->objectDN->read.attrs = NULL;
1330 tmp_map->objectDN->write.attrs = NULL;
1331 tmp_map->objectDN->read.scope = LDAP_SCOPE_ONELEVEL;
1332 tmp_map->objectDN->write.scope = LDAP_SCOPE_UNKNOWN;
1333 }
1334
1335 if (!make_fqdn(tmp_map->objectDN, Domain))
1336 return (-1);
1337 if (tmp_map->objectDN->write.base) {
1338 if (!make_full_dn(&tmp_map->objectDN->write.base, Domain))
1339 return (-1);
1340 }
1341
1342 return (0);
1343 }
1344