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