/*
* 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
* 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 <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"
int cur_line_num = 0;
int start_line_num = 0;
int seq_num = 0;
static
/* high level parsing functions functions */
static int parse_ldap_cmd_line(const char *const *cmdline_options,
static int parse_ldap_config_file(const char *config_file,
/* Forward declarations */
int yp_parse_ldap_config_file(const char *, __nis_ldap_proxy_info *,
/* helper functions */
static config_key get_attrib_num_cmdline(const char *s,
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.
*
* configuration file, and no mapping file, then no mapping
* should be used.
*
* RETURN VALUE:
* 0 Success
* 1 No mapping should be used.
*
* INPUT: command line parameters, configuration file
*/
int
const char *const *cmdline_options,
const char *config_file)
{
int rc = 0;
if (verbose)
if (yp2ldap)
if (cmdline_options != NULL) {
/* NIS to LDAP does not read command line attributes */
if (!yp2ldap)
else
rc = 0;
}
if (rc == 0) {
if (yp2ldap)
else
}
if (config_file == NULL) {
if (yp2ldap) {
} else {
}
}
if (yp2ldap)
else
}
}
rc = 1;
if (rc == 0)
if (rc == -2)
return (-1);
}
if (rc == 0)
if (rc == 0)
if ((rc == 0) && yptol_mode)
rc = map_id_list_init();
if (rc != 0) {
} else if (verbose)
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
const char *const *cmdline_options,
{
int rc = 0;
const char *begin_s;
const char *end_s;
if (verbose)
while (*cmdline_options != NULL) {
if (verbose)
if (attrib_num == key_bad) {
command_line_source = "command line";
rc = -1;
break;
} else if (IS_CONFIG_KEYWORD(attrib_num)) {
} else if (IS_BIND_INFO(attrib_num)) {
} else if (IS_OPER_INFO(attrib_num)) {
} else {
}
if (rc < 0) {
command_line_source = "command line";
break;
}
}
return (rc);
}
static int
{
int rc = 0;
char *attr;
char *attr_val;
int defflags;
int i;
int len;
int attr_len;
void *defp;
if (verbose)
/* Set defread_r() to be case insensitive */
i = 0;
/*
* if nisplusUpdateBatching, make sure
* we don't match nisplusUpdateBatchingTimeout
*/
if (attr_val == 0) {
}
if (attr_val == 0) {
}
if (attr_val == 0) {
}
} else {
}
continue;
if (attrib_num == key_bad) {
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--;
if (verbose) {
}
if (IS_BIND_INFO(attrib_num)) {
} else if (IS_OPER_INFO(attrib_num)) {
}
if (p_error != no_parse_error) {
rc = -1;
break;
}
}
file_source = NULL;
}
return (rc);
}
static int
{
int rc = 0;
char *attr;
char *attr_val;
int defflags;
int i, len;
void *defp;
if (verbose)
/* Set defread_r() to be case insensitive */
i = 0;
sizeof (attr_buf)) {
"Static buffer attr_buf overflow", NULL);
return (-1);
}
continue;
if (attrib_num == key_bad) {
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--;
if (verbose) {
}
if (IS_YP_BIND_INFO(attrib_num)) {
} else if (IS_YP_OPER_INFO(attrib_num)) {
}
if (p_error != no_parse_error) {
rc = -1;
break;
}
}
file_source = NULL;
}
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
const char *s,
const char **begin_s,
const char **end_s)
{
const char *equal_s;
const char *s1;
while (s < s_end && is_whitespace(*s))
s++;
if (*equal_s == EQUAL_CHAR)
break;
return (key_bad);
}
;
if (s1 == s) {
return (key_bad);
}
if (attrib_num != key_bad) {
s1++;
s_end--;
}
return (attrib_num);
}
/*
* FUNCTION: parse_ldap_config_file
*
* Parses the information for LDAP from a configuration
* is used
*
* RETURN VALUE: 0 on success, -1 on failure
*
* INPUT: configuration file name
*/
static int
const char *config_file,
{
int rc = 0;
int fd;
char *attr_val;
int len;
return (-1);
}
start_line_num = 1;
cur_line_num = 1;
if (verbose)
if (IS_CONFIG_KEYWORD(attrib_num)) {
} else if (IS_BIND_INFO(attrib_num)) {
} else if (IS_OPER_INFO(attrib_num)) {
} else {
}
if (rc < 0) {
if (attr_val)
break;
}
if (attr_val)
}
if (attrib_num == key_bad) {
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
const char *config_file,
{
int rc = 0;
int fd;
int len;
return (-1);
}
start_line_num = 1;
cur_line_num = 1;
if (verbose)
if (IS_YP_CONFIG_KEYWORD(attrib_num)) {
} else if (IS_YP_BIND_INFO(attrib_num)) {
} else if (IS_YP_OPER_INFO(attrib_num)) {
} else if (IS_YP_DOMAIN_INFO(attrib_num)) {
} else if (IS_YP_MAP_ATTR(attrib_num)) {
} else {
rc = -1;
}
if (rc < 0) {
if (attr_val)
break;
}
if (attr_val) {
}
}
if (attrib_num == key_bad) {
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
{
char *start_tag;
char *start_val;
char *end_val;
char *cut_here;
char *s;
char *a;
char *attribute_value;
int ret;
for (s = buf; is_whitespace(*s); s++)
;
start_tag = s;
while (*s != '\0' && !is_whitespace(*s))
s++;
if (verbose)
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++;
}
s--;
if (attribute_value == NULL) {
return (key_bad);
}
attr_val[0] = attribute_value;
a = *attr_val;
end_val = s;
cut_here = 0;
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)
*a++ = *s;
*a++ = '\0';
}
if (ret == -1)
return (key_bad);
return (attrib_num);
}
static LDAP *
char *sever_name,
int server_port,
{
int errnum;
return (NULL);
}
} else {
if ((errnum = ldapssl_client_init(
return (NULL);
}
return (NULL);
}
}
&ldapVersion);
/*
* 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)
for (;;) {
} else {
}
if (errnum == LDAP_SUCCESS)
break;
if (errnum == LDAP_CONNECT_ERROR ||
errnum == LDAP_SERVER_DOWN) {
if (!retrying) {
if (verbose)
"LDAP server unavailable. Retrying...",
NULL);
}
(void) sleep(sleep_seconds);
sleep_seconds *= 2;
continue;
}
(void) ldap_unbind(ld);
return (NULL);
}
if (verbose)
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
{
LDAPMessage *e;
int errnum;
char *attr;
char **vals;
int n;
int i;
char *attr_val;
int len;
int rc = 0;
if (e != NULL) {
if (verbose)
if (attrib_num == key_bad) {
break;
}
n = ldap_count_values(vals);
/* parse the attribute values */
for (i = 0; i < n; i++) {
while (is_whitespace(*attr_val))
attr_val++;
if (verbose)
while (len > 0 &&
len--;
if (yp2ldap) {
if (IS_YP_BIND_INFO(attrib_num)) {
len, proxy_info);
} else if (IS_YP_OPER_INFO(attrib_num)) {
} else if (IS_YP_MAP_ATTR(attrib_num)) {
len, table_mapping);
} else {
}
} else {
if (IS_BIND_INFO(attrib_num)) {
len, proxy_info);
} else if (IS_OPER_INFO(attrib_num)) {
} else {
len, table_mapping);
}
}
if (p_error != no_parse_error) {
break;
}
}
} else {
(void) ldap_get_option(ld,
if (errnum != LDAP_SUCCESS)
}
if (p_error != no_parse_error)
break;
}
} else {
if (errnum != LDAP_SUCCESS)
}
}
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
char *url,
char **attrs,
{
int rc;
int errnum;
return (1);
#ifdef LDAP_URL_OPT_SECURE
return (1);
}
} else {
return (1);
}
}
#endif
return (-1);
}
if (errnum != LDAP_SUCCESS) {
rc = -1;
} else {
}
ldap_source = NULL;
(void) ldap_unbind(ld);
(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
char **attrs,
{
int errCode;
int i;
int rc;
NULL, 0);
rc = -1;
} else {
for (i = 0; referralsp[i] != NULL; i++) {
if (rc <= 0)
break;
else
report_info("Cannot use referral \n",
referralsp[i]);
}
if (rc > 0) {
report_error(0, 0);
}
}
if (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
{
int rc = 0;
int errnum;
/* Determine if properly configured for LDAP lookup */
else if (config_info->auth_method ==
if (p_error != no_parse_error) {
return (-1);
}
return (-1);
}
if (verbose)
"Getting configuration from LDAP server(s): ",
/* Determine which attributes should be retrieved */
config_info)) == NULL)
return (-1);
/* Get the attribute values */
"objectclass=nisplusLDAPconfig",
ldap_config_attributes, 0, &resultMsg);
if (errnum == LDAP_REFERRAL) {
} else if (errnum != LDAP_SUCCESS) {
rc = -1;
} else {
}
ldap_source = NULL;
(void) ldap_unbind(ld);
(void) ldap_msgfree(resultMsg);
return (rc);
}
{
const char *begin_s;
const char *end_s;
if (cmdline_options == NULL)
return (FALSE);
while (*cmdline_options != NULL) {
if (attrib_num == a_num)
break;
}
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
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->auth_method ==
if (config_info->tls_method ==
} else {
if (config_info->auth_method ==
if (config_info->tls_method ==
}
} else {
if (yp2ldap) {
} else {
}
}
if (yp2ldap) {
if (proxy_info->follow_referral ==
if (table_info->retrieveError ==
if (table_info->storeError ==
if (table_info->refreshError ==
if (table_info->matchFetch ==
} else {
if (proxy_info->follow_referral ==
if (table_info->retrieveError ==
if (table_info->storeError ==
if (table_info->refreshError ==
if (table_info->matchFetch ==
}
switch (nis_config->initialUpdate) {
break;
break;
break;
}
if (nis_config->threadCreationError ==
if (nis_config->updateBatching ==
/* maxRPCRecordSize is not configurable through LDAP profiles */
}
/*
* 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.
*/