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 2004 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 <unistd.h>
34 #include <errno.h>
35 #include <locale.h>
36 #include <lber.h>
37 #include <ldap.h>
38 #include <syslog.h>
39 #include <dlfcn.h> /* for dynamic loading only */
40
41 #include "ldap_parse.h"
42 #include "nis_parse_ldap_conf.h"
43 #include "nis_parse_ldap_err.h"
44 #include "ldap_util.h"
45 #include "ldap_util.h"
46
47 void append_dot(char **str);
48 void append_comma(char **str);
49 bool_t make_full_dn(char **dn, const char *base);
50 bool_t make_fqdn(__nis_object_dn_t *dn, const char *base);
51 char *get_default_ldap_base(const char *domain);
52 bool_t add_domain(char **objName, const char *domain);
53 bool_t add_column(__nis_table_mapping_t *t, const char *col_name);
54 __nis_mapping_rule_t **dup_mapping_rules(
55 __nis_mapping_rule_t **rules, int n_rules);
56 __nis_mapping_rule_t *dup_mapping_rule(
57 __nis_mapping_rule_t *in);
58 void *s_malloc(size_t size);
59 __nis_mapping_format_t *dup_format_mapping(
60 __nis_mapping_format_t *in);
61 bool_t dup_mapping_element(__nis_mapping_element_t *in,
62 __nis_mapping_element_t *out);
63 bool_t is_string_ok(char *, int);
64
65 extern FILE *cons;
66
67 /*
68 * FUNCTION: free_parse_structs
69 *
70 * Release the resources in parse results
71 *
72 */
73
74 void
free_parse_structs()75 free_parse_structs()
76 {
77 __nis_table_mapping_t *t;
78 __nis_table_mapping_t *t1;
79
80 free_proxy_info(&proxyInfo);
81 for (t = ldapTableMapping; t != NULL; t = t1) {
82 t1 = t->next;
83 free_table_mapping(t);
84 }
85 ldapTableMapping = NULL;
86 }
87
88 /*
89 * FUNCTION: initialize_parse_structs
90 *
91 * Initialize fields to unset values
92 *
93 * INPUT: __nis_ldap_proxy_info, __nis_config_t
94 * and __nisdb_table_mapping_t structures
95 */
96
97 void
initialize_parse_structs(__nis_ldap_proxy_info * proxy_info,__nis_config_t * config_info,__nisdb_table_mapping_t * table_info)98 initialize_parse_structs(
99 __nis_ldap_proxy_info *proxy_info,
100 __nis_config_t *config_info,
101 __nisdb_table_mapping_t *table_info)
102 {
103 proxy_info->default_servers = NULL;
104 proxy_info->auth_method = (auth_method_t)NO_VALUE_SET;
105 proxy_info->tls_method = (tls_method_t)NO_VALUE_SET;
106 proxy_info->tls_cert_db = NULL;
107 proxy_info->default_search_base = NULL;
108 proxy_info->proxy_dn = NULL;
109 proxy_info->proxy_passwd = NULL;
110 proxy_info->default_nis_domain = NULL;
111 proxy_info->bind_timeout.tv_sec = (time_t)NO_VALUE_SET;
112 proxy_info->bind_timeout.tv_usec = 0;
113 proxy_info->search_timeout.tv_sec = (time_t)NO_VALUE_SET;
114 proxy_info->search_timeout.tv_usec = 0;
115 proxy_info->modify_timeout.tv_sec = (time_t)NO_VALUE_SET;
116 proxy_info->modify_timeout.tv_usec = 0;
117 proxy_info->add_timeout.tv_sec = (time_t)NO_VALUE_SET;
118 proxy_info->add_timeout.tv_usec = 0;
119 proxy_info->delete_timeout.tv_sec = (time_t)NO_VALUE_SET;
120 proxy_info->delete_timeout.tv_usec = 0;
121 proxy_info->search_time_limit = (int)NO_VALUE_SET;
122 proxy_info->search_size_limit = (int)NO_VALUE_SET;
123 proxy_info->follow_referral = (follow_referral_t)NO_VALUE_SET;
124
125
126 config_info->initialUpdate = (__nis_initial_update_t)NO_VALUE_SET;
127 config_info->threadCreationError =
128 (__nis_thread_creation_error_t)NO_VALUE_SET;
129 config_info->threadCreationErrorTimeout.attempts = NO_VALUE_SET;
130 config_info->threadCreationErrorTimeout.timeout = (time_t)NO_VALUE_SET;
131 config_info->dumpError = (__nis_dump_error_t)NO_VALUE_SET;
132 config_info->dumpErrorTimeout.attempts = NO_VALUE_SET;
133 config_info->dumpErrorTimeout.timeout = (time_t)NO_VALUE_SET;
134 config_info->resyncService = (__nis_resync_service_t)NO_VALUE_SET;
135 config_info->updateBatching = (__nis_update_batching_t)NO_VALUE_SET;
136 config_info->updateBatchingTimeout.timeout = (time_t)NO_VALUE_SET;
137 config_info->numberOfServiceThreads = (int)NO_VALUE_SET;
138 config_info->emulate_yp = (int)NO_VALUE_SET;
139 config_info->maxRPCRecordSize = (int)NO_VALUE_SET;
140
141 table_info->retrieveError = (__nis_retrieve_error_t)NO_VALUE_SET;
142 table_info->retrieveErrorRetry.attempts = NO_VALUE_SET;
143 table_info->retrieveErrorRetry.timeout = (time_t)NO_VALUE_SET;
144 table_info->storeError = (__nis_store_error_t)NO_VALUE_SET;
145 table_info->storeErrorRetry.attempts = NO_VALUE_SET;
146 table_info->storeErrorRetry.timeout = (time_t)NO_VALUE_SET;
147 table_info->refreshError = (__nis_refresh_error_t)NO_VALUE_SET;
148 table_info->refreshErrorRetry.attempts = NO_VALUE_SET;
149 table_info->refreshErrorRetry.timeout = (time_t)NO_VALUE_SET;
150 table_info->matchFetch = (__nis_match_fetch_t)NO_VALUE_SET;
151 }
152
153 /*
154 * FUNCTION: free_mapping_rule
155 *
156 * Frees __nis_mapping_rule_t
157 *
158 * INPUT: __nis_mapping_rule_t
159 */
160
161 void
free_mapping_rule(__nis_mapping_rule_t * rule)162 free_mapping_rule(__nis_mapping_rule_t *rule)
163 {
164 int i;
165 __nis_mapping_rlhs_t *r;
166
167 if (rule != NULL) {
168 r = &rule->lhs;
169 for (i = 0; i < r->numElements; i++)
170 free_mapping_element(&r->element[i]);
171 if (r->element != NULL)
172 free(r->element);
173
174 r = &rule->rhs;
175 for (i = 0; i < r->numElements; i++)
176 free_mapping_element(&r->element[i]);
177 if (r->element != NULL)
178 free(r->element);
179
180 free(rule);
181 }
182 }
183
184 /*
185 * FUNCTION: free_mapping_element
186 *
187 * Frees __nis_mapping_element_t
188 *
189 * INPUT: __nis_mapping_element_t
190 */
191
192 void
free_mapping_element(__nis_mapping_element_t * e)193 free_mapping_element(__nis_mapping_element_t *e)
194 {
195 int i;
196
197 if (e == NULL)
198 return;
199
200 switch (e->type) {
201 case me_item:
202 free_mapping_item(&e->element.item);
203 break;
204 case me_print:
205 if (e->element.print.fmt != NULL)
206 free_mapping_format(e->element.print.fmt);
207 e->element.print.fmt = NULL;
208 for (i = 0; i < e->element.print.numSubElements; i++)
209 free_mapping_sub_element(
210 &e->element.print.subElement[i]);
211 e->element.print.numSubElements = 0;
212 if (e->element.print.subElement != NULL)
213 free(e->element.print.subElement);
214 e->element.print.subElement = NULL;
215 break;
216 case me_split:
217 free_mapping_item(&e->element.split.item);
218 break;
219 case me_match:
220 if (e->element.match.fmt != NULL)
221 free_mapping_format(e->element.match.fmt);
222 e->element.match.fmt = NULL;
223 for (i = 0; i < e->element.match.numItems; i++)
224 free_mapping_item(&e->element.match.item[i]);
225 e->element.match.numItems = 0;
226 if (e->element.match.item != NULL)
227 free(e->element.match.item);
228 e->element.match.item = NULL;
229 break;
230 case me_extract:
231 if (e->element.extract.fmt != NULL)
232 free_mapping_format(e->element.extract.fmt);
233 e->element.extract.fmt = NULL;
234 free_mapping_item(&e->element.extract.item);
235 break;
236 }
237 e = NULL;
238 }
239
240 /*
241 * FUNCTION: free_table_mapping
242 *
243 * Frees __nis_table_mapping_t
244 *
245 * INPUT: __nis_table_mapping_t
246 */
247
248 /*
249 * free_table_mapping does not remove the table mapping from
250 * its hashed list
251 */
252
253 void
free_table_mapping(__nis_table_mapping_t * mapping)254 free_table_mapping(__nis_table_mapping_t *mapping)
255 {
256 int i;
257
258 if (mapping == NULL)
259 return;
260
261 if (mapping->dbId != NULL)
262 free(mapping->dbId);
263 mapping->dbId = NULL;
264
265 if (mapping->objName != NULL)
266 free(mapping->objName);
267 mapping->objName = NULL;
268
269 for (i = 0; i < mapping->index.numIndexes; i++) {
270 free(mapping->index.name[i]);
271 free_mapping_format(mapping->index.value[i]);
272 }
273
274 if (mapping->index.name != NULL)
275 free(mapping->index.name);
276 mapping->index.name = NULL;
277
278 if (mapping->index.value != NULL)
279 free(mapping->index.value);
280 mapping->index.value = NULL;
281
282 mapping->index.numIndexes = 0;
283
284 if (mapping->column != NULL) {
285 for (i = 0; i < mapping->numColumns; i++) {
286 free(mapping->column[i]);
287 }
288 mapping->numColumns = 0;
289 free(mapping->column);
290 mapping->column = NULL;
291 }
292
293 if (mapping->commentChar != NULL)
294 mapping->commentChar = NULL;
295
296 if (mapping->objectDN != NULL)
297 free_object_dn(mapping->objectDN);
298 mapping->objectDN = NULL;
299
300 if (mapping->separatorStr != NULL)
301 mapping->separatorStr = NULL;
302
303 for (i = 0; i < mapping->numRulesFromLDAP; i++) {
304 if (mapping->ruleFromLDAP[i]) /* See Comment below */
305 free_mapping_rule(mapping->ruleFromLDAP[i]);
306 }
307 mapping->numRulesFromLDAP = 0;
308
309 if (mapping->ruleFromLDAP != NULL)
310 free(mapping->ruleFromLDAP);
311 mapping->ruleFromLDAP = NULL;
312
313 for (i = 0; i < mapping->numRulesToLDAP; i++) {
314 if (mapping->ruleToLDAP[i])
315 /*
316 * Normally mapping->ruleToLDAP[i] should
317 * always be non-null if
318 * mapping->numRulesToLDAP is > 0.
319 * However it is possible to have data
320 * corruption where numRulesToLDAP gets
321 * some integer value even though no real
322 * data is present in mapping->ruleToLDAP.
323 */
324 free_mapping_rule(mapping->ruleToLDAP[i]);
325 }
326 mapping->numRulesToLDAP = 0;
327
328 if (mapping->ruleToLDAP != NULL)
329 free(mapping->ruleToLDAP);
330 mapping->ruleToLDAP = NULL;
331
332 if (mapping->e != NULL) {
333 /* Similar logic as in above comment applies. */
334 for (i = 0; i <= mapping->numSplits; i++) {
335 free_mapping_element(&mapping->e[i]);
336 }
337 free(mapping->e);
338 }
339 mapping->e = NULL;
340
341 mapping->numSplits = 0;
342
343 free(mapping);
344 }
345
346 /*
347 * FUNCTION: free_config_info
348 *
349 * Frees __nis_config_info_t
350 *
351 * INPUT: __nis_config_info_t
352 */
353
354 void
free_config_info(__nis_config_info_t * config_info)355 free_config_info(__nis_config_info_t *config_info)
356 {
357 if (config_info->config_dn != NULL)
358 free(config_info->config_dn);
359 config_info->config_dn = NULL;
360
361 if (config_info->default_servers != NULL)
362 free(config_info->default_servers);
363 config_info->default_servers = NULL;
364
365 if (config_info->proxy_dn != NULL)
366 free(config_info->proxy_dn);
367 config_info->proxy_dn = NULL;
368
369 if (config_info->proxy_passwd != NULL)
370 free(config_info->proxy_passwd);
371 config_info->proxy_passwd = NULL;
372
373 if (config_info->tls_cert_db != NULL)
374 free(config_info->tls_cert_db);
375 config_info->tls_cert_db = NULL;
376 }
377
378 /*
379 * FUNCTION: free_proxy_info
380 *
381 * Frees __nis_ldap_proxy_info
382 *
383 * INPUT: __nis_ldap_proxy_info
384 */
385
386 void
free_proxy_info(__nis_ldap_proxy_info * proxy_info)387 free_proxy_info(__nis_ldap_proxy_info *proxy_info)
388 {
389 if (proxy_info->tls_cert_db != NULL)
390 free(proxy_info->tls_cert_db);
391 proxy_info->tls_cert_db = NULL;
392
393 if (proxy_info->default_servers != NULL)
394 free(proxy_info->default_servers);
395 proxy_info->default_servers = NULL;
396
397 if (proxy_info->default_search_base != NULL)
398 free(proxy_info->default_search_base);
399 proxy_info->default_search_base = NULL;
400
401 if (proxy_info->proxy_dn != NULL)
402 free(proxy_info->proxy_dn);
403 proxy_info->proxy_dn = NULL;
404
405 if (proxy_info->proxy_passwd != NULL)
406 free(proxy_info->proxy_passwd);
407 proxy_info->proxy_passwd = NULL;
408
409 if (proxy_info->default_nis_domain != NULL)
410 free(proxy_info->default_nis_domain);
411 proxy_info->default_nis_domain = NULL;
412 }
413
414 /*
415 * FUNCTION: free_object_dn
416 *
417 * Frees __nis_object_dn_t
418 *
419 * INPUT: __nis_object_dn_t
420 */
421
422 void
free_object_dn(__nis_object_dn_t * obj_dn)423 free_object_dn(__nis_object_dn_t *obj_dn)
424 {
425 __nis_object_dn_t *t;
426 int i;
427
428 while (obj_dn != NULL) {
429 if (obj_dn->read.base != NULL)
430 free(obj_dn->read.base);
431 obj_dn->read.base = NULL;
432 if (obj_dn->read.attrs != NULL)
433 free(obj_dn->read.attrs);
434 obj_dn->read.attrs = NULL;
435 if (obj_dn->write.base != NULL)
436 free(obj_dn->write.base);
437 obj_dn->write.base = NULL;
438 if (obj_dn->write.attrs != NULL)
439 free(obj_dn->write.attrs);
440 obj_dn->write.attrs = NULL;
441 if (obj_dn->dbIdName != NULL)
442 free(obj_dn->dbIdName);
443 obj_dn->dbIdName = NULL;
444 for (i = 0; i < obj_dn->numDbIds; i++)
445 free_mapping_rule(obj_dn->dbId[i]);
446 obj_dn->numDbIds = 0;
447
448 if (obj_dn->dbId != NULL)
449 free(obj_dn->dbId);
450 obj_dn->dbId = NULL;
451
452 t = obj_dn;
453 obj_dn = obj_dn->next;
454 free(t);
455 }
456 }
457
458 /*
459 * FUNCTION: free_index
460 *
461 * Frees __nis_index_t
462 *
463 * INPUT: __nis_index_t
464 */
465
466 void
free_index(__nis_index_t * index)467 free_index(__nis_index_t *index)
468 {
469 int i;
470 for (i = 0; i < index->numIndexes; i++) {
471 free(index->name[i]);
472 free_mapping_format(index->value[i]);
473 }
474 index->numIndexes = 0;
475 if (index->name != NULL)
476 free(index->name);
477 index->name = NULL;
478 if (index->value != NULL)
479 free(index->value);
480 index->value = NULL;
481 }
482
483 /*
484 * FUNCTION: free_mapping_item
485 *
486 * Frees __nis_mapping_item_t
487 *
488 * INPUT: __nis_mapping_item_t
489 */
490
491 void
free_mapping_item(__nis_mapping_item_t * item)492 free_mapping_item(__nis_mapping_item_t *item)
493 {
494 if (item == NULL)
495 return;
496
497 if (item->name != NULL)
498 free(item->name);
499 item->name = NULL;
500 if (item->type == mit_nisplus) {
501 free_index(&item->searchSpec.obj.index);
502 if (item->searchSpec.obj.name != NULL)
503 free(item->searchSpec.obj.name);
504 item->searchSpec.obj.name = NULL;
505 } else if (item->type == mit_ldap) {
506 if (item->searchSpec.triple.base != NULL)
507 free(item->searchSpec.triple.base);
508 item->searchSpec.triple.base = NULL;
509 if (item->searchSpec.triple.attrs != NULL)
510 free(item->searchSpec.triple.attrs);
511 item->searchSpec.triple.attrs = NULL;
512 if (item->searchSpec.triple.element != NULL) {
513 free_mapping_element(
514 item->searchSpec.triple.element);
515 free(item->searchSpec.triple.element);
516 }
517 item->searchSpec.triple.element = NULL;
518 }
519 if (item->exItem != NULL) {
520 free_mapping_item(item->exItem);
521 free(item->exItem);
522 item->exItem = 0;
523 }
524 }
525
526 /*
527 * FUNCTION: free_mapping_format
528 *
529 * Frees __nis_mapping_format_t
530 *
531 * INPUT: __nis_mapping_format_t
532 */
533
534 void
free_mapping_format(__nis_mapping_format_t * fmt)535 free_mapping_format(__nis_mapping_format_t *fmt)
536 {
537 __nis_mapping_format_t *f = fmt;
538
539 while (fmt->type != mmt_end) {
540 switch (fmt->type) {
541 case mmt_item:
542 break;
543 case mmt_string:
544 if (fmt->match.string != NULL)
545 free(fmt->match.string);
546 fmt->match.string = NULL;
547 break;
548 case mmt_single:
549 if (fmt->match.single.lo != NULL)
550 free(fmt->match.single.lo);
551 fmt->match.single.lo = NULL;
552 if (fmt->match.single.hi != NULL)
553 free(fmt->match.single.hi);
554 fmt->match.single.hi = NULL;
555 break;
556 case mmt_limit:
557 break;
558 case mmt_any:
559 break;
560 case mmt_berstring:
561 case mmt_berstring_null:
562 if (fmt->match.berString != NULL)
563 free(fmt->match.berString);
564 fmt->match.berString = NULL;
565 break;
566 case mmt_begin:
567 break;
568 case mmt_end:
569 break;
570 }
571 fmt++;
572 }
573 free(f);
574 }
575
576 /*
577 * FUNCTION: free_mapping_sub_element
578 *
579 * Frees __nis_mapping_sub_element_t
580 *
581 * INPUT: __nis_mapping_sub_element_t
582 */
583
584 void
free_mapping_sub_element(__nis_mapping_sub_element_t * sub)585 free_mapping_sub_element(__nis_mapping_sub_element_t *sub)
586 {
587 int i;
588
589 switch (sub->type) {
590 case me_item:
591 free_mapping_item(&sub->element.item);
592 break;
593 case me_print:
594 if (sub->element.print.fmt != NULL)
595 free_mapping_format(sub->element.print.fmt);
596 sub->element.print.fmt = NULL;
597 for (i = 0; i < sub->element.print.numItems; i++)
598 free_mapping_item(&sub->element.print.item[i]);
599 sub->element.print.numItems = 0;
600 if (sub->element.print.item != NULL)
601 free(sub->element.print.item);
602 sub->element.print.item = NULL;
603 break;
604 case me_split:
605 free_mapping_item(&sub->element.split.item);
606 break;
607 case me_extract:
608 if (sub->element.extract.fmt != NULL)
609 free_mapping_format(sub->element.extract.fmt);
610 sub->element.extract.fmt = NULL;
611 free_mapping_item(&sub->element.extract.item);
612 break;
613 }
614 }
615
616 /*
617 * FUNCTION: read_line
618 *
619 * Gets next line in buffer - using '\' at end of line
620 * to indicate continuation. Lines beginning with # are
621 * ignored. start_line_num and start_line_num are
622 * maintained to track the line number currently being
623 * parsed.
624 *
625 * RETURN VALUE: The number of characters read. 0 for
626 * eof, -1 for error
627 *
628 * INPUT: file descriptor, buffer, and buffer size
629 */
630
631 int
read_line(int fd,char * buffer,int buflen)632 read_line(int fd, char *buffer, int buflen)
633 {
634 int linelen;
635 int rc;
636 char c;
637 bool_t skip_line = FALSE;
638 bool_t begin_line = TRUE;
639 static bool_t prev_cr = FALSE;
640
641 start_line_num = cur_line_num;
642 (void) memset(buffer, 0, buflen);
643 for (; p_error == no_parse_error; ) {
644 linelen = 0;
645 while (linelen < buflen) {
646 rc = read(fd, &c, 1);
647 if (1 == rc) {
648 if (c == '\n' || c == '\r') {
649 if (c == '\n') {
650 if (prev_cr) {
651 prev_cr = FALSE;
652 continue;
653 } else {
654 if (linelen == 0)
655 start_line_num =
656 cur_line_num;
657 else {
658 if (
659 is_string_ok(
660 buffer,
661 linelen)) {
662 (void) memset(
663 buffer, 0,
664 linelen);
665 linelen = 0;
666 cur_line_num++;
667 begin_line =
668 TRUE;
669 continue;
670 }
671 }
672 cur_line_num++;
673 }
674 prev_cr = FALSE;
675 } else {
676 prev_cr = TRUE;
677 if (linelen == 0)
678 start_line_num =
679 cur_line_num;
680 cur_line_num++;
681 }
682 if (skip_line) {
683 skip_line = FALSE;
684 if (linelen == 0)
685 start_line_num =
686 cur_line_num;
687 } else if (linelen > 0 &&
688 buffer[linelen - 1]
689 == ESCAPE_CHAR) {
690 --linelen;
691 } else if (linelen > 0) {
692 buffer[linelen] = '\0';
693 return (linelen);
694 }
695 begin_line = TRUE;
696 } else {
697 if (begin_line)
698 skip_line = c == POUND_SIGN;
699 begin_line = FALSE;
700 if (!skip_line)
701 buffer[linelen++] = c;
702 }
703 } else {
704 if (linelen > 0 &&
705 buffer[linelen - 1] == ESCAPE_CHAR) {
706 /* continuation on last line */
707 p_error = parse_bad_continuation_error;
708 return (-1);
709 } else {
710 buffer[linelen] = '\0';
711 return (linelen);
712 }
713 }
714 }
715 p_error = parse_line_too_long;
716 }
717 return (-1);
718 }
719
720 /*
721 * FUNCTION: finish_parse
722 *
723 * Adds any elements not configured, fully qualifies
724 * names
725 *
726 * RETURN VALUE: 0 on success, -1 on failure
727 */
728
729 int
finish_parse(__nis_ldap_proxy_info * proxy_info,__nis_table_mapping_t ** table_mapping)730 finish_parse(
731 __nis_ldap_proxy_info *proxy_info,
732 __nis_table_mapping_t **table_mapping)
733 {
734 __nis_table_mapping_t *t;
735 __nis_table_mapping_t *t1;
736 __nis_table_mapping_t *t2;
737 __nis_table_mapping_t *t_del = NULL;
738 int i;
739 int j;
740 int k;
741 __nis_object_dn_t *objectDN;
742 __nis_mapping_rlhs_t *lhs;
743 __nis_mapping_element_t *e;
744 char *s;
745 int errnum;
746
747 /* set to default those values yet set */
748 if (proxy_info->auth_method ==
749 (auth_method_t)NO_VALUE_SET) {
750 p_error = parse_no_proxy_auth_error;
751 report_error(NULL, NULL);
752 return (-1);
753 }
754
755 if (proxy_info->default_servers == NULL) {
756 p_error = parse_no_ldap_server_error;
757 report_error(NULL, NULL);
758 return (-1);
759 }
760
761 if (proxy_info->tls_method == (tls_method_t)NO_VALUE_SET)
762 proxy_info->tls_method = no_tls;
763 else if (proxy_info->tls_method == ssl_tls &&
764 (proxy_info->tls_cert_db == NULL ||
765 *proxy_info->tls_cert_db == '\0')) {
766 p_error = parse_no_cert_db;
767 report_error(NULL, NULL);
768 return (-1);
769 }
770
771 if (proxy_info->default_nis_domain == NULL)
772 proxy_info->default_nis_domain =
773 s_strdup(__nis_rpc_domain());
774 else if (*proxy_info->default_nis_domain == '\0') {
775 free(proxy_info->default_nis_domain);
776 proxy_info->default_nis_domain =
777 s_strdup(__nis_rpc_domain());
778 }
779 if (proxy_info->default_nis_domain != NULL)
780 append_dot(&proxy_info->default_nis_domain);
781
782 if (proxy_info->tls_method == ssl_tls) {
783 if ((errnum = ldapssl_client_init(
784 proxy_info->tls_cert_db, NULL)) < 0) {
785 p_error = parse_ldapssl_client_init_error;
786 report_error(ldapssl_err2string(errnum), NULL);
787 return (-1);
788 }
789 }
790
791 if (proxy_info->default_search_base == NULL)
792 proxy_info->default_search_base =
793 get_default_ldap_base(proxy_info->default_nis_domain);
794
795 /* convert a relative dn to a fullly qualified dn */
796 (void) make_full_dn(&proxy_info->proxy_dn,
797 proxy_info->default_search_base);
798
799 if (p_error != no_parse_error) {
800 report_error(NULL, NULL);
801 return (-1);
802 }
803
804 /*
805 * Create a list of potential delete mappings
806 * those have NULL objectDNs, but badly also rules
807 * that are missing object dn's will be included.
808 * We will use the ttl field to determine if the
809 * delete rule is actually used
810 */
811 t2 = NULL;
812 for (t = *table_mapping; t != NULL; t = t1) {
813 t1 = t->next;
814 if (t->objectDN == NULL) {
815 if (t2 == NULL)
816 *table_mapping = t1;
817 else
818 t2->next = t1;
819 t->next = t_del;
820 t_del = t;
821 t->ttl = 0;
822 } else
823 t2 = t;
824 }
825
826 for (t = *table_mapping; t != NULL; t = t->next) {
827 objectDN = t->objectDN;
828 while (objectDN != NULL) {
829 if (objectDN->dbIdName != NULL) {
830 s = objectDN->dbIdName;
831 t1 = find_table_mapping(s, strlen(s), t_del);
832 if (t1 == NULL) {
833 p_error = parse_no_db_del_mapping_rule;
834 report_error2(objectDN->dbIdName, t->dbId);
835 return (-1);
836 } else if (t1->objName != NULL ||
837 t1->numRulesToLDAP == 0 ||
838 t1->numRulesFromLDAP != 0) {
839 p_error = parse_invalid_db_del_mapping_rule;
840 report_error(t1->dbId, NULL);
841 return (-1);
842 }
843 objectDN->dbId =
844 dup_mapping_rules(t1->ruleToLDAP,
845 t1->numRulesToLDAP);
846 if (objectDN->dbId == NULL) {
847 break;
848 }
849 objectDN->numDbIds = t1->numRulesToLDAP;
850 t1->ttl++;
851 }
852 objectDN = objectDN->next;
853 }
854 }
855
856 for (t = t_del; t != NULL; t = t1) {
857 t1 = t->next;
858 if (t->ttl == 0) {
859 p_error = parse_no_object_dn;
860 report_error(t->dbId, NULL);
861 }
862 free_table_mapping(t);
863 }
864
865 if (p_error != no_parse_error)
866 return (-1);
867
868 /* set to default those table mapping values yet set */
869 for (t = *table_mapping; t != NULL; t = t->next) {
870 if (t->objName == 0) {
871 p_error = parse_no_object_dn;
872 report_error(t->dbId, NULL);
873 return (-1);
874 }
875 if (!yp2ldap) {
876 if (!add_domain(&t->objName,
877 proxy_info->default_nis_domain)) {
878 report_error(NULL, NULL);
879 return (-1);
880 }
881 }
882 if (t->initTtlHi == (time_t)NO_VALUE_SET)
883 t->initTtlHi = DEFAULT_TTL_HIGH;
884 if (t->initTtlLo == (time_t)NO_VALUE_SET)
885 t->initTtlLo = DEFAULT_TTL_LOW;
886 if (t->ttl == (time_t)NO_VALUE_SET)
887 t->ttl = DEFAULT_TTL;
888 objectDN = t->objectDN;
889
890 /* fixup relative dn's */
891 while (objectDN != NULL) {
892 if (!yp2ldap) {
893 if (!make_full_dn(&objectDN->read.base,
894 proxy_info->default_search_base))
895 break;
896 }
897 if (objectDN->write.scope != LDAP_SCOPE_UNKNOWN) {
898 if (objectDN->write.base != NULL &&
899 !make_full_dn(&objectDN->write.base,
900 proxy_info->default_search_base))
901 break;
902 if (objectDN->write.base == NULL) {
903 objectDN->write.base =
904 s_strdup(objectDN->read.base);
905 if (objectDN->write.base == NULL)
906 break;
907 }
908 }
909 objectDN = objectDN->next;
910 }
911
912 if (p_error != no_parse_error) {
913 report_error(NULL, NULL);
914 return (-1);
915 }
916
917 /* Check for ruleToLDAP with no rhs */
918 for (i = 0; i < t->numRulesToLDAP; i++) {
919 if (t->ruleToLDAP[i]->rhs.numElements == 0) {
920 p_error = parse_unexpected_data_end_rule;
921 report_error(t->dbId, NULL);
922 return (-1);
923 }
924 }
925
926 /* populate cols field */
927 if (!yp2ldap) {
928 for (i = 0; i < t->numRulesFromLDAP; i++) {
929 lhs = &t->ruleFromLDAP[i]->lhs;
930 for (j = 0; j < lhs->numElements; j++) {
931 e = &lhs->element[j];
932 switch (e->type) {
933 case me_item:
934 if (!add_column(t,
935 e->element.item.name)) {
936 report_error(
937 NULL, NULL);
938 return (-1);
939 }
940 break;
941 case me_match:
942 for (k = 0;
943 k < e->element.match.numItems;
944 k++)
945 if (!add_column(t,
946 e->element.match.item[k].name)) {
947 report_error(
948 NULL, NULL);
949 return (-1);
950 }
951 break;
952 }
953 }
954 }
955 }
956 }
957 return (0);
958 }
959
960 /*
961 * FUNCTION: set_default_values
962 *
963 * Sets unconfigured values to their default value
964 */
965
966 void
set_default_values(__nis_ldap_proxy_info * proxy_info,__nis_config_t * config_info,__nisdb_table_mapping_t * table_info)967 set_default_values(__nis_ldap_proxy_info *proxy_info,
968 __nis_config_t *config_info, __nisdb_table_mapping_t *table_info)
969 {
970 if (proxy_info->bind_timeout.tv_sec == (time_t)NO_VALUE_SET)
971 proxy_info->bind_timeout.tv_sec = DEFAULT_BIND_TIMEOUT;
972 if (proxy_info->search_timeout.tv_sec == (time_t)NO_VALUE_SET)
973 proxy_info->search_timeout.tv_sec =
974 (yp2ldap)?DEFAULT_YP_SEARCH_TIMEOUT:
975 DEFAULT_SEARCH_TIMEOUT;
976 if (proxy_info->modify_timeout.tv_sec == (time_t)NO_VALUE_SET)
977 proxy_info->modify_timeout.tv_sec = DEFAULT_MODIFY_TIMEOUT;
978 if (proxy_info->add_timeout.tv_sec == (time_t)NO_VALUE_SET)
979 proxy_info->add_timeout.tv_sec = DEFAULT_ADD_TIMEOUT;
980 if (proxy_info->delete_timeout.tv_sec == (time_t)NO_VALUE_SET)
981 proxy_info->delete_timeout.tv_sec = DEFAULT_DELETE_TIMEOUT;
982
983 if (proxy_info->search_time_limit == (int)NO_VALUE_SET)
984 proxy_info->search_time_limit = DEFAULT_SEARCH_TIME_LIMIT;
985 if (proxy_info->search_size_limit == (int)NO_VALUE_SET)
986 proxy_info->search_size_limit = DEFAULT_SEARCH_SIZE_LIMIT;
987
988 if (proxy_info->follow_referral == (follow_referral_t)NO_VALUE_SET)
989 proxy_info->follow_referral = no_follow;
990
991 switch (config_info->initialUpdate) {
992 case (__nis_initial_update_t)NO_VALUE_SET:
993 case (__nis_initial_update_t)INITIAL_UPDATE_NO_ACTION:
994 case (__nis_initial_update_t)NO_INITIAL_UPDATE_NO_ACTION:
995 config_info->initialUpdate = ini_none;
996 break;
997 case (__nis_initial_update_t)FROM_NO_INITIAL_UPDATE:
998 config_info->initialUpdate = from_ldap;
999 break;
1000 case (__nis_initial_update_t)TO_NO_INITIAL_UPDATE:
1001 config_info->initialUpdate = to_ldap;
1002 break;
1003 }
1004 if (config_info->threadCreationError ==
1005 (__nis_thread_creation_error_t)NO_VALUE_SET)
1006 config_info->threadCreationError = pass_error;
1007 if (config_info->threadCreationErrorTimeout.attempts == NO_VALUE_SET)
1008 config_info->threadCreationErrorTimeout.attempts =
1009 DEFAULT_THREAD_ERROR_ATTEMPTS;
1010 if (config_info->threadCreationErrorTimeout.timeout ==
1011 (time_t)NO_VALUE_SET)
1012 config_info->threadCreationErrorTimeout.timeout =
1013 DEFAULT_THREAD_ERROR_TIME_OUT;
1014 if (config_info->dumpError ==
1015 (__nis_dump_error_t)NO_VALUE_SET)
1016 config_info->dumpError = de_retry;
1017 if (config_info->dumpErrorTimeout.attempts == NO_VALUE_SET)
1018 config_info->dumpErrorTimeout.attempts =
1019 DEFAULT_DUMP_ERROR_ATTEMPTS;
1020 if (config_info->dumpErrorTimeout.timeout == (time_t)NO_VALUE_SET)
1021 config_info->dumpErrorTimeout.timeout =
1022 DEFAULT_DUMP_ERROR_TIME_OUT;
1023 if (config_info->resyncService ==
1024 (__nis_resync_service_t)NO_VALUE_SET)
1025 config_info->resyncService = from_copy;
1026 if (config_info->updateBatching ==
1027 (__nis_update_batching_t)NO_VALUE_SET)
1028 config_info->updateBatching = accumulate;
1029 if (config_info->updateBatchingTimeout.timeout == (time_t)NO_VALUE_SET)
1030 config_info->updateBatchingTimeout.timeout =
1031 DEFAULT_BATCHING_TIME_OUT;
1032 if (config_info->numberOfServiceThreads == (int)NO_VALUE_SET)
1033 config_info->numberOfServiceThreads =
1034 DEFAULT_NUMBER_OF_THREADS;
1035 if (config_info->emulate_yp == (int)NO_VALUE_SET)
1036 config_info->emulate_yp =
1037 DEFAULT_YP_EMULATION;
1038 if (config_info->maxRPCRecordSize == (int)NO_VALUE_SET)
1039 config_info->maxRPCRecordSize = RPC_MAXDATASIZE;
1040
1041 if (table_info->retrieveError ==
1042 (__nis_retrieve_error_t)NO_VALUE_SET)
1043 table_info->retrieveError = use_cached;
1044 if (table_info->retrieveErrorRetry.attempts == NO_VALUE_SET)
1045 table_info->retrieveErrorRetry.attempts =
1046 DEFAULT_RETRIEVE_ERROR_ATTEMPTS;
1047 if (table_info->retrieveErrorRetry.timeout == (time_t)NO_VALUE_SET)
1048 table_info->retrieveErrorRetry.timeout =
1049 DEFAULT_RETRIEVE_ERROR_TIME_OUT;
1050 if (table_info->storeError ==
1051 (__nis_store_error_t)NO_VALUE_SET)
1052 table_info->storeError = sto_retry;
1053 if (table_info->storeErrorRetry.attempts == NO_VALUE_SET)
1054 table_info->storeErrorRetry.attempts =
1055 DEFAULT_STORE_ERROR_ATTEMPTS;
1056 if (table_info->storeErrorRetry.timeout == (time_t)NO_VALUE_SET)
1057 table_info->storeErrorRetry.timeout =
1058 DEFAULT_STORE_ERROR_TIME_OUT;
1059 if (table_info->refreshError ==
1060 (__nis_refresh_error_t)NO_VALUE_SET)
1061 table_info->refreshError = continue_using;
1062 if (table_info->refreshErrorRetry.attempts == NO_VALUE_SET)
1063 table_info->refreshErrorRetry.attempts =
1064 DEFAULT_REFRESH_ERROR_ATTEMPTS;
1065 if (table_info->refreshErrorRetry.timeout == (time_t)NO_VALUE_SET)
1066 table_info->refreshErrorRetry.timeout =
1067 DEFAULT_REFRESH_ERROR_TIME_OUT;
1068 if (table_info->matchFetch ==
1069 (__nis_match_fetch_t)NO_VALUE_SET)
1070 table_info->matchFetch = no_match_only;
1071 }
1072
1073 __nis_table_mapping_t *
find_table_mapping(const char * s,int len,__nis_table_mapping_t * table_mapping)1074 find_table_mapping(const char *s, int len, __nis_table_mapping_t *table_mapping)
1075 {
1076 __nis_table_mapping_t *t;
1077
1078 for (t = table_mapping; t != NULL; t = t->next)
1079 if (strlen(t->dbId) == len &&
1080 strncasecmp(t->dbId, s, len) == 0)
1081 break;
1082 return (t);
1083 }
1084
1085 void
append_dot(char ** str)1086 append_dot(char **str)
1087 {
1088 char *s = *str;
1089 int len = strlen(s);
1090
1091 if (len == 0 || s[len - 1] != PERIOD_CHAR) {
1092 s = s_realloc(s, len + 2);
1093 if (s != NULL) {
1094 s[len] = PERIOD_CHAR;
1095 s[len+1] = '\0';
1096 *str = s;
1097 }
1098 }
1099 }
1100
1101 void
append_comma(char ** str)1102 append_comma(char **str)
1103 {
1104
1105 char *s = *str;
1106 int len = strlen(s);
1107
1108 if (len == 0 || s[len - 1] != COMMA_CHAR) {
1109 s = s_realloc(s, len + 2);
1110 if (s != NULL) {
1111 s[len] = COMMA_CHAR;
1112 s[len+1] = '\0';
1113 *str = s;
1114 }
1115 }
1116 }
1117
1118 /*
1119 * FUNCTION: make_full_dn
1120 *
1121 * Appends the base dn if a relative ldap dn
1122 * (invoked only for LDAP write cycle)
1123 *
1124 * RETURN VALUE: FALSE if error
1125 * TRUE if __nis_index_t returned
1126 *
1127 * INPUT: the relative dn and ldap base
1128 */
1129
1130 bool_t
make_full_dn(char ** dn,const char * base)1131 make_full_dn(char **dn, const char *base)
1132 {
1133 int len;
1134 int len1;
1135
1136 if (*dn == NULL) {
1137 *dn = s_strdup(base);
1138 } else {
1139 len = strlen(*dn);
1140 if (len > 0 && (*dn)[len-1] == COMMA_CHAR) {
1141 len1 = strlen(base) + 1;
1142 *dn = s_realloc(*dn, len + len1);
1143 if (*dn != NULL)
1144 (void) strcpy(*dn + len, base);
1145 }
1146 }
1147 return (*dn != NULL);
1148 }
1149
1150 /*
1151 * FUNCTION: make_fqdn
1152 *
1153 * Appends the base dn if a relative ldap dn
1154 * (invoked only for LDAP read cycle)
1155 *
1156 * RETURN VALUE: FALSE if error
1157 * TRUE if success
1158 *
1159 * INPUT: the relative dn and ldap base
1160 */
1161 bool_t
make_fqdn(__nis_object_dn_t * dn,const char * base)1162 make_fqdn(__nis_object_dn_t *dn, const char *base)
1163 {
1164 int len;
1165 int len1;
1166
1167 if (dn == NULL) {
1168 return (FALSE);
1169 } else {
1170 while (dn != NULL && dn->read.base != NULL) {
1171 len = strlen(dn->read.base);
1172 if (len > 0 && (dn->read.base)[len-1] == COMMA_CHAR) {
1173 len1 = strlen(base) + 1;
1174 dn->read.base =
1175 s_realloc(dn->read.base, len + len1);
1176 if (dn->read.base != NULL)
1177 (void) strlcpy(dn->read.base + len,
1178 base, len1);
1179 else
1180 return (FALSE);
1181 }
1182 dn = dn->next;
1183 }
1184 }
1185 return (TRUE);
1186 }
1187
1188 /*
1189 * FUNCTION: get_default_ldap_base
1190 *
1191 * Gets the default LDAP search base from the
1192 * nis+ default domain
1193 *
1194 * RETURN VALUE: NULL if error
1195 * the default base
1196 *
1197 * INPUT: the nis domain
1198 */
1199
1200 char *
get_default_ldap_base(const char * domain)1201 get_default_ldap_base(const char *domain)
1202 {
1203
1204 int len = strlen(domain);
1205 int i;
1206 int count = len + 4;
1207 char *base;
1208
1209 for (i = 0; i < len - 1; i++)
1210 if (domain[i] == PERIOD_CHAR)
1211 count += 4;
1212 if ((base = malloc(count)) == NULL) {
1213 p_error = parse_no_mem_error;
1214 } else {
1215 (void) strcpy(base, "dc=");
1216 count = 3;
1217 for (i = 0; i < len - 1; i++) {
1218 if (domain[i] == PERIOD_CHAR) {
1219 (void) strcpy(base + count, ",dc=");
1220 count += 4;
1221 } else {
1222 base[count++] = domain[i];
1223 }
1224 }
1225 base[count] = '\0';
1226 }
1227 return (base);
1228 }
1229
1230 /*
1231 * FUNCTION: add_domain
1232 *
1233 * Appends the base domain if a relative object name
1234 *
1235 * RETURN VALUE: FALSE if error
1236 * TRUE if OK
1237 *
1238 * INPUT: the relative object name and base domain
1239 * name
1240 */
1241
1242 bool_t
add_domain(char ** objName,const char * domain)1243 add_domain(char **objName, const char *domain)
1244 {
1245 int len;
1246 int len1;
1247 bool_t trailing_dot;
1248 char *obj_name;
1249
1250 if (domain == NULL || *objName == NULL) {
1251 p_error = parse_internal_error;
1252 return (FALSE);
1253 }
1254 len1 = strlen(domain);
1255 trailing_dot = (len1 > 0 && domain[len1 - 1] == PERIOD_CHAR) ?
1256 0 : 1;
1257 len = strlen(*objName);
1258 if (len == 0 || (*objName)[len - 1] != PERIOD_CHAR) {
1259 obj_name = s_realloc(*objName,
1260 len + len1 + 2 + trailing_dot);
1261 if (obj_name != NULL) {
1262 obj_name[len++] = PERIOD_CHAR;
1263 (void) strcpy(obj_name + len, domain);
1264 if (trailing_dot != 0) {
1265 obj_name[len + len1] = PERIOD_CHAR;
1266 obj_name[len + len1 + 1] = '\0';
1267 }
1268 *objName = obj_name;
1269 }
1270 }
1271
1272 return (*objName != NULL);
1273 }
1274
1275 bool_t
dup_index(__nis_index_t * in,__nis_index_t * out)1276 dup_index(__nis_index_t *in, __nis_index_t *out)
1277 {
1278 int i;
1279 int j;
1280
1281 out->name = (char **)s_calloc(in->numIndexes, sizeof (char *));
1282 if (out->name == NULL)
1283 return (FALSE);
1284 out->value = (__nis_mapping_format_t **)
1285 s_calloc(in->numIndexes, sizeof (__nis_mapping_format_t *));
1286 if (out->value == NULL) {
1287 free(out->name);
1288 out->name = NULL;
1289 return (FALSE);
1290 }
1291
1292 for (i = 0; i < in->numIndexes; i++) {
1293 out->name[i] = s_strdup(in->name[i]);
1294 if (out->name[i] == NULL)
1295 break;
1296 out->value[i] = dup_format_mapping(in->value[i]);
1297 if (out->value[i] == NULL)
1298 break;
1299 }
1300 if (i < in->numIndexes) {
1301 for (j = 0; j <= i; j++) {
1302 if (out->name[j] != NULL)
1303 free(out->name[j]);
1304 if (out->value[j] != NULL)
1305 free_mapping_format(out->value[j]);
1306 }
1307 free(out->name);
1308 out->name = NULL;
1309 free(out->value);
1310 out->value = NULL;
1311 } else {
1312 out->numIndexes = in->numIndexes;
1313 }
1314 return (i == in->numIndexes);
1315 }
1316
1317 bool_t
dup_mapping_item(__nis_mapping_item_t * in,__nis_mapping_item_t * out)1318 dup_mapping_item(__nis_mapping_item_t *in, __nis_mapping_item_t *out)
1319 {
1320 bool_t ret;
1321
1322 if (in->type == mit_nisplus) {
1323 ret = dup_index(&in->searchSpec.obj.index,
1324 &out->searchSpec.obj.index);
1325 if (!ret)
1326 return (ret);
1327 if (in->searchSpec.obj.name != NULL) {
1328 out->searchSpec.obj.name =
1329 s_strdup(in->searchSpec.obj.name);
1330 if (out->searchSpec.obj.name == NULL)
1331 return (FALSE);
1332 } else
1333 out->searchSpec.obj.name = NULL;
1334 } else if (in->type == mit_ldap) {
1335 if (in->searchSpec.triple.base != NULL) {
1336 out->searchSpec.triple.base =
1337 s_strdup(in->searchSpec.triple.base);
1338 if (out->searchSpec.triple.base == NULL)
1339 return (FALSE);
1340 } else
1341 out->searchSpec.triple.base = NULL;
1342 out->searchSpec.triple.scope =
1343 in->searchSpec.triple.scope;
1344 if (in->searchSpec.triple.attrs != NULL) {
1345 out->searchSpec.triple.attrs =
1346 s_strdup(in->searchSpec.triple.attrs);
1347 if (out->searchSpec.triple.attrs == NULL)
1348 return (FALSE);
1349 } else
1350 out->searchSpec.triple.attrs = NULL;
1351 if (in->searchSpec.triple.element != NULL) {
1352 out->searchSpec.triple.element =
1353 (__nis_mapping_element_t *)
1354 s_calloc(1, sizeof (__nis_mapping_element_t));
1355 if (out->searchSpec.triple.element != NULL)
1356 dup_mapping_element(
1357 in->searchSpec.triple.element,
1358 out->searchSpec.triple.element);
1359 if (out->searchSpec.triple.element == NULL)
1360 return (FALSE);
1361 } else
1362 out->searchSpec.triple.element = NULL;
1363 }
1364
1365 if (in->name != NULL) {
1366 out->name = s_strdup(in->name);
1367 if (out->name == NULL)
1368 return (FALSE);
1369 } else
1370 out->name = NULL;
1371 out->type = in->type;
1372 out->repeat = in->repeat;
1373 if (in->exItem) {
1374 out->exItem = (__nis_mapping_item_t *)s_malloc
1375 (sizeof (__nis_mapping_item_t));
1376 if (out->exItem == NULL)
1377 return (FALSE);
1378 else {
1379 (void) memset
1380 (out->exItem, 0, sizeof (out->exItem[0]));
1381 if (!dup_mapping_item
1382 (in->exItem, out->exItem))
1383 p_error = parse_internal_error;
1384 }
1385 } else
1386 out->exItem = NULL;
1387
1388 return (p_error == no_parse_error);
1389 }
1390
1391 __nis_mapping_format_t *
dup_format_mapping(__nis_mapping_format_t * in)1392 dup_format_mapping(__nis_mapping_format_t *in)
1393 {
1394 int i;
1395 __nis_mapping_format_t *out;
1396 bool_t got_end;
1397
1398 i = 0;
1399 while (in[i].type != mmt_end)
1400 i++;
1401 out = (__nis_mapping_format_t *)s_calloc(
1402 i + 1, sizeof (__nis_mapping_format_t));
1403 if (out != NULL) {
1404 got_end = FALSE;
1405 for (i = 0; !got_end; i++) {
1406 switch (in[i].type) {
1407 case mmt_item:
1408 break;
1409 case mmt_string:
1410 out[i].match.string =
1411 s_strdup(in[i].match.string);
1412 break;
1413 case mmt_single:
1414 out[i].match.single.numRange =
1415 in[i].match.single.numRange;
1416 out[i].match.single.lo =
1417 s_malloc(in[i].match.single.numRange);
1418 if (out[i].match.single.lo == NULL)
1419 break;
1420 out[i].match.single.hi =
1421 s_malloc(in[i].match.single.numRange);
1422 if (out[i].match.single.hi == NULL)
1423 break;
1424 memcpy(out[i].match.single.lo,
1425 in[i].match.single.lo,
1426 in[i].match.single.numRange);
1427 memcpy(out[i].match.single.hi,
1428 in[i].match.single.hi,
1429 in[i].match.single.numRange);
1430 break;
1431 case mmt_limit:
1432 out[i].match.limit = in[i].match.limit;
1433 break;
1434 case mmt_any:
1435 break;
1436 case mmt_berstring:
1437 out[i].match.berString =
1438 s_strdup(in[i].match.berString);
1439 break;
1440 case mmt_begin:
1441 break;
1442 case mmt_end:
1443 got_end = TRUE;
1444 break;
1445 default:
1446 p_error = parse_internal_error;
1447 }
1448 if (p_error != no_parse_error)
1449 break;
1450 out[i].type = in[i].type;
1451 }
1452 if (p_error != no_parse_error) {
1453 free_mapping_format(out);
1454 out = NULL;
1455 }
1456 }
1457
1458 return (out);
1459 }
1460
1461 bool_t
dup_mapping_sub_element(__nis_mapping_sub_element_t * in,__nis_mapping_sub_element_t * out)1462 dup_mapping_sub_element(
1463 __nis_mapping_sub_element_t *in,
1464 __nis_mapping_sub_element_t *out)
1465 {
1466 bool_t ret = FALSE;
1467 int i;
1468
1469 switch (in->type) {
1470 case me_item:
1471 ret = dup_mapping_item(&in->element.item,
1472 &out->element.item);
1473 break;
1474 case me_print:
1475 out->element.print.fmt =
1476 dup_format_mapping(in->element.print.fmt);
1477 if (out->element.print.fmt == NULL)
1478 break;
1479 out->element.print.numItems =
1480 in->element.print.numItems;
1481 out->element.print.item = (__nis_mapping_item_t *)
1482 s_calloc(in->element.print.numItems,
1483 sizeof (__nis_mapping_item_t));
1484 if (out->element.print.item == NULL)
1485 break;
1486 for (i = 0; i < in->element.print.numItems; i++)
1487 if (!dup_mapping_item(
1488 &in->element.print.item[i],
1489 &out->element.print.item[i]))
1490 break;
1491 if (i < in->element.print.numItems)
1492 break;
1493 ret = TRUE;
1494 out->element.print.doElide = in->element.print.doElide;
1495 out->element.print.elide = in->element.print.elide;
1496 break;
1497 case me_split:
1498 ret = dup_mapping_item(&in->element.split.item,
1499 &out->element.split.item);
1500 out->element.split.delim = in->element.split.delim;
1501 break;
1502 case me_extract:
1503 out->element.extract.fmt =
1504 dup_format_mapping(in->element.extract.fmt);
1505 if (out->element.extract.fmt == NULL)
1506 break;
1507 ret = dup_mapping_item(&in->element.extract.item,
1508 &out->element.extract.item);
1509 break;
1510 default:
1511 p_error = parse_internal_error;
1512 }
1513 out->type = in->type;
1514
1515 return (ret);
1516 }
1517
1518 bool_t
dup_mapping_element(__nis_mapping_element_t * in,__nis_mapping_element_t * out)1519 dup_mapping_element(
1520 __nis_mapping_element_t *in,
1521 __nis_mapping_element_t *out)
1522 {
1523 bool_t ret = FALSE;
1524 int i;
1525
1526 if (in == NULL)
1527 return (ret);
1528
1529 switch (in->type) {
1530 case me_item:
1531 ret = dup_mapping_item(&in->element.item,
1532 &out->element.item);
1533 break;
1534 case me_print:
1535 out->element.print.fmt =
1536 dup_format_mapping(in->element.print.fmt);
1537 if (out->element.print.fmt == NULL)
1538 break;
1539 out->element.print.numSubElements =
1540 in->element.print.numSubElements;
1541 out->element.print.subElement =
1542 (__nis_mapping_sub_element_t *)
1543 s_calloc(in->element.print.numSubElements,
1544 sizeof (__nis_mapping_sub_element_t));
1545 if (out->element.print.subElement == NULL)
1546 break;
1547 for (i = 0; i < in->element.print.numSubElements; i++)
1548 if (!dup_mapping_sub_element(
1549 &in->element.print.subElement[i],
1550 &out->element.print.subElement[i]))
1551 break;
1552 if (i < in->element.print.numSubElements)
1553 break;
1554 ret = TRUE;
1555 out->element.print.doElide = in->element.print.doElide;
1556 out->element.print.elide = in->element.print.elide;
1557 break;
1558 case me_split:
1559 ret = dup_mapping_item(&in->element.split.item,
1560 &out->element.split.item);
1561 out->element.split.delim = in->element.split.delim;
1562 break;
1563 case me_match:
1564 out->element.match.fmt =
1565 dup_format_mapping(in->element.match.fmt);
1566 if (out->element.match.fmt == NULL)
1567 break;
1568 out->element.match.numItems =
1569 in->element.match.numItems;
1570 out->element.match.item = (__nis_mapping_item_t *)
1571 s_calloc(in->element.match.numItems,
1572 sizeof (__nis_mapping_item_t));
1573 if (out->element.match.item == NULL)
1574 break;
1575 for (i = 0; i < in->element.match.numItems; i++)
1576 if (!dup_mapping_item(
1577 &in->element.match.item[i],
1578 &out->element.match.item[i]))
1579 break;
1580 if (i < in->element.match.numItems)
1581 break;
1582 ret = TRUE;
1583 break;
1584 case me_extract:
1585 out->element.extract.fmt =
1586 dup_format_mapping(in->element.extract.fmt);
1587 if (out->element.extract.fmt == NULL)
1588 break;
1589 ret = dup_mapping_item(&in->element.extract.item,
1590 &out->element.extract.item);
1591 break;
1592 default:
1593 p_error = parse_internal_error;
1594 }
1595 out->type = in->type;
1596
1597 return (ret);
1598 }
1599
1600 __nis_mapping_rule_t *
dup_mapping_rule(__nis_mapping_rule_t * in)1601 dup_mapping_rule(__nis_mapping_rule_t *in)
1602 {
1603 int i;
1604 __nis_mapping_rlhs_t *r_in;
1605 __nis_mapping_rlhs_t *r_out;
1606 __nis_mapping_rule_t *out;
1607
1608 out = (__nis_mapping_rule_t *)
1609 s_calloc(1, sizeof (__nis_mapping_rule_t));
1610 if (out != NULL) {
1611 r_in = &in->lhs;
1612 r_out = &out->lhs;
1613 r_out->numElements = r_in->numElements;
1614 r_out->element = (__nis_mapping_element_t *)s_calloc
1615 (r_in->numElements, sizeof (__nis_mapping_element_t));
1616 if (r_out->element == NULL) {
1617 free_mapping_rule(out);
1618 return (NULL);
1619 }
1620 for (i = 0; i < r_in->numElements; i++) {
1621 if (!dup_mapping_element(&r_in->element[i],
1622 &r_out->element[i]))
1623 break;
1624 }
1625 if (i < r_in->numElements) {
1626 free_mapping_rule(out);
1627 return (NULL);
1628 }
1629
1630 r_in = &in->rhs;
1631 r_out = &out->rhs;
1632 r_out->numElements = r_in->numElements;
1633 r_out->element = (__nis_mapping_element_t *)s_calloc
1634 (r_in->numElements, sizeof (__nis_mapping_element_t));
1635 if (r_out->element == NULL) {
1636 free_mapping_rule(out);
1637 return (NULL);
1638 }
1639 for (i = 0; i < r_in->numElements; i++) {
1640 if (!dup_mapping_element(&r_in->element[i],
1641 &r_out->element[i]))
1642 break;
1643 }
1644 if (i < r_in->numElements) {
1645 free_mapping_rule(out);
1646 return (NULL);
1647 }
1648 }
1649 return (out);
1650 }
1651
1652 __nis_mapping_rule_t **
dup_mapping_rules(__nis_mapping_rule_t ** rules,int n_rules)1653 dup_mapping_rules(__nis_mapping_rule_t **rules, int n_rules)
1654 {
1655 int i, j;
1656 __nis_mapping_rule_t **r;
1657
1658 r = (__nis_mapping_rule_t **)s_calloc(n_rules,
1659 sizeof (__nis_mapping_rule_t *));
1660 if (r != NULL) {
1661 for (i = 0; i < n_rules; i++) {
1662 r[i] = dup_mapping_rule(rules[i]);
1663 if (r[i] == NULL) {
1664 for (j = 0; j < i; j++)
1665 free_mapping_rule(r[j]);
1666 free(r);
1667 r = NULL;
1668 break;
1669 }
1670 }
1671 }
1672 return (r);
1673 }
1674
1675 /*
1676 * FUNCTION: add_column
1677 *
1678 * Adds a column name to the column list in __nis_table_mapping_t
1679 *
1680 * RETURN VALUE: FALSE if error
1681 * TRUE if __nis_index_t returned
1682 *
1683 * INPUT: the __nis_table_mapping_t and column name
1684 */
1685
1686 bool_t
add_column(__nis_table_mapping_t * t,const char * col_name)1687 add_column(__nis_table_mapping_t *t, const char *col_name)
1688 {
1689 int i;
1690 char **cols = NULL;
1691
1692 if (!yp2ldap) {
1693 for (i = 0; i < t->numColumns; i++) {
1694 if (strcasecmp(col_name, t->column[i]) == 0)
1695 return (TRUE);
1696 }
1697 }
1698 cols = (char **)s_realloc(t->column, (t->numColumns + 1) *
1699 sizeof (char *));
1700 if (cols == NULL)
1701 return (FALSE);
1702 t->column = cols;
1703 cols[t->numColumns] = s_strdup(col_name);
1704 if (cols[t->numColumns] == NULL)
1705 return (FALSE);
1706 t->numColumns++;
1707 return (TRUE);
1708 }
1709
1710 /*
1711 * FUNCTION: add_element
1712 *
1713 * Adds a __nis_mapping_element_t to __nis_mapping_rlhs_t
1714 *
1715 * RETURN VALUE: FALSE if error
1716 * TRUE if __nis_index_t returned
1717 *
1718 * INPUT: the __nis_mapping_element_t and
1719 * __nis_mapping_rlhs_t
1720 */
1721
1722 bool_t
add_element(__nis_mapping_element_t * e,__nis_mapping_rlhs_t * m)1723 add_element(
1724 __nis_mapping_element_t *e,
1725 __nis_mapping_rlhs_t *m)
1726 {
1727 __nis_mapping_element_t *e1;
1728 int i;
1729 int n = m->numElements;
1730
1731 e1 = (__nis_mapping_element_t *)s_realloc(m->element,
1732 (n + 1) * sizeof (__nis_mapping_element_t));
1733 if (e1 == NULL) {
1734 e1 = m->element;
1735 for (i = 0; i < n; i++)
1736 free_mapping_element(e1++);
1737 if (m->element != NULL)
1738 free(m->element);
1739 m->element = NULL;
1740 m->numElements = 0;
1741 } else {
1742 e1[m->numElements++] = *e;
1743 free(e);
1744 m->element = (__nis_mapping_element_t *)e1;
1745 }
1746 return (e1 != NULL);
1747 }
1748
1749 /*
1750 * FUNCTION: get_next_object_dn_token
1751 *
1752 * Get the next token in parsing object_dn
1753 *
1754 * RETURN VALUE: NULL if error
1755 * position of beginning next token after
1756 * token
1757 *
1758 * INPUT: the attribute value
1759 */
1760
1761 const char *
get_next_object_dn_token(const char ** begin_ret,const char ** end_ret,object_dn_token * token)1762 get_next_object_dn_token(
1763 const char **begin_ret,
1764 const char **end_ret,
1765 object_dn_token *token)
1766 {
1767 object_dn_token t = dn_no_token;
1768 const char *s = *begin_ret;
1769 const char *begin;
1770 const char *end = *end_ret;
1771 const char *s1;
1772 bool_t in_quotes;
1773
1774 while (s < end && is_whitespace(*s))
1775 s++;
1776 if (s >= end) {
1777 /* EMPTY */
1778 } else if (*s == SEMI_COLON_CHAR) {
1779 t = dn_semi_token;
1780 s++;
1781 } else if (*s == QUESTION_MARK) {
1782 t = dn_ques_token;
1783 s++;
1784 } else if (*s == COLON_CHAR) {
1785 t = dn_colon_token;
1786 s++;
1787 } else if (*s == OPEN_PAREN_CHAR) {
1788 begin = s;
1789 s = get_ldap_filter(&begin, &end);
1790 if (s != NULL) {
1791 t = dn_text_token;
1792 *begin_ret = begin;
1793 *end_ret = end;
1794 }
1795 } else {
1796 begin = s;
1797 in_quotes = FALSE;
1798 while (s < end) {
1799 if (*s == ESCAPE_CHAR) {
1800 if (s + 2 > end) {
1801 p_error = parse_unmatched_escape;
1802 s = NULL;
1803 break;
1804 }
1805 s++;
1806 } else if (*s == DOUBLE_QUOTE_CHAR) {
1807 in_quotes = ! in_quotes;
1808 } else if (in_quotes)
1809 ;
1810 else if (*s == SEMI_COLON_CHAR ||
1811 *s == QUESTION_MARK ||
1812 *s == COLON_CHAR)
1813 break;
1814 s++;
1815 }
1816 if (s != NULL) {
1817 s1 = s - 1;
1818 while (is_whitespace(*s1))
1819 s1--;
1820 s1++;
1821 if (same_string("base", begin, s1 - begin))
1822 t = dn_base_token;
1823 else if (same_string("one", begin, s1 - begin))
1824 t = dn_one_token;
1825 else if (same_string("sub", begin, s1 - begin))
1826 t = dn_sub_token;
1827 else
1828 t = dn_text_token;
1829 *begin_ret = begin;
1830 *end_ret = s1;
1831 }
1832 }
1833 *token = t;
1834 return (s);
1835 }
1836
1837 /*
1838 * FUNCTION: get_next_token
1839 *
1840 * Get the next token in parsing mapping attribute
1841 *
1842 * RETURN VALUE: NULL if error
1843 * position of beginning next token after
1844 * token
1845 *
1846 * INPUT: the attribute value
1847 */
1848
1849 const char *
get_next_token(const char ** begin_token,const char ** end_token,token_type * t)1850 get_next_token(const char **begin_token, const char **end_token, token_type *t)
1851 {
1852 const char *s = *begin_token;
1853 const char *end_s = *end_token;
1854 const char *s_begin;
1855
1856 while (s < end_s && is_whitespace(*s))
1857 s++;
1858 if (s == end_s) {
1859 *t = no_token;
1860 return (s);
1861 }
1862
1863 s_begin = s;
1864
1865 if (*s == OPEN_PAREN_CHAR) {
1866 *begin_token = s;
1867 s++;
1868 *end_token = s;
1869 while (s < end_s && is_whitespace(*s))
1870 s++;
1871 *t = open_paren_token;
1872 } else if (*s == DOUBLE_QUOTE_CHAR) {
1873 s++;
1874 while (s < end_s) {
1875 if (*s == ESCAPE_CHAR)
1876 s += 2;
1877 else if (*s == DOUBLE_QUOTE_CHAR)
1878 break;
1879 else
1880 s++;
1881 }
1882 if (s >= end_s) {
1883 p_error = parse_unmatched_escape;
1884 return (NULL);
1885 }
1886
1887 *t = quoted_string_token;
1888 *begin_token = s_begin + 1;
1889 *end_token = s++;
1890 } else if (*s == EQUAL_CHAR || *s == COMMA_CHAR ||
1891 *s == CLOSE_PAREN_CHAR || *s == COLON_CHAR) {
1892 if (*s == EQUAL_CHAR)
1893 *t = equal_token;
1894 else if (*s == COMMA_CHAR)
1895 *t = comma_token;
1896 else if (*s == CLOSE_PAREN_CHAR)
1897 *t = close_paren_token;
1898 else
1899 *t = colon_token;
1900 *begin_token = s;
1901 *end_token = ++s;
1902 } else {
1903 s_begin = s;
1904 while (s < end_s && !is_whitespace(*s)) {
1905 if (*s == ESCAPE_CHAR)
1906 s += 2;
1907 else if (*s == EQUAL_CHAR || *s == CLOSE_PAREN_CHAR ||
1908 *s == OPEN_PAREN_CHAR || *s == COMMA_CHAR ||
1909 *s == COLON_CHAR || *s == OPEN_BRACKET ||
1910 *s == CLOSE_BRACKET)
1911 break;
1912 else
1913 s++;
1914 }
1915 if (s > end_s) {
1916 p_error = parse_unmatched_escape;
1917 return (NULL);
1918 }
1919 *t = string_token;
1920 *end_token = s;
1921 *begin_token = s_begin;
1922 }
1923 if (s) {
1924 while (s < end_s && is_whitespace(*s))
1925 s++;
1926 }
1927 return (s);
1928 }
1929
1930 /*
1931 * FUNCTION: skip_token
1932 *
1933 * Skip over the specified token - An error is set if
1934 * next token does not match expected token
1935 *
1936 * RETURN VALUE: NULL if error
1937 * position of beginning next token after
1938 * token
1939 *
1940 * INPUT: the attribute value
1941 */
1942
1943 const char *
skip_token(const char * s,const char * end_s,token_type t)1944 skip_token(const char *s, const char *end_s, token_type t)
1945 {
1946 bool_t match;
1947 char c = 0;
1948
1949 if (s == NULL)
1950 return (s);
1951 while (s < end_s && is_whitespace(*s))
1952 s++;
1953 c = (s == end_s) ? 0 : *s;
1954 switch (t) {
1955 case equal_token:
1956 match = c == EQUAL_CHAR;
1957 if (!match)
1958 p_error = parse_equal_expected_error;
1959 break;
1960 case comma_token:
1961 match = c == COMMA_CHAR;
1962 if (!match)
1963 p_error = parse_comma_expected_error;
1964 break;
1965 case close_paren_token:
1966 match = c == CLOSE_PAREN_CHAR;
1967 if (!match)
1968 p_error = parse_close_paren_expected_error;
1969 break;
1970 default:
1971 match = FALSE;
1972 break;
1973 }
1974 if (match) {
1975 s++;
1976 while (s < end_s && is_whitespace(*s))
1977 s++;
1978 } else {
1979 s = NULL;
1980 }
1981 return (s);
1982 }
1983
1984 /*
1985 * FUNCTION: get_next_extract_format_item
1986 *
1987 * Get the next format token from the string. Note that
1988 * get_next_extract_format_item may change the input string.
1989 *
1990 * RETURN VALUE: NULL if error
1991 * position of beginning next token after
1992 * token
1993 *
1994 * INPUT: the format string
1995 */
1996
1997 const char *
get_next_extract_format_item(const char * begin_fmt,const char * end_fmt,__nis_mapping_format_t * fmt)1998 get_next_extract_format_item(
1999 const char *begin_fmt,
2000 const char *end_fmt,
2001 __nis_mapping_format_t *fmt)
2002 {
2003 const char *s = begin_fmt;
2004 const char *s_end = end_fmt;
2005 bool_t escape;
2006 bool_t in_range;
2007 bool_t got_char;
2008 bool_t done;
2009 int numRange;
2010 char *lo = NULL;
2011 char *hi = NULL;
2012 bool_t skip_ber;
2013
2014 for (; p_error == no_parse_error; ) {
2015 if (s >= s_end)
2016 break;
2017
2018 if (*s == PERCENT_SIGN) {
2019 s++;
2020 /*
2021 * If the format is %s, it is interpreted
2022 * as a string.
2023 */
2024 if (s >= s_end) {
2025 p_error = parse_unsupported_format;
2026 break;
2027 }
2028 skip_ber = FALSE;
2029 switch (*s) {
2030 case 's':
2031 fmt->type = mmt_item;
2032 break;
2033 case 'n': /* null */
2034 case 'x': /* skip the next element */
2035 skip_ber = TRUE;
2036 /* FALLTHRU */
2037 case 'b': /* boolean */
2038 case 'e': /* enumerated */
2039 case 'i': /* int */
2040 case 'o': /* octet string */
2041 case 'B': /* bit string */
2042 fmt->match.berString = s_strndup(s, 1);
2043 fmt->type = skip_ber ?
2044 mmt_berstring_null :
2045 mmt_berstring;
2046 break;
2047 case 'a': /* octet string */
2048 if (yp2ldap) {
2049 fmt->match.berString =
2050 s_strndup(s, 1);
2051 fmt->type = skip_ber ?
2052 mmt_berstring_null :
2053 mmt_berstring;
2054 break;
2055 } /* else FALLTHRU */
2056 case '{': /* begin sequence */
2057 case '[': /* begin set */
2058 case '}': /* end sequence */
2059 case ']': /* end set */
2060 case 'l': /* length of next item */
2061 case 'O': /* octet string */
2062 case 't': /* tag of next item */
2063 case 'T': /* skip tag of next item */
2064 case 'v': /* seq of strings */
2065 case 'V': /* seq of strings + lengths */
2066 default:
2067 p_error = parse_bad_ber_format;
2068 break;
2069 }
2070 s++;
2071 } else if (*s == ASTERIX_CHAR) {
2072 fmt->type = mmt_any;
2073 s++;
2074 while (s < s_end && *s == ASTERIX_CHAR)
2075 s++;
2076
2077 } else if (*s == OPEN_BRACKET) {
2078 escape = FALSE;
2079 in_range = FALSE;
2080 got_char = FALSE;
2081 numRange = 0;
2082 done = FALSE;
2083 s++;
2084 for (; s < s_end; s++) {
2085 if (escape) {
2086 escape = FALSE;
2087 } else if (*s == DASH_CHAR) {
2088 if (in_range || !got_char) {
2089 p_error = parse_unexpected_dash;
2090 break;
2091 }
2092 in_range = TRUE;
2093 got_char = FALSE;
2094 continue;
2095 } else if (*s == CLOSE_BRACKET) {
2096 if (in_range) {
2097 p_error = parse_unexpected_dash;
2098 }
2099 done = TRUE;
2100 break;
2101 } else if (*s == ESCAPE_CHAR) {
2102 escape = TRUE;
2103 continue;
2104 }
2105 if (in_range) {
2106 hi[numRange - 1] = *s;
2107 in_range = FALSE;
2108 } else {
2109 lo = s_realloc(lo, numRange + 1);
2110 hi = s_realloc(hi, numRange + 1);
2111 if (lo == NULL || hi == NULL)
2112 break;
2113 lo[numRange] = *s;
2114 hi[numRange] = *s;
2115 numRange++;
2116 got_char = TRUE;
2117 }
2118 }
2119 if (p_error != no_parse_error) {
2120 break;
2121 } else if (!done) {
2122 p_error = parse_mismatched_brackets;
2123 break;
2124 }
2125 s++;
2126 fmt->type = mmt_single;
2127 fmt->match.single.numRange = numRange;
2128 fmt->match.single.lo = (unsigned char *)lo;
2129 fmt->match.single.hi = (unsigned char *)hi;
2130 } else {
2131 /* go to next key symbol - copy escaped key symbols */
2132 escape = FALSE;
2133 done = FALSE;
2134 while (s < s_end) {
2135 if (escape)
2136 escape = FALSE;
2137 else {
2138 switch (*s) {
2139 case OPEN_BRACKET:
2140 case ASTERIX_CHAR:
2141 case PERCENT_SIGN:
2142 done = TRUE;
2143 break;
2144 case ESCAPE_CHAR:
2145 escape = !escape;
2146 break;
2147 default:
2148 break;
2149 }
2150 }
2151 if (done)
2152 break;
2153 s++;
2154 }
2155 if (escape) {
2156 p_error = parse_unmatched_escape;
2157 break;
2158 }
2159 fmt->type = mmt_string;
2160 fmt->match.string =
2161 s_strndup_esc(begin_fmt, s - begin_fmt);
2162 if (fmt->match.string == NULL)
2163 break;
2164 }
2165
2166 if (p_error == no_parse_error)
2167 return (s);
2168 }
2169 if (lo != NULL)
2170 free(lo);
2171 if (hi != NULL)
2172 free(hi);
2173 return (NULL);
2174 }
2175
2176 /*
2177 * FUNCTION: get_next_print_format_item
2178 *
2179 * Get the next format token from the string
2180 *
2181 * RETURN VALUE: NULL if error
2182 * position of beginning next token after
2183 * token
2184 *
2185 * INPUT: the format string
2186 */
2187
2188 const char *
get_next_print_format_item(const char * begin_fmt,const char * end_fmt,__nis_mapping_format_t * fmt)2189 get_next_print_format_item(
2190 const char *begin_fmt,
2191 const char *end_fmt,
2192 __nis_mapping_format_t *fmt)
2193 {
2194 const char *s = begin_fmt;
2195 const char *s_end = end_fmt;
2196 bool_t skip_ber;
2197
2198 for (; p_error == no_parse_error; ) {
2199 if (s >= s_end) {
2200 p_error = parse_internal_error;
2201 break;
2202 }
2203
2204 if (*s == PERCENT_SIGN) {
2205 s++;
2206 if (s >= s_end) {
2207 p_error = parse_unsupported_format;
2208 break;
2209 }
2210 skip_ber = FALSE;
2211 /*
2212 * If the format is %s, it is interpretted
2213 * as a string.
2214 */
2215 switch (*s) {
2216 case 's':
2217 fmt->type = mmt_item;
2218 break;
2219 case 'n': /* null */
2220 case 'x': /* skip the next element */
2221 skip_ber = TRUE;
2222 /* FALLTHRU */
2223 case 'b': /* boolean */
2224 case 'e': /* enumerated */
2225 case 'i': /* int */
2226 case 'o': /* octet string */
2227 case 'B': /* bit string */
2228 fmt->match.berString = s_strndup(s, 1);
2229 fmt->type = skip_ber ?
2230 mmt_berstring_null :
2231 mmt_berstring;
2232 break;
2233 case '{': /* begin sequence */
2234 case '[': /* begin set */
2235 case '}': /* end sequence */
2236 case ']': /* end set */
2237 case 'a': /* octet string */
2238 case 'l': /* length of next item */
2239 case 'O': /* octet string */
2240 case 't': /* tag of next item */
2241 case 'T': /* skip tag of next item */
2242 case 'v': /* seq of strings */
2243 case 'V': /* seq of strings + lengths */
2244 default:
2245 p_error = parse_bad_ber_format;
2246 break;
2247 }
2248 s++;
2249 } else {
2250 while (s < s_end) {
2251 if (*s == PERCENT_SIGN)
2252 break;
2253 else if (*s == ESCAPE_CHAR)
2254 s++;
2255 s++;
2256 }
2257 if (s > s_end) {
2258 p_error = parse_unmatched_escape;
2259 break;
2260 }
2261 fmt->match.string =
2262 s_strndup_esc(begin_fmt, s - begin_fmt);
2263 if (fmt->match.string == NULL)
2264 break;
2265 fmt->type = mmt_string;
2266 }
2267 if (p_error == no_parse_error)
2268 return (s);
2269 }
2270 return (NULL);
2271 }
2272
2273 /*
2274 * FUNCTION: get_ldap_filter
2275 *
2276 * Gets an LDAP filter - see RFC 2254. Note that this does not
2277 * determine if the ldap filter is valid. This only determines
2278 * that the parentheses are balanced.
2279 *
2280 * RETURN VALUE: NULL if error
2281 * position of beginning next token after
2282 * filter
2283 *
2284 * INPUT: the begin and end of string
2285 *
2286 * OUTPUT: the begin and end of LDAP filter
2287 *
2288 */
2289
2290 const char *
get_ldap_filter(const char ** begin,const char ** end)2291 get_ldap_filter(const char **begin, const char **end)
2292 {
2293 const char *s = *begin;
2294 const char *s_begin;
2295 const char *s_end = *end;
2296 int nParen;
2297
2298 for (; p_error == no_parse_error; ) {
2299 while (s < s_end && is_whitespace(*s))
2300 s++;
2301 if (s == s_end) {
2302 s = NULL;
2303 break;
2304 }
2305
2306 s_begin = s;
2307 if (*s == OPEN_PAREN_CHAR) {
2308 nParen = 1;
2309 s++;
2310 while (s < s_end && nParen > 0) {
2311 if (*s == ESCAPE_CHAR)
2312 s++;
2313 else if (*s == OPEN_PAREN_CHAR)
2314 nParen++;
2315 else if (*s == CLOSE_PAREN_CHAR)
2316 nParen--;
2317 s++;
2318 }
2319 if (nParen == 0) {
2320 *begin = s_begin;
2321 *end = s;
2322 while (s < s_end && is_whitespace(*s))
2323 s++;
2324 } else
2325 s = NULL;
2326 } else
2327 s = NULL;
2328 if (p_error == no_parse_error)
2329 break;
2330 }
2331 if (s == NULL)
2332 p_error = parse_invalid_ldap_search_filter;
2333
2334 return (s);
2335 }
2336
2337 /*
2338 * FUNCTION: get_ava_list
2339 *
2340 * Gets an attribute value assertion list
2341 *
2342 * RETURN VALUE: NULL if error
2343 * position of beginning next token after
2344 * after attribute assertion
2345 *
2346 * INPUT: the begin and end of string
2347 * Indicator if ava list is part of a nisplus
2348 * item
2349 *
2350 * OUTPUT: the begin and end of LDAP filter
2351 *
2352 */
2353
2354 const char *
get_ava_list(const char ** begin,const char ** end,bool_t end_nisplus)2355 get_ava_list(const char **begin, const char **end, bool_t end_nisplus)
2356 {
2357 const char *s = *begin;
2358 const char *s_begin;
2359 const char *s_end = *end;
2360 bool_t in_quote;
2361 bool_t got_equal;
2362 bool_t got_data;
2363
2364 for (; p_error == no_parse_error; ) {
2365 while (s < s_end && is_whitespace(*s))
2366 s++;
2367 if (s == s_end) {
2368 s = NULL;
2369 break;
2370 }
2371
2372 in_quote = FALSE;
2373 got_equal = FALSE;
2374 got_data = FALSE;
2375 s_begin = s;
2376 while (s < s_end) {
2377 if (*s == ESCAPE_CHAR) {
2378 s++;
2379 got_data = TRUE;
2380 } else if (*s == DOUBLE_QUOTE_CHAR) {
2381 in_quote = !in_quote;
2382 got_data = TRUE;
2383 } else if (in_quote)
2384 ;
2385 else if (*s == EQUAL_CHAR) {
2386 if (end_nisplus && got_data && got_equal)
2387 break;
2388 if (!got_data || got_equal) {
2389 got_equal = FALSE;
2390 break;
2391 }
2392 got_equal = TRUE;
2393 got_data = FALSE;
2394 } else if (*s == COMMA_CHAR) {
2395 if (!got_data || !got_equal)
2396 break;
2397 got_data = FALSE;
2398 got_equal = FALSE;
2399 } else if (is_whitespace(*s))
2400 ;
2401 else
2402 got_data = TRUE;
2403 s++;
2404 }
2405 if (!got_data || !got_equal || in_quote)
2406 s = NULL;
2407 else {
2408 *begin = s_begin;
2409 *end = s;
2410 while (s < s_end && is_whitespace(*s))
2411 s++;
2412 }
2413 if (p_error == no_parse_error)
2414 break;
2415 }
2416 if (s == NULL)
2417 p_error = parse_invalid_ldap_search_filter;
2418
2419 return (s);
2420 }
2421
2422 /* Utility functions */
2423 bool_t
validate_dn(const char * s,int len)2424 validate_dn(const char *s, int len)
2425 {
2426 const char *end = s + len;
2427 bool_t valid;
2428
2429 valid = skip_get_dn(s, end) == end;
2430
2431 if (!valid)
2432 p_error = parse_bad_dn;
2433 return (valid);
2434 }
2435
2436 bool_t
validate_ldap_filter(const char * s,const char * end)2437 validate_ldap_filter(const char *s, const char *end)
2438 {
2439 const char *s_begin;
2440 const char *s_end;
2441
2442 s_begin = s;
2443 s_end = end;
2444
2445 if (*s == OPEN_PAREN_CHAR) {
2446 s = get_ldap_filter(&s_begin, &s_end);
2447 } else {
2448 /* Assume an attribute value list */
2449 s = get_ava_list(&s_begin, &s_end, FALSE);
2450 }
2451 if (s == NULL || s_end != end)
2452 p_error = parse_invalid_ldap_search_filter;
2453
2454 return (p_error == no_parse_error);
2455 }
2456
2457 char *
s_strndup(const char * s,int n)2458 s_strndup(const char *s, int n)
2459 {
2460 char *d = (char *)malloc(n + 1);
2461
2462 if (d != NULL) {
2463 (void) memcpy(d, s, n);
2464 d[n] = '\0';
2465 } else {
2466 p_error = parse_no_mem_error;
2467 }
2468
2469 return (d);
2470 }
2471
2472 char *
s_strndup_esc(const char * s,int n)2473 s_strndup_esc(const char *s, int n)
2474 {
2475 char *d = (char *)malloc(n + 1);
2476 int i;
2477 int j;
2478
2479 if (d != NULL) {
2480 for (i = 0, j = 0; i < n; i++) {
2481 if (s[i] == ESCAPE_CHAR)
2482 i++;
2483 d[j++] = s[i];
2484 }
2485 d[j] = '\0';
2486 } else {
2487 p_error = parse_no_mem_error;
2488 }
2489
2490 return (d);
2491 }
2492
2493 void *
s_calloc(size_t n,size_t size)2494 s_calloc(size_t n, size_t size)
2495 {
2496 void *d = (char *)calloc(n, size);
2497
2498 if (d == NULL) {
2499 p_error = parse_no_mem_error;
2500 }
2501
2502 return (d);
2503 }
2504
2505 void *
s_malloc(size_t size)2506 s_malloc(size_t size)
2507 {
2508 void *d = malloc(size);
2509 if (d == NULL)
2510 p_error = parse_no_mem_error;
2511 return (d);
2512 }
2513
2514 void *
s_realloc(void * s,size_t size)2515 s_realloc(void *s, size_t size)
2516 {
2517 s = realloc(s, size);
2518 if (s == NULL)
2519 p_error = parse_no_mem_error;
2520 return (s);
2521 }
2522
2523 char *
s_strdup(const char * s)2524 s_strdup(const char *s)
2525 {
2526 return (s != NULL ? s_strndup(s, strlen(s)) : NULL);
2527 }
2528
2529 bool_t
is_whitespace(int c)2530 is_whitespace(int c)
2531 {
2532 return (c == ' ' || c == '\t');
2533 }
2534
2535 bool_t
is_string_ok(char * buffer,int buflen)2536 is_string_ok(char *buffer, int buflen)
2537 {
2538 int i;
2539
2540 if (buffer == NULL)
2541 return (FALSE);
2542
2543 for (i = 0; i < buflen; i++) {
2544 if (!is_whitespace(buffer[i])) {
2545 if (buffer[i] == POUND_SIGN)
2546 return (TRUE);
2547 else
2548 return (FALSE);
2549 }
2550 }
2551 return (TRUE);
2552 }
2553
2554 /*
2555 * Returns true if the first string is contained at the beginning of the
2556 * second string. Otherwise returns false.
2557 */
2558
2559 bool_t
contains_string(const char * s1,const char * s2)2560 contains_string(const char *s1, const char *s2)
2561 {
2562 return (strncasecmp(s1, s2, strlen(s1)) == 0);
2563 }
2564
2565 /*
2566 * Returns the next character position in the second string, if the first
2567 * string is contained at the beginning of the second string. Otherwise
2568 * returns NULL.
2569 */
2570
2571 const char *
skip_string(const char * s1,const char * s2,int len)2572 skip_string(const char *s1, const char *s2, int len)
2573 {
2574 int len1 = strlen(s1);
2575
2576 if (len >= len1 && strncasecmp(s1, s2, strlen(s1)) == 0)
2577 return (s2 + len1);
2578 else
2579 return (NULL);
2580 }
2581
2582 /*
2583 * The second string is not necessarily null terminated.
2584 * same_string returns true if the second string matches the first.
2585 * Otherwise returns false.
2586 */
2587
2588 bool_t
same_string(const char * s1,const char * s2,int len)2589 same_string(const char *s1, const char *s2, int len)
2590 {
2591 int len1 = strlen(s1);
2592
2593 return (len1 == len && strncasecmp(s1, s2, len1) == 0);
2594 }
2595
2596 void
report_error(const char * str,const char * attr)2597 report_error(const char *str, const char *attr)
2598 {
2599 char fmt_buf[1024];
2600 int pos = 0;
2601
2602 if (command_line_source != NULL) {
2603 snprintf(fmt_buf, sizeof (fmt_buf), "Error parsing %s: ",
2604 command_line_source);
2605 pos = strlen(fmt_buf);
2606 } else if (file_source != NULL) {
2607 snprintf(fmt_buf, sizeof (fmt_buf), "Error parsing file '%s': ",
2608 file_source);
2609 pos = strlen(fmt_buf);
2610 } else if (ldap_source != NULL) {
2611 snprintf(fmt_buf, sizeof (fmt_buf), "Error for LDAP dn '%s': ",
2612 ldap_source);
2613 pos = strlen(fmt_buf);
2614 }
2615
2616 if (start_line_num != 0) {
2617 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "at line %d: ",
2618 start_line_num);
2619 pos += strlen(fmt_buf + pos);
2620 }
2621
2622 if (attr != NULL) {
2623 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos,
2624 "for attribute %s: ", attr);
2625 pos += strlen(fmt_buf + pos);
2626 }
2627
2628 if (cons != NULL) {
2629 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "%s\n",
2630 parse_error_msg[p_error]);
2631 fprintf(cons, fmt_buf, str == NULL ? "" : str);
2632 } else {
2633 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "%s",
2634 parse_error_msg[p_error]);
2635 syslog(LOG_ERR, fmt_buf, str == NULL ? "" : str);
2636 }
2637 }
2638
2639 void
report_error2(const char * str1,const char * str2)2640 report_error2(
2641 const char *str1,
2642 const char *str2)
2643 {
2644 char fmt_buf[1024];
2645
2646 if (cons != NULL) {
2647 snprintf(fmt_buf, sizeof (fmt_buf),
2648 "%s\n", parse_error_msg[p_error]);
2649 fprintf(cons, fmt_buf, str1, str2);
2650 } else {
2651 syslog(LOG_ERR, parse_error_msg[p_error], str1, str2);
2652 }
2653 }
2654
2655 void
report_conn_error(conn_error e,const char * str1,const char * str2)2656 report_conn_error(
2657 conn_error e,
2658 const char *str1,
2659 const char *str2)
2660 {
2661 char fmt_buf[1024];
2662
2663 if (cons != NULL) {
2664 snprintf(fmt_buf, sizeof (fmt_buf),
2665 "%s\n", conn_error_msg[e]);
2666 fprintf(cons, fmt_buf,
2667 str1 == NULL ? "" : str1,
2668 str2 == NULL ? "" : str2);
2669 } else {
2670 syslog(LOG_ERR,
2671 conn_error_msg[e],
2672 str1 == NULL ? "" : str1,
2673 str2 == NULL ? "" : str2);
2674 }
2675 }
2676
2677 void
report_info(const char * str,const char * arg)2678 report_info(
2679 const char *str,
2680 const char *arg)
2681 {
2682 if (cons != NULL) {
2683 fputs(str, cons);
2684 if (arg != NULL)
2685 fputs(arg, cons);
2686 fputs("\n", cons);
2687 } else
2688 syslog(LOG_INFO, str, arg);
2689 }
2690