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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <stdio.h>
  27 #include <string.h>
  28 #include <stdlib.h>
  29 #include <ctype.h>
  30 #include <fcntl.h>
  31 #include <unistd.h>
  32 #include <errno.h>
  33 #include <locale.h>
  34 #include <sys/stat.h>
  35 #include <lber.h>
  36 #include <ldap.h>
  37 #include <deflt.h>
  38 
  39 #include "ldap_map.h"
  40 
  41 #include "ldap_parse.h"
  42 #include "ldap_glob.h"
  43 #include "nis_parse_ldap_conf.h"
  44 
  45 __nis_ldap_proxy_info   proxyInfo               =
  46         {NULL, (auth_method_t)NO_VALUE_SET, (tls_method_t)NO_VALUE_SET, NULL,
  47                 NULL, NULL, NULL, NULL, (follow_referral_t)NO_VALUE_SET};
  48 __nis_config_t          ldapConfig;
  49 __nisdb_table_mapping_t ldapDBTableMapping;
  50 __nis_table_mapping_t   *ldapTableMapping       = NULL;
  51 __yp_domain_context_t   ypDomains;
  52 
  53 parse_error             p_error                 = no_parse_error;
  54 int                     cur_line_num            = 0;
  55 int                     start_line_num          = 0;
  56 int                     seq_num                 = 0;
  57 const char              *warn_file              = NULL;
  58 
  59 char                    _key_val[38];
  60 const char              *command_line_source    = NULL;
  61 const char              *file_source            = NULL;
  62 const char              *ldap_source            = NULL;
  63 
  64 static
  65 const char *const       *cmdline_config         = NULL;
  66 static bool_t           got_config_data         = FALSE;
  67 
  68 /* high level parsing functions functions */
  69 static int parse_ldap_cmd_line(const char *const *cmdline_options,
  70     __nis_ldap_proxy_info *proxy_info, __nis_config_t *nis_config,
  71     __nis_table_mapping_t **table_mapping, __nis_config_info_t *config_info,
  72     __nisdb_table_mapping_t *table_info);
  73 static int parse_ldap_default_conf(__nis_ldap_proxy_info *proxy_info,
  74     __nis_config_t *nis_config, __nis_config_info_t *config_info,
  75     __nisdb_table_mapping_t *table_info);
  76 static int parse_ldap_config_file(const char *config_file,
  77     __nis_ldap_proxy_info *proxy_info, __nis_config_t *nis_config,
  78     __nis_table_mapping_t **table_mapping, __nis_config_info_t *config_info,
  79     __nisdb_table_mapping_t *table_info);
  80 static int parse_ldap_config_dn_attrs(__nis_ldap_proxy_info *proxy_info,
  81     __nis_config_t *nis_config, __nis_table_mapping_t **table_mapping,
  82     __nis_config_info_t *config_info, __nisdb_table_mapping_t *table_info);
  83 static int yp_parse_ldap_default_conf(__nis_ldap_proxy_info *proxy_info,
  84         __nis_config_t *nis_config, __nis_config_info_t *config_info,
  85         __nisdb_table_mapping_t *table_info);
  86 
  87 
  88 /* helper functions */
  89 static config_key get_attrib_num_cmdline(const char *s,
  90     const char **begin_s, const char **end_s);
  91 static config_key get_file_attr_val(int fd, char **attr_val);
  92 static void get_attribute_list(
  93         const __nis_ldap_proxy_info *proxy_info,
  94         const __nis_config_t *nis_config,
  95         const __nis_config_info_t *config_info,
  96         const __nisdb_table_mapping_t *table_info,
  97         char **ldap_config_attributes);
  98 
  99 /*
 100  * FUNCTION:    parse_ldap_migration
 101  *
 102  *      Parses the information for LDAP. The values are first
 103  *      obtained from the command line, secondly from the preference
 104  *      file, and finally from an LDAP profile (if so configured in
 105  *      the command line or preference file). Any unset values will
 106  *      be set to their default values.
 107  *
 108  *      If no command line options, no settings in the /etc/default
 109  *  configuration file, and no mapping file, then no mapping
 110  *  should be used.
 111  *
 112  * RETURN VALUE:
 113  *                      0       Success
 114  *                      -1      Config file stat/open or parse error
 115  *                      1       No mapping should be used.
 116  *
 117  * INPUT:               command line parameters, configuration file
 118  */
 119 
 120 int
 121 parse_ldap_migration(
 122         const char *const       *cmdline_options,
 123         const char              *config_file)
 124 {
 125         int                     rc      = 0;
 126         __nis_config_info_t     config_info
 127                                 = {NULL, NULL, (auth_method_t)NO_VALUE_SET,
 128                                         (tls_method_t)NO_VALUE_SET, NULL,
 129                                         NULL, NULL};
 130         struct stat             buf;
 131         int i = 0;
 132 
 133         p_error = no_parse_error;
 134 
 135         if (verbose)
 136                 report_info("Getting LDAP configuration", NULL);
 137 
 138         initialize_parse_structs(&proxyInfo, &ldapConfig, &ldapDBTableMapping);
 139 
 140         if (yp2ldap)
 141                 initialize_yp_parse_structs(&ypDomains);
 142 
 143         if (cmdline_options != NULL) {
 144                 got_config_data = TRUE;
 145                 /* NIS to LDAP does not read command line attributes */
 146                 if (!yp2ldap)
 147                         rc = parse_ldap_cmd_line(cmdline_options, &proxyInfo,
 148                             &ldapConfig, &ldapTableMapping, &config_info,
 149                             &ldapDBTableMapping);
 150                 else
 151                         rc = 0;
 152         }
 153 
 154         if (rc == 0) {
 155                 if (yp2ldap)
 156                         rc = yp_parse_ldap_default_conf(&proxyInfo, &ldapConfig,
 157                             &config_info, &ldapDBTableMapping);
 158                 else
 159                         rc = parse_ldap_default_conf(&proxyInfo, &ldapConfig,
 160                             &config_info, &ldapDBTableMapping);
 161         }
 162 
 163         if (config_file == NULL) {
 164                 if (yp2ldap) {
 165                         if (stat(YP_DEFAULT_MAPPING_FILE, &buf) == 0)
 166                                 config_file = YP_DEFAULT_MAPPING_FILE;
 167                 } else {
 168                         if (stat(DEFAULT_MAPPING_FILE, &buf) == 0)
 169                                 config_file = DEFAULT_MAPPING_FILE;
 170                 }
 171         }
 172 
 173         if (rc == 0 && config_file != NULL) {
 174                 got_config_data = TRUE;
 175                 warn_file = config_file;
 176                 cmdline_config = cmdline_options;
 177                 if (yp2ldap)
 178                         rc = yp_parse_ldap_config_file(config_file, &proxyInfo,
 179                             &ldapConfig, &ldapTableMapping, &config_info,
 180                             &ldapDBTableMapping, &ypDomains);
 181                 else
 182                         rc = parse_ldap_config_file(config_file, &proxyInfo,
 183                             &ldapConfig, &ldapTableMapping, &config_info,
 184                             &ldapDBTableMapping);
 185 
 186                 warn_file = NULL;
 187                 cmdline_config = NULL;
 188         }
 189         if (rc == 0 && (config_info.config_dn != NULL) &&
 190             (config_info.config_dn[0] != '\0')) {
 191                 rc = parse_ldap_config_dn_attrs(&proxyInfo,
 192                     &ldapConfig, &ldapTableMapping, &config_info,
 193                     &ldapDBTableMapping);
 194         }
 195 
 196         free_config_info(&config_info);
 197 
 198         if (rc == 0 && got_config_data == FALSE)
 199                 rc = 1;
 200 
 201         set_default_values(&proxyInfo, &ldapConfig, &ldapDBTableMapping);
 202 
 203         if (yp2ldap == 1 && rc == 0) {
 204                 rc = second_parser_pass(&ldapTableMapping);
 205                 if (rc == 0)
 206                         rc = final_parser_pass(&ldapTableMapping, &ypDomains);
 207                 if (rc == -2)
 208                         return (-1);
 209         }
 210 
 211         if (rc == 0)
 212                 rc = finish_parse(&proxyInfo, &ldapTableMapping);
 213 
 214         if (rc == 0)
 215                 rc = linked2hash(ldapTableMapping);
 216 
 217         if ((rc == 0) && yptol_mode)
 218                 rc = map_id_list_init();
 219 
 220         if (rc != 0) {
 221                 free_parse_structs();
 222         } else if (verbose)
 223                 report_info("LDAP configuration complete", NULL);
 224         return (rc);
 225 }
 226 
 227 /*
 228  * FUNCTION:    parse_ldap_cmd_line
 229  *
 230  *      Parses the information for LDAP from the command line
 231  *
 232  * RETURN VALUE:        0 on success, -1 on failure
 233  *
 234  * INPUT:               command line values
 235  */
 236 
 237 static int
 238 parse_ldap_cmd_line(
 239         const char *const       *cmdline_options,
 240         __nis_ldap_proxy_info   *proxy_info,
 241         __nis_config_t          *nis_config,
 242         __nis_table_mapping_t   **table_mapping,
 243         __nis_config_info_t     *config_info,
 244         __nisdb_table_mapping_t *table_info)
 245 {
 246         int             rc = 0;
 247         config_key      attrib_num;
 248         const char      *begin_s;
 249         const char      *end_s;
 250 
 251         if (verbose)
 252                 report_info("Command line values: ", NULL);
 253         while (*cmdline_options != NULL) {
 254                 if (verbose)
 255                         report_info("\t", *cmdline_options);
 256 
 257                 attrib_num = get_attrib_num_cmdline(
 258                     *cmdline_options, &begin_s, &end_s);
 259                 if (attrib_num == key_bad) {
 260                         command_line_source = "command line";
 261                         report_error(*cmdline_options, NULL);
 262                         command_line_source = NULL;
 263                         rc = -1;
 264                         break;
 265                 } else if (IS_CONFIG_KEYWORD(attrib_num)) {
 266                         rc = add_config_attribute(attrib_num,
 267                             begin_s, end_s - begin_s, config_info);
 268                 } else if (IS_BIND_INFO(attrib_num)) {
 269                         rc = add_bind_attribute(attrib_num,
 270                             begin_s, end_s - begin_s, proxy_info);
 271                 } else if (IS_OPER_INFO(attrib_num)) {
 272                         rc = add_operation_attribute(attrib_num,
 273                             begin_s, end_s - begin_s, nis_config,
 274                             table_info);
 275                 } else {
 276                         rc = add_mapping_attribute(attrib_num,
 277                             begin_s, end_s - begin_s, table_mapping);
 278                 }
 279 
 280                 if (rc < 0) {
 281                         command_line_source = "command line";
 282                         report_error(begin_s, _key_val);
 283                         command_line_source = NULL;
 284                         break;
 285                 }
 286                 cmdline_options++;
 287         }
 288         return (rc);
 289 }
 290 
 291 static int
 292 parse_ldap_default_conf(
 293         __nis_ldap_proxy_info *proxy_info,
 294         __nis_config_t *nis_config,
 295         __nis_config_info_t *config_info,
 296         __nisdb_table_mapping_t *table_info)
 297 {
 298         int             rc = 0;
 299         char            *ldap_config_attributes[n_config_keys];
 300         char            attr_buf[128];
 301         char            *attr;
 302         char            *attr_val;
 303         int             defflags;
 304         config_key      attrib_num;
 305         int             i;
 306         int             len;
 307         int             attr_len;
 308         void            *defp;
 309 
 310         if ((defp = defopen_r(ETCCONFFILE)) != NULL) {
 311                 file_source = ETCCONFFILE;
 312                 if (verbose)
 313                         report_info("default configuration values: ", NULL);
 314                 /* Set defread_r() to be case insensitive */
 315                 defflags = defcntl_r(DC_GETFLAGS, 0, defp);
 316                 TURNOFF(defflags, DC_CASE);
 317                 (void) defcntl_r(DC_SETFLAGS, defflags, defp);
 318 
 319                 get_attribute_list(proxy_info, nis_config, config_info,
 320                     table_info, ldap_config_attributes);
 321                 i = 0;
 322                 while ((attr = ldap_config_attributes[i++]) != NULL) {
 323                         (void) strlcpy(attr_buf, attr, sizeof (attr_buf));
 324                         /*
 325                          * if nisplusUpdateBatching, make sure
 326                          * we don't match nisplusUpdateBatchingTimeout
 327                          */
 328                         if (strcmp(attr, UPDATE_BATCHING) == 0) {
 329                                 attr_len = strlen(attr);
 330                                 attr_buf[attr_len] = '=';
 331                                 attr_buf[attr_len + 1] = '\0';
 332                                 attr_val = defread_r(attr_buf, defp);
 333 
 334                                 if (attr_val == 0) {
 335                                         attr_buf[attr_len] = ' ';
 336                                         attr_val = defread_r(attr_buf, defp);
 337                                 }
 338                                 if (attr_val == 0) {
 339                                         attr_buf[attr_len] = '\t';
 340                                         attr_val = defread_r(attr_buf, defp);
 341                                 }
 342                                 if (attr_val == 0) {
 343                                         attr_buf[attr_len] = '\n';
 344                                         attr_val = defread_r(attr_buf, defp);
 345                                 }
 346                         } else {
 347                                 attr_val = defread_r(attr_buf, defp);
 348                         }
 349                         if (attr_val == NULL)
 350                                 continue;
 351 
 352                         got_config_data = TRUE;
 353                         attrib_num = get_attrib_num(attr, strlen(attr));
 354                         if (attrib_num == key_bad) {
 355                                 report_error(attr, NULL);
 356                                 rc = -1;
 357                                 break;
 358                         }
 359 
 360                         /*
 361                          * Allow either entries of the form
 362                          *      attr val
 363                          *         or
 364                          *      attr = val
 365                          */
 366                         while (is_whitespace(*attr_val))
 367                                 attr_val++;
 368                         if (*attr_val == '=')
 369                                 attr_val++;
 370                         while (is_whitespace(*attr_val))
 371                                 attr_val++;
 372                         len = strlen(attr_val);
 373                         while (len > 0 && is_whitespace(attr_val[len - 1]))
 374                                 len--;
 375 
 376                         if (verbose) {
 377                                 report_info("\t", attr);
 378                                 report_info("\t\t", attr_val);
 379                         }
 380                         if (IS_BIND_INFO(attrib_num)) {
 381                                 rc = add_bind_attribute(attrib_num,
 382                                     attr_val, len, proxy_info);
 383                         } else if (IS_OPER_INFO(attrib_num)) {
 384                                 rc = add_operation_attribute(attrib_num,
 385                                     attr_val, len, nis_config,
 386                                     table_info);
 387                         }
 388                         if (p_error != no_parse_error) {
 389                                 report_error(attr_val, attr);
 390                                 rc = -1;
 391                                 break;
 392                         }
 393                 }
 394                 file_source = NULL;
 395                 /* Close the /etc/default file */
 396                 defclose_r(defp);
 397         }
 398         return (rc);
 399 }
 400 
 401 static int
 402 yp_parse_ldap_default_conf(
 403         __nis_ldap_proxy_info *proxy_info,
 404         __nis_config_t  *nis_config,
 405         __nis_config_info_t *config_info,
 406         __nisdb_table_mapping_t *table_info)
 407 {
 408         int rc = 0;
 409         char            *ldap_config_attributes[n_config_keys];
 410         char            attr_buf[128];
 411         char            *attr;
 412         char            *attr_val;
 413         int             defflags;
 414         config_key      attrib_num;
 415         int     i, len, attr_len;
 416         void            *defp;
 417 
 418         if ((defp = defopen_r(YP_ETCCONFFILE)) != NULL) {
 419                 file_source = YP_ETCCONFFILE;
 420                 if (verbose)
 421                         report_info("default configuration values: ", NULL);
 422                 /* Set defread_r() to be case insensitive */
 423                 defflags = defcntl_r(DC_GETFLAGS, 0, defp);
 424                 TURNOFF(defflags, DC_CASE);
 425                 (void) defcntl_r(DC_SETFLAGS, defflags, defp);
 426 
 427                 get_attribute_list(proxy_info, nis_config, config_info,
 428                     table_info, ldap_config_attributes);
 429                 i = 0;
 430                 while ((attr = ldap_config_attributes[i++]) != NULL) {
 431                         if ((strlcpy(attr_buf, attr, sizeof (attr_buf))) >=
 432                             sizeof (attr_buf)) {
 433                                 report_error(
 434                                     "Static buffer attr_buf overflow", NULL);
 435                                 defclose_r(defp);
 436                                 return (-1);
 437                         }
 438 
 439                         if ((attr_val = defread_r(attr_buf, defp)) == NULL)
 440                                 continue;
 441 
 442                         got_config_data = TRUE;
 443                         attrib_num = get_attrib_num(attr, strlen(attr));
 444                         if (attrib_num == key_bad) {
 445                                 report_error(attr, NULL);
 446                                 rc = -1;
 447                                 break;
 448                         }
 449 
 450                         /*
 451                          * Allow either entries of the form
 452                          * attr val
 453                          * or
 454                          * attr = val
 455                          */
 456                         while (is_whitespace(*attr_val))
 457                                 attr_val++;
 458                         if (*attr_val == '=')
 459                                 attr_val++;
 460                         while (is_whitespace(*attr_val))
 461                                 attr_val++;
 462                         len = strlen(attr_val);
 463                         while (len > 0 && is_whitespace(attr_val[len - 1]))
 464                                 len--;
 465 
 466                         if (verbose) {
 467                                 report_info("\t", attr);
 468                                 report_info("\t\t", attr_val);
 469                         }
 470                         if (IS_YP_BIND_INFO(attrib_num)) {
 471                                 rc = add_bind_attribute(attrib_num,
 472                                     attr_val, len, proxy_info);
 473                         } else if (IS_YP_OPER_INFO(attrib_num)) {
 474                                 rc = add_operation_attribute(attrib_num,
 475                                     attr_val, len, nis_config,
 476                                     table_info);
 477                         }
 478                         if (p_error != no_parse_error) {
 479                                 report_error(attr_val, attr);
 480                                 rc = -1;
 481                                 break;
 482                         }
 483                 }
 484                 file_source = NULL;
 485                 /* Close the /etc/default file */
 486                 defclose_r(defp);
 487         }
 488         return (rc);
 489 }
 490 
 491 /*
 492  * FUNCTION:    get_attrib_num_cmdline
 493  *
 494  *      Parses the information for LDAP from the command line
 495  *      The form of the command line request is
 496  *              -x attribute=value
 497  *
 498  * RETURN VALUE:        0 on success, -1 on failure
 499  *
 500  * INPUT:               command line values
 501  */
 502 
 503 static config_key
 504 get_attrib_num_cmdline(
 505         const char      *s,
 506         const char      **begin_s,
 507         const char      **end_s)
 508 {
 509         const char      *s_end          = s + strlen(s);
 510         const char      *equal_s;
 511         const char      *s1;
 512         config_key      attrib_num;
 513 
 514         while (s < s_end && is_whitespace(*s))
 515                 s++;
 516 
 517         for (equal_s = s; equal_s < s_end; equal_s++)
 518                 if (*equal_s == EQUAL_CHAR)
 519                         break;
 520 
 521         if (equal_s == s_end) {
 522                 p_error = parse_bad_command_line_attribute_format;
 523                 return (key_bad);
 524         }
 525 
 526         for (s1 = equal_s; s1 > s && is_whitespace(s1[-1]); s1--)
 527                 ;
 528 
 529         if (s1 == s) {
 530                 p_error = parse_bad_command_line_attribute_format;
 531                 return (key_bad);
 532         }
 533 
 534         attrib_num = get_attrib_num(s, s1 - s);
 535 
 536         if (attrib_num != key_bad) {
 537                 s1 = equal_s + 1;
 538                 while (s1 < s_end && is_whitespace(*s1))
 539                         s1++;
 540                 *begin_s = s1;
 541                 while (s_end > s1 && is_whitespace(s_end[-1]))
 542                         s_end--;
 543                 *end_s = s_end;
 544         }
 545 
 546         return (attrib_num);
 547 }
 548 
 549 /*
 550  * FUNCTION:    parse_ldap_config_file
 551  *
 552  *      Parses the information for LDAP from a configuration
 553  *      file. If no file is specified, /var/nis/NIS+LDAPmapping
 554  *      is used
 555  *
 556  * RETURN VALUE:        0 on success, -1 on failure
 557  *
 558  * INPUT:               configuration file name
 559  */
 560 
 561 static int
 562 parse_ldap_config_file(
 563         const char              *config_file,
 564         __nis_ldap_proxy_info   *proxy_info,
 565         __nis_config_t          *nis_config,
 566         __nis_table_mapping_t   **table_mapping,
 567         __nis_config_info_t     *config_info,
 568         __nisdb_table_mapping_t *table_info)
 569 {
 570         int             rc = 0;
 571         config_key      attrib_num;
 572         int             fd;
 573         char            *attr_val;
 574         int             len;
 575 
 576         if ((fd = open(config_file, O_RDONLY)) == -1) {
 577                 p_error = parse_open_file_error;
 578                 report_error(config_file, NULL);
 579                 return (-1);
 580         }
 581 
 582         start_line_num = 1;
 583         cur_line_num = 1;
 584 
 585         if (verbose)
 586                 report_info("Reading configuration from ", config_file);
 587 
 588         file_source = config_file;
 589         while ((attrib_num = get_file_attr_val(fd, &attr_val)) > 0) {
 590                 len = attr_val == NULL ? 0 : strlen(attr_val);
 591                 if (IS_CONFIG_KEYWORD(attrib_num)) {
 592                         rc = add_config_attribute(attrib_num,
 593                             attr_val, len, config_info);
 594                 } else if (IS_BIND_INFO(attrib_num)) {
 595                         rc = add_bind_attribute(attrib_num,
 596                             attr_val, len, proxy_info);
 597                 } else if (IS_OPER_INFO(attrib_num)) {
 598                         rc = add_operation_attribute(attrib_num,
 599                             attr_val, len, nis_config, table_info);
 600                 } else {
 601                         rc = add_mapping_attribute(attrib_num,
 602                             attr_val, len, table_mapping);
 603                 }
 604 
 605                 if (rc < 0) {
 606                         report_error(attr_val == NULL ?
 607                             "<no attribute>" : attr_val, _key_val);
 608                         if (attr_val)
 609                                 free(attr_val);
 610                         break;
 611                 }
 612                 if (attr_val)
 613                         free(attr_val);
 614         }
 615 
 616         (void) close(fd);
 617         if (attrib_num == key_bad) {
 618                 report_error(_key_val, NULL);
 619                 rc = -1;
 620         }
 621         start_line_num = 0;
 622         file_source = NULL;
 623         return (rc);
 624 }
 625 
 626 /*
 627  * FUNCTION:    yp_parse_ldap_config_file
 628  *
 629  * Parses the information for LDAP from a configuration
 630  * file. If no file is specified, /var/yp/NISLDAPmapping
 631  * is used
 632  *
 633  * RETURN VALUE:    0 on success, -1 on failure
 634  *
 635  * INPUT:       configuration file name
 636  */
 637 
 638 int
 639 yp_parse_ldap_config_file(
 640         const char      *config_file,
 641         __nis_ldap_proxy_info   *proxy_info,
 642         __nis_config_t                  *nis_config,
 643         __nis_table_mapping_t   **table_mapping,
 644         __nis_config_info_t             *config_info,
 645         __nisdb_table_mapping_t *table_info,
 646         __yp_domain_context_t   *ypDomains)
 647 {
 648         int     rc = 0;
 649         int     numDomains = 0;
 650         config_key      attrib_num;
 651         int     fd;
 652         char    *attr_val = NULL;
 653         int             len;
 654 
 655         if ((fd = open(config_file, O_RDONLY)) == -1) {
 656                 p_error = parse_open_file_error;
 657                 report_error(config_file, NULL);
 658                 return (-1);
 659         }
 660 
 661         start_line_num = 1;
 662         cur_line_num = 1;
 663 
 664         if (verbose)
 665                 report_info("Reading configuration from ", config_file);
 666 
 667         file_source = config_file;
 668         while ((attrib_num = get_file_attr_val(fd, &attr_val)) > 0) {
 669                 len = attr_val == NULL ? 0 : strlen(attr_val);
 670                 if (IS_YP_CONFIG_KEYWORD(attrib_num)) {
 671                         rc = add_config_attribute(attrib_num,
 672                             attr_val, len, config_info);
 673                 } else if (IS_YP_BIND_INFO(attrib_num)) {
 674                         rc = add_bind_attribute(attrib_num,
 675                             attr_val, len, proxy_info);
 676                 } else if (IS_YP_OPER_INFO(attrib_num)) {
 677                         rc = add_operation_attribute(attrib_num,
 678                             attr_val, len, nis_config, table_info);
 679                 } else if (IS_YP_DOMAIN_INFO(attrib_num)) {
 680                         rc = add_ypdomains_attribute(attrib_num,
 681                             attr_val, len, ypDomains);
 682                 } else if (IS_YP_MAP_ATTR(attrib_num)) {
 683                         rc = add_mapping_attribute(attrib_num,
 684                             attr_val, len, table_mapping);
 685                 } else {
 686                         rc = -1;
 687                         p_error = parse_unsupported_format;
 688                 }
 689 
 690                 if (rc < 0) {
 691                         report_error(attr_val == NULL ?
 692                             "<no attribute>" : attr_val, _key_val);
 693                         if (attr_val)
 694                                 free(attr_val);
 695                         break;
 696                 }
 697                 if (attr_val) {
 698                         free(attr_val);
 699                         attr_val = NULL;
 700                 }
 701         }
 702 
 703         (void) close(fd);
 704         if (attrib_num == key_bad) {
 705                 report_error(_key_val, NULL);
 706                 rc = -1;
 707         }
 708         start_line_num = 0;
 709         file_source = NULL;
 710         return (rc);
 711 }
 712 
 713 /*
 714  * FUNCTION:    get_file_attr_val
 715  *
 716  *      Gets the next attribute from the configuration file.
 717  *
 718  * RETURN VALUE:        The config key if more attributes
 719  *                      no_more_keys if eof
 720  *                      key_bad if error
 721  */
 722 
 723 static config_key
 724 get_file_attr_val(int fd, char **attr_val)
 725 {
 726         char            buf[BUFSIZE];
 727         char            *start_tag;
 728         char            *start_val;
 729         char            *end_val;
 730         char            *cut_here;
 731         char            *s;
 732         char            *a;
 733         char            *attribute_value;
 734         int             ret;
 735         config_key      attrib_num = no_more_keys;
 736         int             found_quote = 0;
 737 
 738         *attr_val = NULL;
 739 
 740         if ((ret = read_line(fd, buf, sizeof (buf))) > 0) {
 741                 for (s = buf; is_whitespace(*s); s++)
 742                         ;
 743 
 744                 start_tag = s;
 745                 while (*s != '\0' && !is_whitespace(*s))
 746                         s++;
 747 
 748                 if (verbose)
 749                         report_info("\t", start_tag);
 750                 attrib_num = get_attrib_num(start_tag, s - start_tag);
 751                 if (attrib_num == key_bad)
 752                         return (key_bad);
 753 
 754                 while (is_whitespace(*s))
 755                         s++;
 756                 if (*s == '\0')
 757                         return (attrib_num);
 758                 start_val = s;
 759 
 760                 /* note that read_line will not return a line ending with \ */
 761                 for (; *s != '\0'; s++) {
 762                         if (*s == ESCAPE_CHAR)
 763                                 s++;
 764                 }
 765                 while (s > start_val && is_whitespace(s[-1]))
 766                         s--;
 767 
 768                 attribute_value =
 769                     calloc(1, (size_t)(s - start_val) + 1);
 770                 if (attribute_value == NULL) {
 771                         p_error = parse_no_mem_error;
 772                         return (key_bad);
 773                 }
 774                 attr_val[0] = attribute_value;
 775 
 776                 a = *attr_val;
 777                 end_val = s;
 778                 cut_here = 0;
 779                 for (s = start_val; s < end_val; s++) {
 780                         if (*s == POUND_SIGN) {
 781                                         cut_here = s;
 782                                         while (s < end_val) {
 783                                                 if (*s == DOUBLE_QUOTE_CHAR ||
 784                                                     *s == SINGLE_QUOTE_CHAR) {
 785                                                         cut_here = 0;
 786                                                         break;
 787                                                 }
 788                                                 s++;
 789                                         }
 790                         }
 791                 }
 792                 if (cut_here != 0)
 793                         end_val = cut_here;
 794 
 795                 for (s = start_val; s < end_val; s++)
 796                         *a++ = *s;
 797                 *a++ = '\0';
 798         }
 799         if (ret == -1)
 800                 return (key_bad);
 801 
 802         return (attrib_num);
 803 }
 804 
 805 static LDAP *
 806 connect_to_ldap_config_server(
 807         char                    *sever_name,
 808         int                     server_port,
 809         __nis_config_info_t     *config_info)
 810 {
 811         int             rc              = 0;
 812         LDAP            *ld             = NULL;
 813         int             ldapVersion     = LDAP_VERSION3;
 814         int             derefOption     = LDAP_DEREF_ALWAYS;
 815         int             timelimit       = LDAP_NO_LIMIT;
 816         int             sizelimit       = LDAP_NO_LIMIT;
 817         int             errnum;
 818         bool_t          retrying        = FALSE;
 819         int             sleep_seconds   = 1;
 820         struct berval   cred;
 821 
 822         if (config_info->tls_method == no_tls) {
 823                 ld = ldap_init(sever_name, server_port);
 824                 if (ld == NULL) {
 825                         p_error = parse_ldap_init_error;
 826                         report_error(strerror(errno), NULL);
 827                         return (NULL);
 828                 }
 829         } else {
 830                 if ((errnum = ldapssl_client_init(
 831                     config_info->tls_cert_db, NULL)) < 0) {
 832                         p_error = parse_ldapssl_client_init_error;
 833                         report_error(ldapssl_err2string(errnum), NULL);
 834                         return (NULL);
 835                 }
 836                 ld = ldapssl_init(sever_name, server_port, 1);
 837                 if (ld == NULL) {
 838                         p_error = parse_ldapssl_init_error;
 839                         report_error(strerror(errno), NULL);
 840                         return (NULL);
 841                 }
 842         }
 843 
 844         (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
 845             &ldapVersion);
 846         (void) ldap_set_option(ld, LDAP_OPT_DEREF, &derefOption);
 847         (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
 848         (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &timelimit);
 849         (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
 850 
 851         /*
 852          * Attempt to bind to the LDAP server.
 853          * We will loop until success or until an error other
 854          * than LDAP_CONNECT_ERROR or LDAP_SERVER_DOWN
 855          */
 856         if (verbose)
 857                 report_info("Connecting to ", sever_name);
 858 
 859         for (;;) {
 860                 if (config_info->auth_method == simple) {
 861                         errnum = ldap_simple_bind_s(ld, config_info->proxy_dn,
 862                             config_info->proxy_passwd);
 863                 } else if (config_info->auth_method == cram_md5) {
 864                         cred.bv_len = strlen(config_info->proxy_passwd);
 865                         cred.bv_val = config_info->proxy_passwd;
 866                         errnum = ldap_sasl_cram_md5_bind_s(ld,
 867                             config_info->proxy_dn, &cred, NULL, NULL);
 868                 } else if (config_info->auth_method == digest_md5) {
 869                         cred.bv_len = strlen(config_info->proxy_passwd);
 870                         cred.bv_val = config_info->proxy_passwd;
 871                         errnum = ldap_x_sasl_digest_md5_bind_s(ld,
 872                             config_info->proxy_dn, &cred, NULL, NULL);
 873                 } else {
 874                         errnum = ldap_simple_bind_s(ld, NULL, NULL);
 875                 }
 876 
 877                 if (errnum == LDAP_SUCCESS)
 878                         break;
 879 
 880                 if (errnum == LDAP_CONNECT_ERROR ||
 881                     errnum == LDAP_SERVER_DOWN) {
 882                         if (!retrying) {
 883                                 if (verbose)
 884                                         report_info(
 885                                         "LDAP server unavailable. Retrying...",
 886                                             NULL);
 887                                 retrying = TRUE;
 888                         }
 889                         (void) sleep(sleep_seconds);
 890                         sleep_seconds *= 2;
 891                         if (sleep_seconds > MAX_LDAP_CONFIG_RETRY_TIME)
 892                                 sleep_seconds = MAX_LDAP_CONFIG_RETRY_TIME;
 893                         p_error = no_parse_error;
 894                         continue;
 895                 }
 896                 p_error = parse_ldap_bind_error;
 897                 report_error2(config_info->proxy_dn, ldap_err2string(errnum));
 898                 (void) ldap_unbind(ld);
 899                 return (NULL);
 900         }
 901 
 902         if (verbose)
 903                 report_info("Reading values from ", config_info->config_dn);
 904 
 905         return (ld);
 906 }
 907 
 908 /*
 909  * FUNCTION:    process_ldap_config_result
 910  *
 911  *      Extracts the LDAPMessage containing the nis+/LDAP
 912  *      configuration
 913  *
 914  * RETURN VALUE:        0 on success, -1 on failure
 915  *
 916  * INPUT:               LDAP            the LDAP connection
 917  *                      LDAPMessage     the LDAP message
 918  */
 919 
 920 static int
 921 process_ldap_config_result(
 922         LDAP                    *ld,
 923         LDAPMessage             *resultMsg,
 924         __nis_ldap_proxy_info   *proxy_info,
 925         __nis_config_t          *nis_config,
 926         __nis_table_mapping_t   **table_mapping,
 927         __nisdb_table_mapping_t *table_info)
 928 {
 929         LDAPMessage     *e;
 930         int             errnum;
 931         char            *attr;
 932         BerElement      *ber            = NULL;
 933         config_key      attrib_num;
 934         char            **vals;
 935         int             n;
 936         int             i;
 937         char            *attr_val;
 938         int             len;
 939         int             rc = 0;
 940         bool_t          error_reported  = FALSE;
 941 
 942         e = ldap_first_entry(ld, resultMsg);
 943 
 944         if (e != NULL) {
 945                 for (attr = ldap_first_attribute(ld, e, &ber); attr != NULL;
 946                     attr = ldap_next_attribute(ld, e, ber)) {
 947                         if (verbose)
 948                                 report_info("\t", attr);
 949                         attrib_num = get_attrib_num(attr, strlen(attr));
 950                         if (attrib_num == key_bad) {
 951                                 report_error(attr, NULL);
 952                                 break;
 953                         }
 954                         if ((vals = ldap_get_values(ld, e, attr)) != NULL) {
 955                                 n = ldap_count_values(vals);
 956                                 /* parse the attribute values */
 957                                 for (i = 0; i < n; i++) {
 958                                         attr_val = vals[i];
 959                                         while (is_whitespace(*attr_val))
 960                                                 attr_val++;
 961                                         if (verbose)
 962                                                 report_info("\t\t", attr_val);
 963                                         len = strlen(attr_val);
 964                                         while (len > 0 &&
 965                                             is_whitespace(attr_val[len - 1]))
 966                                                 len--;
 967                 if (yp2ldap) {
 968                         if (IS_YP_BIND_INFO(attrib_num)) {
 969                                 rc = add_bind_attribute(attrib_num, attr_val,
 970                                     len, proxy_info);
 971                         } else if (IS_YP_OPER_INFO(attrib_num)) {
 972                                 rc = add_operation_attribute(attrib_num,
 973                                     attr_val, len, nis_config, table_info);
 974                         } else if (IS_YP_MAP_ATTR(attrib_num)) {
 975                                 rc = add_mapping_attribute(attrib_num, attr_val,
 976                                     len, table_mapping);
 977                         } else {
 978                                 p_error = parse_unsupported_format;
 979                         }
 980                 } else {
 981                         if (IS_BIND_INFO(attrib_num)) {
 982                                 rc = add_bind_attribute(attrib_num, attr_val,
 983                                     len, proxy_info);
 984                         } else if (IS_OPER_INFO(attrib_num)) {
 985                                 rc = add_operation_attribute(attrib_num,
 986                                     attr_val, len, nis_config, table_info);
 987                         } else {
 988                                 rc = add_mapping_attribute(attrib_num, attr_val,
 989                                     len, table_mapping);
 990                         }
 991                 }
 992                                         if (p_error != no_parse_error) {
 993                                                 report_error(attr_val, attr);
 994                                                 error_reported = TRUE;
 995                                                 break;
 996                                         }
 997                                 }
 998                                 ldap_value_free(vals);
 999                         } else {
1000                                 (void) ldap_get_option(ld,
1001                                     LDAP_OPT_ERROR_NUMBER, &errnum);
1002                                 if (errnum != LDAP_SUCCESS)
1003                                         p_error = parse_ldap_get_values_error;
1004                         }
1005                         ldap_memfree(attr);
1006                         if (p_error != no_parse_error)
1007                                 break;
1008                 }
1009         } else {
1010                 errnum = ldap_result2error(ld, resultMsg, FALSE);
1011                 if (errnum != LDAP_SUCCESS)
1012                         p_error = parse_ldap_search_error;
1013         }
1014         if (ber != NULL)
1015                 ber_free(ber, 0);
1016 
1017         if (!error_reported && p_error != no_parse_error) {
1018                 report_error(ldap_err2string(errnum), 0);
1019         }
1020 
1021         if (p_error != no_parse_error)
1022                 rc = -1;
1023         return (rc);
1024 }
1025 
1026 /*
1027  * FUNCTION:    process_ldap_referral
1028  *
1029  *      Retrieves the configuration for a referral url
1030  *
1031  * RETURN VALUE:        0 on success, -1 on failure, 1 on skip
1032  *
1033  * INPUT:               url             the ldap url
1034  *                      __nis_ldap_proxy_info
1035  */
1036 
1037 static int
1038 process_ldap_referral(
1039         char                    *url,
1040         char                    **attrs,
1041         __nis_ldap_proxy_info   *proxy_info,
1042         __nis_config_t          *nis_config,
1043         __nis_table_mapping_t   **table_mapping,
1044         __nis_config_info_t     *config_info,
1045         __nisdb_table_mapping_t *table_info)
1046 {
1047         LDAPURLDesc     *ludpp          = NULL;
1048         int             rc;
1049         LDAP            *ld             = NULL;
1050         int             errnum;
1051         LDAPMessage     *resultMsg      = NULL;
1052 
1053         if ((rc = ldap_url_parse(url, &ludpp)) != LDAP_SUCCESS)
1054                 return (1);
1055 
1056 #ifdef LDAP_URL_OPT_SECURE
1057         if (ludpp->lud_options & LDAP_URL_OPT_SECURE) {
1058                 if (config_info->tls_method != ssl_tls) {
1059                         ldap_free_urldesc(ludpp);
1060                         return (1);
1061                 }
1062         } else {
1063                 if (config_info->tls_method != no_tls) {
1064                         ldap_free_urldesc(ludpp);
1065                         return (1);
1066                 }
1067         }
1068 #endif
1069 
1070         if ((ld = connect_to_ldap_config_server(ludpp->lud_host,
1071             ludpp->lud_port, config_info)) == NULL) {
1072                 ldap_free_urldesc(ludpp);
1073                 return (-1);
1074         }
1075 
1076         errnum = ldap_search_s(ld, config_info->config_dn, LDAP_SCOPE_BASE,
1077             "objectclass=nisplusLDAPconfig", attrs, 0, &resultMsg);
1078 
1079         ldap_source = config_info->config_dn;
1080 
1081         if (errnum != LDAP_SUCCESS) {
1082                 p_error = parse_ldap_search_error;
1083                 report_error(ldap_err2string(errnum), 0);
1084                 rc = -1;
1085         } else {
1086                 rc = process_ldap_config_result(ld, resultMsg, proxy_info,
1087                     nis_config, table_mapping, table_info);
1088         }
1089 
1090         ldap_source = NULL;
1091         (void) ldap_unbind(ld);
1092         if (resultMsg != NULL)
1093                 (void) ldap_msgfree(resultMsg);
1094 
1095         return (rc);
1096 }
1097 
1098 /*
1099  * FUNCTION:    process_ldap_referral_msg
1100  *
1101  *      Retrieves the configuration from referred servers
1102  *
1103  * RETURN VALUE:        0 on success, -1 on failure
1104  *
1105  * INPUT:               LDAP            the LDAP connection
1106  *                      LDAPMessage     the LDAP message
1107  *                      __nis_ldap_proxy_info
1108  */
1109 
1110 static int
1111 process_ldap_referral_msg(
1112         LDAP                    *ld,
1113         LDAPMessage             *resultMsg,
1114         char                    **attrs,
1115         __nis_ldap_proxy_info   *proxy_info,
1116         __nis_config_t          *nis_config,
1117         __nis_table_mapping_t   **table_mapping,
1118         __nis_config_info_t     *config_info,
1119         __nisdb_table_mapping_t *table_info)
1120 {
1121         int     errCode;
1122         char    **referralsp    = NULL;
1123         int     i;
1124         int     rc;
1125 
1126         rc = ldap_parse_result(ld, resultMsg, &errCode, NULL, NULL, &referralsp,
1127             NULL, 0);
1128 
1129         if (rc != LDAP_SUCCESS || errCode != LDAP_REFERRAL) {
1130                 p_error = parse_ldap_get_values_error;
1131                 report_error(ldap_err2string(errCode), 0);
1132                 rc = -1;
1133         } else {
1134                 for (i = 0; referralsp[i] != NULL; i++) {
1135                         rc = process_ldap_referral(referralsp[i], attrs,
1136                             proxy_info, nis_config, table_mapping,
1137                             config_info, table_info);
1138                         if (rc <= 0)
1139                                 break;
1140                         else
1141                                 report_info("Cannot use referral \n",
1142                                     referralsp[i]);
1143 
1144                 }
1145                 if (rc > 0) {
1146                         p_error = parse_no_available_referrals_error;
1147                         report_error(0, 0);
1148                 }
1149         }
1150 
1151         if (referralsp)
1152                 ldap_value_free(referralsp);
1153 
1154         return (rc);
1155 }
1156 
1157 /*
1158  * FUNCTION:    parse_ldap_config_dn_attrs
1159  *
1160  *      Parses the information for LDAP from the LDAP profile
1161  *      - the profile object name, the LDAP server, and the
1162  *      authentication method must be specified.
1163  *
1164  * RETURN VALUE:        0 on success, -1 on failure
1165  *
1166  * INPUT:               __nis_ldap_proxy_info
1167  */
1168 
1169 static int
1170 parse_ldap_config_dn_attrs(
1171         __nis_ldap_proxy_info   *proxy_info,
1172         __nis_config_t          *nis_config,
1173         __nis_table_mapping_t   **table_mapping,
1174         __nis_config_info_t     *config_info,
1175         __nisdb_table_mapping_t *table_info)
1176 {
1177         int             rc              = 0;
1178         LDAP            *ld             = NULL;
1179         int             errnum;
1180         char            *ldap_config_attributes[n_config_keys];
1181         LDAPMessage     *resultMsg      = NULL;
1182 
1183         /* Determine if properly configured for LDAP lookup */
1184         if (config_info->auth_method == simple &&
1185             config_info->proxy_dn == NULL)
1186                 p_error = parse_no_proxy_dn_error;
1187         else if (config_info->auth_method ==
1188             (auth_method_t)NO_VALUE_SET)
1189                 p_error = parse_no_config_auth_error;
1190         else if ((config_info->default_servers == NULL) ||
1191             (config_info->default_servers[0] == '\0'))
1192                 p_error = parse_no_config_server_addr;
1193         if (p_error != no_parse_error) {
1194                 report_error(NULL, NULL);
1195                 return (-1);
1196         }
1197 
1198         if (config_info->tls_method == (tls_method_t)NO_VALUE_SET)
1199                 config_info->tls_method = no_tls;
1200         else if (config_info->tls_method == ssl_tls &&
1201             (config_info->tls_cert_db == NULL ||
1202             *config_info->tls_cert_db == '\0')) {
1203                 p_error = parse_no_config_cert_db;
1204                 report_error(NULL, NULL);
1205                 return (-1);
1206         }
1207 
1208         if (verbose)
1209                 report_info(
1210                     "Getting configuration from LDAP server(s): ",
1211                     config_info->default_servers);
1212 
1213         /* Determine which attributes should be retrieved */
1214         get_attribute_list(proxy_info, nis_config, NULL, table_info,
1215             ldap_config_attributes);
1216 
1217         if ((ld = connect_to_ldap_config_server(config_info->default_servers, 0,
1218             config_info)) == NULL)
1219                 return (-1);
1220 
1221         /* Get the attribute values */
1222         errnum = ldap_search_s(ld, config_info->config_dn, LDAP_SCOPE_BASE,
1223             "objectclass=nisplusLDAPconfig",
1224             ldap_config_attributes, 0, &resultMsg);
1225         ldap_source = config_info->config_dn;
1226 
1227         if (errnum == LDAP_REFERRAL) {
1228                 rc = process_ldap_referral_msg(ld, resultMsg,
1229                     ldap_config_attributes, proxy_info, nis_config,
1230                     table_mapping, config_info, table_info);
1231         } else if (errnum != LDAP_SUCCESS) {
1232                 p_error = parse_ldap_search_error;
1233                 report_error(ldap_err2string(errnum), 0);
1234                 rc = -1;
1235         } else {
1236                 rc = process_ldap_config_result(ld, resultMsg, proxy_info,
1237                     nis_config, table_mapping, table_info);
1238         }
1239 
1240         ldap_source = NULL;
1241         (void) ldap_unbind(ld);
1242         if (resultMsg != NULL)
1243                 (void) ldap_msgfree(resultMsg);
1244 
1245         return (rc);
1246 }
1247 
1248 bool_t
1249 is_cmd_line_option(config_key a_num)
1250 {
1251         const char *const       *cmdline_options = cmdline_config;
1252         config_key              attrib_num;
1253         const char              *begin_s;
1254         const char              *end_s;
1255 
1256         if (cmdline_options == NULL)
1257                 return (FALSE);
1258 
1259         while (*cmdline_options != NULL) {
1260                 attrib_num = get_attrib_num_cmdline(
1261                     *cmdline_options, &begin_s, &end_s);
1262                 if (attrib_num == a_num)
1263                         break;
1264                 cmdline_options++;
1265         }
1266         return (*cmdline_options != NULL);
1267 }
1268 
1269 /*
1270  * FUNCTION:    get_attribute_list
1271  *
1272  *      Get a list of attributes from the LDAP server that have not yet
1273  *      been gotten. If config_info is NULL, the associated parameters
1274  *      are not needed.
1275  *
1276  * RETURN VALUE:        none
1277  *
1278  * INPUT:               Returns a list of parameters in attributes
1279  *                      which is assumed to be of sufficient size.
1280  */
1281 
1282 static void
1283 get_attribute_list(
1284         const __nis_ldap_proxy_info     *proxy_info,
1285         const __nis_config_t            *nis_config,
1286         const __nis_config_info_t       *config_info,
1287         const __nisdb_table_mapping_t   *table_info,
1288         char                            **attributes)
1289 {
1290         int             n_attrs;
1291 
1292         /* Determine which attributes should be retrieved */
1293         n_attrs = 0;
1294 
1295         if (config_info != NULL) {
1296                 if (yp2ldap) {
1297                         if (config_info->config_dn == NULL)
1298                                 attributes[n_attrs++] = YP_CONFIG_DN;
1299                         if (config_info->default_servers == NULL)
1300                                 attributes[n_attrs++] = YP_CONFIG_SERVER_LIST;
1301                         if (config_info->auth_method ==
1302                             (auth_method_t)NO_VALUE_SET)
1303                                 attributes[n_attrs++] = YP_CONFIG_AUTH_METHOD;
1304                         if (config_info->tls_method ==
1305                             (tls_method_t)NO_VALUE_SET)
1306                                 attributes[n_attrs++] = YP_CONFIG_TLS_OPTION;
1307                         if (config_info->proxy_dn == NULL)
1308                                 attributes[n_attrs++] = YP_CONFIG_PROXY_USER;
1309                         if (config_info->proxy_passwd == NULL)
1310                                 attributes[n_attrs++] = YP_CONFIG_PROXY_PASSWD;
1311                         if (config_info->tls_cert_db == NULL)
1312                                 attributes[n_attrs++] = YP_CONFIG_TLS_CERT_DB;
1313                 } else {
1314                         if (config_info->config_dn == NULL)
1315                                 attributes[n_attrs++] = CONFIG_DN;
1316                         if (config_info->default_servers == NULL)
1317                                 attributes[n_attrs++] = CONFIG_SERVER_LIST;
1318                         if (config_info->auth_method ==
1319                             (auth_method_t)NO_VALUE_SET)
1320                                 attributes[n_attrs++] = CONFIG_AUTH_METHOD;
1321                         if (config_info->tls_method ==
1322                             (tls_method_t)NO_VALUE_SET)
1323                                 attributes[n_attrs++] = CONFIG_TLS_OPTION;
1324                         if (config_info->proxy_dn == NULL)
1325                                 attributes[n_attrs++] = CONFIG_PROXY_USER;
1326                         if (config_info->proxy_passwd == NULL)
1327                                 attributes[n_attrs++] = CONFIG_PROXY_PASSWD;
1328                         if (config_info->tls_cert_db == NULL)
1329                                 attributes[n_attrs++] = CONFIG_TLS_CERT_DB;
1330                 }
1331         } else {
1332                 if (yp2ldap) {
1333                         attributes[n_attrs++] = YP_DOMAIN_CONTEXT;
1334                         attributes[n_attrs++] = YPPASSWDD_DOMAINS;
1335                         attributes[n_attrs++] = YP_DB_ID_MAP;
1336                         attributes[n_attrs++] = YP_COMMENT_CHAR;
1337                         attributes[n_attrs++] = YP_MAP_FLAGS;
1338                         attributes[n_attrs++] = YP_ENTRY_TTL;
1339                         attributes[n_attrs++] = YP_NAME_FIELDS;
1340                         attributes[n_attrs++] = YP_SPLIT_FIELD;
1341                         attributes[n_attrs++] = YP_REPEATED_FIELD_SEPARATORS;
1342                         attributes[n_attrs++] = YP_LDAP_OBJECT_DN;
1343                         attributes[n_attrs++] = NIS_TO_LDAP_MAP;
1344                         attributes[n_attrs++] = LDAP_TO_NIS_MAP;
1345                 } else {
1346                         attributes[n_attrs++] = DB_ID_MAP;
1347                         attributes[n_attrs++] = ENTRY_TTL;
1348                         attributes[n_attrs++] = LDAP_OBJECT_DN;
1349                         attributes[n_attrs++] = NISPLUS_TO_LDAP_MAP;
1350                         attributes[n_attrs++] = LDAP_TO_NISPLUS_MAP;
1351                 }
1352         }
1353 
1354         if (yp2ldap) {
1355                 if (proxy_info->default_servers == NULL)
1356                         attributes[n_attrs++] = PREFERRED_SERVERS;
1357                 if (proxy_info->auth_method == (auth_method_t)NO_VALUE_SET)
1358                         attributes[n_attrs++] = AUTH_METHOD;
1359                 if (proxy_info->tls_method == (tls_method_t)NO_VALUE_SET)
1360                         attributes[n_attrs++] = YP_TLS_OPTION;
1361                 if (proxy_info->tls_cert_db == NULL)
1362                         attributes[n_attrs++] = YP_TLS_CERT_DB;
1363                 if (proxy_info->default_search_base == NULL)
1364                         attributes[n_attrs++] = SEARCH_BASE;
1365                 if (proxy_info->proxy_dn == NULL)
1366                         attributes[n_attrs++] = YP_PROXY_USER;
1367                 if (proxy_info->proxy_passwd == NULL)
1368                         attributes[n_attrs++] = YP_PROXY_PASSWD;
1369                 if (proxy_info->default_nis_domain == NULL)
1370                         attributes[n_attrs++] = YP_LDAP_BASE_DOMAIN;
1371                 if (proxy_info->bind_timeout.tv_sec ==
1372                     (time_t)NO_VALUE_SET)
1373                         attributes[n_attrs++] = YP_BIND_TIMEOUT;
1374                 if (proxy_info->search_timeout.tv_sec ==
1375                     (time_t)NO_VALUE_SET)
1376                         attributes[n_attrs++] = YP_SEARCH_TIMEOUT;
1377                 if (proxy_info->modify_timeout.tv_sec ==
1378                     (time_t)NO_VALUE_SET)
1379                         attributes[n_attrs++] = YP_MODIFY_TIMEOUT;
1380                 if (proxy_info->add_timeout.tv_sec == (time_t)NO_VALUE_SET)
1381                         attributes[n_attrs++] = YP_ADD_TIMEOUT;
1382                 if (proxy_info->delete_timeout.tv_sec ==
1383                     (time_t)NO_VALUE_SET)
1384                         attributes[n_attrs++] = YP_DELETE_TIMEOUT;
1385                 if (proxy_info->search_time_limit == (int)NO_VALUE_SET)
1386                         attributes[n_attrs++] = YP_SEARCH_TIME_LIMIT;
1387                 if (proxy_info->search_size_limit == (int)NO_VALUE_SET)
1388                         attributes[n_attrs++] = YP_SEARCH_SIZE_LIMIT;
1389                 if (proxy_info->follow_referral ==
1390                     (follow_referral_t)NO_VALUE_SET)
1391                         attributes[n_attrs++] = YP_FOLLOW_REFERRAL;
1392 
1393                 if (table_info->retrieveError ==
1394                     (__nis_retrieve_error_t)NO_VALUE_SET)
1395                         attributes[n_attrs++] = YP_RETRIEVE_ERROR_ACTION;
1396                 if (table_info->retrieveErrorRetry.attempts == NO_VALUE_SET)
1397                         attributes[n_attrs++] = YP_RETREIVE_ERROR_ATTEMPTS;
1398                 if (table_info->retrieveErrorRetry.timeout ==
1399                     (time_t)NO_VALUE_SET)
1400                         attributes[n_attrs++] = YP_RETREIVE_ERROR_TIMEOUT;
1401                 if (table_info->storeError ==
1402                     (__nis_store_error_t)NO_VALUE_SET)
1403                         attributes[n_attrs++] = YP_STORE_ERROR_ACTION;
1404                 if (table_info->storeErrorRetry.attempts == NO_VALUE_SET)
1405                         attributes[n_attrs++] = YP_STORE_ERROR_ATTEMPTS;
1406                 if (table_info->storeErrorRetry.timeout ==
1407                     (time_t)NO_VALUE_SET)
1408                         attributes[n_attrs++] = YP_STORE_ERROR_TIMEOUT;
1409                 if (table_info->refreshError ==
1410                     (__nis_refresh_error_t)NO_VALUE_SET)
1411                         attributes[n_attrs++] = REFRESH_ERROR_ACTION;
1412                 if (table_info->refreshErrorRetry.attempts == NO_VALUE_SET)
1413                         attributes[n_attrs++] = REFRESH_ERROR_ATTEMPTS;
1414                 if (table_info->refreshErrorRetry.timeout ==
1415                     (time_t)NO_VALUE_SET)
1416                         attributes[n_attrs++] = REFRESH_ERROR_TIMEOUT;
1417                 if (table_info->matchFetch ==
1418                     (__nis_match_fetch_t)NO_VALUE_SET)
1419                         attributes[n_attrs++] = YP_MATCH_FETCH;
1420         } else {
1421                 if (proxy_info->default_servers == NULL)
1422                         attributes[n_attrs++] = PREFERRED_SERVERS;
1423                 if (proxy_info->auth_method == (auth_method_t)NO_VALUE_SET)
1424                         attributes[n_attrs++] = AUTH_METHOD;
1425                 if (proxy_info->tls_method == (tls_method_t)NO_VALUE_SET)
1426                         attributes[n_attrs++] = TLS_OPTION;
1427                 if (proxy_info->tls_cert_db == NULL)
1428                         attributes[n_attrs++] = TLS_CERT_DB;
1429                 if (proxy_info->default_search_base == NULL)
1430                         attributes[n_attrs++] = SEARCH_BASE;
1431                 if (proxy_info->proxy_dn == NULL)
1432                         attributes[n_attrs++] = PROXY_USER;
1433                 if (proxy_info->proxy_passwd == NULL)
1434                         attributes[n_attrs++] = PROXY_PASSWD;
1435                 if (proxy_info->default_nis_domain == NULL)
1436                         attributes[n_attrs++] = LDAP_BASE_DOMAIN;
1437                 if (proxy_info->bind_timeout.tv_sec ==
1438                     (time_t)NO_VALUE_SET)
1439                         attributes[n_attrs++] = BIND_TIMEOUT;
1440                 if (proxy_info->search_timeout.tv_sec ==
1441                     (time_t)NO_VALUE_SET)
1442                         attributes[n_attrs++] = SEARCH_TIMEOUT;
1443                 if (proxy_info->modify_timeout.tv_sec ==
1444                     (time_t)NO_VALUE_SET)
1445                         attributes[n_attrs++] = MODIFY_TIMEOUT;
1446                 if (proxy_info->add_timeout.tv_sec == (time_t)NO_VALUE_SET)
1447                         attributes[n_attrs++] = ADD_TIMEOUT;
1448                 if (proxy_info->delete_timeout.tv_sec ==
1449                     (time_t)NO_VALUE_SET)
1450                         attributes[n_attrs++] = DELETE_TIMEOUT;
1451                 if (proxy_info->search_time_limit == (int)NO_VALUE_SET)
1452                         attributes[n_attrs++] = SEARCH_TIME_LIMIT;
1453                 if (proxy_info->search_size_limit == (int)NO_VALUE_SET)
1454                         attributes[n_attrs++] = SEARCH_SIZE_LIMIT;
1455                 if (proxy_info->follow_referral ==
1456                     (follow_referral_t)NO_VALUE_SET)
1457                         attributes[n_attrs++] = FOLLOW_REFERRAL;
1458 
1459                 if (table_info->retrieveError ==
1460                     (__nis_retrieve_error_t)NO_VALUE_SET)
1461                         attributes[n_attrs++] = RETRIEVE_ERROR_ACTION;
1462                 if (table_info->retrieveErrorRetry.attempts == NO_VALUE_SET)
1463                         attributes[n_attrs++] = RETREIVE_ERROR_ATTEMPTS;
1464                 if (table_info->retrieveErrorRetry.timeout ==
1465                     (time_t)NO_VALUE_SET)
1466                         attributes[n_attrs++] = RETREIVE_ERROR_TIMEOUT;
1467                 if (table_info->storeError ==
1468                     (__nis_store_error_t)NO_VALUE_SET)
1469                         attributes[n_attrs++] = STORE_ERROR_ACTION;
1470                 if (table_info->storeErrorRetry.attempts == NO_VALUE_SET)
1471                         attributes[n_attrs++] = STORE_ERROR_ATTEMPTS;
1472                 if (table_info->storeErrorRetry.timeout ==
1473                     (time_t)NO_VALUE_SET)
1474                         attributes[n_attrs++] = STORE_ERROR_TIMEOUT;
1475                 if (table_info->refreshError ==
1476                     (__nis_refresh_error_t)NO_VALUE_SET)
1477                         attributes[n_attrs++] = REFRESH_ERROR_ACTION;
1478                 if (table_info->refreshErrorRetry.attempts == NO_VALUE_SET)
1479                         attributes[n_attrs++] = REFRESH_ERROR_ATTEMPTS;
1480                 if (table_info->refreshErrorRetry.timeout ==
1481                     (time_t)NO_VALUE_SET)
1482                         attributes[n_attrs++] = REFRESH_ERROR_TIMEOUT;
1483                 if (table_info->matchFetch ==
1484                     (__nis_match_fetch_t)NO_VALUE_SET)
1485                         attributes[n_attrs++] = MATCH_FETCH;
1486         }
1487 
1488         switch (nis_config->initialUpdate) {
1489         case (__nis_initial_update_t)NO_VALUE_SET:
1490                 attributes[n_attrs++] = INITIAL_UPDATE_ACTION;
1491                 attributes[n_attrs++] = INITIAL_UPDATE_ONLY;
1492                 break;
1493         case (__nis_initial_update_t)INITIAL_UPDATE_NO_ACTION:
1494         case (__nis_initial_update_t)NO_INITIAL_UPDATE_NO_ACTION:
1495                 attributes[n_attrs++] = INITIAL_UPDATE_ACTION;
1496                 break;
1497         case (__nis_initial_update_t)FROM_NO_INITIAL_UPDATE:
1498         case (__nis_initial_update_t)TO_NO_INITIAL_UPDATE:
1499                 attributes[n_attrs++] = INITIAL_UPDATE_ONLY;
1500                 break;
1501         }
1502 
1503         if (nis_config->threadCreationError ==
1504             (__nis_thread_creation_error_t)NO_VALUE_SET)
1505                 attributes[n_attrs++] = THREAD_CREATE_ERROR_ACTION;
1506         if (nis_config->threadCreationErrorTimeout.attempts == NO_VALUE_SET)
1507                 attributes[n_attrs++] = THREAD_CREATE_ERROR_ATTEMPTS;
1508         if (nis_config->threadCreationErrorTimeout.timeout ==
1509             (time_t)NO_VALUE_SET)
1510                 attributes[n_attrs++] = THREAD_CREATE_ERROR_TIMEOUT;
1511         if (nis_config->dumpError == (__nis_dump_error_t)NO_VALUE_SET)
1512                 attributes[n_attrs++] = DUMP_ERROR_ACTION;
1513         if (nis_config->dumpErrorTimeout.attempts == NO_VALUE_SET)
1514                 attributes[n_attrs++] = DUMP_ERROR_ATTEMPTS;
1515         if (nis_config->dumpErrorTimeout.timeout == (time_t)NO_VALUE_SET)
1516                 attributes[n_attrs++] = DUMP_ERROR_TIMEOUT;
1517         if (nis_config->resyncService == (__nis_resync_service_t)NO_VALUE_SET)
1518                 attributes[n_attrs++] = RESYNC;
1519         if (nis_config->updateBatching ==
1520             (__nis_update_batching_t)NO_VALUE_SET)
1521                 attributes[n_attrs++] = UPDATE_BATCHING;
1522         if (nis_config->updateBatchingTimeout.timeout == (time_t)NO_VALUE_SET)
1523                 attributes[n_attrs++] = UPDATE_BATCHING_TIMEOUT;
1524         if (nis_config->numberOfServiceThreads == (int)NO_VALUE_SET)
1525                 attributes[n_attrs++] = NUMBER_THEADS;
1526         if (nis_config->emulate_yp == (int)NO_VALUE_SET)
1527                 attributes[n_attrs++] = YP_EMULATION;
1528 
1529         /* maxRPCRecordSize is not configurable through LDAP profiles */
1530         if (nis_config->maxRPCRecordSize == (int)NO_VALUE_SET)
1531                 attributes[n_attrs++] = MAX_RPC_RECSIZE;
1532 
1533         attributes[n_attrs++] = NULL;
1534 }
1535 
1536 /*
1537  *      Notes on adding new attributes
1538  *      1. Determine where the attribute value will be saved
1539  *          Currently, the following structures are defined:
1540  *              __nis_config_info_t     config_info
1541  *              __nis_ldap_proxy_info   proxyInfo
1542  *              __nis_config_t          ldapConfig
1543  *              __nisdb_table_mapping_t ldapDBTableMapping
1544  *              __nis_table_mapping_t   ldapTableMapping
1545  *          or add a new structure or variable - this will require
1546  *          more code.
1547  *      2. Initialize the value to a known unconfigured value.
1548  *          This can be done in initialize_parse_structs or
1549  *          parse_ldap_migration.
1550  *      3. In the header file nis_parse_ldap_conf.h, add the name
1551  *          of the attribute. (Currently, the attribute name is assumed
1552  *          to be the same for the command line, the preference file,
1553  *          and LDAP.) The names are grouped logically. Add a corresponding
1554  *          config_key to the enum. Note that position in this file is
1555  *          essential because the macros such as IS_BIND_INFO depend on
1556  *          the sequence. The corresponding macro (IS_CONFIG_KEYWORD,
1557  *          IS_BIND_INFO, or IS_OPER_INFO) may need to be adjusted. These
1558  *          are used to partition the attributes into smaller chunks.
1559  *      4. Add the correspond entry to the keyword_lookup array in
1560  *          nis_parse_ldap_attr.c, which is used to determine the config_key
1561  *          from the corresponding key word.
1562  *      5. Add the attribute to the list of attributes to retrieve from
1563  *          the LDAP server if no value has been set in the function
1564  *          parse_ldap_config_dn_attrs. (This assumes that the attribute
1565  *          is not used to get the configuration from the LDAP server.)
1566  *      6. Add logic to parse the individual attribute in
1567  *          add_config_attribute, add_bind_attribute,
1568  *          add_operation_attribute, or add_mapping_attribute depending
1569  *          which group of attributes the added attribute belongs to.
1570  *      7. In set_default_values, if the attribute value has not been set, set
1571  *          the default value. If any additional fixup is needed depending
1572  *          on other configuration values, it should be done here.
1573  *      8. If an attribute name is a subset of another, parse_ldap_default_conf
1574  *          should be modified.
1575  */