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