dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libnisdb / nis_parse_ldap_util.c
blob659e03316780f89a0443c656bfc68d4622bf7ac4
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2015 Gary Mills
24 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
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 */
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"
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);
65 extern FILE *cons;
68 * FUNCTION: free_parse_structs
70 * Release the resources in parse results
74 void
75 free_parse_structs()
77 __nis_table_mapping_t *t;
78 __nis_table_mapping_t *t1;
80 free_proxy_info(&proxyInfo);
81 for (t = ldapTableMapping; t != NULL; t = t1) {
82 t1 = t->next;
83 free_table_mapping(t);
85 ldapTableMapping = NULL;
89 * FUNCTION: initialize_parse_structs
91 * Initialize fields to unset values
93 * INPUT: __nis_ldap_proxy_info, __nis_config_t
94 * and __nisdb_table_mapping_t structures
97 void
98 initialize_parse_structs(
99 __nis_ldap_proxy_info *proxy_info,
100 __nis_config_t *config_info,
101 __nisdb_table_mapping_t *table_info)
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;
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;
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;
154 * FUNCTION: free_mapping_rule
156 * Frees __nis_mapping_rule_t
158 * INPUT: __nis_mapping_rule_t
161 void
162 free_mapping_rule(__nis_mapping_rule_t *rule)
164 int i;
165 __nis_mapping_rlhs_t *r;
167 if (rule != NULL) {
168 r = &rule->lhs;
169 for (i = 0; i < r->numElements; i++)
170 free_mapping_element(&r->element[i]);
171 free(r->element);
173 r = &rule->rhs;
174 for (i = 0; i < r->numElements; i++)
175 free_mapping_element(&r->element[i]);
176 free(r->element);
178 free(rule);
183 * FUNCTION: free_mapping_element
185 * Frees __nis_mapping_element_t
187 * INPUT: __nis_mapping_element_t
190 void
191 free_mapping_element(__nis_mapping_element_t *e)
193 int i;
195 if (e == NULL)
196 return;
198 switch (e->type) {
199 case me_item:
200 free_mapping_item(&e->element.item);
201 break;
202 case me_print:
203 if (e->element.print.fmt != NULL)
204 free_mapping_format(e->element.print.fmt);
205 e->element.print.fmt = NULL;
206 for (i = 0; i < e->element.print.numSubElements; i++)
207 free_mapping_sub_element(
208 &e->element.print.subElement[i]);
209 e->element.print.numSubElements = 0;
210 free(e->element.print.subElement);
211 e->element.print.subElement = NULL;
212 break;
213 case me_split:
214 free_mapping_item(&e->element.split.item);
215 break;
216 case me_match:
217 if (e->element.match.fmt != NULL)
218 free_mapping_format(e->element.match.fmt);
219 e->element.match.fmt = NULL;
220 for (i = 0; i < e->element.match.numItems; i++)
221 free_mapping_item(&e->element.match.item[i]);
222 e->element.match.numItems = 0;
223 free(e->element.match.item);
224 e->element.match.item = NULL;
225 break;
226 case me_extract:
227 if (e->element.extract.fmt != NULL)
228 free_mapping_format(e->element.extract.fmt);
229 e->element.extract.fmt = NULL;
230 free_mapping_item(&e->element.extract.item);
231 break;
233 e = NULL;
237 * FUNCTION: free_table_mapping
239 * Frees __nis_table_mapping_t
241 * INPUT: __nis_table_mapping_t
245 * free_table_mapping does not remove the table mapping from
246 * its hashed list
249 void
250 free_table_mapping(__nis_table_mapping_t *mapping)
252 int i;
254 if (mapping == NULL)
255 return;
257 free(mapping->dbId);
258 mapping->dbId = NULL;
260 free(mapping->objName);
261 mapping->objName = NULL;
263 for (i = 0; i < mapping->index.numIndexes; i++) {
264 free(mapping->index.name[i]);
265 free_mapping_format(mapping->index.value[i]);
268 free(mapping->index.name);
269 mapping->index.name = NULL;
271 free(mapping->index.value);
272 mapping->index.value = NULL;
274 mapping->index.numIndexes = 0;
276 if (mapping->column != NULL) {
277 for (i = 0; i < mapping->numColumns; i++) {
278 free(mapping->column[i]);
280 mapping->numColumns = 0;
281 free(mapping->column);
282 mapping->column = NULL;
285 if (mapping->commentChar != '\0')
286 mapping->commentChar = '\0';
288 if (mapping->objectDN != NULL)
289 free_object_dn(mapping->objectDN);
290 mapping->objectDN = NULL;
292 if (mapping->separatorStr != NULL)
293 mapping->separatorStr = NULL;
295 for (i = 0; i < mapping->numRulesFromLDAP; i++) {
296 if (mapping->ruleFromLDAP[i]) /* See Comment below */
297 free_mapping_rule(mapping->ruleFromLDAP[i]);
299 mapping->numRulesFromLDAP = 0;
301 free(mapping->ruleFromLDAP);
302 mapping->ruleFromLDAP = NULL;
304 for (i = 0; i < mapping->numRulesToLDAP; i++) {
305 if (mapping->ruleToLDAP[i])
307 * Normally mapping->ruleToLDAP[i] should
308 * always be non-null if
309 * mapping->numRulesToLDAP is > 0.
310 * However it is possible to have data
311 * corruption where numRulesToLDAP gets
312 * some integer value even though no real
313 * data is present in mapping->ruleToLDAP.
315 free_mapping_rule(mapping->ruleToLDAP[i]);
317 mapping->numRulesToLDAP = 0;
319 free(mapping->ruleToLDAP);
320 mapping->ruleToLDAP = NULL;
322 if (mapping->e != NULL) {
323 /* Similar logic as in above comment applies. */
324 for (i = 0; i <= mapping->numSplits; i++) {
325 free_mapping_element(&mapping->e[i]);
327 free(mapping->e);
329 mapping->e = NULL;
331 mapping->numSplits = 0;
333 free(mapping);
337 * FUNCTION: free_config_info
339 * Frees __nis_config_info_t
341 * INPUT: __nis_config_info_t
344 void
345 free_config_info(__nis_config_info_t *config_info)
347 free(config_info->config_dn);
348 config_info->config_dn = NULL;
350 free(config_info->default_servers);
351 config_info->default_servers = NULL;
353 free(config_info->proxy_dn);
354 config_info->proxy_dn = NULL;
356 free(config_info->proxy_passwd);
357 config_info->proxy_passwd = NULL;
359 free(config_info->tls_cert_db);
360 config_info->tls_cert_db = NULL;
364 * FUNCTION: free_proxy_info
366 * Frees __nis_ldap_proxy_info
368 * INPUT: __nis_ldap_proxy_info
371 void
372 free_proxy_info(__nis_ldap_proxy_info *proxy_info)
374 free(proxy_info->tls_cert_db);
375 proxy_info->tls_cert_db = NULL;
377 free(proxy_info->default_servers);
378 proxy_info->default_servers = NULL;
380 free(proxy_info->default_search_base);
381 proxy_info->default_search_base = NULL;
383 free(proxy_info->proxy_dn);
384 proxy_info->proxy_dn = NULL;
386 free(proxy_info->proxy_passwd);
387 proxy_info->proxy_passwd = NULL;
389 free(proxy_info->default_nis_domain);
390 proxy_info->default_nis_domain = NULL;
394 * FUNCTION: free_object_dn
396 * Frees __nis_object_dn_t
398 * INPUT: __nis_object_dn_t
401 void
402 free_object_dn(__nis_object_dn_t *obj_dn)
404 __nis_object_dn_t *t;
405 int i;
407 while (obj_dn != NULL) {
408 free(obj_dn->read.base);
409 obj_dn->read.base = NULL;
410 free(obj_dn->read.attrs);
411 obj_dn->read.attrs = NULL;
412 free(obj_dn->write.base);
413 obj_dn->write.base = NULL;
414 free(obj_dn->write.attrs);
415 obj_dn->write.attrs = NULL;
416 free(obj_dn->dbIdName);
417 obj_dn->dbIdName = NULL;
418 for (i = 0; i < obj_dn->numDbIds; i++)
419 free_mapping_rule(obj_dn->dbId[i]);
420 obj_dn->numDbIds = 0;
422 free(obj_dn->dbId);
423 obj_dn->dbId = NULL;
425 t = obj_dn;
426 obj_dn = obj_dn->next;
427 free(t);
432 * FUNCTION: free_index
434 * Frees __nis_index_t
436 * INPUT: __nis_index_t
439 void
440 free_index(__nis_index_t *index)
442 int i;
443 for (i = 0; i < index->numIndexes; i++) {
444 free(index->name[i]);
445 free_mapping_format(index->value[i]);
447 index->numIndexes = 0;
448 free(index->name);
449 index->name = NULL;
450 free(index->value);
451 index->value = NULL;
455 * FUNCTION: free_mapping_item
457 * Frees __nis_mapping_item_t
459 * INPUT: __nis_mapping_item_t
462 void
463 free_mapping_item(__nis_mapping_item_t *item)
465 if (item == NULL)
466 return;
468 free(item->name);
469 item->name = NULL;
470 if (item->type == mit_nisplus) {
471 free_index(&item->searchSpec.obj.index);
472 free(item->searchSpec.obj.name);
473 item->searchSpec.obj.name = NULL;
474 } else if (item->type == mit_ldap) {
475 free(item->searchSpec.triple.base);
476 item->searchSpec.triple.base = NULL;
477 free(item->searchSpec.triple.attrs);
478 item->searchSpec.triple.attrs = NULL;
479 if (item->searchSpec.triple.element != NULL) {
480 free_mapping_element(
481 item->searchSpec.triple.element);
482 free(item->searchSpec.triple.element);
484 item->searchSpec.triple.element = NULL;
486 if (item->exItem != NULL) {
487 free_mapping_item(item->exItem);
488 free(item->exItem);
489 item->exItem = 0;
494 * FUNCTION: free_mapping_format
496 * Frees __nis_mapping_format_t
498 * INPUT: __nis_mapping_format_t
501 void
502 free_mapping_format(__nis_mapping_format_t *fmt)
504 __nis_mapping_format_t *f = fmt;
506 while (fmt->type != mmt_end) {
507 switch (fmt->type) {
508 case mmt_item:
509 break;
510 case mmt_string:
511 free(fmt->match.string);
512 fmt->match.string = NULL;
513 break;
514 case mmt_single:
515 free(fmt->match.single.lo);
516 fmt->match.single.lo = NULL;
517 free(fmt->match.single.hi);
518 fmt->match.single.hi = NULL;
519 break;
520 case mmt_limit:
521 break;
522 case mmt_any:
523 break;
524 case mmt_berstring:
525 case mmt_berstring_null:
526 free(fmt->match.berString);
527 fmt->match.berString = NULL;
528 break;
529 case mmt_begin:
530 break;
531 case mmt_end:
532 break;
534 fmt++;
536 free(f);
540 * FUNCTION: free_mapping_sub_element
542 * Frees __nis_mapping_sub_element_t
544 * INPUT: __nis_mapping_sub_element_t
547 void
548 free_mapping_sub_element(__nis_mapping_sub_element_t *sub)
550 int i;
552 switch (sub->type) {
553 case me_item:
554 free_mapping_item(&sub->element.item);
555 break;
556 case me_print:
557 if (sub->element.print.fmt != NULL)
558 free_mapping_format(sub->element.print.fmt);
559 sub->element.print.fmt = NULL;
560 for (i = 0; i < sub->element.print.numItems; i++)
561 free_mapping_item(&sub->element.print.item[i]);
562 sub->element.print.numItems = 0;
563 free(sub->element.print.item);
564 sub->element.print.item = NULL;
565 break;
566 case me_split:
567 free_mapping_item(&sub->element.split.item);
568 break;
569 case me_extract:
570 if (sub->element.extract.fmt != NULL)
571 free_mapping_format(sub->element.extract.fmt);
572 sub->element.extract.fmt = NULL;
573 free_mapping_item(&sub->element.extract.item);
574 break;
579 * FUNCTION: read_line
581 * Gets next line in buffer - using '\' at end of line
582 * to indicate continuation. Lines beginning with # are
583 * ignored. start_line_num and start_line_num are
584 * maintained to track the line number currently being
585 * parsed.
587 * RETURN VALUE: The number of characters read. 0 for
588 * eof, -1 for error
590 * INPUT: file descriptor, buffer, and buffer size
594 read_line(int fd, char *buffer, int buflen)
596 int linelen;
597 int rc;
598 char c;
599 bool_t skip_line = FALSE;
600 bool_t begin_line = TRUE;
601 static bool_t prev_cr = FALSE;
603 start_line_num = cur_line_num;
604 (void) memset(buffer, 0, buflen);
605 for (; p_error == no_parse_error; ) {
606 linelen = 0;
607 while (linelen < buflen) {
608 rc = read(fd, &c, 1);
609 if (1 == rc) {
610 if (c == '\n' || c == '\r') {
611 if (c == '\n') {
612 if (prev_cr) {
613 prev_cr = FALSE;
614 continue;
615 } else {
616 if (linelen == 0)
617 start_line_num =
618 cur_line_num;
619 else {
620 if (
621 is_string_ok(
622 buffer,
623 linelen)) {
624 (void) memset(
625 buffer, 0,
626 linelen);
627 linelen = 0;
628 cur_line_num++;
629 begin_line =
630 TRUE;
631 continue;
634 cur_line_num++;
636 prev_cr = FALSE;
637 } else {
638 prev_cr = TRUE;
639 if (linelen == 0)
640 start_line_num =
641 cur_line_num;
642 cur_line_num++;
644 if (skip_line) {
645 skip_line = FALSE;
646 if (linelen == 0)
647 start_line_num =
648 cur_line_num;
649 } else if (linelen > 0 &&
650 buffer[linelen - 1]
651 == ESCAPE_CHAR) {
652 --linelen;
653 } else if (linelen > 0) {
654 buffer[linelen] = '\0';
655 return (linelen);
657 begin_line = TRUE;
658 } else {
659 if (begin_line)
660 skip_line = c == POUND_SIGN;
661 begin_line = FALSE;
662 if (!skip_line)
663 buffer[linelen++] = c;
665 } else {
666 if (linelen > 0 &&
667 buffer[linelen - 1] == ESCAPE_CHAR) {
668 /* continuation on last line */
669 p_error = parse_bad_continuation_error;
670 return (-1);
671 } else {
672 buffer[linelen] = '\0';
673 return (linelen);
677 p_error = parse_line_too_long;
679 return (-1);
683 * FUNCTION: finish_parse
685 * Adds any elements not configured, fully qualifies
686 * names
688 * RETURN VALUE: 0 on success, -1 on failure
692 finish_parse(
693 __nis_ldap_proxy_info *proxy_info,
694 __nis_table_mapping_t **table_mapping)
696 __nis_table_mapping_t *t;
697 __nis_table_mapping_t *t1;
698 __nis_table_mapping_t *t2;
699 __nis_table_mapping_t *t_del = NULL;
700 int i;
701 int j;
702 int k;
703 __nis_object_dn_t *objectDN;
704 __nis_mapping_rlhs_t *lhs;
705 __nis_mapping_element_t *e;
706 char *s;
707 int errnum;
709 /* set to default those values yet set */
710 if (proxy_info->auth_method ==
711 (auth_method_t)NO_VALUE_SET) {
712 p_error = parse_no_proxy_auth_error;
713 report_error(NULL, NULL);
714 return (-1);
717 if (proxy_info->default_servers == NULL) {
718 p_error = parse_no_ldap_server_error;
719 report_error(NULL, NULL);
720 return (-1);
723 if (proxy_info->tls_method == (tls_method_t)NO_VALUE_SET)
724 proxy_info->tls_method = no_tls;
725 else if (proxy_info->tls_method == ssl_tls &&
726 (proxy_info->tls_cert_db == NULL ||
727 *proxy_info->tls_cert_db == '\0')) {
728 p_error = parse_no_cert_db;
729 report_error(NULL, NULL);
730 return (-1);
733 if (proxy_info->default_nis_domain == NULL)
734 proxy_info->default_nis_domain =
735 s_strdup(__nis_rpc_domain());
736 else if (*proxy_info->default_nis_domain == '\0') {
737 free(proxy_info->default_nis_domain);
738 proxy_info->default_nis_domain =
739 s_strdup(__nis_rpc_domain());
741 if (proxy_info->default_nis_domain != NULL)
742 append_dot(&proxy_info->default_nis_domain);
744 if (proxy_info->tls_method == ssl_tls) {
745 if ((errnum = ldapssl_client_init(
746 proxy_info->tls_cert_db, NULL)) < 0) {
747 p_error = parse_ldapssl_client_init_error;
748 report_error(ldapssl_err2string(errnum), NULL);
749 return (-1);
753 if (proxy_info->default_search_base == NULL)
754 proxy_info->default_search_base =
755 get_default_ldap_base(proxy_info->default_nis_domain);
757 /* convert a relative dn to a fullly qualified dn */
758 (void) make_full_dn(&proxy_info->proxy_dn,
759 proxy_info->default_search_base);
761 if (p_error != no_parse_error) {
762 report_error(NULL, NULL);
763 return (-1);
767 * Create a list of potential delete mappings
768 * those have NULL objectDNs, but badly also rules
769 * that are missing object dn's will be included.
770 * We will use the ttl field to determine if the
771 * delete rule is actually used
773 t2 = NULL;
774 for (t = *table_mapping; t != NULL; t = t1) {
775 t1 = t->next;
776 if (t->objectDN == NULL) {
777 if (t2 == NULL)
778 *table_mapping = t1;
779 else
780 t2->next = t1;
781 t->next = t_del;
782 t_del = t;
783 t->ttl = 0;
784 } else
785 t2 = t;
788 for (t = *table_mapping; t != NULL; t = t->next) {
789 objectDN = t->objectDN;
790 while (objectDN != NULL) {
791 if (objectDN->dbIdName != NULL) {
792 s = objectDN->dbIdName;
793 t1 = find_table_mapping(s, strlen(s), t_del);
794 if (t1 == NULL) {
795 p_error = parse_no_db_del_mapping_rule;
796 report_error2(objectDN->dbIdName, t->dbId);
797 return (-1);
798 } else if (t1->objName != NULL ||
799 t1->numRulesToLDAP == 0 ||
800 t1->numRulesFromLDAP != 0) {
801 p_error = parse_invalid_db_del_mapping_rule;
802 report_error(t1->dbId, NULL);
803 return (-1);
805 objectDN->dbId =
806 dup_mapping_rules(t1->ruleToLDAP,
807 t1->numRulesToLDAP);
808 if (objectDN->dbId == NULL) {
809 break;
811 objectDN->numDbIds = t1->numRulesToLDAP;
812 t1->ttl++;
814 objectDN = objectDN->next;
818 for (t = t_del; t != NULL; t = t1) {
819 t1 = t->next;
820 if (t->ttl == 0) {
821 p_error = parse_no_object_dn;
822 report_error(t->dbId, NULL);
824 free_table_mapping(t);
827 if (p_error != no_parse_error)
828 return (-1);
830 /* set to default those table mapping values yet set */
831 for (t = *table_mapping; t != NULL; t = t->next) {
832 if (t->objName == 0) {
833 p_error = parse_no_object_dn;
834 report_error(t->dbId, NULL);
835 return (-1);
837 if (!yp2ldap) {
838 if (!add_domain(&t->objName,
839 proxy_info->default_nis_domain)) {
840 report_error(NULL, NULL);
841 return (-1);
844 if (t->initTtlHi == (time_t)NO_VALUE_SET)
845 t->initTtlHi = DEFAULT_TTL_HIGH;
846 if (t->initTtlLo == (time_t)NO_VALUE_SET)
847 t->initTtlLo = DEFAULT_TTL_LOW;
848 if (t->ttl == (time_t)NO_VALUE_SET)
849 t->ttl = DEFAULT_TTL;
850 objectDN = t->objectDN;
852 /* fixup relative dn's */
853 while (objectDN != NULL) {
854 if (!yp2ldap) {
855 if (!make_full_dn(&objectDN->read.base,
856 proxy_info->default_search_base))
857 break;
859 if (objectDN->write.scope != LDAP_SCOPE_UNKNOWN) {
860 if (objectDN->write.base != NULL &&
861 !make_full_dn(&objectDN->write.base,
862 proxy_info->default_search_base))
863 break;
864 if (objectDN->write.base == NULL) {
865 objectDN->write.base =
866 s_strdup(objectDN->read.base);
867 if (objectDN->write.base == NULL)
868 break;
871 objectDN = objectDN->next;
874 if (p_error != no_parse_error) {
875 report_error(NULL, NULL);
876 return (-1);
879 /* Check for ruleToLDAP with no rhs */
880 for (i = 0; i < t->numRulesToLDAP; i++) {
881 if (t->ruleToLDAP[i]->rhs.numElements == 0) {
882 p_error = parse_unexpected_data_end_rule;
883 report_error(t->dbId, NULL);
884 return (-1);
888 /* populate cols field */
889 if (!yp2ldap) {
890 for (i = 0; i < t->numRulesFromLDAP; i++) {
891 lhs = &t->ruleFromLDAP[i]->lhs;
892 for (j = 0; j < lhs->numElements; j++) {
893 e = &lhs->element[j];
894 switch (e->type) {
895 case me_item:
896 if (!add_column(t,
897 e->element.item.name)) {
898 report_error(
899 NULL, NULL);
900 return (-1);
902 break;
903 case me_match:
904 for (k = 0;
905 k < e->element.match.numItems;
906 k++)
907 if (!add_column(t,
908 e->element.match.item[k].name)) {
909 report_error(
910 NULL, NULL);
911 return (-1);
913 break;
919 return (0);
923 * FUNCTION: set_default_values
925 * Sets unconfigured values to their default value
928 void
929 set_default_values(__nis_ldap_proxy_info *proxy_info,
930 __nis_config_t *config_info, __nisdb_table_mapping_t *table_info)
932 if (proxy_info->bind_timeout.tv_sec == (time_t)NO_VALUE_SET)
933 proxy_info->bind_timeout.tv_sec = DEFAULT_BIND_TIMEOUT;
934 if (proxy_info->search_timeout.tv_sec == (time_t)NO_VALUE_SET)
935 proxy_info->search_timeout.tv_sec =
936 (yp2ldap)?DEFAULT_YP_SEARCH_TIMEOUT:
937 DEFAULT_SEARCH_TIMEOUT;
938 if (proxy_info->modify_timeout.tv_sec == (time_t)NO_VALUE_SET)
939 proxy_info->modify_timeout.tv_sec = DEFAULT_MODIFY_TIMEOUT;
940 if (proxy_info->add_timeout.tv_sec == (time_t)NO_VALUE_SET)
941 proxy_info->add_timeout.tv_sec = DEFAULT_ADD_TIMEOUT;
942 if (proxy_info->delete_timeout.tv_sec == (time_t)NO_VALUE_SET)
943 proxy_info->delete_timeout.tv_sec = DEFAULT_DELETE_TIMEOUT;
945 if (proxy_info->search_time_limit == (int)NO_VALUE_SET)
946 proxy_info->search_time_limit = DEFAULT_SEARCH_TIME_LIMIT;
947 if (proxy_info->search_size_limit == (int)NO_VALUE_SET)
948 proxy_info->search_size_limit = DEFAULT_SEARCH_SIZE_LIMIT;
950 if (proxy_info->follow_referral == (follow_referral_t)NO_VALUE_SET)
951 proxy_info->follow_referral = no_follow;
953 switch (config_info->initialUpdate) {
954 case (__nis_initial_update_t)NO_VALUE_SET:
955 case (__nis_initial_update_t)INITIAL_UPDATE_NO_ACTION:
956 case (__nis_initial_update_t)NO_INITIAL_UPDATE_NO_ACTION:
957 config_info->initialUpdate = ini_none;
958 break;
959 case (__nis_initial_update_t)FROM_NO_INITIAL_UPDATE:
960 config_info->initialUpdate = from_ldap;
961 break;
962 case (__nis_initial_update_t)TO_NO_INITIAL_UPDATE:
963 config_info->initialUpdate = to_ldap;
964 break;
966 if (config_info->threadCreationError ==
967 (__nis_thread_creation_error_t)NO_VALUE_SET)
968 config_info->threadCreationError = pass_error;
969 if (config_info->threadCreationErrorTimeout.attempts == NO_VALUE_SET)
970 config_info->threadCreationErrorTimeout.attempts =
971 DEFAULT_THREAD_ERROR_ATTEMPTS;
972 if (config_info->threadCreationErrorTimeout.timeout ==
973 (time_t)NO_VALUE_SET)
974 config_info->threadCreationErrorTimeout.timeout =
975 DEFAULT_THREAD_ERROR_TIME_OUT;
976 if (config_info->dumpError ==
977 (__nis_dump_error_t)NO_VALUE_SET)
978 config_info->dumpError = de_retry;
979 if (config_info->dumpErrorTimeout.attempts == NO_VALUE_SET)
980 config_info->dumpErrorTimeout.attempts =
981 DEFAULT_DUMP_ERROR_ATTEMPTS;
982 if (config_info->dumpErrorTimeout.timeout == (time_t)NO_VALUE_SET)
983 config_info->dumpErrorTimeout.timeout =
984 DEFAULT_DUMP_ERROR_TIME_OUT;
985 if (config_info->resyncService ==
986 (__nis_resync_service_t)NO_VALUE_SET)
987 config_info->resyncService = from_copy;
988 if (config_info->updateBatching ==
989 (__nis_update_batching_t)NO_VALUE_SET)
990 config_info->updateBatching = accumulate;
991 if (config_info->updateBatchingTimeout.timeout == (time_t)NO_VALUE_SET)
992 config_info->updateBatchingTimeout.timeout =
993 DEFAULT_BATCHING_TIME_OUT;
994 if (config_info->numberOfServiceThreads == (int)NO_VALUE_SET)
995 config_info->numberOfServiceThreads =
996 DEFAULT_NUMBER_OF_THREADS;
997 if (config_info->emulate_yp == (int)NO_VALUE_SET)
998 config_info->emulate_yp =
999 DEFAULT_YP_EMULATION;
1000 if (config_info->maxRPCRecordSize == (int)NO_VALUE_SET)
1001 config_info->maxRPCRecordSize = RPC_MAXDATASIZE;
1003 if (table_info->retrieveError ==
1004 (__nis_retrieve_error_t)NO_VALUE_SET)
1005 table_info->retrieveError = use_cached;
1006 if (table_info->retrieveErrorRetry.attempts == NO_VALUE_SET)
1007 table_info->retrieveErrorRetry.attempts =
1008 DEFAULT_RETRIEVE_ERROR_ATTEMPTS;
1009 if (table_info->retrieveErrorRetry.timeout == (time_t)NO_VALUE_SET)
1010 table_info->retrieveErrorRetry.timeout =
1011 DEFAULT_RETRIEVE_ERROR_TIME_OUT;
1012 if (table_info->storeError ==
1013 (__nis_store_error_t)NO_VALUE_SET)
1014 table_info->storeError = sto_retry;
1015 if (table_info->storeErrorRetry.attempts == NO_VALUE_SET)
1016 table_info->storeErrorRetry.attempts =
1017 DEFAULT_STORE_ERROR_ATTEMPTS;
1018 if (table_info->storeErrorRetry.timeout == (time_t)NO_VALUE_SET)
1019 table_info->storeErrorRetry.timeout =
1020 DEFAULT_STORE_ERROR_TIME_OUT;
1021 if (table_info->refreshError ==
1022 (__nis_refresh_error_t)NO_VALUE_SET)
1023 table_info->refreshError = continue_using;
1024 if (table_info->refreshErrorRetry.attempts == NO_VALUE_SET)
1025 table_info->refreshErrorRetry.attempts =
1026 DEFAULT_REFRESH_ERROR_ATTEMPTS;
1027 if (table_info->refreshErrorRetry.timeout == (time_t)NO_VALUE_SET)
1028 table_info->refreshErrorRetry.timeout =
1029 DEFAULT_REFRESH_ERROR_TIME_OUT;
1030 if (table_info->matchFetch ==
1031 (__nis_match_fetch_t)NO_VALUE_SET)
1032 table_info->matchFetch = no_match_only;
1035 __nis_table_mapping_t *
1036 find_table_mapping(const char *s, int len, __nis_table_mapping_t *table_mapping)
1038 __nis_table_mapping_t *t;
1040 for (t = table_mapping; t != NULL; t = t->next)
1041 if (strlen(t->dbId) == len &&
1042 strncasecmp(t->dbId, s, len) == 0)
1043 break;
1044 return (t);
1047 void
1048 append_dot(char **str)
1050 char *s = *str;
1051 int len = strlen(s);
1053 if (len == 0 || s[len - 1] != PERIOD_CHAR) {
1054 s = s_realloc(s, len + 2);
1055 if (s != NULL) {
1056 s[len] = PERIOD_CHAR;
1057 s[len+1] = '\0';
1058 *str = s;
1063 void
1064 append_comma(char **str)
1067 char *s = *str;
1068 int len = strlen(s);
1070 if (len == 0 || s[len - 1] != COMMA_CHAR) {
1071 s = s_realloc(s, len + 2);
1072 if (s != NULL) {
1073 s[len] = COMMA_CHAR;
1074 s[len+1] = '\0';
1075 *str = s;
1081 * FUNCTION: make_full_dn
1083 * Appends the base dn if a relative ldap dn
1084 * (invoked only for LDAP write cycle)
1086 * RETURN VALUE: FALSE if error
1087 * TRUE if __nis_index_t returned
1089 * INPUT: the relative dn and ldap base
1092 bool_t
1093 make_full_dn(char **dn, const char *base)
1095 int len;
1096 int len1;
1098 if (*dn == NULL) {
1099 *dn = s_strdup(base);
1100 } else {
1101 len = strlen(*dn);
1102 if (len > 0 && (*dn)[len-1] == COMMA_CHAR) {
1103 len1 = strlen(base) + 1;
1104 *dn = s_realloc(*dn, len + len1);
1105 if (*dn != NULL)
1106 (void) strcpy(*dn + len, base);
1109 return (*dn != NULL);
1113 * FUNCTION: make_fqdn
1115 * Appends the base dn if a relative ldap dn
1116 * (invoked only for LDAP read cycle)
1118 * RETURN VALUE: FALSE if error
1119 * TRUE if success
1121 * INPUT: the relative dn and ldap base
1123 bool_t
1124 make_fqdn(__nis_object_dn_t *dn, const char *base)
1126 int len;
1127 int len1;
1129 if (dn == NULL) {
1130 return (FALSE);
1131 } else {
1132 while (dn != NULL && dn->read.base != NULL) {
1133 len = strlen(dn->read.base);
1134 if (len > 0 && (dn->read.base)[len-1] == COMMA_CHAR) {
1135 len1 = strlen(base) + 1;
1136 dn->read.base =
1137 s_realloc(dn->read.base, len + len1);
1138 if (dn->read.base != NULL)
1139 (void) strlcpy(dn->read.base + len,
1140 base, len1);
1141 else
1142 return (FALSE);
1144 dn = dn->next;
1147 return (TRUE);
1151 * FUNCTION: get_default_ldap_base
1153 * Gets the default LDAP search base from the
1154 * nis+ default domain
1156 * RETURN VALUE: NULL if error
1157 * the default base
1159 * INPUT: the nis domain
1162 char *
1163 get_default_ldap_base(const char *domain)
1166 int len = strlen(domain);
1167 int i;
1168 int count = len + 4;
1169 char *base;
1171 for (i = 0; i < len - 1; i++)
1172 if (domain[i] == PERIOD_CHAR)
1173 count += 4;
1174 if ((base = malloc(count)) == NULL) {
1175 p_error = parse_no_mem_error;
1176 } else {
1177 (void) strcpy(base, "dc=");
1178 count = 3;
1179 for (i = 0; i < len - 1; i++) {
1180 if (domain[i] == PERIOD_CHAR) {
1181 (void) strcpy(base + count, ",dc=");
1182 count += 4;
1183 } else {
1184 base[count++] = domain[i];
1187 base[count] = '\0';
1189 return (base);
1193 * FUNCTION: add_domain
1195 * Appends the base domain if a relative object name
1197 * RETURN VALUE: FALSE if error
1198 * TRUE if OK
1200 * INPUT: the relative object name and base domain
1201 * name
1204 bool_t
1205 add_domain(char **objName, const char *domain)
1207 int len;
1208 int len1;
1209 bool_t trailing_dot;
1210 char *obj_name;
1212 if (domain == NULL || *objName == NULL) {
1213 p_error = parse_internal_error;
1214 return (FALSE);
1216 len1 = strlen(domain);
1217 trailing_dot = (len1 > 0 && domain[len1 - 1] == PERIOD_CHAR) ?
1218 0 : 1;
1219 len = strlen(*objName);
1220 if (len == 0 || (*objName)[len - 1] != PERIOD_CHAR) {
1221 obj_name = s_realloc(*objName,
1222 len + len1 + 2 + trailing_dot);
1223 if (obj_name != NULL) {
1224 obj_name[len++] = PERIOD_CHAR;
1225 (void) strcpy(obj_name + len, domain);
1226 if (trailing_dot != 0) {
1227 obj_name[len + len1] = PERIOD_CHAR;
1228 obj_name[len + len1 + 1] = '\0';
1230 *objName = obj_name;
1234 return (*objName != NULL);
1237 bool_t
1238 dup_index(__nis_index_t *in, __nis_index_t *out)
1240 int i;
1241 int j;
1243 out->name = (char **)s_calloc(in->numIndexes, sizeof (char *));
1244 if (out->name == NULL)
1245 return (FALSE);
1246 out->value = (__nis_mapping_format_t **)
1247 s_calloc(in->numIndexes, sizeof (__nis_mapping_format_t *));
1248 if (out->value == NULL) {
1249 free(out->name);
1250 out->name = NULL;
1251 return (FALSE);
1254 for (i = 0; i < in->numIndexes; i++) {
1255 out->name[i] = s_strdup(in->name[i]);
1256 if (out->name[i] == NULL)
1257 break;
1258 out->value[i] = dup_format_mapping(in->value[i]);
1259 if (out->value[i] == NULL)
1260 break;
1262 if (i < in->numIndexes) {
1263 for (j = 0; j <= i; j++) {
1264 free(out->name[j]);
1265 if (out->value[j] != NULL)
1266 free_mapping_format(out->value[j]);
1268 free(out->name);
1269 out->name = NULL;
1270 free(out->value);
1271 out->value = NULL;
1272 } else {
1273 out->numIndexes = in->numIndexes;
1275 return (i == in->numIndexes);
1278 bool_t
1279 dup_mapping_item(__nis_mapping_item_t *in, __nis_mapping_item_t *out)
1281 bool_t ret;
1283 if (in->type == mit_nisplus) {
1284 ret = dup_index(&in->searchSpec.obj.index,
1285 &out->searchSpec.obj.index);
1286 if (!ret)
1287 return (ret);
1288 if (in->searchSpec.obj.name != NULL) {
1289 out->searchSpec.obj.name =
1290 s_strdup(in->searchSpec.obj.name);
1291 if (out->searchSpec.obj.name == NULL)
1292 return (FALSE);
1293 } else
1294 out->searchSpec.obj.name = NULL;
1295 } else if (in->type == mit_ldap) {
1296 if (in->searchSpec.triple.base != NULL) {
1297 out->searchSpec.triple.base =
1298 s_strdup(in->searchSpec.triple.base);
1299 if (out->searchSpec.triple.base == NULL)
1300 return (FALSE);
1301 } else
1302 out->searchSpec.triple.base = NULL;
1303 out->searchSpec.triple.scope =
1304 in->searchSpec.triple.scope;
1305 if (in->searchSpec.triple.attrs != NULL) {
1306 out->searchSpec.triple.attrs =
1307 s_strdup(in->searchSpec.triple.attrs);
1308 if (out->searchSpec.triple.attrs == NULL)
1309 return (FALSE);
1310 } else
1311 out->searchSpec.triple.attrs = NULL;
1312 if (in->searchSpec.triple.element != NULL) {
1313 out->searchSpec.triple.element =
1314 (__nis_mapping_element_t *)
1315 s_calloc(1, sizeof (__nis_mapping_element_t));
1316 if (out->searchSpec.triple.element != NULL)
1317 dup_mapping_element(
1318 in->searchSpec.triple.element,
1319 out->searchSpec.triple.element);
1320 if (out->searchSpec.triple.element == NULL)
1321 return (FALSE);
1322 } else
1323 out->searchSpec.triple.element = NULL;
1326 if (in->name != NULL) {
1327 out->name = s_strdup(in->name);
1328 if (out->name == NULL)
1329 return (FALSE);
1330 } else
1331 out->name = NULL;
1332 out->type = in->type;
1333 out->repeat = in->repeat;
1334 if (in->exItem) {
1335 out->exItem = (__nis_mapping_item_t *)s_malloc
1336 (sizeof (__nis_mapping_item_t));
1337 if (out->exItem == NULL)
1338 return (FALSE);
1339 else {
1340 (void) memset
1341 (out->exItem, 0, sizeof (out->exItem[0]));
1342 if (!dup_mapping_item
1343 (in->exItem, out->exItem))
1344 p_error = parse_internal_error;
1346 } else
1347 out->exItem = NULL;
1349 return (p_error == no_parse_error);
1352 __nis_mapping_format_t *
1353 dup_format_mapping(__nis_mapping_format_t *in)
1355 int i;
1356 __nis_mapping_format_t *out;
1357 bool_t got_end;
1359 i = 0;
1360 while (in[i].type != mmt_end)
1361 i++;
1362 out = (__nis_mapping_format_t *)s_calloc(
1363 i + 1, sizeof (__nis_mapping_format_t));
1364 if (out != NULL) {
1365 got_end = FALSE;
1366 for (i = 0; !got_end; i++) {
1367 switch (in[i].type) {
1368 case mmt_item:
1369 break;
1370 case mmt_string:
1371 out[i].match.string =
1372 s_strdup(in[i].match.string);
1373 break;
1374 case mmt_single:
1375 out[i].match.single.numRange =
1376 in[i].match.single.numRange;
1377 out[i].match.single.lo =
1378 s_malloc(in[i].match.single.numRange);
1379 if (out[i].match.single.lo == NULL)
1380 break;
1381 out[i].match.single.hi =
1382 s_malloc(in[i].match.single.numRange);
1383 if (out[i].match.single.hi == NULL)
1384 break;
1385 memcpy(out[i].match.single.lo,
1386 in[i].match.single.lo,
1387 in[i].match.single.numRange);
1388 memcpy(out[i].match.single.hi,
1389 in[i].match.single.hi,
1390 in[i].match.single.numRange);
1391 break;
1392 case mmt_limit:
1393 out[i].match.limit = in[i].match.limit;
1394 break;
1395 case mmt_any:
1396 break;
1397 case mmt_berstring:
1398 out[i].match.berString =
1399 s_strdup(in[i].match.berString);
1400 break;
1401 case mmt_begin:
1402 break;
1403 case mmt_end:
1404 got_end = TRUE;
1405 break;
1406 default:
1407 p_error = parse_internal_error;
1409 if (p_error != no_parse_error)
1410 break;
1411 out[i].type = in[i].type;
1413 if (p_error != no_parse_error) {
1414 free_mapping_format(out);
1415 out = NULL;
1419 return (out);
1422 bool_t
1423 dup_mapping_sub_element(
1424 __nis_mapping_sub_element_t *in,
1425 __nis_mapping_sub_element_t *out)
1427 bool_t ret = FALSE;
1428 int i;
1430 switch (in->type) {
1431 case me_item:
1432 ret = dup_mapping_item(&in->element.item,
1433 &out->element.item);
1434 break;
1435 case me_print:
1436 out->element.print.fmt =
1437 dup_format_mapping(in->element.print.fmt);
1438 if (out->element.print.fmt == NULL)
1439 break;
1440 out->element.print.numItems =
1441 in->element.print.numItems;
1442 out->element.print.item = (__nis_mapping_item_t *)
1443 s_calloc(in->element.print.numItems,
1444 sizeof (__nis_mapping_item_t));
1445 if (out->element.print.item == NULL)
1446 break;
1447 for (i = 0; i < in->element.print.numItems; i++)
1448 if (!dup_mapping_item(
1449 &in->element.print.item[i],
1450 &out->element.print.item[i]))
1451 break;
1452 if (i < in->element.print.numItems)
1453 break;
1454 ret = TRUE;
1455 out->element.print.doElide = in->element.print.doElide;
1456 out->element.print.elide = in->element.print.elide;
1457 break;
1458 case me_split:
1459 ret = dup_mapping_item(&in->element.split.item,
1460 &out->element.split.item);
1461 out->element.split.delim = in->element.split.delim;
1462 break;
1463 case me_extract:
1464 out->element.extract.fmt =
1465 dup_format_mapping(in->element.extract.fmt);
1466 if (out->element.extract.fmt == NULL)
1467 break;
1468 ret = dup_mapping_item(&in->element.extract.item,
1469 &out->element.extract.item);
1470 break;
1471 default:
1472 p_error = parse_internal_error;
1474 out->type = in->type;
1476 return (ret);
1479 bool_t
1480 dup_mapping_element(
1481 __nis_mapping_element_t *in,
1482 __nis_mapping_element_t *out)
1484 bool_t ret = FALSE;
1485 int i;
1487 if (in == NULL)
1488 return (ret);
1490 switch (in->type) {
1491 case me_item:
1492 ret = dup_mapping_item(&in->element.item,
1493 &out->element.item);
1494 break;
1495 case me_print:
1496 out->element.print.fmt =
1497 dup_format_mapping(in->element.print.fmt);
1498 if (out->element.print.fmt == NULL)
1499 break;
1500 out->element.print.numSubElements =
1501 in->element.print.numSubElements;
1502 out->element.print.subElement =
1503 (__nis_mapping_sub_element_t *)
1504 s_calloc(in->element.print.numSubElements,
1505 sizeof (__nis_mapping_sub_element_t));
1506 if (out->element.print.subElement == NULL)
1507 break;
1508 for (i = 0; i < in->element.print.numSubElements; i++)
1509 if (!dup_mapping_sub_element(
1510 &in->element.print.subElement[i],
1511 &out->element.print.subElement[i]))
1512 break;
1513 if (i < in->element.print.numSubElements)
1514 break;
1515 ret = TRUE;
1516 out->element.print.doElide = in->element.print.doElide;
1517 out->element.print.elide = in->element.print.elide;
1518 break;
1519 case me_split:
1520 ret = dup_mapping_item(&in->element.split.item,
1521 &out->element.split.item);
1522 out->element.split.delim = in->element.split.delim;
1523 break;
1524 case me_match:
1525 out->element.match.fmt =
1526 dup_format_mapping(in->element.match.fmt);
1527 if (out->element.match.fmt == NULL)
1528 break;
1529 out->element.match.numItems =
1530 in->element.match.numItems;
1531 out->element.match.item = (__nis_mapping_item_t *)
1532 s_calloc(in->element.match.numItems,
1533 sizeof (__nis_mapping_item_t));
1534 if (out->element.match.item == NULL)
1535 break;
1536 for (i = 0; i < in->element.match.numItems; i++)
1537 if (!dup_mapping_item(
1538 &in->element.match.item[i],
1539 &out->element.match.item[i]))
1540 break;
1541 if (i < in->element.match.numItems)
1542 break;
1543 ret = TRUE;
1544 break;
1545 case me_extract:
1546 out->element.extract.fmt =
1547 dup_format_mapping(in->element.extract.fmt);
1548 if (out->element.extract.fmt == NULL)
1549 break;
1550 ret = dup_mapping_item(&in->element.extract.item,
1551 &out->element.extract.item);
1552 break;
1553 default:
1554 p_error = parse_internal_error;
1556 out->type = in->type;
1558 return (ret);
1561 __nis_mapping_rule_t *
1562 dup_mapping_rule(__nis_mapping_rule_t *in)
1564 int i;
1565 __nis_mapping_rlhs_t *r_in;
1566 __nis_mapping_rlhs_t *r_out;
1567 __nis_mapping_rule_t *out;
1569 out = (__nis_mapping_rule_t *)
1570 s_calloc(1, sizeof (__nis_mapping_rule_t));
1571 if (out != NULL) {
1572 r_in = &in->lhs;
1573 r_out = &out->lhs;
1574 r_out->numElements = r_in->numElements;
1575 r_out->element = (__nis_mapping_element_t *)s_calloc
1576 (r_in->numElements, sizeof (__nis_mapping_element_t));
1577 if (r_out->element == NULL) {
1578 free_mapping_rule(out);
1579 return (NULL);
1581 for (i = 0; i < r_in->numElements; i++) {
1582 if (!dup_mapping_element(&r_in->element[i],
1583 &r_out->element[i]))
1584 break;
1586 if (i < r_in->numElements) {
1587 free_mapping_rule(out);
1588 return (NULL);
1591 r_in = &in->rhs;
1592 r_out = &out->rhs;
1593 r_out->numElements = r_in->numElements;
1594 r_out->element = (__nis_mapping_element_t *)s_calloc
1595 (r_in->numElements, sizeof (__nis_mapping_element_t));
1596 if (r_out->element == NULL) {
1597 free_mapping_rule(out);
1598 return (NULL);
1600 for (i = 0; i < r_in->numElements; i++) {
1601 if (!dup_mapping_element(&r_in->element[i],
1602 &r_out->element[i]))
1603 break;
1605 if (i < r_in->numElements) {
1606 free_mapping_rule(out);
1607 return (NULL);
1610 return (out);
1613 __nis_mapping_rule_t **
1614 dup_mapping_rules(__nis_mapping_rule_t **rules, int n_rules)
1616 int i, j;
1617 __nis_mapping_rule_t **r;
1619 r = (__nis_mapping_rule_t **)s_calloc(n_rules,
1620 sizeof (__nis_mapping_rule_t *));
1621 if (r != NULL) {
1622 for (i = 0; i < n_rules; i++) {
1623 r[i] = dup_mapping_rule(rules[i]);
1624 if (r[i] == NULL) {
1625 for (j = 0; j < i; j++)
1626 free_mapping_rule(r[j]);
1627 free(r);
1628 r = NULL;
1629 break;
1633 return (r);
1637 * FUNCTION: add_column
1639 * Adds a column name to the column list in __nis_table_mapping_t
1641 * RETURN VALUE: FALSE if error
1642 * TRUE if __nis_index_t returned
1644 * INPUT: the __nis_table_mapping_t and column name
1647 bool_t
1648 add_column(__nis_table_mapping_t *t, const char *col_name)
1650 int i;
1651 char **cols = NULL;
1653 if (!yp2ldap) {
1654 for (i = 0; i < t->numColumns; i++) {
1655 if (strcasecmp(col_name, t->column[i]) == 0)
1656 return (TRUE);
1659 cols = (char **)s_realloc(t->column, (t->numColumns + 1) *
1660 sizeof (char *));
1661 if (cols == NULL)
1662 return (FALSE);
1663 t->column = cols;
1664 cols[t->numColumns] = s_strdup(col_name);
1665 if (cols[t->numColumns] == NULL)
1666 return (FALSE);
1667 t->numColumns++;
1668 return (TRUE);
1672 * FUNCTION: add_element
1674 * Adds a __nis_mapping_element_t to __nis_mapping_rlhs_t
1676 * RETURN VALUE: FALSE if error
1677 * TRUE if __nis_index_t returned
1679 * INPUT: the __nis_mapping_element_t and
1680 * __nis_mapping_rlhs_t
1683 bool_t
1684 add_element(
1685 __nis_mapping_element_t *e,
1686 __nis_mapping_rlhs_t *m)
1688 __nis_mapping_element_t *e1;
1689 int i;
1690 int n = m->numElements;
1692 e1 = (__nis_mapping_element_t *)s_realloc(m->element,
1693 (n + 1) * sizeof (__nis_mapping_element_t));
1694 if (e1 == NULL) {
1695 e1 = m->element;
1696 for (i = 0; i < n; i++)
1697 free_mapping_element(e1++);
1698 free(m->element);
1699 m->element = NULL;
1700 m->numElements = 0;
1701 } else {
1702 e1[m->numElements++] = *e;
1703 free(e);
1704 m->element = (__nis_mapping_element_t *)e1;
1706 return (e1 != NULL);
1710 * FUNCTION: get_next_object_dn_token
1712 * Get the next token in parsing object_dn
1714 * RETURN VALUE: NULL if error
1715 * position of beginning next token after
1716 * token
1718 * INPUT: the attribute value
1721 const char *
1722 get_next_object_dn_token(
1723 const char **begin_ret,
1724 const char **end_ret,
1725 object_dn_token *token)
1727 object_dn_token t = dn_no_token;
1728 const char *s = *begin_ret;
1729 const char *begin;
1730 const char *end = *end_ret;
1731 const char *s1;
1732 bool_t in_quotes;
1734 while (s < end && is_whitespace(*s))
1735 s++;
1736 if (s >= end) {
1737 /* EMPTY */
1738 } else if (*s == SEMI_COLON_CHAR) {
1739 t = dn_semi_token;
1740 s++;
1741 } else if (*s == QUESTION_MARK) {
1742 t = dn_ques_token;
1743 s++;
1744 } else if (*s == COLON_CHAR) {
1745 t = dn_colon_token;
1746 s++;
1747 } else if (*s == OPEN_PAREN_CHAR) {
1748 begin = s;
1749 s = get_ldap_filter(&begin, &end);
1750 if (s != NULL) {
1751 t = dn_text_token;
1752 *begin_ret = begin;
1753 *end_ret = end;
1755 } else {
1756 begin = s;
1757 in_quotes = FALSE;
1758 while (s < end) {
1759 if (*s == ESCAPE_CHAR) {
1760 if (s + 2 > end) {
1761 p_error = parse_unmatched_escape;
1762 s = NULL;
1763 break;
1765 s++;
1766 } else if (*s == DOUBLE_QUOTE_CHAR) {
1767 in_quotes = ! in_quotes;
1768 } else if (in_quotes)
1770 else if (*s == SEMI_COLON_CHAR ||
1771 *s == QUESTION_MARK ||
1772 *s == COLON_CHAR)
1773 break;
1774 s++;
1776 if (s != NULL) {
1777 s1 = s - 1;
1778 while (is_whitespace(*s1))
1779 s1--;
1780 s1++;
1781 if (same_string("base", begin, s1 - begin))
1782 t = dn_base_token;
1783 else if (same_string("one", begin, s1 - begin))
1784 t = dn_one_token;
1785 else if (same_string("sub", begin, s1 - begin))
1786 t = dn_sub_token;
1787 else
1788 t = dn_text_token;
1789 *begin_ret = begin;
1790 *end_ret = s1;
1793 *token = t;
1794 return (s);
1798 * FUNCTION: get_next_token
1800 * Get the next token in parsing mapping attribute
1802 * RETURN VALUE: NULL if error
1803 * position of beginning next token after
1804 * token
1806 * INPUT: the attribute value
1809 const char *
1810 get_next_token(const char **begin_token, const char **end_token, token_type *t)
1812 const char *s = *begin_token;
1813 const char *end_s = *end_token;
1814 const char *s_begin;
1816 while (s < end_s && is_whitespace(*s))
1817 s++;
1818 if (s == end_s) {
1819 *t = no_token;
1820 return (s);
1823 s_begin = s;
1825 if (*s == OPEN_PAREN_CHAR) {
1826 *begin_token = s;
1827 s++;
1828 *end_token = s;
1829 while (s < end_s && is_whitespace(*s))
1830 s++;
1831 *t = open_paren_token;
1832 } else if (*s == DOUBLE_QUOTE_CHAR) {
1833 s++;
1834 while (s < end_s) {
1835 if (*s == ESCAPE_CHAR)
1836 s += 2;
1837 else if (*s == DOUBLE_QUOTE_CHAR)
1838 break;
1839 else
1840 s++;
1842 if (s >= end_s) {
1843 p_error = parse_unmatched_escape;
1844 return (NULL);
1847 *t = quoted_string_token;
1848 *begin_token = s_begin + 1;
1849 *end_token = s++;
1850 } else if (*s == EQUAL_CHAR || *s == COMMA_CHAR ||
1851 *s == CLOSE_PAREN_CHAR || *s == COLON_CHAR) {
1852 if (*s == EQUAL_CHAR)
1853 *t = equal_token;
1854 else if (*s == COMMA_CHAR)
1855 *t = comma_token;
1856 else if (*s == CLOSE_PAREN_CHAR)
1857 *t = close_paren_token;
1858 else
1859 *t = colon_token;
1860 *begin_token = s;
1861 *end_token = ++s;
1862 } else {
1863 s_begin = s;
1864 while (s < end_s && !is_whitespace(*s)) {
1865 if (*s == ESCAPE_CHAR)
1866 s += 2;
1867 else if (*s == EQUAL_CHAR || *s == CLOSE_PAREN_CHAR ||
1868 *s == OPEN_PAREN_CHAR || *s == COMMA_CHAR ||
1869 *s == COLON_CHAR || *s == OPEN_BRACKET ||
1870 *s == CLOSE_BRACKET)
1871 break;
1872 else
1873 s++;
1875 if (s > end_s) {
1876 p_error = parse_unmatched_escape;
1877 return (NULL);
1879 *t = string_token;
1880 *end_token = s;
1881 *begin_token = s_begin;
1883 if (s) {
1884 while (s < end_s && is_whitespace(*s))
1885 s++;
1887 return (s);
1891 * FUNCTION: skip_token
1893 * Skip over the specified token - An error is set if
1894 * next token does not match expected token
1896 * RETURN VALUE: NULL if error
1897 * position of beginning next token after
1898 * token
1900 * INPUT: the attribute value
1903 const char *
1904 skip_token(const char *s, const char *end_s, token_type t)
1906 bool_t match;
1907 char c = 0;
1909 if (s == NULL)
1910 return (s);
1911 while (s < end_s && is_whitespace(*s))
1912 s++;
1913 c = (s == end_s) ? 0 : *s;
1914 switch (t) {
1915 case equal_token:
1916 match = c == EQUAL_CHAR;
1917 if (!match)
1918 p_error = parse_equal_expected_error;
1919 break;
1920 case comma_token:
1921 match = c == COMMA_CHAR;
1922 if (!match)
1923 p_error = parse_comma_expected_error;
1924 break;
1925 case close_paren_token:
1926 match = c == CLOSE_PAREN_CHAR;
1927 if (!match)
1928 p_error = parse_close_paren_expected_error;
1929 break;
1930 default:
1931 match = FALSE;
1932 break;
1934 if (match) {
1935 s++;
1936 while (s < end_s && is_whitespace(*s))
1937 s++;
1938 } else {
1939 s = NULL;
1941 return (s);
1945 * FUNCTION: get_next_extract_format_item
1947 * Get the next format token from the string. Note that
1948 * get_next_extract_format_item may change the input string.
1950 * RETURN VALUE: NULL if error
1951 * position of beginning next token after
1952 * token
1954 * INPUT: the format string
1957 const char *
1958 get_next_extract_format_item(
1959 const char *begin_fmt,
1960 const char *end_fmt,
1961 __nis_mapping_format_t *fmt)
1963 const char *s = begin_fmt;
1964 const char *s_end = end_fmt;
1965 bool_t escape;
1966 bool_t in_range;
1967 bool_t got_char;
1968 bool_t done;
1969 int numRange;
1970 char *lo = NULL;
1971 char *hi = NULL;
1972 bool_t skip_ber;
1974 for (; p_error == no_parse_error; ) {
1975 if (s >= s_end)
1976 break;
1978 if (*s == PERCENT_SIGN) {
1979 s++;
1981 * If the format is %s, it is interpreted
1982 * as a string.
1984 if (s >= s_end) {
1985 p_error = parse_unsupported_format;
1986 break;
1988 skip_ber = FALSE;
1989 switch (*s) {
1990 case 's':
1991 fmt->type = mmt_item;
1992 break;
1993 case 'n': /* null */
1994 case 'x': /* skip the next element */
1995 skip_ber = TRUE;
1996 /* FALLTHRU */
1997 case 'b': /* boolean */
1998 case 'e': /* enumerated */
1999 case 'i': /* int */
2000 case 'o': /* octet string */
2001 case 'B': /* bit string */
2002 fmt->match.berString = s_strndup(s, 1);
2003 fmt->type = skip_ber ?
2004 mmt_berstring_null :
2005 mmt_berstring;
2006 break;
2007 case 'a': /* octet string */
2008 if (yp2ldap) {
2009 fmt->match.berString =
2010 s_strndup(s, 1);
2011 fmt->type = skip_ber ?
2012 mmt_berstring_null :
2013 mmt_berstring;
2014 break;
2015 } /* else FALLTHRU */
2016 case '{': /* begin sequence */
2017 case '[': /* begin set */
2018 case '}': /* end sequence */
2019 case ']': /* end set */
2020 case 'l': /* length of next item */
2021 case 'O': /* octet string */
2022 case 't': /* tag of next item */
2023 case 'T': /* skip tag of next item */
2024 case 'v': /* seq of strings */
2025 case 'V': /* seq of strings + lengths */
2026 default:
2027 p_error = parse_bad_ber_format;
2028 break;
2030 s++;
2031 } else if (*s == ASTERIX_CHAR) {
2032 fmt->type = mmt_any;
2033 s++;
2034 while (s < s_end && *s == ASTERIX_CHAR)
2035 s++;
2037 } else if (*s == OPEN_BRACKET) {
2038 escape = FALSE;
2039 in_range = FALSE;
2040 got_char = FALSE;
2041 numRange = 0;
2042 done = FALSE;
2043 s++;
2044 for (; s < s_end; s++) {
2045 if (escape) {
2046 escape = FALSE;
2047 } else if (*s == DASH_CHAR) {
2048 if (in_range || !got_char) {
2049 p_error = parse_unexpected_dash;
2050 break;
2052 in_range = TRUE;
2053 got_char = FALSE;
2054 continue;
2055 } else if (*s == CLOSE_BRACKET) {
2056 if (in_range) {
2057 p_error = parse_unexpected_dash;
2059 done = TRUE;
2060 break;
2061 } else if (*s == ESCAPE_CHAR) {
2062 escape = TRUE;
2063 continue;
2065 if (in_range) {
2066 hi[numRange - 1] = *s;
2067 in_range = FALSE;
2068 } else {
2069 lo = s_realloc(lo, numRange + 1);
2070 hi = s_realloc(hi, numRange + 1);
2071 if (lo == NULL || hi == NULL)
2072 break;
2073 lo[numRange] = *s;
2074 hi[numRange] = *s;
2075 numRange++;
2076 got_char = TRUE;
2079 if (p_error != no_parse_error) {
2080 break;
2081 } else if (!done) {
2082 p_error = parse_mismatched_brackets;
2083 break;
2085 s++;
2086 fmt->type = mmt_single;
2087 fmt->match.single.numRange = numRange;
2088 fmt->match.single.lo = (unsigned char *)lo;
2089 fmt->match.single.hi = (unsigned char *)hi;
2090 } else {
2091 /* go to next key symbol - copy escaped key symbols */
2092 escape = FALSE;
2093 done = FALSE;
2094 while (s < s_end) {
2095 if (escape)
2096 escape = FALSE;
2097 else {
2098 switch (*s) {
2099 case OPEN_BRACKET:
2100 case ASTERIX_CHAR:
2101 case PERCENT_SIGN:
2102 done = TRUE;
2103 break;
2104 case ESCAPE_CHAR:
2105 escape = !escape;
2106 break;
2107 default:
2108 break;
2111 if (done)
2112 break;
2113 s++;
2115 if (escape) {
2116 p_error = parse_unmatched_escape;
2117 break;
2119 fmt->type = mmt_string;
2120 fmt->match.string =
2121 s_strndup_esc(begin_fmt, s - begin_fmt);
2122 if (fmt->match.string == NULL)
2123 break;
2126 if (p_error == no_parse_error)
2127 return (s);
2129 free(lo);
2130 free(hi);
2131 return (NULL);
2135 * FUNCTION: get_next_print_format_item
2137 * Get the next format token from the string
2139 * RETURN VALUE: NULL if error
2140 * position of beginning next token after
2141 * token
2143 * INPUT: the format string
2146 const char *
2147 get_next_print_format_item(
2148 const char *begin_fmt,
2149 const char *end_fmt,
2150 __nis_mapping_format_t *fmt)
2152 const char *s = begin_fmt;
2153 const char *s_end = end_fmt;
2154 bool_t skip_ber;
2156 for (; p_error == no_parse_error; ) {
2157 if (s >= s_end) {
2158 p_error = parse_internal_error;
2159 break;
2162 if (*s == PERCENT_SIGN) {
2163 s++;
2164 if (s >= s_end) {
2165 p_error = parse_unsupported_format;
2166 break;
2168 skip_ber = FALSE;
2170 * If the format is %s, it is interpretted
2171 * as a string.
2173 switch (*s) {
2174 case 's':
2175 fmt->type = mmt_item;
2176 break;
2177 case 'n': /* null */
2178 case 'x': /* skip the next element */
2179 skip_ber = TRUE;
2180 /* FALLTHRU */
2181 case 'b': /* boolean */
2182 case 'e': /* enumerated */
2183 case 'i': /* int */
2184 case 'o': /* octet string */
2185 case 'B': /* bit string */
2186 fmt->match.berString = s_strndup(s, 1);
2187 fmt->type = skip_ber ?
2188 mmt_berstring_null :
2189 mmt_berstring;
2190 break;
2191 case '{': /* begin sequence */
2192 case '[': /* begin set */
2193 case '}': /* end sequence */
2194 case ']': /* end set */
2195 case 'a': /* octet string */
2196 case 'l': /* length of next item */
2197 case 'O': /* octet string */
2198 case 't': /* tag of next item */
2199 case 'T': /* skip tag of next item */
2200 case 'v': /* seq of strings */
2201 case 'V': /* seq of strings + lengths */
2202 default:
2203 p_error = parse_bad_ber_format;
2204 break;
2206 s++;
2207 } else {
2208 while (s < s_end) {
2209 if (*s == PERCENT_SIGN)
2210 break;
2211 else if (*s == ESCAPE_CHAR)
2212 s++;
2213 s++;
2215 if (s > s_end) {
2216 p_error = parse_unmatched_escape;
2217 break;
2219 fmt->match.string =
2220 s_strndup_esc(begin_fmt, s - begin_fmt);
2221 if (fmt->match.string == NULL)
2222 break;
2223 fmt->type = mmt_string;
2225 if (p_error == no_parse_error)
2226 return (s);
2228 return (NULL);
2232 * FUNCTION: get_ldap_filter
2234 * Gets an LDAP filter - see RFC 2254. Note that this does not
2235 * determine if the ldap filter is valid. This only determines
2236 * that the parentheses are balanced.
2238 * RETURN VALUE: NULL if error
2239 * position of beginning next token after
2240 * filter
2242 * INPUT: the begin and end of string
2244 * OUTPUT: the begin and end of LDAP filter
2248 const char *
2249 get_ldap_filter(const char **begin, const char **end)
2251 const char *s = *begin;
2252 const char *s_begin;
2253 const char *s_end = *end;
2254 int nParen;
2256 for (; p_error == no_parse_error; ) {
2257 while (s < s_end && is_whitespace(*s))
2258 s++;
2259 if (s == s_end) {
2260 s = NULL;
2261 break;
2264 s_begin = s;
2265 if (*s == OPEN_PAREN_CHAR) {
2266 nParen = 1;
2267 s++;
2268 while (s < s_end && nParen > 0) {
2269 if (*s == ESCAPE_CHAR)
2270 s++;
2271 else if (*s == OPEN_PAREN_CHAR)
2272 nParen++;
2273 else if (*s == CLOSE_PAREN_CHAR)
2274 nParen--;
2275 s++;
2277 if (nParen == 0) {
2278 *begin = s_begin;
2279 *end = s;
2280 while (s < s_end && is_whitespace(*s))
2281 s++;
2282 } else
2283 s = NULL;
2284 } else
2285 s = NULL;
2286 if (p_error == no_parse_error)
2287 break;
2289 if (s == NULL)
2290 p_error = parse_invalid_ldap_search_filter;
2292 return (s);
2296 * FUNCTION: get_ava_list
2298 * Gets an attribute value assertion list
2300 * RETURN VALUE: NULL if error
2301 * position of beginning next token after
2302 * after attribute assertion
2304 * INPUT: the begin and end of string
2305 * Indicator if ava list is part of a nisplus
2306 * item
2308 * OUTPUT: the begin and end of LDAP filter
2312 const char *
2313 get_ava_list(const char **begin, const char **end, bool_t end_nisplus)
2315 const char *s = *begin;
2316 const char *s_begin;
2317 const char *s_end = *end;
2318 bool_t in_quote;
2319 bool_t got_equal;
2320 bool_t got_data;
2322 for (; p_error == no_parse_error; ) {
2323 while (s < s_end && is_whitespace(*s))
2324 s++;
2325 if (s == s_end) {
2326 s = NULL;
2327 break;
2330 in_quote = FALSE;
2331 got_equal = FALSE;
2332 got_data = FALSE;
2333 s_begin = s;
2334 while (s < s_end) {
2335 if (*s == ESCAPE_CHAR) {
2336 s++;
2337 got_data = TRUE;
2338 } else if (*s == DOUBLE_QUOTE_CHAR) {
2339 in_quote = !in_quote;
2340 got_data = TRUE;
2341 } else if (in_quote)
2343 else if (*s == EQUAL_CHAR) {
2344 if (end_nisplus && got_data && got_equal)
2345 break;
2346 if (!got_data || got_equal) {
2347 got_equal = FALSE;
2348 break;
2350 got_equal = TRUE;
2351 got_data = FALSE;
2352 } else if (*s == COMMA_CHAR) {
2353 if (!got_data || !got_equal)
2354 break;
2355 got_data = FALSE;
2356 got_equal = FALSE;
2357 } else if (is_whitespace(*s))
2359 else
2360 got_data = TRUE;
2361 s++;
2363 if (!got_data || !got_equal || in_quote)
2364 s = NULL;
2365 else {
2366 *begin = s_begin;
2367 *end = s;
2368 while (s < s_end && is_whitespace(*s))
2369 s++;
2371 if (p_error == no_parse_error)
2372 break;
2374 if (s == NULL)
2375 p_error = parse_invalid_ldap_search_filter;
2377 return (s);
2380 /* Utility functions */
2381 bool_t
2382 validate_dn(const char *s, int len)
2384 const char *end = s + len;
2385 bool_t valid;
2387 valid = skip_get_dn(s, end) == end;
2389 if (!valid)
2390 p_error = parse_bad_dn;
2391 return (valid);
2394 bool_t
2395 validate_ldap_filter(const char *s, const char *end)
2397 const char *s_begin;
2398 const char *s_end;
2400 s_begin = s;
2401 s_end = end;
2403 if (*s == OPEN_PAREN_CHAR) {
2404 s = get_ldap_filter(&s_begin, &s_end);
2405 } else {
2406 /* Assume an attribute value list */
2407 s = get_ava_list(&s_begin, &s_end, FALSE);
2409 if (s == NULL || s_end != end)
2410 p_error = parse_invalid_ldap_search_filter;
2412 return (p_error == no_parse_error);
2415 char *
2416 s_strndup(const char *s, int n)
2418 char *d = (char *)malloc(n + 1);
2420 if (d != NULL) {
2421 (void) memcpy(d, s, n);
2422 d[n] = '\0';
2423 } else {
2424 p_error = parse_no_mem_error;
2427 return (d);
2430 char *
2431 s_strndup_esc(const char *s, int n)
2433 char *d = (char *)malloc(n + 1);
2434 int i;
2435 int j;
2437 if (d != NULL) {
2438 for (i = 0, j = 0; i < n; i++) {
2439 if (s[i] == ESCAPE_CHAR)
2440 i++;
2441 d[j++] = s[i];
2443 d[j] = '\0';
2444 } else {
2445 p_error = parse_no_mem_error;
2448 return (d);
2451 void *
2452 s_calloc(size_t n, size_t size)
2454 void *d = (char *)calloc(n, size);
2456 if (d == NULL) {
2457 p_error = parse_no_mem_error;
2460 return (d);
2463 void *
2464 s_malloc(size_t size)
2466 void *d = malloc(size);
2467 if (d == NULL)
2468 p_error = parse_no_mem_error;
2469 return (d);
2472 void *
2473 s_realloc(void *s, size_t size)
2475 s = realloc(s, size);
2476 if (s == NULL)
2477 p_error = parse_no_mem_error;
2478 return (s);
2481 char *
2482 s_strdup(const char *s)
2484 return (s != NULL ? s_strndup(s, strlen(s)) : NULL);
2487 bool_t
2488 is_whitespace(int c)
2490 return (c == ' ' || c == '\t');
2493 bool_t
2494 is_string_ok(char *buffer, int buflen)
2496 int i;
2498 if (buffer == NULL)
2499 return (FALSE);
2501 for (i = 0; i < buflen; i++) {
2502 if (!is_whitespace(buffer[i])) {
2503 if (buffer[i] == POUND_SIGN)
2504 return (TRUE);
2505 else
2506 return (FALSE);
2509 return (TRUE);
2513 * Returns true if the first string is contained at the beginning of the
2514 * second string. Otherwise returns false.
2517 bool_t
2518 contains_string(const char *s1, const char *s2)
2520 return (strncasecmp(s1, s2, strlen(s1)) == 0);
2524 * Returns the next character position in the second string, if the first
2525 * string is contained at the beginning of the second string. Otherwise
2526 * returns NULL.
2529 const char *
2530 skip_string(const char *s1, const char *s2, int len)
2532 int len1 = strlen(s1);
2534 if (len >= len1 && strncasecmp(s1, s2, strlen(s1)) == 0)
2535 return (s2 + len1);
2536 else
2537 return (NULL);
2541 * The second string is not necessarily null terminated.
2542 * same_string returns true if the second string matches the first.
2543 * Otherwise returns false.
2546 bool_t
2547 same_string(const char *s1, const char *s2, int len)
2549 int len1 = strlen(s1);
2551 return (len1 == len && strncasecmp(s1, s2, len1) == 0);
2554 void
2555 report_error(const char *str, const char *attr)
2557 char fmt_buf[1024];
2558 int pos = 0;
2560 if (command_line_source != NULL) {
2561 snprintf(fmt_buf, sizeof (fmt_buf), "Error parsing %s: ",
2562 command_line_source);
2563 pos = strlen(fmt_buf);
2564 } else if (file_source != NULL) {
2565 snprintf(fmt_buf, sizeof (fmt_buf), "Error parsing file '%s': ",
2566 file_source);
2567 pos = strlen(fmt_buf);
2568 } else if (ldap_source != NULL) {
2569 snprintf(fmt_buf, sizeof (fmt_buf), "Error for LDAP dn '%s': ",
2570 ldap_source);
2571 pos = strlen(fmt_buf);
2574 if (start_line_num != 0) {
2575 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "at line %d: ",
2576 start_line_num);
2577 pos += strlen(fmt_buf + pos);
2580 if (attr != NULL) {
2581 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos,
2582 "for attribute %s: ", attr);
2583 pos += strlen(fmt_buf + pos);
2586 if (cons != NULL) {
2587 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "%s\n",
2588 parse_error_msg[p_error]);
2589 fprintf(cons, fmt_buf, str == NULL ? "" : str);
2590 } else {
2591 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "%s",
2592 parse_error_msg[p_error]);
2593 syslog(LOG_ERR, fmt_buf, str == NULL ? "" : str);
2597 void
2598 report_error2(
2599 const char *str1,
2600 const char *str2)
2602 char fmt_buf[1024];
2604 if (cons != NULL) {
2605 snprintf(fmt_buf, sizeof (fmt_buf),
2606 "%s\n", parse_error_msg[p_error]);
2607 fprintf(cons, fmt_buf, str1, str2);
2608 } else {
2609 syslog(LOG_ERR, parse_error_msg[p_error], str1, str2);
2613 void
2614 report_conn_error(
2615 conn_error e,
2616 const char *str1,
2617 const char *str2)
2619 char fmt_buf[1024];
2621 if (cons != NULL) {
2622 snprintf(fmt_buf, sizeof (fmt_buf),
2623 "%s\n", conn_error_msg[e]);
2624 fprintf(cons, fmt_buf,
2625 str1 == NULL ? "" : str1,
2626 str2 == NULL ? "" : str2);
2627 } else {
2628 syslog(LOG_ERR,
2629 conn_error_msg[e],
2630 str1 == NULL ? "" : str1,
2631 str2 == NULL ? "" : str2);
2635 void
2636 report_info(
2637 const char *str,
2638 const char *arg)
2640 if (cons != NULL) {
2641 fputs(str, cons);
2642 if (arg != NULL)
2643 fputs(arg, cons);
2644 fputs("\n", cons);
2645 } else
2646 syslog(LOG_INFO, str, arg);