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