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