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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <string.h> 30 #include <stdlib.h> 31 #include <ctype.h> 32 #include <fcntl.h> 33 #include <unistd.h> 34 #include <errno.h> 35 #include <locale.h> 36 #include <sys/stat.h> 37 #include <lber.h> 38 #include <ldap.h> 39 #include <deflt.h> 40 41 #include "ldap_map.h" 42 43 #include "ldap_parse.h" 44 #include "ldap_glob.h" 45 #include "nis_parse_ldap_conf.h" 46 47 __nis_ldap_proxy_info proxyInfo = 48 {NULL, (auth_method_t)NO_VALUE_SET, (tls_method_t)NO_VALUE_SET, NULL, 49 NULL, NULL, NULL, NULL, (follow_referral_t)NO_VALUE_SET}; 50 __nis_config_t ldapConfig; 51 __nisdb_table_mapping_t ldapDBTableMapping; 52 __nis_table_mapping_t *ldapTableMapping = NULL; 53 __yp_domain_context_t ypDomains; 54 55 parse_error p_error = no_parse_error; 56 int cur_line_num = 0; 57 int start_line_num = 0; 58 int seq_num = 0; 59 const char *warn_file = NULL; 60 61 char _key_val[38]; 62 const char *command_line_source = NULL; 63 const char *file_source = NULL; 64 const char *ldap_source = NULL; 65 66 static 67 const char *const *cmdline_config = NULL; 68 static bool_t got_config_data = FALSE; 69 70 /* high level parsing functions functions */ 71 static int parse_ldap_cmd_line(const char *const *cmdline_options, 72 __nis_ldap_proxy_info *proxy_info, __nis_config_t *nis_config, 73 __nis_table_mapping_t **table_mapping, __nis_config_info_t *config_info, 74 __nisdb_table_mapping_t *table_info); 75 static int parse_ldap_default_conf(__nis_ldap_proxy_info *proxy_info, 76 __nis_config_t *nis_config, __nis_config_info_t *config_info, 77 __nisdb_table_mapping_t *table_info); 78 static int parse_ldap_config_file(const char *config_file, 79 __nis_ldap_proxy_info *proxy_info, __nis_config_t *nis_config, 80 __nis_table_mapping_t **table_mapping, __nis_config_info_t *config_info, 81 __nisdb_table_mapping_t *table_info); 82 static int parse_ldap_config_dn_attrs(__nis_ldap_proxy_info *proxy_info, 83 __nis_config_t *nis_config, __nis_table_mapping_t **table_mapping, 84 __nis_config_info_t *config_info, __nisdb_table_mapping_t *table_info); 85 static int yp_parse_ldap_default_conf(__nis_ldap_proxy_info *proxy_info, 86 __nis_config_t *nis_config, __nis_config_info_t *config_info, 87 __nisdb_table_mapping_t *table_info); 88 89 90 /* helper functions */ 91 static config_key get_attrib_num_cmdline(const char *s, 92 const char **begin_s, const char **end_s); 93 static config_key get_file_attr_val(int fd, char **attr_val); 94 static void get_attribute_list( 95 const __nis_ldap_proxy_info *proxy_info, 96 const __nis_config_t *nis_config, 97 const __nis_config_info_t *config_info, 98 const __nisdb_table_mapping_t *table_info, 99 char **ldap_config_attributes); 100 101 /* 102 * FUNCTION: parse_ldap_migration 103 * 104 * Parses the information for LDAP. The values are first 105 * obtained from the command line, secondly from the preference 106 * file, and finally from an LDAP profile (if so configured in 107 * the command line or preference file). Any unset values will 108 * be set to their default values. 109 * 110 * If no command line options, no settings in the /etc/default 111 * configuration file, and no mapping file, then no mapping 112 * should be used. 113 * 114 * RETURN VALUE: 115 * 0 Success 116 * -1 Config file stat/open or parse error 117 * 1 No mapping should be used. 118 * 119 * INPUT: command line parameters, configuration file 120 */ 121 122 int 123 parse_ldap_migration( 124 const char *const *cmdline_options, 125 const char *config_file) 126 { 127 int rc = 0; 128 __nis_config_info_t config_info 129 = {NULL, NULL, (auth_method_t)NO_VALUE_SET, 130 (tls_method_t)NO_VALUE_SET, NULL, 131 NULL, NULL}; 132 struct stat buf; 133 int i = 0; 134 135 p_error = no_parse_error; 136 137 if (verbose) 138 report_info("Getting LDAP configuration", NULL); 139 140 initialize_parse_structs(&proxyInfo, &ldapConfig, &ldapDBTableMapping); 141 142 if (yp2ldap) 143 initialize_yp_parse_structs(&ypDomains); 144 145 if (cmdline_options != NULL) { 146 got_config_data = TRUE; 147 /* NIS to LDAP does not read command line attributes */ 148 if (!yp2ldap) 149 rc = parse_ldap_cmd_line(cmdline_options, &proxyInfo, 150 &ldapConfig, &ldapTableMapping, &config_info, 151 &ldapDBTableMapping); 152 else 153 rc = 0; 154 } 155 156 if (rc == 0) { 157 if (yp2ldap) 158 rc = yp_parse_ldap_default_conf(&proxyInfo, &ldapConfig, 159 &config_info, &ldapDBTableMapping); 160 else 161 rc = parse_ldap_default_conf(&proxyInfo, &ldapConfig, 162 &config_info, &ldapDBTableMapping); 163 } 164 165 if (config_file == NULL) { 166 if (yp2ldap) { 167 if (stat(YP_DEFAULT_MAPPING_FILE, &buf) == 0) 168 config_file = YP_DEFAULT_MAPPING_FILE; 169 } else { 170 if (stat(DEFAULT_MAPPING_FILE, &buf) == 0) 171 config_file = DEFAULT_MAPPING_FILE; 172 } 173 } 174 175 if (rc == 0 && config_file != NULL) { 176 got_config_data = TRUE; 177 warn_file = config_file; 178 cmdline_config = cmdline_options; 179 if (yp2ldap) 180 rc = yp_parse_ldap_config_file(config_file, &proxyInfo, 181 &ldapConfig, &ldapTableMapping, &config_info, 182 &ldapDBTableMapping, &ypDomains); 183 else 184 rc = parse_ldap_config_file(config_file, &proxyInfo, 185 &ldapConfig, &ldapTableMapping, &config_info, 186 &ldapDBTableMapping); 187 188 warn_file = NULL; 189 cmdline_config = NULL; 190 } 191 if (rc == 0 && (config_info.config_dn != NULL) && 192 (config_info.config_dn[0] != '\0')) { 193 rc = parse_ldap_config_dn_attrs(&proxyInfo, 194 &ldapConfig, &ldapTableMapping, &config_info, 195 &ldapDBTableMapping); 196 } 197 198 free_config_info(&config_info); 199 200 if (rc == 0 && got_config_data == FALSE) 201 rc = 1; 202 203 set_default_values(&proxyInfo, &ldapConfig, &ldapDBTableMapping); 204 205 if (yp2ldap == 1 && rc == 0) { 206 rc = second_parser_pass(&ldapTableMapping); 207 if (rc == 0) 208 rc = final_parser_pass(&ldapTableMapping, &ypDomains); 209 if (rc == -2) 210 return (-1); 211 } 212 213 if (rc == 0) 214 rc = finish_parse(&proxyInfo, &ldapTableMapping); 215 216 if (rc == 0) 217 rc = linked2hash(ldapTableMapping); 218 219 if ((rc == 0) && yptol_mode) 220 rc = map_id_list_init(); 221 222 if (rc != 0) { 223 free_parse_structs(); 224 } else if (verbose) 225 report_info("LDAP configuration complete", NULL); 226 return (rc); 227 } 228 229 /* 230 * FUNCTION: parse_ldap_cmd_line 231 * 232 * Parses the information for LDAP from the command line 233 * 234 * RETURN VALUE: 0 on success, -1 on failure 235 * 236 * INPUT: command line values 237 */ 238 239 static int 240 parse_ldap_cmd_line( 241 const char *const *cmdline_options, 242 __nis_ldap_proxy_info *proxy_info, 243 __nis_config_t *nis_config, 244 __nis_table_mapping_t **table_mapping, 245 __nis_config_info_t *config_info, 246 __nisdb_table_mapping_t *table_info) 247 { 248 int rc = 0; 249 config_key attrib_num; 250 const char *begin_s; 251 const char *end_s; 252 253 if (verbose) 254 report_info("Command line values: ", NULL); 255 while (*cmdline_options != NULL) { 256 if (verbose) 257 report_info("\t", *cmdline_options); 258 259 attrib_num = get_attrib_num_cmdline( 260 *cmdline_options, &begin_s, &end_s); 261 if (attrib_num == key_bad) { 262 command_line_source = "command line"; 263 report_error(*cmdline_options, NULL); 264 command_line_source = NULL; 265 rc = -1; 266 break; 267 } else if (IS_CONFIG_KEYWORD(attrib_num)) { 268 rc = add_config_attribute(attrib_num, 269 begin_s, end_s - begin_s, config_info); 270 } else if (IS_BIND_INFO(attrib_num)) { 271 rc = add_bind_attribute(attrib_num, 272 begin_s, end_s - begin_s, proxy_info); 273 } else if (IS_OPER_INFO(attrib_num)) { 274 rc = add_operation_attribute(attrib_num, 275 begin_s, end_s - begin_s, nis_config, 276 table_info); 277 } else { 278 rc = add_mapping_attribute(attrib_num, 279 begin_s, end_s - begin_s, table_mapping); 280 } 281 282 if (rc < 0) { 283 command_line_source = "command line"; 284 report_error(begin_s, _key_val); 285 command_line_source = NULL; 286 break; 287 } 288 cmdline_options++; 289 } 290 return (rc); 291 } 292 293 static int 294 parse_ldap_default_conf( 295 __nis_ldap_proxy_info *proxy_info, 296 __nis_config_t *nis_config, 297 __nis_config_info_t *config_info, 298 __nisdb_table_mapping_t *table_info) 299 { 300 int rc = 0; 301 char *ldap_config_attributes[n_config_keys]; 302 char attr_buf[128]; 303 char *attr; 304 static char *attr_val; 305 int defflags; 306 config_key attrib_num; 307 int i; 308 int len; 309 int attr_len; 310 311 if (defopen(ETCCONFFILE) == 0) { 312 file_source = ETCCONFFILE; 313 if (verbose) 314 report_info( 315 "default configuration values: ", NULL); 316 /* Set defread() to be case insensitive */ 317 defflags = defcntl(DC_GETFLAGS, 0); 318 TURNOFF(defflags, DC_CASE); 319 (void) defcntl(DC_SETFLAGS, defflags); 320 321 get_attribute_list(proxy_info, nis_config, config_info, 322 table_info, ldap_config_attributes); 323 i = 0; 324 while ((attr = ldap_config_attributes[i++]) != NULL) { 325 strlcpy(attr_buf, attr, sizeof (attr_buf)); 326 /* 327 * if nisplusUpdateBatching, make sure 328 * we don't match nisplusUpdateBatchingTimeout 329 */ 330 if (strcmp(attr, UPDATE_BATCHING) == 0) { 331 attr_len = strlen(attr); 332 attr_buf[attr_len] = '='; 333 attr_buf[attr_len + 1] = '\0'; 334 attr_val = defread(attr_buf); 335 336 if (attr_val == 0) { 337 attr_buf[attr_len] = ' '; 338 attr_val = defread(attr_buf); 339 } 340 if (attr_val == 0) { 341 attr_buf[attr_len] = '\t'; 342 attr_val = defread(attr_buf); 343 } 344 if (attr_val == 0) { 345 attr_buf[attr_len] = '\n'; 346 attr_val = defread(attr_buf); 347 } 348 } else { 349 attr_val = defread(attr_buf); 350 } 351 if (attr_val == 0) 352 continue; 353 354 got_config_data = TRUE; 355 attrib_num = get_attrib_num(attr, strlen(attr)); 356 if (attrib_num == key_bad) { 357 report_error(attr, NULL); 358 rc = -1; 359 break; 360 } 361 362 /* 363 * Allow either entries of the form 364 * attr val 365 * or 366 * attr = val 367 */ 368 while (is_whitespace(*attr_val)) 369 attr_val++; 370 if (*attr_val == '=') 371 attr_val++; 372 while (is_whitespace(*attr_val)) 373 attr_val++; 374 len = strlen(attr_val); 375 while (len > 0 && 376 is_whitespace(attr_val[len - 1])) 377 len--; 378 379 if (verbose) { 380 report_info("\t", attr); 381 report_info("\t\t", attr_val); 382 } 383 if (IS_BIND_INFO(attrib_num)) { 384 rc = add_bind_attribute(attrib_num, 385 attr_val, len, proxy_info); 386 } else if (IS_OPER_INFO(attrib_num)) { 387 rc = add_operation_attribute(attrib_num, 388 attr_val, len, nis_config, 389 table_info); 390 } 391 if (p_error != no_parse_error) { 392 report_error(attr_val, attr); 393 rc = -1; 394 break; 395 } 396 } 397 file_source = NULL; 398 /* Close the /etc/default file */ 399 (void) defopen(0); 400 } 401 return (rc); 402 } 403 404 static int 405 yp_parse_ldap_default_conf( 406 __nis_ldap_proxy_info *proxy_info, 407 __nis_config_t *nis_config, 408 __nis_config_info_t *config_info, 409 __nisdb_table_mapping_t *table_info) 410 { 411 int rc = 0; 412 char *ldap_config_attributes[n_config_keys]; 413 char attr_buf[128]; 414 char *attr; 415 static char *attr_val; 416 int defflags; 417 config_key attrib_num; 418 int i, len, attr_len; 419 420 if ((defopen(YP_ETCCONFFILE)) == 0) { 421 file_source = YP_ETCCONFFILE; 422 if (verbose) 423 report_info("default configuration values: ", NULL); 424 /* Set defread() to be case insensitive */ 425 defflags = defcntl(DC_GETFLAGS, 0); 426 TURNOFF(defflags, DC_CASE); 427 (void) defcntl(DC_SETFLAGS, defflags); 428 429 get_attribute_list(proxy_info, nis_config, config_info, 430 table_info, ldap_config_attributes); 431 i = 0; 432 while ((attr = ldap_config_attributes[i++]) != NULL) { 433 if ((strlcpy(attr_buf, attr, 434 sizeof (attr_buf))) >= 435 sizeof (attr_buf)) { 436 report_error( 437 "Static buffer attr_buf overflow", NULL); 438 return (-1); 439 } 440 441 if ((attr_val = defread(attr_buf)) == 0) 442 continue; 443 444 got_config_data = TRUE; 445 attrib_num = get_attrib_num(attr, strlen(attr)); 446 if (attrib_num == key_bad) { 447 report_error(attr, NULL); 448 rc = -1; 449 break; 450 } 451 452 /* 453 * Allow either entries of the form 454 * attr val 455 * or 456 * attr = val 457 */ 458 while (is_whitespace(*attr_val)) 459 attr_val++; 460 if (*attr_val == '=') 461 attr_val++; 462 while (is_whitespace(*attr_val)) 463 attr_val++; 464 len = strlen(attr_val); 465 while (len > 0 && 466 is_whitespace(attr_val[len - 1])) 467 len--; 468 469 if (verbose) { 470 report_info("\t", attr); 471 report_info("\t\t", attr_val); 472 } 473 if (IS_YP_BIND_INFO(attrib_num)) { 474 rc = add_bind_attribute(attrib_num, 475 attr_val, len, proxy_info); 476 } else if (IS_YP_OPER_INFO(attrib_num)) { 477 rc = add_operation_attribute(attrib_num, 478 attr_val, len, nis_config, 479 table_info); 480 } 481 if (p_error != no_parse_error) { 482 report_error(attr_val, attr); 483 rc = -1; 484 break; 485 } 486 } 487 file_source = NULL; 488 /* Close the /etc/default file */ 489 (void) defopen(0); 490 } 491 return (rc); 492 } 493 494 /* 495 * FUNCTION: get_attrib_num_cmdline 496 * 497 * Parses the information for LDAP from the command line 498 * The form of the command line request is 499 * -x attribute=value 500 * 501 * RETURN VALUE: 0 on success, -1 on failure 502 * 503 * INPUT: command line values 504 */ 505 506 static config_key 507 get_attrib_num_cmdline( 508 const char *s, 509 const char **begin_s, 510 const char **end_s) 511 { 512 const char *s_end = s + strlen(s); 513 const char *equal_s; 514 const char *s1; 515 config_key attrib_num; 516 517 while (s < s_end && is_whitespace(*s)) 518 s++; 519 520 for (equal_s = s; equal_s < s_end; equal_s++) 521 if (*equal_s == EQUAL_CHAR) 522 break; 523 524 if (equal_s == s_end) { 525 p_error = parse_bad_command_line_attribute_format; 526 return (key_bad); 527 } 528 529 for (s1 = equal_s; s1 > s && is_whitespace(s1[-1]); s1--) 530 ; 531 532 if (s1 == s) { 533 p_error = parse_bad_command_line_attribute_format; 534 return (key_bad); 535 } 536 537 attrib_num = get_attrib_num(s, s1 - s); 538 539 if (attrib_num != key_bad) { 540 s1 = equal_s + 1; 541 while (s1 < s_end && is_whitespace(*s1)) 542 s1++; 543 *begin_s = s1; 544 while (s_end > s1 && is_whitespace(s_end[-1])) 545 s_end--; 546 *end_s = s_end; 547 } 548 549 return (attrib_num); 550 } 551 552 /* 553 * FUNCTION: parse_ldap_config_file 554 * 555 * Parses the information for LDAP from a configuration 556 * file. If no file is specified, /var/nis/NIS+LDAPmapping 557 * is used 558 * 559 * RETURN VALUE: 0 on success, -1 on failure 560 * 561 * INPUT: configuration file name 562 */ 563 564 static int 565 parse_ldap_config_file( 566 const char *config_file, 567 __nis_ldap_proxy_info *proxy_info, 568 __nis_config_t *nis_config, 569 __nis_table_mapping_t **table_mapping, 570 __nis_config_info_t *config_info, 571 __nisdb_table_mapping_t *table_info) 572 { 573 int rc = 0; 574 config_key attrib_num; 575 int fd; 576 char *attr_val; 577 int len; 578 579 if ((fd = open(config_file, O_RDONLY)) == -1) { 580 p_error = parse_open_file_error; 581 report_error(config_file, NULL); 582 return (-1); 583 } 584 585 start_line_num = 1; 586 cur_line_num = 1; 587 588 if (verbose) 589 report_info("Reading configuration from ", config_file); 590 591 file_source = config_file; 592 while ((attrib_num = get_file_attr_val(fd, &attr_val)) > 0) { 593 len = attr_val == NULL ? 0 : strlen(attr_val); 594 if (IS_CONFIG_KEYWORD(attrib_num)) { 595 rc = add_config_attribute(attrib_num, 596 attr_val, len, config_info); 597 } else if (IS_BIND_INFO(attrib_num)) { 598 rc = add_bind_attribute(attrib_num, 599 attr_val, len, proxy_info); 600 } else if (IS_OPER_INFO(attrib_num)) { 601 rc = add_operation_attribute(attrib_num, 602 attr_val, len, nis_config, table_info); 603 } else { 604 rc = add_mapping_attribute(attrib_num, 605 attr_val, len, table_mapping); 606 } 607 608 if (rc < 0) { 609 report_error(attr_val == NULL ? 610 "<no attribute>" : attr_val, _key_val); 611 if (attr_val) 612 free(attr_val); 613 break; 614 } 615 if (attr_val) 616 free(attr_val); 617 } 618 619 (void) close(fd); 620 if (attrib_num == key_bad) { 621 report_error(_key_val, NULL); 622 rc = -1; 623 } 624 start_line_num = 0; 625 file_source = NULL; 626 return (rc); 627 } 628 629 /* 630 * FUNCTION: yp_parse_ldap_config_file 631 * 632 * Parses the information for LDAP from a configuration 633 * file. If no file is specified, /var/yp/NISLDAPmapping 634 * is used 635 * 636 * RETURN VALUE: 0 on success, -1 on failure 637 * 638 * INPUT: configuration file name 639 */ 640 641 int 642 yp_parse_ldap_config_file( 643 const char *config_file, 644 __nis_ldap_proxy_info *proxy_info, 645 __nis_config_t *nis_config, 646 __nis_table_mapping_t **table_mapping, 647 __nis_config_info_t *config_info, 648 __nisdb_table_mapping_t *table_info, 649 __yp_domain_context_t *ypDomains) 650 { 651 int rc = 0; 652 int numDomains = 0; 653 config_key attrib_num; 654 int fd; 655 char *attr_val = NULL; 656 int len; 657 658 if ((fd = open(config_file, O_RDONLY)) == -1) { 659 p_error = parse_open_file_error; 660 report_error(config_file, NULL); 661 return (-1); 662 } 663 664 start_line_num = 1; 665 cur_line_num = 1; 666 667 if (verbose) 668 report_info("Reading configuration from ", config_file); 669 670 file_source = config_file; 671 while ((attrib_num = get_file_attr_val(fd, &attr_val)) > 0) { 672 len = attr_val == NULL ? 0 : strlen(attr_val); 673 if (IS_YP_CONFIG_KEYWORD(attrib_num)) { 674 rc = add_config_attribute(attrib_num, 675 attr_val, len, config_info); 676 } else if (IS_YP_BIND_INFO(attrib_num)) { 677 rc = add_bind_attribute(attrib_num, 678 attr_val, len, proxy_info); 679 } else if (IS_YP_OPER_INFO(attrib_num)) { 680 rc = add_operation_attribute(attrib_num, 681 attr_val, len, nis_config, table_info); 682 } else if (IS_YP_DOMAIN_INFO(attrib_num)) { 683 rc = add_ypdomains_attribute(attrib_num, 684 attr_val, len, ypDomains); 685 } else if (IS_YP_MAP_ATTR(attrib_num)) { 686 rc = add_mapping_attribute(attrib_num, 687 attr_val, len, table_mapping); 688 } else { 689 rc = -1; 690 p_error = parse_unsupported_format; 691 } 692 693 if (rc < 0) { 694 report_error(attr_val == NULL ? 695 "<no attribute>" : attr_val, _key_val); 696 if (attr_val) 697 free(attr_val); 698 break; 699 } 700 if (attr_val) { 701 free(attr_val); 702 attr_val = NULL; 703 } 704 } 705 706 (void) close(fd); 707 if (attrib_num == key_bad) { 708 report_error(_key_val, NULL); 709 rc = -1; 710 } 711 start_line_num = 0; 712 file_source = NULL; 713 return (rc); 714 } 715 716 /* 717 * FUNCTION: get_file_attr_val 718 * 719 * Gets the next attribute from the configuration file. 720 * 721 * RETURN VALUE: The config key if more attributes 722 * no_more_keys if eof 723 * key_bad if error 724 */ 725 726 static config_key 727 get_file_attr_val(int fd, char **attr_val) 728 { 729 char buf[BUFSIZE]; 730 char *start_tag; 731 char *start_val; 732 char *end_val; 733 char *cut_here; 734 char *s; 735 char *a; 736 char *attribute_value; 737 int ret; 738 config_key attrib_num = no_more_keys; 739 int found_quote = 0; 740 741 *attr_val = NULL; 742 743 if ((ret = read_line(fd, buf, sizeof (buf))) > 0) { 744 for (s = buf; is_whitespace(*s); s++) 745 ; 746 747 start_tag = s; 748 while (*s != '\0' && !is_whitespace(*s)) 749 s++; 750 751 if (verbose) 752 report_info("\t", start_tag); 753 attrib_num = get_attrib_num(start_tag, s - start_tag); 754 if (attrib_num == key_bad) 755 return (key_bad); 756 757 while (is_whitespace(*s)) 758 s++; 759 if (*s == '\0') 760 return (attrib_num); 761 start_val = s; 762 763 /* note that read_line will not return a line ending with \ */ 764 for (; *s != '\0'; s++) { 765 if (*s == ESCAPE_CHAR) 766 s++; 767 } 768 while (s > start_val && is_whitespace(s[-1])) 769 s--; 770 771 attribute_value = 772 (char *)calloc(1, (size_t)(s - start_val) + 1); 773 if (attribute_value == NULL) { 774 p_error = parse_no_mem_error; 775 return (key_bad); 776 } 777 attr_val[0] = attribute_value; 778 779 a = *attr_val; 780 end_val = s; 781 cut_here = 0; 782 for (s = start_val; s < end_val; s++) { 783 if (*s == POUND_SIGN) { 784 cut_here = s; 785 while (s < end_val) { 786 if (*s == DOUBLE_QUOTE_CHAR || 787 *s == SINGLE_QUOTE_CHAR) { 788 cut_here = 0; 789 break; 790 } 791 s++; 792 } 793 } 794 } 795 if (cut_here != 0) 796 end_val = cut_here; 797 798 for (s = start_val; s < end_val; s++) 799 *a++ = *s; 800 *a++ = '\0'; 801 } 802 if (ret == -1) 803 return (key_bad); 804 805 return (attrib_num); 806 } 807 808 static LDAP * 809 connect_to_ldap_config_server( 810 char *sever_name, 811 int server_port, 812 __nis_config_info_t *config_info) 813 { 814 int rc = 0; 815 LDAP *ld = NULL; 816 int ldapVersion = LDAP_VERSION3; 817 int derefOption = LDAP_DEREF_ALWAYS; 818 int timelimit = LDAP_NO_LIMIT; 819 int sizelimit = LDAP_NO_LIMIT; 820 int errnum; 821 bool_t retrying = FALSE; 822 int sleep_seconds = 1; 823 struct berval cred; 824 825 if (config_info->tls_method == no_tls) { 826 ld = ldap_init(sever_name, server_port); 827 if (ld == NULL) { 828 p_error = parse_ldap_init_error; 829 report_error(strerror(errno), NULL); 830 return (NULL); 831 } 832 } else { 833 if ((errnum = ldapssl_client_init( 834 config_info->tls_cert_db, NULL)) < 0) { 835 p_error = parse_ldapssl_client_init_error; 836 report_error(ldapssl_err2string(errnum), NULL); 837 return (NULL); 838 } 839 ld = ldapssl_init(sever_name, server_port, 1); 840 if (ld == NULL) { 841 p_error = parse_ldapssl_init_error; 842 report_error(strerror(errno), NULL); 843 return (NULL); 844 } 845 } 846 847 (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, 848 &ldapVersion); 849 (void) ldap_set_option(ld, LDAP_OPT_DEREF, &derefOption); 850 (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 851 (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &timelimit); 852 (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit); 853 854 /* 855 * Attempt to bind to the LDAP server. 856 * We will loop until success or until an error other 857 * than LDAP_CONNECT_ERROR or LDAP_SERVER_DOWN 858 */ 859 if (verbose) 860 report_info("Connecting to ", sever_name); 861 862 for (;;) { 863 if (config_info->auth_method == simple) { 864 errnum = ldap_simple_bind_s(ld, config_info->proxy_dn, 865 config_info->proxy_passwd); 866 } else if (config_info->auth_method == cram_md5) { 867 cred.bv_len = strlen(config_info->proxy_passwd); 868 cred.bv_val = config_info->proxy_passwd; 869 errnum = ldap_sasl_cram_md5_bind_s(ld, 870 config_info->proxy_dn, &cred, NULL, NULL); 871 } else if (config_info->auth_method == digest_md5) { 872 cred.bv_len = strlen(config_info->proxy_passwd); 873 cred.bv_val = config_info->proxy_passwd; 874 errnum = ldap_x_sasl_digest_md5_bind_s(ld, 875 config_info->proxy_dn, &cred, NULL, NULL); 876 } else { 877 errnum = ldap_simple_bind_s(ld, NULL, NULL); 878 } 879 880 if (errnum == LDAP_SUCCESS) 881 break; 882 883 if (errnum == LDAP_CONNECT_ERROR || 884 errnum == LDAP_SERVER_DOWN) { 885 if (!retrying) { 886 if (verbose) 887 report_info( 888 "LDAP server unavailable. Retrying...", 889 NULL); 890 retrying = TRUE; 891 } 892 (void) sleep(sleep_seconds); 893 sleep_seconds *= 2; 894 if (sleep_seconds > MAX_LDAP_CONFIG_RETRY_TIME) 895 sleep_seconds = MAX_LDAP_CONFIG_RETRY_TIME; 896 p_error = no_parse_error; 897 continue; 898 } 899 p_error = parse_ldap_bind_error; 900 report_error2(config_info->proxy_dn, ldap_err2string(errnum)); 901 (void) ldap_unbind(ld); 902 return (NULL); 903 } 904 905 if (verbose) 906 report_info("Reading values from ", config_info->config_dn); 907 908 return (ld); 909 } 910 911 /* 912 * FUNCTION: process_ldap_config_result 913 * 914 * Extracts the LDAPMessage containing the nis+/LDAP 915 * configuration 916 * 917 * RETURN VALUE: 0 on success, -1 on failure 918 * 919 * INPUT: LDAP the LDAP connection 920 * LDAPMessage the LDAP message 921 */ 922 923 static int 924 process_ldap_config_result( 925 LDAP *ld, 926 LDAPMessage *resultMsg, 927 __nis_ldap_proxy_info *proxy_info, 928 __nis_config_t *nis_config, 929 __nis_table_mapping_t **table_mapping, 930 __nisdb_table_mapping_t *table_info) 931 { 932 LDAPMessage *e; 933 int errnum; 934 char *attr; 935 BerElement *ber = NULL; 936 config_key attrib_num; 937 char **vals; 938 int n; 939 int i; 940 char *attr_val; 941 int len; 942 int rc = 0; 943 bool_t error_reported = FALSE; 944 945 e = ldap_first_entry(ld, resultMsg); 946 947 if (e != NULL) { 948 for (attr = ldap_first_attribute(ld, e, &ber); 949 attr != NULL; 950 attr = ldap_next_attribute(ld, e, ber)) { 951 if (verbose) 952 report_info("\t", attr); 953 attrib_num = get_attrib_num(attr, strlen(attr)); 954 if (attrib_num == key_bad) { 955 report_error(attr, NULL); 956 break; 957 } 958 if ((vals = ldap_get_values(ld, e, attr)) != NULL) { 959 n = ldap_count_values(vals); 960 /* parse the attribute values */ 961 for (i = 0; i < n; i++) { 962 attr_val = vals[i]; 963 while (is_whitespace(*attr_val)) 964 attr_val++; 965 if (verbose) 966 report_info("\t\t", attr_val); 967 len = strlen(attr_val); 968 while (len > 0 && 969 is_whitespace(attr_val[len - 1])) 970 len--; 971 if (yp2ldap) { 972 if (IS_YP_BIND_INFO(attrib_num)) { 973 rc = add_bind_attribute( 974 attrib_num, attr_val, 975 len, proxy_info); 976 } else if (IS_YP_OPER_INFO( 977 attrib_num)) { 978 rc = add_operation_attribute( 979 attrib_num, attr_val, len, 980 nis_config, table_info); 981 } else if (IS_YP_MAP_ATTR( 982 attrib_num)) { 983 rc = add_mapping_attribute( 984 attrib_num, attr_val, len, 985 table_mapping); 986 } else { 987 p_error = 988 parse_unsupported_format; 989 } 990 } else { 991 if (IS_BIND_INFO(attrib_num)) { 992 rc = add_bind_attribute( 993 attrib_num, attr_val, len, 994 proxy_info); 995 } else if (IS_OPER_INFO(attrib_num)) { 996 rc = add_operation_attribute( 997 attrib_num, attr_val, len, 998 nis_config, 999 table_info); 1000 } else { 1001 rc = add_mapping_attribute( 1002 attrib_num, attr_val, len, 1003 table_mapping); 1004 } 1005 } 1006 if (p_error != no_parse_error) { 1007 report_error(attr_val, attr); 1008 error_reported = TRUE; 1009 break; 1010 } 1011 } 1012 ldap_value_free(vals); 1013 } else { 1014 (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, 1015 &errnum); 1016 if (errnum != LDAP_SUCCESS) 1017 p_error = parse_ldap_get_values_error; 1018 } 1019 ldap_memfree(attr); 1020 if (p_error != no_parse_error) 1021 break; 1022 } 1023 } else { 1024 errnum = ldap_result2error(ld, resultMsg, FALSE); 1025 if (errnum != LDAP_SUCCESS) 1026 p_error = parse_ldap_search_error; 1027 } 1028 if (ber != NULL) 1029 ber_free(ber, 0); 1030 1031 if (!error_reported && p_error != no_parse_error) { 1032 report_error(ldap_err2string(errnum), 0); 1033 } 1034 1035 if (p_error != no_parse_error) 1036 rc = -1; 1037 return (rc); 1038 } 1039 1040 /* 1041 * FUNCTION: process_ldap_referral 1042 * 1043 * Retrieves the configuration for a referral url 1044 * 1045 * RETURN VALUE: 0 on success, -1 on failure, 1 on skip 1046 * 1047 * INPUT: url the ldap url 1048 * __nis_ldap_proxy_info 1049 */ 1050 1051 static int 1052 process_ldap_referral( 1053 char *url, 1054 char **attrs, 1055 __nis_ldap_proxy_info *proxy_info, 1056 __nis_config_t *nis_config, 1057 __nis_table_mapping_t **table_mapping, 1058 __nis_config_info_t *config_info, 1059 __nisdb_table_mapping_t *table_info) 1060 { 1061 LDAPURLDesc *ludpp = NULL; 1062 int rc; 1063 LDAP *ld = NULL; 1064 int errnum; 1065 LDAPMessage *resultMsg = NULL; 1066 1067 if ((rc = ldap_url_parse(url, &ludpp)) != LDAP_SUCCESS) 1068 return (1); 1069 1070 #ifdef LDAP_URL_OPT_SECURE 1071 if (ludpp->lud_options & LDAP_URL_OPT_SECURE) { 1072 if (config_info->tls_method != ssl_tls) { 1073 ldap_free_urldesc(ludpp); 1074 return (1); 1075 } 1076 } else { 1077 if (config_info->tls_method != no_tls) { 1078 ldap_free_urldesc(ludpp); 1079 return (1); 1080 } 1081 } 1082 #endif 1083 1084 if ((ld = connect_to_ldap_config_server(ludpp->lud_host, 1085 ludpp->lud_port, config_info)) == NULL) { 1086 ldap_free_urldesc(ludpp); 1087 return (-1); 1088 } 1089 1090 errnum = ldap_search_s(ld, config_info->config_dn,