/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2015 Gary Mills
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <locale.h>
#include <sys/stat.h>
#include <lber.h>
#include <ldap.h>
#include <deflt.h>
#include "ldap_map.h"
#include "ldap_parse.h"
#include "ldap_glob.h"
#include "nis_parse_ldap_conf.h"
__nis_ldap_proxy_info proxyInfo =
{NULL, (auth_method_t)NO_VALUE_SET, (tls_method_t)NO_VALUE_SET, NULL,
NULL, NULL, NULL, NULL, (follow_referral_t)NO_VALUE_SET};
__nis_config_t ldapConfig;
__nisdb_table_mapping_t ldapDBTableMapping;
__nis_table_mapping_t *ldapTableMapping = NULL;
__yp_domain_context_t ypDomains;
parse_error p_error = no_parse_error;
int cur_line_num = 0;
int start_line_num = 0;
int seq_num = 0;
const char *warn_file = NULL;
char _key_val[38];
const char *command_line_source = NULL;
const char *file_source = NULL;
const char *ldap_source = NULL;
static
const char *const *cmdline_config = NULL;
static bool_t got_config_data = FALSE;
/* high level parsing functions functions */
static int parse_ldap_cmd_line(const char *const *cmdline_options,
__nis_ldap_proxy_info *proxy_info, __nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping, __nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info);
static int parse_ldap_default_conf(__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config, __nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info);
static int parse_ldap_config_file(const char *config_file,
__nis_ldap_proxy_info *proxy_info, __nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping, __nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info);
static int parse_ldap_config_dn_attrs(__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config, __nis_table_mapping_t **table_mapping,
__nis_config_info_t *config_info, __nisdb_table_mapping_t *table_info);
static int yp_parse_ldap_default_conf(__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config, __nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info);
/* Forward declarations */
int yp_parse_ldap_config_file(const char *, __nis_ldap_proxy_info *,
__nis_config_t *, __nis_table_mapping_t **, __nis_config_info_t *,
__nisdb_table_mapping_t *, __yp_domain_context_t *);
/* helper functions */
static config_key get_attrib_num_cmdline(const char *s,
const char **begin_s, const char **end_s);
static config_key get_file_attr_val(int fd, char **attr_val);
static void get_attribute_list(
const __nis_ldap_proxy_info *proxy_info,
const __nis_config_t *nis_config,
const __nis_config_info_t *config_info,
const __nisdb_table_mapping_t *table_info,
char **ldap_config_attributes);
/*
* FUNCTION: parse_ldap_migration
*
* Parses the information for LDAP. The values are first
* obtained from the command line, secondly from the preference
* file, and finally from an LDAP profile (if so configured in
* the command line or preference file). Any unset values will
* be set to their default values.
*
* If no command line options, no settings in the /etc/default
* configuration file, and no mapping file, then no mapping
* should be used.
*
* RETURN VALUE:
* 0 Success
* -1 Config file stat/open or parse error
* 1 No mapping should be used.
*
* INPUT: command line parameters, configuration file
*/
int
parse_ldap_migration(
const char *const *cmdline_options,
const char *config_file)
{
int rc = 0;
__nis_config_info_t config_info
= {NULL, NULL, (auth_method_t)NO_VALUE_SET,
(tls_method_t)NO_VALUE_SET, NULL,
NULL, NULL};
struct stat buf;
p_error = no_parse_error;
if (verbose)
report_info("Getting LDAP configuration", NULL);
initialize_parse_structs(&proxyInfo, &ldapConfig, &ldapDBTableMapping);
if (yp2ldap)
initialize_yp_parse_structs(&ypDomains);
if (cmdline_options != NULL) {
got_config_data = TRUE;
/* NIS to LDAP does not read command line attributes */
if (!yp2ldap)
rc = parse_ldap_cmd_line(cmdline_options, &proxyInfo,
&ldapConfig, &ldapTableMapping, &config_info,
&ldapDBTableMapping);
else
rc = 0;
}
if (rc == 0) {
if (yp2ldap)
rc = yp_parse_ldap_default_conf(&proxyInfo, &ldapConfig,
&config_info, &ldapDBTableMapping);
else
rc = parse_ldap_default_conf(&proxyInfo, &ldapConfig,
&config_info, &ldapDBTableMapping);
}
if (config_file == NULL) {
if (yp2ldap) {
if (stat(YP_DEFAULT_MAPPING_FILE, &buf) == 0)
config_file = YP_DEFAULT_MAPPING_FILE;
} else {
if (stat(DEFAULT_MAPPING_FILE, &buf) == 0)
config_file = DEFAULT_MAPPING_FILE;
}
}
if (rc == 0 && config_file != NULL) {
got_config_data = TRUE;
warn_file = config_file;
cmdline_config = cmdline_options;
if (yp2ldap)
rc = yp_parse_ldap_config_file(config_file, &proxyInfo,
&ldapConfig, &ldapTableMapping, &config_info,
&ldapDBTableMapping, &ypDomains);
else
rc = parse_ldap_config_file(config_file, &proxyInfo,
&ldapConfig, &ldapTableMapping, &config_info,
&ldapDBTableMapping);
warn_file = NULL;
cmdline_config = NULL;
}
if (rc == 0 && (config_info.config_dn != NULL) &&
(config_info.config_dn[0] != '\0')) {
rc = parse_ldap_config_dn_attrs(&proxyInfo,
&ldapConfig, &ldapTableMapping, &config_info,
&ldapDBTableMapping);
}
free_config_info(&config_info);
if (rc == 0 && got_config_data == FALSE)
rc = 1;
set_default_values(&proxyInfo, &ldapConfig, &ldapDBTableMapping);
if (yp2ldap == 1 && rc == 0) {
rc = second_parser_pass(&ldapTableMapping);
if (rc == 0)
rc = final_parser_pass(&ldapTableMapping, &ypDomains);
if (rc == -2)
return (-1);
}
if (rc == 0)
rc = finish_parse(&proxyInfo, &ldapTableMapping);
if (rc == 0)
rc = linked2hash(ldapTableMapping);
if ((rc == 0) && yptol_mode)
rc = map_id_list_init();
if (rc != 0) {
free_parse_structs();
} else if (verbose)
report_info("LDAP configuration complete", NULL);
return (rc);
}
/*
* FUNCTION: parse_ldap_cmd_line
*
* Parses the information for LDAP from the command line
*
* RETURN VALUE: 0 on success, -1 on failure
*
* INPUT: command line values
*/
static int
parse_ldap_cmd_line(
const char *const *cmdline_options,
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping,
__nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info)
{
int rc = 0;
config_key attrib_num;
const char *begin_s;
const char *end_s;
if (verbose)
report_info("Command line values: ", NULL);
while (*cmdline_options != NULL) {
if (verbose)
report_info("\t", *cmdline_options);
attrib_num = get_attrib_num_cmdline(
*cmdline_options, &begin_s, &end_s);
if (attrib_num == key_bad) {
command_line_source = "command line";
report_error(*cmdline_options, NULL);
command_line_source = NULL;
rc = -1;
break;
} else if (IS_CONFIG_KEYWORD(attrib_num)) {
rc = add_config_attribute(attrib_num,
begin_s, end_s - begin_s, config_info);
} else if (IS_BIND_INFO(attrib_num)) {
rc = add_bind_attribute(attrib_num,
begin_s, end_s - begin_s, proxy_info);
} else if (IS_OPER_INFO(attrib_num)) {
rc = add_operation_attribute(attrib_num,
begin_s, end_s - begin_s, nis_config,
table_info);
} else {
rc = add_mapping_attribute(attrib_num,
begin_s, end_s - begin_s, table_mapping);
}
if (rc < 0) {
command_line_source = "command line";
report_error(begin_s, _key_val);
command_line_source = NULL;
break;
}
cmdline_options++;
}
return (rc);
}
static int
parse_ldap_default_conf(
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info)
{
int rc = 0;
char *ldap_config_attributes[n_config_keys];
char attr_buf[128];
char *attr;
char *attr_val;
int defflags;
config_key attrib_num;
int i;
int len;
int attr_len;
void *defp;
if ((defp = defopen_r(ETCCONFFILE)) != NULL) {
file_source = ETCCONFFILE;
if (verbose)
report_info("default configuration values: ", NULL);
/* Set defread_r() to be case insensitive */
defflags = defcntl_r(DC_GETFLAGS, 0, defp);
TURNOFF(defflags, DC_CASE);
(void) defcntl_r(DC_SETFLAGS, defflags, defp);
get_attribute_list(proxy_info, nis_config, config_info,
table_info, ldap_config_attributes);
i = 0;
while ((attr = ldap_config_attributes[i++]) != NULL) {
(void) strlcpy(attr_buf, attr, sizeof (attr_buf));
/*
* if nisplusUpdateBatching, make sure
* we don't match nisplusUpdateBatchingTimeout
*/
if (strcmp(attr, UPDATE_BATCHING) == 0) {
attr_len = strlen(attr);
attr_buf[attr_len] = '=';
attr_buf[attr_len + 1] = '\0';
attr_val = defread_r(attr_buf, defp);
if (attr_val == 0) {
attr_buf[attr_len] = ' ';
attr_val = defread_r(attr_buf, defp);
}
if (attr_val == 0) {
attr_buf[attr_len] = '\t';
attr_val = defread_r(attr_buf, defp);
}
if (attr_val == 0) {
attr_buf[attr_len] = '\n';
attr_val = defread_r(attr_buf, defp);
}
} else {
attr_val = defread_r(attr_buf, defp);
}
if (attr_val == NULL)
continue;
got_config_data = TRUE;
attrib_num = get_attrib_num(attr, strlen(attr));
if (attrib_num == key_bad) {
report_error(attr, NULL);
rc = -1;
break;
}
/*
* Allow either entries of the form
* attr val
* or
* attr = val
*/
while (is_whitespace(*attr_val))
attr_val++;
if (*attr_val == '=')
attr_val++;
while (is_whitespace(*attr_val))
attr_val++;
len = strlen(attr_val);
while (len > 0 && is_whitespace(attr_val[len - 1]))
len--;
if (verbose) {
report_info("\t", attr);
report_info("\t\t", attr_val);
}
if (IS_BIND_INFO(attrib_num)) {
rc = add_bind_attribute(attrib_num,
attr_val, len, proxy_info);
} else if (IS_OPER_INFO(attrib_num)) {
rc = add_operation_attribute(attrib_num,
attr_val, len, nis_config,
table_info);
}
if (p_error != no_parse_error) {
report_error(attr_val, attr);
rc = -1;
break;
}
}
file_source = NULL;
/* Close the /etc/default file */
defclose_r(defp);
}
return (rc);
}
static int
yp_parse_ldap_default_conf(
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info)
{
int rc = 0;
char *ldap_config_attributes[n_config_keys];
char attr_buf[128];
char *attr;
char *attr_val;
int defflags;
config_key attrib_num;
int i, len;
void *defp;
if ((defp = defopen_r(YP_ETCCONFFILE)) != NULL) {
file_source = YP_ETCCONFFILE;
if (verbose)
report_info("default configuration values: ", NULL);
/* Set defread_r() to be case insensitive */
defflags = defcntl_r(DC_GETFLAGS, 0, defp);
TURNOFF(defflags, DC_CASE);
(void) defcntl_r(DC_SETFLAGS, defflags, defp);
get_attribute_list(proxy_info, nis_config, config_info,
table_info, ldap_config_attributes);
i = 0;
while ((attr = ldap_config_attributes[i++]) != NULL) {
if ((strlcpy(attr_buf, attr, sizeof (attr_buf))) >=
sizeof (attr_buf)) {
report_error(
"Static buffer attr_buf overflow", NULL);
defclose_r(defp);
return (-1);
}
if ((attr_val = defread_r(attr_buf, defp)) == NULL)
continue;
got_config_data = TRUE;
attrib_num = get_attrib_num(attr, strlen(attr));
if (attrib_num == key_bad) {
report_error(attr, NULL);
rc = -1;
break;
}
/*
* Allow either entries of the form
* attr val
* or
* attr = val
*/
while (is_whitespace(*attr_val))
attr_val++;
if (*attr_val == '=')
attr_val++;
while (is_whitespace(*attr_val))
attr_val++;
len = strlen(attr_val);
while (len > 0 && is_whitespace(attr_val[len - 1]))
len--;
if (verbose) {
report_info("\t", attr);
report_info("\t\t", attr_val);
}
if (IS_YP_BIND_INFO(attrib_num)) {
rc = add_bind_attribute(attrib_num,
attr_val, len, proxy_info);
} else if (IS_YP_OPER_INFO(attrib_num)) {
rc = add_operation_attribute(attrib_num,
attr_val, len, nis_config,
table_info);
}
if (p_error != no_parse_error) {
report_error(attr_val, attr);
rc = -1;
break;
}
}
file_source = NULL;
/* Close the /etc/default file */
defclose_r(defp);
}
return (rc);
}
/*
* FUNCTION: get_attrib_num_cmdline
*
* Parses the information for LDAP from the command line
* The form of the command line request is
* -x attribute=value
*
* RETURN VALUE: 0 on success, -1 on failure
*
* INPUT: command line values
*/
static config_key
get_attrib_num_cmdline(
const char *s,
const char **begin_s,
const char **end_s)
{
const char *s_end = s + strlen(s);
const char *equal_s;
const char *s1;
config_key attrib_num;
while (s < s_end && is_whitespace(*s))
s++;
for (equal_s = s; equal_s < s_end; equal_s++)
if (*equal_s == EQUAL_CHAR)
break;
if (equal_s == s_end) {
p_error = parse_bad_command_line_attribute_format;
return (key_bad);
}
for (s1 = equal_s; s1 > s && is_whitespace(s1[-1]); s1--)
;
if (s1 == s) {
p_error = parse_bad_command_line_attribute_format;
return (key_bad);
}
attrib_num = get_attrib_num(s, s1 - s);
if (attrib_num != key_bad) {
s1 = equal_s + 1;
while (s1 < s_end && is_whitespace(*s1))
s1++;
*begin_s = s1;
while (s_end > s1 && is_whitespace(s_end[-1]))
s_end--;
*end_s = s_end;
}
return (attrib_num);
}
/*
* FUNCTION: parse_ldap_config_file
*
* Parses the information for LDAP from a configuration
* file. If no file is specified, /var/nis/NIS+LDAPmapping
* is used
*
* RETURN VALUE: 0 on success, -1 on failure
*
* INPUT: configuration file name
*/
static int
parse_ldap_config_file(
const char *config_file,
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping,
__nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info)
{
int rc = 0;
config_key attrib_num;
int fd;
char *attr_val;
int len;
if ((fd = open(config_file, O_RDONLY)) == -1) {
p_error = parse_open_file_error;
report_error(config_file, NULL);
return (-1);
}
start_line_num = 1;
cur_line_num = 1;
if (verbose)
report_info("Reading configuration from ", config_file);
file_source = config_file;
while ((attrib_num = get_file_attr_val(fd, &attr_val)) > 0) {
len = attr_val == NULL ? 0 : strlen(attr_val);
if (IS_CONFIG_KEYWORD(attrib_num)) {
rc = add_config_attribute(attrib_num,
attr_val, len, config_info);
} else if (IS_BIND_INFO(attrib_num)) {
rc = add_bind_attribute(attrib_num,
attr_val, len, proxy_info);
} else if (IS_OPER_INFO(attrib_num)) {
rc = add_operation_attribute(attrib_num,
attr_val, len, nis_config, table_info);
} else {
rc = add_mapping_attribute(attrib_num,
attr_val, len, table_mapping);
}
if (rc < 0) {
report_error(attr_val == NULL ?
"<no attribute>" : attr_val, _key_val);
if (attr_val)
free(attr_val);
break;
}
if (attr_val)
free(attr_val);
}
(void) close(fd);
if (attrib_num == key_bad) {
report_error(_key_val, NULL);
rc = -1;
}
start_line_num = 0;
file_source = NULL;
return (rc);
}
/*
* FUNCTION: yp_parse_ldap_config_file
*
* Parses the information for LDAP from a configuration
* file. If no file is specified, /var/yp/NISLDAPmapping
* is used
*
* RETURN VALUE: 0 on success, -1 on failure
*
* INPUT: configuration file name
*/
int
yp_parse_ldap_config_file(
const char *config_file,
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping,
__nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info,
__yp_domain_context_t *ypDomains)
{
int rc = 0;
config_key attrib_num;
int fd;
char *attr_val = NULL;
int len;
if ((fd = open(config_file, O_RDONLY)) == -1) {
p_error = parse_open_file_error;
report_error(config_file, NULL);
return (-1);
}
start_line_num = 1;
cur_line_num = 1;
if (verbose)
report_info("Reading configuration from ", config_file);
file_source = config_file;
while ((attrib_num = get_file_attr_val(fd, &attr_val)) > 0) {
len = attr_val == NULL ? 0 : strlen(attr_val);
if (IS_YP_CONFIG_KEYWORD(attrib_num)) {
rc = add_config_attribute(attrib_num,
attr_val, len, config_info);
} else if (IS_YP_BIND_INFO(attrib_num)) {
rc = add_bind_attribute(attrib_num,
attr_val, len, proxy_info);
} else if (IS_YP_OPER_INFO(attrib_num)) {
rc = add_operation_attribute(attrib_num,
attr_val, len, nis_config, table_info);
} else if (IS_YP_DOMAIN_INFO(attrib_num)) {
rc = add_ypdomains_attribute(attrib_num,
attr_val, len, ypDomains);
} else if (IS_YP_MAP_ATTR(attrib_num)) {
rc = add_mapping_attribute(attrib_num,
attr_val, len, table_mapping);
} else {
rc = -1;
p_error = parse_unsupported_format;
}
if (rc < 0) {
report_error(attr_val == NULL ?
"<no attribute>" : attr_val, _key_val);
if (attr_val)
free(attr_val);
break;
}
if (attr_val) {
free(attr_val);
attr_val = NULL;
}
}
(void) close(fd);
if (attrib_num == key_bad) {
report_error(_key_val, NULL);
rc = -1;
}
start_line_num = 0;
file_source = NULL;
return (rc);
}
/*
* FUNCTION: get_file_attr_val
*
* Gets the next attribute from the configuration file.
*
* RETURN VALUE: The config key if more attributes
* no_more_keys if eof
* key_bad if error
*/
static config_key
get_file_attr_val(int fd, char **attr_val)
{
char buf[BUFSIZE];
char *start_tag;
char *start_val;
char *end_val;
char *cut_here;
char *s;
char *a;
char *attribute_value;
int ret;
config_key attrib_num = no_more_keys;
*attr_val = NULL;
if ((ret = read_line(fd, buf, sizeof (buf))) > 0) {
for (s = buf; is_whitespace(*s); s++)
;
start_tag = s;
while (*s != '\0' && !is_whitespace(*s))
s++;
if (verbose)
report_info("\t", start_tag);
attrib_num = get_attrib_num(start_tag, s - start_tag);
if (attrib_num == key_bad)
return (key_bad);
while (is_whitespace(*s))
s++;
if (*s == '\0')
return (attrib_num);
start_val = s;
/* note that read_line will not return a line ending with \ */
for (; *s != '\0'; s++) {
if (*s == ESCAPE_CHAR)
s++;
}
while (s > start_val && is_whitespace(s[-1]))
s--;
attribute_value =
calloc(1, (size_t)(s - start_val) + 1);
if (attribute_value == NULL) {
p_error = parse_no_mem_error;
return (key_bad);
}
attr_val[0] = attribute_value;
a = *attr_val;
end_val = s;
cut_here = 0;
for (s = start_val; s < end_val; s++) {
if (*s == POUND_SIGN) {
cut_here = s;
while (s < end_val) {
if (*s == DOUBLE_QUOTE_CHAR ||
*s == SINGLE_QUOTE_CHAR) {
cut_here = 0;
break;
}
s++;
}
}
}
if (cut_here != 0)
end_val = cut_here;
for (s = start_val; s < end_val; s++)
*a++ = *s;
*a++ = '\0';
}
if (ret == -1)
return (key_bad);
return (attrib_num);
}
static LDAP *
connect_to_ldap_config_server(
char *sever_name,
int server_port,
__nis_config_info_t *config_info)
{
LDAP *ld = NULL;
int ldapVersion = LDAP_VERSION3;
int derefOption = LDAP_DEREF_ALWAYS;
int timelimit = LDAP_NO_LIMIT;
int sizelimit = LDAP_NO_LIMIT;
int errnum;
bool_t retrying = FALSE;
int sleep_seconds = 1;
struct berval cred;
if (config_info->tls_method == no_tls) {
ld = ldap_init(sever_name, server_port);
if (ld == NULL) {
p_error = parse_ldap_init_error;
report_error(strerror(errno), NULL);
return (NULL);
}
} else {
if ((errnum = ldapssl_client_init(
config_info->tls_cert_db, NULL)) < 0) {
p_error = parse_ldapssl_client_init_error;
report_error(ldapssl_err2string(errnum), NULL);
return (NULL);
}
ld = ldapssl_init(sever_name, server_port, 1);
if (ld == NULL) {
p_error = parse_ldapssl_init_error;
report_error(strerror(errno), NULL);
return (NULL);
}
}
(void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
&ldapVersion);
(void) ldap_set_option(ld, LDAP_OPT_DEREF, &derefOption);
(void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
(void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &timelimit);
(void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
/*
* Attempt to bind to the LDAP server.
* We will loop until success or until an error other
* than LDAP_CONNECT_ERROR or LDAP_SERVER_DOWN
*/
if (verbose)
report_info("Connecting to ", sever_name);
for (;;) {
if (config_info->auth_method == simple) {
errnum = ldap_simple_bind_s(ld, config_info->proxy_dn,
config_info->proxy_passwd);
} else if (config_info->auth_method == cram_md5) {
cred.bv_len = strlen(config_info->proxy_passwd);
cred.bv_val = config_info->proxy_passwd;
errnum = ldap_sasl_cram_md5_bind_s(ld,
config_info->proxy_dn, &cred, NULL, NULL);
} else if (config_info->auth_method == digest_md5) {
cred.bv_len = strlen(config_info->proxy_passwd);
cred.bv_val = config_info->proxy_passwd;
errnum = ldap_x_sasl_digest_md5_bind_s(ld,
config_info->proxy_dn, &cred, NULL, NULL);
} else {
errnum = ldap_simple_bind_s(ld, NULL, NULL);
}
if (errnum == LDAP_SUCCESS)
break;
if (errnum == LDAP_CONNECT_ERROR ||
errnum == LDAP_SERVER_DOWN) {
if (!retrying) {
if (verbose)
report_info(
"LDAP server unavailable. Retrying...",
NULL);
retrying = TRUE;
}
(void) sleep(sleep_seconds);
sleep_seconds *= 2;
if (sleep_seconds > MAX_LDAP_CONFIG_RETRY_TIME)
sleep_seconds = MAX_LDAP_CONFIG_RETRY_TIME;
p_error = no_parse_error;
continue;
}
p_error = parse_ldap_bind_error;
report_error2(config_info->proxy_dn, ldap_err2string(errnum));
(void) ldap_unbind(ld);
return (NULL);
}
if (verbose)
report_info("Reading values from ", config_info->config_dn);
return (ld);
}
/*
* FUNCTION: process_ldap_config_result
*
* Extracts the LDAPMessage containing the nis+/LDAP
* configuration
*
* RETURN VALUE: 0 on success, -1 on failure
*
* INPUT: LDAP the LDAP connection
* LDAPMessage the LDAP message
*/
static int
process_ldap_config_result(
LDAP *ld,
LDAPMessage *resultMsg,
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping,
__nisdb_table_mapping_t *table_info)
{
LDAPMessage *e;
int errnum;
char *attr;
BerElement *ber = NULL;
config_key attrib_num;
char **vals;
int n;
int i;
char *attr_val;
int len;
int rc = 0;
bool_t error_reported = FALSE;
e = ldap_first_entry(ld, resultMsg);
if (e != NULL) {
for (attr = ldap_first_attribute(ld, e, &ber); attr != NULL;
attr = ldap_next_attribute(ld, e, ber)) {
if (verbose)
report_info("\t", attr);
attrib_num = get_attrib_num(attr, strlen(attr));
if (attrib_num == key_bad) {
report_error(attr, NULL);
break;
}
if ((vals = ldap_get_values(ld, e, attr)) != NULL) {
n = ldap_count_values(vals);
/* parse the attribute values */
for (i = 0; i < n; i++) {
attr_val = vals[i];
while (is_whitespace(*attr_val))
attr_val++;
if (verbose)
report_info("\t\t", attr_val);
len = strlen(attr_val);
while (len > 0 &&
is_whitespace(attr_val[len - 1]))
len--;
if (yp2ldap) {
if (IS_YP_BIND_INFO(attrib_num)) {
rc = add_bind_attribute(attrib_num, attr_val,
len, proxy_info);
} else if (IS_YP_OPER_INFO(attrib_num)) {
rc = add_operation_attribute(attrib_num,
attr_val, len, nis_config, table_info);
} else if (IS_YP_MAP_ATTR(attrib_num)) {
rc = add_mapping_attribute(attrib_num, attr_val,
len, table_mapping);
} else {
p_error = parse_unsupported_format;
}
} else {
if (IS_BIND_INFO(attrib_num)) {
rc = add_bind_attribute(attrib_num, attr_val,
len, proxy_info);
} else if (IS_OPER_INFO(attrib_num)) {
rc = add_operation_attribute(attrib_num,
attr_val, len, nis_config, table_info);
} else {
rc = add_mapping_attribute(attrib_num, attr_val,
len, table_mapping);
}
}
if (p_error != no_parse_error) {
report_error(attr_val, attr);
error_reported = TRUE;
break;
}
}
ldap_value_free(vals);
} else {
(void) ldap_get_option(ld,
LDAP_OPT_ERROR_NUMBER, &errnum);
if (errnum != LDAP_SUCCESS)
p_error = parse_ldap_get_values_error;
}
ldap_memfree(attr);
if (p_error != no_parse_error)
break;
}
} else {
errnum = ldap_result2error(ld, resultMsg, FALSE);
if (errnum != LDAP_SUCCESS)
p_error = parse_ldap_search_error;
}
if (ber != NULL)
ber_free(ber, 0);
if (!error_reported && p_error != no_parse_error) {
report_error(ldap_err2string(errnum), 0);
}
if (p_error != no_parse_error)
rc = -1;
return (rc);
}
/*
* FUNCTION: process_ldap_referral
*
* Retrieves the configuration for a referral url
*
* RETURN VALUE: 0 on success, -1 on failure, 1 on skip
*
* INPUT: url the ldap url
* __nis_ldap_proxy_info
*/
static int
process_ldap_referral(
char *url,
char **attrs,
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping,
__nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info)
{
LDAPURLDesc *ludpp = NULL;
int rc;
LDAP *ld = NULL;
int errnum;
LDAPMessage *resultMsg = NULL;
if ((rc = ldap_url_parse(url, &ludpp)) != LDAP_SUCCESS)
return (1);
#ifdef LDAP_URL_OPT_SECURE
if (ludpp->lud_options & LDAP_URL_OPT_SECURE) {
if (config_info->tls_method != ssl_tls) {
ldap_free_urldesc(ludpp);
return (1);
}
} else {
if (config_info->tls_method != no_tls) {
ldap_free_urldesc(ludpp);
return (1);
}
}
#endif
if ((ld = connect_to_ldap_config_server(ludpp->lud_host,
ludpp->lud_port, config_info)) == NULL) {
ldap_free_urldesc(ludpp);
return (-1);
}
errnum = ldap_search_s(ld, config_info->config_dn, LDAP_SCOPE_BASE,
"objectclass=nisplusLDAPconfig", attrs, 0, &resultMsg);
ldap_source = config_info->config_dn;
if (errnum != LDAP_SUCCESS) {
p_error = parse_ldap_search_error;
report_error(ldap_err2string(errnum), 0);
rc = -1;
} else {
rc = process_ldap_config_result(ld, resultMsg, proxy_info,
nis_config, table_mapping, table_info);
}
ldap_source = NULL;
(void) ldap_unbind(ld);
if (resultMsg != NULL)
(void) ldap_msgfree(resultMsg);
return (rc);
}
/*
* FUNCTION: process_ldap_referral_msg
*
* Retrieves the configuration from referred servers
*
* RETURN VALUE: 0 on success, -1 on failure
*
* INPUT: LDAP the LDAP connection
* LDAPMessage the LDAP message
* __nis_ldap_proxy_info
*/
static int
process_ldap_referral_msg(
LDAP *ld,
LDAPMessage *resultMsg,
char **attrs,
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping,
__nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info)
{
int errCode;
char **referralsp = NULL;
int i;
int rc;
rc = ldap_parse_result(ld, resultMsg, &errCode, NULL, NULL, &referralsp,
NULL, 0);
if (rc != LDAP_SUCCESS || errCode != LDAP_REFERRAL) {
p_error = parse_ldap_get_values_error;
report_error(ldap_err2string(errCode), 0);
rc = -1;
} else {
for (i = 0; referralsp[i] != NULL; i++) {
rc = process_ldap_referral(referralsp[i], attrs,
proxy_info, nis_config, table_mapping,
config_info, table_info);
if (rc <= 0)
break;
else
report_info("Cannot use referral \n",
referralsp[i]);
}
if (rc > 0) {
p_error = parse_no_available_referrals_error;
report_error(0, 0);
}
}
if (referralsp)
ldap_value_free(referralsp);
return (rc);
}
/*
* FUNCTION: parse_ldap_config_dn_attrs
*
* Parses the information for LDAP from the LDAP profile
* - the profile object name, the LDAP server, and the
* authentication method must be specified.
*
* RETURN VALUE: 0 on success, -1 on failure
*
* INPUT: __nis_ldap_proxy_info
*/
static int
parse_ldap_config_dn_attrs(
__nis_ldap_proxy_info *proxy_info,
__nis_config_t *nis_config,
__nis_table_mapping_t **table_mapping,
__nis_config_info_t *config_info,
__nisdb_table_mapping_t *table_info)
{
int rc = 0;
LDAP *ld = NULL;
int errnum;
char *ldap_config_attributes[n_config_keys];
LDAPMessage *resultMsg = NULL;
/* Determine if properly configured for LDAP lookup */
if (config_info->auth_method == simple &&
config_info->proxy_dn == NULL)
p_error = parse_no_proxy_dn_error;
else if (config_info->auth_method ==
(auth_method_t)NO_VALUE_SET)
p_error = parse_no_config_auth_error;
else if ((config_info->default_servers == NULL) ||
(config_info->default_servers[0] == '\0'))
p_error = parse_no_config_server_addr;
if (p_error != no_parse_error) {
report_error(NULL, NULL);
return (-1);
}
if (config_info->tls_method == (tls_method_t)NO_VALUE_SET)
config_info->tls_method = no_tls;
else if (config_info->tls_method == ssl_tls &&
(config_info->tls_cert_db == NULL ||
*config_info->tls_cert_db == '\0')) {
p_error = parse_no_config_cert_db;
report_error(NULL, NULL);
return (-1);
}
if (verbose)
report_info(
"Getting configuration from LDAP server(s): ",
config_info->default_servers);
/* Determine which attributes should be retrieved */
get_attribute_list(proxy_info, nis_config, NULL, table_info,
ldap_config_attributes);
if ((ld = connect_to_ldap_config_server(config_info->default_servers, 0,
config_info)) == NULL)
return (-1);
/* Get the attribute values */
errnum = ldap_search_s(ld, config_info->config_dn, LDAP_SCOPE_BASE,
"objectclass=nisplusLDAPconfig",
ldap_config_attributes, 0, &resultMsg);
ldap_source = config_info->config_dn;
if (errnum == LDAP_REFERRAL) {
rc = process_ldap_referral_msg(ld, resultMsg,
ldap_config_attributes, proxy_info, nis_config,
table_mapping, config_info, table_info);
} else if (errnum != LDAP_SUCCESS) {
p_error = parse_ldap_search_error;
report_error(ldap_err2string(errnum), 0);
rc = -1;
} else {
rc = process_ldap_config_result(ld, resultMsg, proxy_info,
nis_config, table_mapping, table_info);
}
ldap_source = NULL;
(void) ldap_unbind(ld);
if (resultMsg != NULL)
(void) ldap_msgfree(resultMsg);
return (rc);
}
bool_t
is_cmd_line_option(config_key a_num)
{
const char *const *cmdline_options = cmdline_config;
config_key attrib_num;
const char *begin_s;
const char *end_s;
if (cmdline_options == NULL)
return (FALSE);
while (*cmdline_options != NULL) {
attrib_num = get_attrib_num_cmdline(
*cmdline_options, &begin_s, &end_s);
if (attrib_num == a_num)
break;
cmdline_options++;
}
return (*cmdline_options != NULL);
}
/*
* FUNCTION: get_attribute_list
*
* Get a list of attributes from the LDAP server that have not yet
* been gotten. If config_info is NULL, the associated parameters
* are not needed.
*
* RETURN VALUE: none
*
* INPUT: Returns a list of parameters in attributes
* which is assumed to be of sufficient size.
*/
static void
get_attribute_list(
const __nis_ldap_proxy_info *proxy_info,
const __nis_config_t *nis_config,
const __nis_config_info_t *config_info,
const __nisdb_table_mapping_t *table_info,
char **attributes)
{
int n_attrs;
/* Determine which attributes should be retrieved */
n_attrs = 0;
if (config_info != NULL) {
if (yp2ldap) {
if (config_info->config_dn == NULL)
attributes[n_attrs++] = YP_CONFIG_DN;
if (config_info->default_servers == NULL)
attributes[n_attrs++] = YP_CONFIG_SERVER_LIST;
if (config_info->auth_method ==
(auth_method_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_CONFIG_AUTH_METHOD;
if (config_info->tls_method ==
(tls_method_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_CONFIG_TLS_OPTION;
if (config_info->proxy_dn == NULL)
attributes[n_attrs++] = YP_CONFIG_PROXY_USER;
if (config_info->proxy_passwd == NULL)
attributes[n_attrs++] = YP_CONFIG_PROXY_PASSWD;
if (config_info->tls_cert_db == NULL)
attributes[n_attrs++] = YP_CONFIG_TLS_CERT_DB;
} else {
if (config_info->config_dn == NULL)
attributes[n_attrs++] = CONFIG_DN;
if (config_info->default_servers == NULL)
attributes[n_attrs++] = CONFIG_SERVER_LIST;
if (config_info->auth_method ==
(auth_method_t)NO_VALUE_SET)
attributes[n_attrs++] = CONFIG_AUTH_METHOD;
if (config_info->tls_method ==
(tls_method_t)NO_VALUE_SET)
attributes[n_attrs++] = CONFIG_TLS_OPTION;
if (config_info->proxy_dn == NULL)
attributes[n_attrs++] = CONFIG_PROXY_USER;
if (config_info->proxy_passwd == NULL)
attributes[n_attrs++] = CONFIG_PROXY_PASSWD;
if (config_info->tls_cert_db == NULL)
attributes[n_attrs++] = CONFIG_TLS_CERT_DB;
}
} else {
if (yp2ldap) {
attributes[n_attrs++] = YP_DOMAIN_CONTEXT;
attributes[n_attrs++] = YPPASSWDD_DOMAINS;
attributes[n_attrs++] = YP_DB_ID_MAP;
attributes[n_attrs++] = YP_COMMENT_CHAR;
attributes[n_attrs++] = YP_MAP_FLAGS;
attributes[n_attrs++] = YP_ENTRY_TTL;
attributes[n_attrs++] = YP_NAME_FIELDS;
attributes[n_attrs++] = YP_SPLIT_FIELD;
attributes[n_attrs++] = YP_REPEATED_FIELD_SEPARATORS;
attributes[n_attrs++] = YP_LDAP_OBJECT_DN;
attributes[n_attrs++] = NIS_TO_LDAP_MAP;
attributes[n_attrs++] = LDAP_TO_NIS_MAP;
} else {
attributes[n_attrs++] = DB_ID_MAP;
attributes[n_attrs++] = ENTRY_TTL;
attributes[n_attrs++] = LDAP_OBJECT_DN;
attributes[n_attrs++] = NISPLUS_TO_LDAP_MAP;
attributes[n_attrs++] = LDAP_TO_NISPLUS_MAP;
}
}
if (yp2ldap) {
if (proxy_info->default_servers == NULL)
attributes[n_attrs++] = PREFERRED_SERVERS;
if (proxy_info->auth_method == (auth_method_t)NO_VALUE_SET)
attributes[n_attrs++] = AUTH_METHOD;
if (proxy_info->tls_method == (tls_method_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_TLS_OPTION;
if (proxy_info->tls_cert_db == NULL)
attributes[n_attrs++] = YP_TLS_CERT_DB;
if (proxy_info->default_search_base == NULL)
attributes[n_attrs++] = SEARCH_BASE;
if (proxy_info->proxy_dn == NULL)
attributes[n_attrs++] = YP_PROXY_USER;
if (proxy_info->proxy_passwd == NULL)
attributes[n_attrs++] = YP_PROXY_PASSWD;
if (proxy_info->default_nis_domain == NULL)
attributes[n_attrs++] = YP_LDAP_BASE_DOMAIN;
if (proxy_info->bind_timeout.tv_sec ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_BIND_TIMEOUT;
if (proxy_info->search_timeout.tv_sec ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_SEARCH_TIMEOUT;
if (proxy_info->modify_timeout.tv_sec ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_MODIFY_TIMEOUT;
if (proxy_info->add_timeout.tv_sec == (time_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_ADD_TIMEOUT;
if (proxy_info->delete_timeout.tv_sec ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_DELETE_TIMEOUT;
if (proxy_info->search_time_limit == (int)NO_VALUE_SET)
attributes[n_attrs++] = YP_SEARCH_TIME_LIMIT;
if (proxy_info->search_size_limit == (int)NO_VALUE_SET)
attributes[n_attrs++] = YP_SEARCH_SIZE_LIMIT;
if (proxy_info->follow_referral ==
(follow_referral_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_FOLLOW_REFERRAL;
if (table_info->retrieveError ==
(__nis_retrieve_error_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_RETRIEVE_ERROR_ACTION;
if (table_info->retrieveErrorRetry.attempts == NO_VALUE_SET)
attributes[n_attrs++] = YP_RETREIVE_ERROR_ATTEMPTS;
if (table_info->retrieveErrorRetry.timeout ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_RETREIVE_ERROR_TIMEOUT;
if (table_info->storeError ==
(__nis_store_error_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_STORE_ERROR_ACTION;
if (table_info->storeErrorRetry.attempts == NO_VALUE_SET)
attributes[n_attrs++] = YP_STORE_ERROR_ATTEMPTS;
if (table_info->storeErrorRetry.timeout ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_STORE_ERROR_TIMEOUT;
if (table_info->refreshError ==
(__nis_refresh_error_t)NO_VALUE_SET)
attributes[n_attrs++] = REFRESH_ERROR_ACTION;
if (table_info->refreshErrorRetry.attempts == NO_VALUE_SET)
attributes[n_attrs++] = REFRESH_ERROR_ATTEMPTS;
if (table_info->refreshErrorRetry.timeout ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = REFRESH_ERROR_TIMEOUT;
if (table_info->matchFetch ==
(__nis_match_fetch_t)NO_VALUE_SET)
attributes[n_attrs++] = YP_MATCH_FETCH;
} else {
if (proxy_info->default_servers == NULL)
attributes[n_attrs++] = PREFERRED_SERVERS;
if (proxy_info->auth_method == (auth_method_t)NO_VALUE_SET)
attributes[n_attrs++] = AUTH_METHOD;
if (proxy_info->tls_method == (tls_method_t)NO_VALUE_SET)
attributes[n_attrs++] = TLS_OPTION;
if (proxy_info->tls_cert_db == NULL)
attributes[n_attrs++] = TLS_CERT_DB;
if (proxy_info->default_search_base == NULL)
attributes[n_attrs++] = SEARCH_BASE;
if (proxy_info->proxy_dn == NULL)
attributes[n_attrs++] = PROXY_USER;
if (proxy_info->proxy_passwd == NULL)
attributes[n_attrs++] = PROXY_PASSWD;
if (proxy_info->default_nis_domain == NULL)
attributes[n_attrs++] = LDAP_BASE_DOMAIN;
if (proxy_info->bind_timeout.tv_sec ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = BIND_TIMEOUT;
if (proxy_info->search_timeout.tv_sec ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = SEARCH_TIMEOUT;
if (proxy_info->modify_timeout.tv_sec ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = MODIFY_TIMEOUT;
if (proxy_info->add_timeout.tv_sec == (time_t)NO_VALUE_SET)
attributes[n_attrs++] = ADD_TIMEOUT;
if (proxy_info->delete_timeout.tv_sec ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = DELETE_TIMEOUT;
if (proxy_info->search_time_limit == (int)NO_VALUE_SET)
attributes[n_attrs++] = SEARCH_TIME_LIMIT;
if (proxy_info->search_size_limit == (int)NO_VALUE_SET)
attributes[n_attrs++] = SEARCH_SIZE_LIMIT;
if (proxy_info->follow_referral ==
(follow_referral_t)NO_VALUE_SET)
attributes[n_attrs++] = FOLLOW_REFERRAL;
if (table_info->retrieveError ==
(__nis_retrieve_error_t)NO_VALUE_SET)
attributes[n_attrs++] = RETRIEVE_ERROR_ACTION;
if (table_info->retrieveErrorRetry.attempts == NO_VALUE_SET)
attributes[n_attrs++] = RETREIVE_ERROR_ATTEMPTS;
if (table_info->retrieveErrorRetry.timeout ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = RETREIVE_ERROR_TIMEOUT;
if (table_info->storeError ==
(__nis_store_error_t)NO_VALUE_SET)
attributes[n_attrs++] = STORE_ERROR_ACTION;
if (table_info->storeErrorRetry.attempts == NO_VALUE_SET)
attributes[n_attrs++] = STORE_ERROR_ATTEMPTS;
if (table_info->storeErrorRetry.timeout ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = STORE_ERROR_TIMEOUT;
if (table_info->refreshError ==
(__nis_refresh_error_t)NO_VALUE_SET)
attributes[n_attrs++] = REFRESH_ERROR_ACTION;
if (table_info->refreshErrorRetry.attempts == NO_VALUE_SET)
attributes[n_attrs++] = REFRESH_ERROR_ATTEMPTS;
if (table_info->refreshErrorRetry.timeout ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = REFRESH_ERROR_TIMEOUT;
if (table_info->matchFetch ==
(__nis_match_fetch_t)NO_VALUE_SET)
attributes[n_attrs++] = MATCH_FETCH;
}
switch (nis_config->initialUpdate) {
case (__nis_initial_update_t)NO_VALUE_SET:
attributes[n_attrs++] = INITIAL_UPDATE_ACTION;
attributes[n_attrs++] = INITIAL_UPDATE_ONLY;
break;
case (__nis_initial_update_t)INITIAL_UPDATE_NO_ACTION:
case (__nis_initial_update_t)NO_INITIAL_UPDATE_NO_ACTION:
attributes[n_attrs++] = INITIAL_UPDATE_ACTION;
break;
case (__nis_initial_update_t)FROM_NO_INITIAL_UPDATE:
case (__nis_initial_update_t)TO_NO_INITIAL_UPDATE:
attributes[n_attrs++] = INITIAL_UPDATE_ONLY;
break;
}
if (nis_config->threadCreationError ==
(__nis_thread_creation_error_t)NO_VALUE_SET)
attributes[n_attrs++] = THREAD_CREATE_ERROR_ACTION;
if (nis_config->threadCreationErrorTimeout.attempts == NO_VALUE_SET)
attributes[n_attrs++] = THREAD_CREATE_ERROR_ATTEMPTS;
if (nis_config->threadCreationErrorTimeout.timeout ==
(time_t)NO_VALUE_SET)
attributes[n_attrs++] = THREAD_CREATE_ERROR_TIMEOUT;
if (nis_config->dumpError == (__nis_dump_error_t)NO_VALUE_SET)
attributes[n_attrs++] = DUMP_ERROR_ACTION;
if (nis_config->dumpErrorTimeout.attempts == NO_VALUE_SET)
attributes[n_attrs++] = DUMP_ERROR_ATTEMPTS;
if (nis_config->dumpErrorTimeout.timeout == (time_t)NO_VALUE_SET)
attributes[n_attrs++] = DUMP_ERROR_TIMEOUT;
if (nis_config->resyncService == (__nis_resync_service_t)NO_VALUE_SET)
attributes[n_attrs++] = RESYNC;
if (nis_config->updateBatching ==
(__nis_update_batching_t)NO_VALUE_SET)
attributes[n_attrs++] = UPDATE_BATCHING;
if (nis_config->updateBatchingTimeout.timeout == (time_t)NO_VALUE_SET)
attributes[n_attrs++] = UPDATE_BATCHING_TIMEOUT;
if (nis_config->numberOfServiceThreads == (int)NO_VALUE_SET)
attributes[n_attrs++] = NUMBER_THEADS;
if (nis_config->emulate_yp == (int)NO_VALUE_SET)
attributes[n_attrs++] = YP_EMULATION;
/* maxRPCRecordSize is not configurable through LDAP profiles */
if (nis_config->maxRPCRecordSize == (int)NO_VALUE_SET)
attributes[n_attrs++] = MAX_RPC_RECSIZE;
attributes[n_attrs++] = NULL;
}
/*
* Notes on adding new attributes
* 1. Determine where the attribute value will be saved
* Currently, the following structures are defined:
* __nis_config_info_t config_info
* __nis_ldap_proxy_info proxyInfo
* __nis_config_t ldapConfig
* __nisdb_table_mapping_t ldapDBTableMapping
* __nis_table_mapping_t ldapTableMapping
* or add a new structure or variable - this will require
* more code.
* 2. Initialize the value to a known unconfigured value.
* This can be done in initialize_parse_structs or
* parse_ldap_migration.
* 3. In the header file nis_parse_ldap_conf.h, add the name
* of the attribute. (Currently, the attribute name is assumed
* to be the same for the command line, the preference file,
* and LDAP.) The names are grouped logically. Add a corresponding
* config_key to the enum. Note that position in this file is
* essential because the macros such as IS_BIND_INFO depend on
* the sequence. The corresponding macro (IS_CONFIG_KEYWORD,
* IS_BIND_INFO, or IS_OPER_INFO) may need to be adjusted. These
* are used to partition the attributes into smaller chunks.
* 4. Add the correspond entry to the keyword_lookup array in
* nis_parse_ldap_attr.c, which is used to determine the config_key
* from the corresponding key word.
* 5. Add the attribute to the list of attributes to retrieve from
* the LDAP server if no value has been set in the function
* parse_ldap_config_dn_attrs. (This assumes that the attribute
* is not used to get the configuration from the LDAP server.)
* 6. Add logic to parse the individual attribute in
* add_config_attribute, add_bind_attribute,
* add_operation_attribute, or add_mapping_attribute depending
* which group of attributes the added attribute belongs to.
* 7. In set_default_values, if the attribute value has not been set, set
* the default value. If any additional fixup is needed depending
* on other configuration values, it should be done here.
* 8. If an attribute name is a subset of another, parse_ldap_default_conf
* should be modified.
*/