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