Home | History | Annotate | Download | only in libnisdb
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <stdio.h>
     30 #include <string.h>
     31 #include <stdlib.h>
     32 #include <ctype.h>
     33 #include <fcntl.h>
     34 #include <unistd.h>
     35 #include <errno.h>
     36 #include <locale.h>
     37 #include <lber.h>
     38 #include <ldap.h>
     39 #include <syslog.h>
     40 
     41 #include "ldap_parse.h"
     42 #include "nis_parse_ldap_conf.h"
     43 
     44 extern FILE *cons;
     45 
     46 static bool_t get_timeval_t(const char *s, int len, struct timeval *t,
     47 	time_t default_val);
     48 static bool_t get_limit(const char *s, int len, int *limit, int default_val);
     49 static bool_t get_time_t(const char *s, time_t *t, time_t default_val);
     50 static bool_t get_uint_val(const char *attrib_val, int *val, int default_val);
     51 static bool_t get_int_val(const char *attrib_val, int *val, int default_val);
     52 static void warn_duplicate_val(config_key attrib_num);
     53 
     54 static struct {
     55 	const char	*key_name;
     56 	config_key	key_id;
     57 } keyword_lookup[] = {
     58 	{CONFIG_DN,		key_config_dn},
     59 	{YP_CONFIG_DN,	key_yp_config_dn},
     60 	{CONFIG_SERVER_LIST,	key_config_server_list},
     61 	{YP_CONFIG_SERVER_LIST,	key_yp_config_server_list},
     62 	{CONFIG_AUTH_METHOD,	key_config_auth_method},
     63 	{YP_CONFIG_AUTH_METHOD,	key_yp_config_auth_method},
     64 	{CONFIG_TLS_OPTION,		key_config_tls_option},
     65 	{YP_CONFIG_TLS_OPTION,	key_yp_config_tls_option},
     66 	{CONFIG_TLS_CERT_DB,	key_config_tls_certificate_db},
     67 	{YP_CONFIG_TLS_CERT_DB,	key_yp_config_tls_certificate_db},
     68 	{CONFIG_PROXY_USER,		key_config_proxy_user},
     69 	{YP_CONFIG_PROXY_USER,	key_yp_config_proxy_user},
     70 	{CONFIG_PROXY_PASSWD,	key_config_proxy_passwd},
     71 	{YP_CONFIG_PROXY_PASSWD,	key_yp_config_proxy_passwd},
     72 	{PREFERRED_SERVERS,		key_preferred_servers},
     73 	{AUTH_METHOD,		key_auth_method},
     74 	{TLS_OPTION,		key_tls_option},
     75 	{YP_TLS_OPTION,		key_yp_tls_option},
     76 	{TLS_CERT_DB,		key_tls_certificate_db},
     77 	{YP_TLS_CERT_DB,	key_yp_tls_certificate_db},
     78 	{SEARCH_BASE,		key_search_base},
     79 	{PROXY_USER,		key_proxy_user},
     80 	{YP_PROXY_USER,		key_yp_proxy_user},
     81 	{PROXY_PASSWD,		key_proxy_passwd},
     82 	{YP_PROXY_PASSWD,	key_yp_proxy_passwd},
     83 	{LDAP_BASE_DOMAIN,	key_ldap_base_domain},
     84 	{YP_LDAP_BASE_DOMAIN,	key_yp_ldap_base_domain},
     85 	{BIND_TIMEOUT,		key_bind_timeout},
     86 	{YP_BIND_TIMEOUT,	key_yp_bind_timeout},
     87 	{SEARCH_TIMEOUT,	key_search_timeout},
     88 	{YP_SEARCH_TIMEOUT,	key_yp_search_timeout},
     89 	{MODIFY_TIMEOUT,	key_modify_timeout},
     90 	{YP_MODIFY_TIMEOUT,	key_yp_modify_timeout},
     91 	{ADD_TIMEOUT,		key_add_timeout},
     92 	{YP_ADD_TIMEOUT,	key_yp_add_timeout},
     93 
     94 	{DELETE_TIMEOUT,	key_delete_timeout},
     95 	{YP_DELETE_TIMEOUT,	key_yp_delete_timeout},
     96 	{SEARCH_TIME_LIMIT,	key_search_time_limit},
     97 	{YP_SEARCH_TIME_LIMIT,	key_yp_search_time_limit},
     98 	{SEARCH_SIZE_LIMIT,	key_search_size_limit},
     99 	{YP_SEARCH_SIZE_LIMIT,	key_yp_search_size_limit},
    100 	{FOLLOW_REFERRAL,	key_follow_referral},
    101 	{YP_FOLLOW_REFERRAL,	key_yp_follow_referral},
    102 	{INITIAL_UPDATE_ACTION,	key_initial_update_action},
    103 	{INITIAL_UPDATE_ONLY,	key_initial_update_only},
    104 	{RETRIEVE_ERROR_ACTION,	key_retrieve_error_action},
    105 	{YP_RETRIEVE_ERROR_ACTION,	key_yp_retrieve_error_action},
    106 	{RETREIVE_ERROR_ATTEMPTS,
    107 				key_retrieve_error_attempts},
    108 	{YP_RETREIVE_ERROR_ATTEMPTS,
    109 				key_yp_retrieve_error_attempts},
    110 	{RETREIVE_ERROR_TIMEOUT,
    111 				key_retreive_error_timeout},
    112 	{YP_RETREIVE_ERROR_TIMEOUT,
    113 				key_yp_retreive_error_timeout},
    114 	{STORE_ERROR_ACTION,	key_store_error_action},
    115 	{YP_STORE_ERROR_ACTION,	key_yp_store_error_action},
    116 	{STORE_ERROR_ATTEMPTS,	key_store_error_attempts},
    117 	{YP_STORE_ERROR_ATTEMPTS,	key_yp_store_error_attempts},
    118 	{STORE_ERROR_TIMEOUT,	key_store_error_timeout},
    119 	{YP_STORE_ERROR_TIMEOUT,	key_yp_store_error_timeout},
    120 
    121 	{REFRESH_ERROR_ACTION,	key_refresh_error_action},
    122 
    123 	{REFRESH_ERROR_ATTEMPTS,
    124 				key_refresh_error_attempts},
    125 	{REFRESH_ERROR_TIMEOUT,	key_refresh_error_timeout},
    126 	{THREAD_CREATE_ERROR_ACTION,
    127 				key_thread_create_error_action},
    128 	{THREAD_CREATE_ERROR_ATTEMPTS,
    129 				key_thread_create_error_attempts},
    130 	{THREAD_CREATE_ERROR_TIMEOUT,
    131 				key_thread_create_error_timeout},
    132 	{DUMP_ERROR_ACTION,	key_dump_error_action},
    133 	{DUMP_ERROR_ATTEMPTS,	key_dump_error_attempts},
    134 	{DUMP_ERROR_TIMEOUT,	key_dump_error_timeout},
    135 	{RESYNC,		key_resync},
    136 	{UPDATE_BATCHING,	key_update_batching},
    137 	{UPDATE_BATCHING_TIMEOUT,
    138 				key_update_batching_timeout},
    139 	{MATCH_FETCH,		key_match_fetch},
    140 	{YP_MATCH_FETCH,	key_yp_match_fetch},
    141 	{NUMBER_THEADS,		key_number_threads},
    142 	{YP_EMULATION,		key_yp_emulation},
    143 	{MAX_RPC_RECSIZE,	key_max_rpc_recsize},
    144 	{YP_DOMAIN_CONTEXT,	key_yp_domain_context},
    145 	{YPPASSWDD_DOMAINS,	key_yppasswdd_domains},
    146 	{DB_ID_MAP,		key_db_id_map},
    147 	{YP_DB_ID_MAP,	key_yp_db_id_map},
    148 	{YP_COMMENT_CHAR,	key_yp_comment_char},
    149 	{YP_MAP_FLAGS,		key_yp_map_flags},
    150 	{ENTRY_TTL,		key_entry_ttl},
    151 	{YP_ENTRY_TTL,	key_yp_entry_ttl},
    152 	{YP_NAME_FIELDS,	key_yp_name_fields},
    153 	{YP_SPLIT_FIELD,	key_yp_split_field},
    154 	{YP_REPEATED_FIELD_SEPARATORS,	key_yp_repeated_field_separators},
    155 	{LDAP_OBJECT_DN,	key_ldap_object_dn},
    156 	{YP_LDAP_OBJECT_DN,	key_yp_ldap_object_dn},
    157 	{LDAP_TO_NISPLUS_MAP,	key_ldap_to_nisplus_map},
    158 	{LDAP_TO_NIS_MAP,	key_ldap_to_nis_map},
    159 	{NISPLUS_TO_LDAP_MAP,	key_nisplus_to_ldap_map},
    160 	{NIS_TO_LDAP_MAP,	key_nis_to_ldap_map}
    161 };
    162 
    163 /*
    164  * FUNCTION:	add_config_attribute
    165  *
    166  *	Adds the attribute value to __nis_config_info_t
    167  *	if the value is not yet set.
    168  *
    169  * RETURN VALUE:	0 on success, -1 on failure
    170  *
    171  * INPUT:		attribute number and value (assumed to be non-NULL)
    172  */
    173 
    174 int
    175 add_config_attribute(
    176 	config_key		attrib_num,
    177 	const char		*attrib_val,
    178 	int			attrib_len,
    179 	__nis_config_info_t	*config_info)
    180 {
    181 	switch (attrib_num) {
    182 		case key_yp_config_dn:
    183 		case key_config_dn:
    184 			if (config_info->config_dn == NULL) {
    185 				if (!validate_dn(attrib_val, attrib_len))
    186 					break;
    187 				config_info->config_dn =
    188 					s_strndup(attrib_val, attrib_len);
    189 			} else {
    190 				warn_duplicate_val(attrib_num);
    191 			}
    192 			break;
    193 		case key_yp_config_server_list:
    194 		case key_config_server_list:
    195 			if (config_info->default_servers == NULL) {
    196 				config_info->default_servers =
    197 					s_strndup(attrib_val, attrib_len);
    198 			} else {
    199 				warn_duplicate_val(attrib_num);
    200 			}
    201 			break;
    202 		case key_yp_config_auth_method:
    203 		case key_config_auth_method:
    204 			if (config_info->auth_method ==
    205 			    (auth_method_t)NO_VALUE_SET) {
    206 				if (same_string("none", attrib_val,
    207 						attrib_len))
    208 					config_info->auth_method = none;
    209 				else if (same_string("simple", attrib_val,
    210 						attrib_len))
    211 					config_info->auth_method = simple;
    212 				else if (same_string("sasl/cram-md5",
    213 						attrib_val, attrib_len))
    214 					config_info->auth_method = cram_md5;
    215 				else if (same_string("sasl/digest-md5",
    216 						attrib_val, attrib_len))
    217 					config_info->auth_method = digest_md5;
    218 				else
    219 					p_error = parse_bad_auth_method_error;
    220 			} else {
    221 				warn_duplicate_val(attrib_num);
    222 			}
    223 			break;
    224 		case key_yp_config_tls_option:
    225 		case key_config_tls_option:
    226 			if (config_info->tls_method ==
    227 			    (tls_method_t)NO_VALUE_SET) {
    228 				if (same_string("none", attrib_val,
    229 						attrib_len))
    230 					config_info->tls_method = no_tls;
    231 				else if (same_string("ssl", attrib_val,
    232 						attrib_len))
    233 					config_info->tls_method = ssl_tls;
    234 				else
    235 					p_error = parse_bad_tls_option_error;
    236 			} else {
    237 				warn_duplicate_val(attrib_num);
    238 			}
    239 			break;
    240 		case key_yp_config_tls_certificate_db:
    241 		case key_config_tls_certificate_db:
    242 			if (config_info->tls_cert_db == NULL) {
    243 				config_info->tls_cert_db =
    244 					s_strndup(attrib_val, attrib_len);
    245 			} else {
    246 				warn_duplicate_val(attrib_num);
    247 			}
    248 			break;
    249 		case key_yp_config_proxy_user:
    250 		case key_config_proxy_user:
    251 			if (config_info->proxy_dn == NULL) {
    252 				config_info->proxy_dn =
    253 					s_strndup(attrib_val, attrib_len);
    254 			} else {
    255 				warn_duplicate_val(attrib_num);
    256 			}
    257 			break;
    258 		case key_yp_config_proxy_passwd:
    259 		case key_config_proxy_passwd:
    260 			if (config_info->proxy_passwd == NULL) {
    261 				config_info->proxy_passwd =
    262 					s_strndup_esc(attrib_val, attrib_len);
    263 			} else {
    264 				warn_duplicate_val(attrib_num);
    265 			}
    266 			break;
    267 		default:
    268 			p_error = parse_internal_error;
    269 			break;
    270 	}
    271 	return (p_error == no_parse_error ? 0 : -1);
    272 }
    273 
    274 /*
    275  * FUNCTION:	add_bind_attribute
    276  *
    277  *	Adds the attribute value to __nis_ldap_proxy_info
    278  *	if the value is not yet set.
    279  *
    280  * RETURN VALUE:	0 on success, -1 on failure
    281  *
    282  * INPUT:		attribute number and value (assumed to be non-NULL)
    283  */
    284 
    285 int
    286 add_bind_attribute(
    287 	config_key		attrib_num,
    288 	const char		*attrib_val,
    289 	int			attrib_len,
    290 	__nis_ldap_proxy_info	*proxy_info)
    291 {
    292 	struct timeval	t;
    293 	int		limit;
    294 
    295 	switch (attrib_num) {
    296 		case key_yp_preferred_servers:
    297 		case key_preferred_servers:
    298 			if (proxy_info->default_servers == NULL) {
    299 				proxy_info->default_servers =
    300 					s_strndup(attrib_val, attrib_len);
    301 			} else {
    302 				warn_duplicate_val(attrib_num);
    303 			}
    304 			break;
    305 		case key_yp_auth_method:
    306 		case key_auth_method:
    307 			if (proxy_info->auth_method ==
    308 			    (auth_method_t)NO_VALUE_SET) {
    309 				if (same_string("none", attrib_val,
    310 						attrib_len))
    311 					proxy_info->auth_method = none;
    312 				else if (same_string("simple", attrib_val,
    313 						attrib_len))
    314 					proxy_info->auth_method = simple;
    315 				else if (same_string("sasl/cram-md5",
    316 						attrib_val, attrib_len))
    317 					proxy_info->auth_method = cram_md5;
    318 				else if (same_string("sasl/digest-md5",
    319 						attrib_val, attrib_len))
    320 					proxy_info->auth_method = digest_md5;
    321 				else
    322 					p_error = parse_bad_auth_method_error;
    323 			} else {
    324 				warn_duplicate_val(attrib_num);
    325 			}
    326 			break;
    327 		case key_yp_tls_option:
    328 		case key_tls_option:
    329 			if (proxy_info->tls_method ==
    330 			    (tls_method_t)NO_VALUE_SET) {
    331 				if (same_string("none", attrib_val,
    332 						attrib_len))
    333 					proxy_info->tls_method = no_tls;
    334 				else if (same_string("ssl", attrib_val,
    335 						attrib_len))
    336 					proxy_info->tls_method = ssl_tls;
    337 				else
    338 					p_error = parse_bad_tls_option_error;
    339 			} else {
    340 				warn_duplicate_val(attrib_num);
    341 			}
    342 			break;
    343 		case key_yp_tls_certificate_db:
    344 		case key_tls_certificate_db:
    345 			if (proxy_info->tls_cert_db == NULL) {
    346 				proxy_info->tls_cert_db =
    347 					s_strndup(attrib_val, attrib_len);
    348 			} else {
    349 				warn_duplicate_val(attrib_num);
    350 			}
    351 			break;
    352 		case key_yp_search_base:
    353 		case key_search_base:
    354 			if (proxy_info->default_search_base == NULL) {
    355 				if (!validate_dn(attrib_val, attrib_len))
    356 					break;
    357 				proxy_info->default_search_base =
    358 					s_strndup(attrib_val, attrib_len);
    359 			} else {
    360 				warn_duplicate_val(attrib_num);
    361 			}
    362 			break;
    363 		case key_yp_proxy_user:
    364 		case key_proxy_user:
    365 			if (proxy_info->proxy_dn == NULL) {
    366 				proxy_info->proxy_dn =
    367 					s_strndup(attrib_val, attrib_len);
    368 			} else {
    369 				warn_duplicate_val(attrib_num);
    370 			}
    371 			break;
    372 		case key_yp_proxy_passwd:
    373 		case key_proxy_passwd:
    374 			if (proxy_info->proxy_passwd == NULL) {
    375 				proxy_info->proxy_passwd =
    376 					s_strndup_esc(attrib_val, attrib_len);
    377 			} else {
    378 				warn_duplicate_val(attrib_num);
    379 			}
    380 			break;
    381 		case key_yp_ldap_base_domain:
    382 		case key_ldap_base_domain:
    383 			if (proxy_info->default_nis_domain == NULL) {
    384 				proxy_info->default_nis_domain =
    385 					s_strndup_esc(attrib_val, attrib_len);
    386 			} else {
    387 				warn_duplicate_val(attrib_num);
    388 			}
    389 			break;
    390 		case key_yp_bind_timeout:
    391 		case key_bind_timeout:
    392 			if (proxy_info->bind_timeout.tv_sec ==
    393 			    (time_t)NO_VALUE_SET) {
    394 				if (!get_timeval_t(attrib_val, attrib_len, &t,
    395 						DEFAULT_BIND_TIMEOUT))
    396 					break;
    397 				proxy_info->bind_timeout = t;
    398 			} else {
    399 				warn_duplicate_val(attrib_num);
    400 			}
    401 			break;
    402 		case key_yp_search_timeout:
    403 			if (proxy_info->search_timeout.tv_sec ==
    404 			    (time_t)NO_VALUE_SET) {
    405 				if (!get_timeval_t(attrib_val, attrib_len, &t,
    406 						DEFAULT_YP_SEARCH_TIMEOUT))
    407 					break;
    408 				proxy_info->search_timeout = t;
    409 			} else {
    410 				warn_duplicate_val(attrib_num);
    411 			}
    412 			break;
    413 
    414 		case key_search_timeout:
    415 			if (proxy_info->search_timeout.tv_sec ==
    416 			    (time_t)NO_VALUE_SET) {
    417 				if (!get_timeval_t(attrib_val, attrib_len, &t,
    418 						DEFAULT_SEARCH_TIMEOUT))
    419 					break;
    420 				proxy_info->search_timeout = t;
    421 			} else {
    422 				warn_duplicate_val(attrib_num);
    423 			}
    424 			break;
    425 		case key_yp_modify_timeout:
    426 		case key_modify_timeout:
    427 			if (proxy_info->modify_timeout.tv_sec ==
    428 			    (time_t)NO_VALUE_SET) {
    429 				if (!get_timeval_t(attrib_val, attrib_len, &t,
    430 						DEFAULT_MODIFY_TIMEOUT))
    431 					break;
    432 				proxy_info->modify_timeout = t;
    433 			} else {
    434 				warn_duplicate_val(attrib_num);
    435 			}
    436 			break;
    437 		case key_yp_add_timeout:
    438 		case key_add_timeout:
    439 			if (proxy_info->add_timeout.tv_sec ==
    440 			    (time_t)NO_VALUE_SET) {
    441 				if (!get_timeval_t(attrib_val, attrib_len, &t,
    442 						DEFAULT_ADD_TIMEOUT))
    443 					break;
    444 				proxy_info->add_timeout = t;
    445 			} else {
    446 				warn_duplicate_val(attrib_num);
    447 			}
    448 			break;
    449 		case key_yp_delete_timeout:
    450 		case key_delete_timeout:
    451 			if (proxy_info->delete_timeout.tv_sec ==
    452 			    (time_t)NO_VALUE_SET) {
    453 				if (!get_timeval_t(attrib_val, attrib_len, &t,
    454 						DEFAULT_DELETE_TIMEOUT))
    455 					break;
    456 				proxy_info->delete_timeout = t;
    457 			} else {
    458 				warn_duplicate_val(attrib_num);
    459 			}
    460 			break;
    461 		case key_yp_search_time_limit:
    462 		case key_search_time_limit:
    463 			if (proxy_info->search_time_limit ==
    464 			    (int)NO_VALUE_SET) {
    465 				if (!get_limit(attrib_val, attrib_len, &limit,
    466 						DEFAULT_SEARCH_TIME_LIMIT))
    467 					break;
    468 				proxy_info->search_time_limit = limit;
    469 			} else {
    470 				warn_duplicate_val(attrib_num);
    471 			}
    472 			break;
    473 		case key_yp_search_size_limit:
    474 		case key_search_size_limit:
    475 			if (proxy_info->search_size_limit ==
    476 			    (int)NO_VALUE_SET) {
    477 				if (!get_limit(attrib_val, attrib_len, &limit,
    478 						DEFAULT_SEARCH_SIZE_LIMIT))
    479 					break;
    480 				proxy_info->search_size_limit = limit;
    481 			} else {
    482 				warn_duplicate_val(attrib_num);
    483 			}
    484 			break;
    485 		case key_yp_follow_referral:
    486 		case key_follow_referral:
    487 			if (proxy_info->follow_referral ==
    488 					(follow_referral_t)NO_VALUE_SET) {
    489 			    if (same_string("yes", attrib_val, attrib_len))
    490 				proxy_info->follow_referral = follow;
    491 			    else if (same_string("no", attrib_val, attrib_len))
    492 				proxy_info->follow_referral = no_follow;
    493 			    else
    494 				p_error = parse_yes_or_no_expected_error;
    495 			} else {
    496 				warn_duplicate_val(attrib_num);
    497 			}
    498 			break;
    499 		default:
    500 			p_error = parse_internal_error;
    501 			break;
    502 	}
    503 	return (p_error == no_parse_error ? 0 : -1);
    504 }
    505 
    506 /*
    507  * FUNCTION:	add_operation_attribute
    508  *
    509  *	Adds the attribute value to __nis_config_t and
    510  *	__nisdb_table_mapping_t if the value is not yet set.
    511  *
    512  * RETURN VALUE:	0 on success, -1 on failure
    513  *
    514  * INPUT:		attribute number and value (assumed to be non-NULL)
    515  */
    516 
    517 int
    518 add_operation_attribute(
    519 	config_key		attrib_num,
    520 	const char		*attrib_val,
    521 	int			attrib_len,
    522 	__nis_config_t		*config_info,
    523 	__nisdb_table_mapping_t	*table_info)
    524 {
    525 	char	buf[1024];
    526 	int	i;
    527 	int	len;
    528 	time_t	timeout;
    529 	bool_t	last_digit = FALSE;
    530 
    531 	for (i = 0, len = 0; i < attrib_len; i++) {
    532 		if (!last_digit &&
    533 			is_whitespace(attrib_val[i]))
    534 				continue;
    535 		buf[len++] = attrib_val[i];
    536 		if (len >= sizeof (buf)) {
    537 			p_error = parse_line_too_long;
    538 			return (-1);
    539 		}
    540 		last_digit = isdigit(attrib_val[i]);
    541 	}
    542 	buf[len] = '\0';
    543 
    544 	switch (attrib_num) {
    545 	    case key_initial_update_action:
    546 		if (config_info->initialUpdate ==
    547 			(__nis_initial_update_t)NO_VALUE_SET) {
    548 		    if (strcasecmp("none", buf) == 0)
    549 			    config_info->initialUpdate = ini_none;
    550 		    else if (strcasecmp("from_ldap", buf) == 0)
    551 			    config_info->initialUpdate =
    552 				(__nis_initial_update_t)FROM_NO_INITIAL_UPDATE;
    553 		    else if (strcasecmp("to_ldap", buf) == 0)
    554 			    config_info->initialUpdate =
    555 				(__nis_initial_update_t)TO_NO_INITIAL_UPDATE;
    556 		    else
    557 			p_error = parse_initial_update_action_error;
    558 		} else if (config_info->initialUpdate ==
    559 			(__nis_initial_update_t)INITIAL_UPDATE_NO_ACTION) {
    560 		    if (strcasecmp("none", buf) == 0)
    561 			    config_info->initialUpdate = ini_none;
    562 		    else if (strcasecmp("from_ldap", buf) == 0)
    563 			    config_info->initialUpdate = from_ldap_update_only;
    564 		    else if (strcasecmp("to_ldap", buf) == 0)
    565 			    config_info->initialUpdate = to_ldap_update_only;
    566 		    else
    567 			p_error = parse_initial_update_action_error;
    568 		} else if (config_info->initialUpdate ==
    569 			(__nis_initial_update_t)NO_INITIAL_UPDATE_NO_ACTION) {
    570 		    if (strcasecmp("none", buf) == 0)
    571 			    config_info->initialUpdate = ini_none;
    572 		    else if (strcasecmp("from_ldap", buf) == 0)
    573 			    config_info->initialUpdate = from_ldap;
    574 		    else if (strcasecmp("to_ldap", buf) == 0)
    575 			    config_info->initialUpdate = to_ldap;
    576 		    else
    577 			p_error = parse_initial_update_action_error;
    578 		} else {
    579 		    warn_duplicate_val(attrib_num);
    580 		}
    581 		break;
    582 	    case key_initial_update_only:
    583 		if (config_info->initialUpdate ==
    584 			(__nis_initial_update_t)NO_VALUE_SET) {
    585 		    if (strcasecmp("yes", buf) == 0)
    586 			    config_info->initialUpdate =
    587 				(__nis_initial_update_t)
    588 					INITIAL_UPDATE_NO_ACTION;
    589 		    else if (strcasecmp("no", buf) == 0)
    590 			    config_info->initialUpdate =
    591 				(__nis_initial_update_t)
    592 					NO_INITIAL_UPDATE_NO_ACTION;
    593 		    else
    594 			p_error = parse_initial_update_only_error;
    595 		} else if (config_info->initialUpdate ==
    596 			(__nis_initial_update_t)FROM_NO_INITIAL_UPDATE) {
    597 		    if (strcasecmp("yes", buf) == 0)
    598 			    config_info->initialUpdate = from_ldap_update_only;
    599 		    else if (strcasecmp("no", buf) == 0)
    600 			    config_info->initialUpdate = from_ldap;
    601 		    else
    602 			p_error = parse_initial_update_only_error;
    603 		} else if (config_info->initialUpdate ==
    604 			(__nis_initial_update_t)TO_NO_INITIAL_UPDATE) {
    605 		    if (strcasecmp("yes", buf) == 0)
    606 			    config_info->initialUpdate = to_ldap_update_only;
    607 		    else if (strcasecmp("no", buf) == 0)
    608 			    config_info->initialUpdate = to_ldap;
    609 		    else
    610 			p_error = parse_initial_update_only_error;
    611 		} else if (config_info->initialUpdate != ini_none) {
    612 		    warn_duplicate_val(attrib_num);
    613 		}
    614 		break;
    615 	    case key_thread_create_error_action:
    616 		if (config_info->threadCreationError ==
    617 			(__nis_thread_creation_error_t)NO_VALUE_SET) {
    618 		    if (strcasecmp("pass_error", buf) == 0)
    619 			    config_info->threadCreationError = pass_error;
    620 		    else if (strcasecmp("retry", buf) == 0)
    621 			    config_info->threadCreationError = cre_retry;
    622 		    else
    623 			p_error = parse_thread_create_error_action_error;
    624 		} else {
    625 		    warn_duplicate_val(attrib_num);
    626 		}
    627 		break;
    628 	    case key_thread_create_error_attempts:
    629 		if (config_info->threadCreationErrorTimeout.attempts ==
    630 			NO_VALUE_SET) {
    631 		    if (get_int_val(buf, &i, DEFAULT_THREAD_ERROR_ATTEMPTS))
    632 			config_info->threadCreationErrorTimeout.attempts = i;
    633 		} else {
    634 		    warn_duplicate_val(attrib_num);
    635 		}
    636 		break;
    637 	    case key_thread_create_error_timeout:
    638 		if (config_info->threadCreationErrorTimeout.timeout ==
    639 			(time_t)NO_VALUE_SET) {
    640 		    if (get_time_t(buf, &timeout,
    641 				DEFAULT_THREAD_ERROR_TIME_OUT))
    642 			config_info->threadCreationErrorTimeout.timeout =
    643 				timeout;
    644 		} else {
    645 		    warn_duplicate_val(attrib_num);
    646 		}
    647 		break;
    648 	    case key_dump_error_action:
    649 		if (config_info->dumpError ==
    650 			(__nis_dump_error_t)NO_VALUE_SET) {
    651 		    if (strcasecmp("rollback", buf) == 0)
    652 			    config_info->dumpError = rollback;
    653 		    else if (strcasecmp("retry", buf) == 0)
    654 			    config_info->dumpError = de_retry;
    655 		    else
    656 			p_error = parse_dump_error_action_error;
    657 		} else {
    658 		    warn_duplicate_val(attrib_num);
    659 		}
    660 		break;
    661 	    case key_dump_error_attempts:
    662 		if (config_info->dumpErrorTimeout.attempts == NO_VALUE_SET) {
    663 		    if (get_int_val(buf, &i, DEFAULT_DUMP_ERROR_ATTEMPTS))
    664 			config_info->dumpErrorTimeout.attempts = i;
    665 		} else {
    666 		    warn_duplicate_val(attrib_num);
    667 		}
    668 		break;
    669 	    case key_dump_error_timeout:
    670 		if (config_info->dumpErrorTimeout.timeout ==
    671 			(time_t)NO_VALUE_SET) {
    672 		    if (get_time_t(buf, &timeout,
    673 				DEFAULT_DUMP_ERROR_TIME_OUT))
    674 			config_info->dumpErrorTimeout.timeout = timeout;
    675 		} else {
    676 		    warn_duplicate_val(attrib_num);
    677 		}
    678 		break;
    679 	    case key_resync:
    680 		if (config_info->resyncService ==
    681 			(__nis_resync_service_t)NO_VALUE_SET) {
    682 		    if (strcasecmp("directory_locked", buf) == 0)
    683 			    config_info->resyncService = directory_locked;
    684 		    else if (strcasecmp("from_copy", buf) == 0)
    685 			    config_info->resyncService = from_copy;
    686 		    else if (strcasecmp("from_live", buf) == 0)
    687 			    config_info->resyncService = from_live;
    688 		    else
    689 			p_error = parse_resync_error;
    690 		} else {
    691 		    warn_duplicate_val(attrib_num);
    692 		}
    693 		break;
    694 	    case key_update_batching:
    695 		if (config_info->updateBatching ==
    696 			(__nis_update_batching_t)NO_VALUE_SET) {
    697 		    if (strcasecmp("none", buf) == 0)
    698 			    config_info->updateBatching = upd_none;
    699 		    else if (strcasecmp("accumulate", buf) == 0) {
    700 			    config_info->updateBatching = accumulate;
    701 		    } else if (strcasecmp("bounded_accumulate", buf) == 0) {
    702 			    config_info->updateBatching = bounded_accumulate;
    703 		    } else
    704 			p_error = parse_update_batching_error;
    705 		} else {
    706 		    warn_duplicate_val(attrib_num);
    707 		}
    708 		break;
    709 	    case key_update_batching_timeout:
    710 		if (config_info->updateBatchingTimeout.timeout ==
    711 			(time_t)NO_VALUE_SET) {
    712 		    if (get_time_t(buf, &timeout, DEFAULT_BATCHING_TIME_OUT))
    713 			config_info->updateBatchingTimeout.timeout = timeout;
    714 		} else {
    715 		    warn_duplicate_val(attrib_num);
    716 		}
    717 		break;
    718 	    case key_number_threads:
    719 		if (config_info->numberOfServiceThreads ==
    720 			(int)NO_VALUE_SET) {
    721 		    if (get_uint_val(buf, &i, DEFAULT_NUMBER_OF_THREADS))
    722 			    config_info->numberOfServiceThreads = i;
    723 		} else {
    724 		    warn_duplicate_val(attrib_num);
    725 		}
    726 		break;
    727 	    case key_yp_emulation:
    728 		if (config_info->emulate_yp ==
    729 			(int)NO_VALUE_SET) {
    730 		    if (strcasecmp("yes", buf) == 0)
    731 			    config_info->emulate_yp = TRUE;
    732 		} else {
    733 		    warn_duplicate_val(attrib_num);
    734 		}
    735 		break;
    736 		case key_yp_retrieve_error_action:
    737 		if (table_info->retrieveError ==
    738 			(__nis_retrieve_error_t)NO_VALUE_SET) {
    739 			if (strcasecmp("use_cached", buf) == 0)
    740 				table_info->retrieveError = use_cached;
    741 			else if (strcasecmp("fail", buf) == 0)
    742 				table_info->retrieveError = fail;
    743 			else
    744 		p_error = parse_yp_retrieve_error_action_error;
    745 		} else {
    746 			warn_duplicate_val(attrib_num);
    747 		}
    748 		break;
    749 	    case key_retrieve_error_action:
    750 		if (table_info->retrieveError ==
    751 			(__nis_retrieve_error_t)NO_VALUE_SET) {
    752 		    if (strcasecmp("use_cached", buf) == 0)
    753 			    table_info->retrieveError = use_cached;
    754 		    else if (strcasecmp("try_again", buf) == 0)
    755 			    table_info->retrieveError = try_again;
    756 		    else if (strcasecmp("unavail", buf) == 0)
    757 			    table_info->retrieveError = ret_unavail;
    758 		    else if (strcasecmp("no_such_name", buf) == 0)
    759 			    table_info->retrieveError = no_such_name;
    760 		    else if (strcasecmp("retry", buf) == 0)
    761 			    table_info->retrieveError = ret_retry;
    762 		    else
    763 			p_error = parse_retrieve_error_action_error;
    764 		} else {
    765 		    warn_duplicate_val(attrib_num);
    766 		}
    767 		break;
    768 		case key_yp_retrieve_error_attempts:
    769 	    case key_retrieve_error_attempts:
    770 		if (table_info->retrieveErrorRetry.attempts == NO_VALUE_SET) {
    771 		    if (get_int_val(buf, &i, DEFAULT_RETRIEVE_ERROR_ATTEMPTS))
    772 			table_info->retrieveErrorRetry.attempts = i;
    773 		} else {
    774 		    warn_duplicate_val(attrib_num);
    775 		}
    776 		break;
    777 		case key_yp_retreive_error_timeout:
    778 	    case key_retreive_error_timeout:
    779 		if (table_info->retrieveErrorRetry.timeout ==
    780 			(time_t)NO_VALUE_SET) {
    781 		    if (get_time_t(buf, &timeout,
    782 				DEFAULT_RETRIEVE_ERROR_TIME_OUT))
    783 			table_info->retrieveErrorRetry.timeout = timeout;
    784 		} else {
    785 		    warn_duplicate_val(attrib_num);
    786 		}
    787 		break;
    788 		case key_yp_store_error_action:
    789 		if (table_info->storeError ==
    790 			(__nis_store_error_t)NO_VALUE_SET) {
    791 			if (strcasecmp("retry", buf) == 0)
    792 				table_info->storeError = sto_retry;
    793 			else if (strcasecmp("fail", buf) == 0)
    794 				table_info->storeError = sto_fail;
    795 			else
    796 			p_error = parse_yp_store_error_action_error;
    797 		} else {
    798 			warn_duplicate_val(attrib_num);
    799 		}
    800 		break;
    801 	    case key_store_error_action:
    802 		if (table_info->storeError ==
    803 			(__nis_store_error_t)NO_VALUE_SET) {
    804 		    if (strcasecmp("system_error", buf) == 0)
    805 			    table_info->storeError = system_error;
    806 		    else if (strcasecmp("unavail", buf) == 0)
    807 			    table_info->storeError = sto_unavail;
    808 		    else if (strcasecmp("retry", buf) == 0)
    809 			    table_info->storeError = sto_retry;
    810 		    else
    811 			p_error = parse_store_error_action_error;
    812 		} else {
    813 		    warn_duplicate_val(attrib_num);
    814 		}
    815 		break;
    816 		case key_yp_store_error_attempts:
    817 	    case key_store_error_attempts:
    818 		if (table_info->storeErrorRetry.attempts == NO_VALUE_SET) {
    819 		    if (get_int_val(buf, &i,
    820 				DEFAULT_STORE_ERROR_ATTEMPTS))
    821 			table_info->storeErrorRetry.attempts = i;
    822 		} else {
    823 		    warn_duplicate_val(attrib_num);
    824 		}
    825 		break;
    826 		case key_yp_store_error_timeout:
    827 	    case key_store_error_timeout:
    828 		if (table_info->storeErrorRetry.timeout ==
    829 			(time_t)NO_VALUE_SET) {
    830 		    if (get_time_t(buf, &timeout,
    831 				DEFAULT_STORE_ERROR_TIME_OUT))
    832 			table_info->storeErrorRetry.timeout = timeout;
    833 		} else {
    834 		    warn_duplicate_val(attrib_num);
    835 		}
    836 		break;
    837 	    case key_refresh_error_action:
    838 		if (table_info->refreshError ==
    839 			(__nis_refresh_error_t)NO_VALUE_SET) {
    840 		    if (strcasecmp("continue_using", buf) == 0)
    841 			    table_info->refreshError = continue_using;
    842 		    else if (strcasecmp("cache_expired", buf) == 0)
    843 			    table_info->refreshError = cache_expired;
    844 		    else if (strcasecmp("tryagain", buf) == 0)
    845 			    table_info->refreshError = tryagain;
    846 		    else if (strcasecmp("retry", buf) == 0)
    847 			    table_info->refreshError = ref_retry;
    848 		    else if (strcasecmp("continue_using,retry", buf) == 0 ||
    849 			strcasecmp("retry,continue_using", buf) == 0)
    850 			    table_info->refreshError = continue_using_retry;
    851 		    else
    852 			p_error = parse_refresh_error_action_error;
    853 		} else {
    854 		    warn_duplicate_val(attrib_num);
    855 		}
    856 		break;
    857 	    case key_refresh_error_attempts:
    858 		if (table_info->refreshErrorRetry.attempts == NO_VALUE_SET) {
    859 		    if (get_int_val(buf, &i, DEFAULT_REFRESH_ERROR_ATTEMPTS))
    860 			table_info->refreshErrorRetry.attempts = i;
    861 		} else {
    862 		    warn_duplicate_val(attrib_num);
    863 		}
    864 		break;
    865 	    case key_refresh_error_timeout:
    866 		if (table_info->refreshErrorRetry.timeout ==
    867 			(time_t)NO_VALUE_SET) {
    868 		    if (get_time_t(buf, &timeout,
    869 				DEFAULT_REFRESH_ERROR_TIME_OUT))
    870 			table_info->refreshErrorRetry.timeout = timeout;
    871 		} else {
    872 		    warn_duplicate_val(attrib_num);
    873 		}
    874 		break;
    875 		case key_yp_match_fetch:
    876 	    case key_match_fetch:
    877 		if (table_info->matchFetch ==
    878 			(__nis_match_fetch_t)NO_VALUE_SET) {
    879 		    if (strcasecmp("no_match_only", buf) == 0)
    880 			    table_info->matchFetch = no_match_only;
    881 		    else if (strcasecmp("always", buf) == 0)
    882 			    table_info->matchFetch = mat_always;
    883 		    else if (strcasecmp("never", buf) == 0)
    884 			    table_info->matchFetch = mat_never;
    885 		    else
    886 			p_error = parse_match_fetch_error;
    887 		} else {
    888 		    warn_duplicate_val(attrib_num);
    889 		}
    890 		break;
    891 	    case key_max_rpc_recsize:
    892 		if (config_info->maxRPCRecordSize ==
    893 			(int)NO_VALUE_SET) {
    894 		    if (get_uint_val(buf, &i, RPC_MAXDATASIZE))
    895 			    config_info->maxRPCRecordSize = i;
    896 		} else {
    897 		    warn_duplicate_val(attrib_num);
    898 		}
    899 		break;
    900 	    default:
    901 		p_error = parse_internal_error;
    902 		break;
    903 	}
    904 
    905 	return (p_error == no_parse_error ? 0 : -1);
    906 }
    907 
    908 /*
    909  * FUNCTION:	get_attrib_num
    910  *
    911  *	Get the attribute number for the corresponding keyword.
    912  *
    913  * RETURN VALUE:	attribute number on success,
    914  *			key_bad on failure
    915  *
    916  * INPUT:		the attribute name string (assumed to be non-NULL)
    917  */
    918 
    919 config_key
    920 get_attrib_num(const char *s, int n)
    921 {
    922 	int		k;
    923 	int		i;
    924 	config_key	attrib_num = key_bad;
    925 
    926 	k = n < sizeof (_key_val) ? n : sizeof (_key_val) - 1;
    927 	(void) memcpy(_key_val, s, k);
    928 	_key_val[k] = '\0';
    929 
    930 	for (i = 0; i < sizeof (keyword_lookup) /
    931 			sizeof (keyword_lookup[0]); i++) {
    932 		if (strncasecmp(s, keyword_lookup[i].key_name, n) == 0 &&
    933 				strlen(keyword_lookup[i].key_name) == n) {
    934 			attrib_num = keyword_lookup[i].key_id;
    935 			break;
    936 		}
    937 	}
    938 
    939 	if (attrib_num == key_bad) {
    940 		p_error = parse_bad_key;
    941 	}
    942 
    943 	return (attrib_num);
    944 }
    945 
    946 /*
    947  * FUNCTION:	get_timeval_t
    948  *
    949  *	Extract time from string
    950  *
    951  * RETURN VALUE:	TRUE if parsed
    952  *			FALSE otherwise
    953  *
    954  * INPUT:		the attribute value string (assumed to be non-NULL)
    955  */
    956 
    957 static bool_t
    958 get_timeval_t(
    959 	const char	*s,
    960 	int		len,
    961 	struct timeval	*t,
    962 	time_t		default_val)
    963 {
    964 	time_t		tv_sec		= 0;
    965 	time_t		tv_usec		= 0;
    966 	time_t		digit;
    967 	time_t		mult		= 100000;
    968 	bool_t		got_digit	= FALSE;
    969 	bool_t		got_period	= FALSE;
    970 	const char	*s_end		= s + len;