/*
* 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 (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
*/
/* libsldap - cachemgr side configuration components */
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <libintl.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <syslog.h>
#include <locale.h>
#include <errno.h>
#include <sys/time.h>
#include "ns_sldap.h"
#include "ns_internal.h"
#include "ns_cache_door.h"
#define ALWAYS 1
/*
* **************************************************************
* Configuration File Routines
* **************************************************************
*/
/* Size of the errstr buffer needs to be MAXERROR */
static int
read_line(FILE *fp, char *buffer, int buflen, char *errstr)
{
int linelen;
char c;
*errstr = '\0';
for (linelen = 0; linelen < buflen; ) {
c = getc(fp);
if (c == EOF)
break;
switch (c) {
case '\n':
if (linelen > 0 && buffer[linelen - 1] == '\\') {
/* Continuation line found */
--linelen;
} else {
/* end of line found */
buffer[linelen] = '\0';
return (linelen);
}
break;
default:
buffer[linelen++] = c;
}
}
if (linelen >= buflen) {
(void) snprintf(errstr, MAXERROR,
gettext("Buffer overflow, line too long."));
return (-2);
} else if (linelen > 0 && buffer[linelen - 1] == '\\') {
(void) snprintf(errstr, MAXERROR,
gettext("Unterminated continuation line."));
return (-2);
} else {
/* end of file */
buffer[linelen] = '\0';
}
return (linelen > 0 ? linelen : -1);
}
static ns_parse_status
read_file(ns_config_t *ptr, int cred_file, ns_ldap_error_t **error)
{
ParamIndexType i = 0;
char errstr[MAXERROR];
char buffer[BUFSIZE], *name, *value;
int emptyfile, lineno;
FILE *fp;
int ret;
int linelen;
char *file;
int first = 1;
if (cred_file) {
file = NSCREDFILE;
} else {
file = NSCONFIGFILE;
}
fp = fopen(file, "rF");
if (fp == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Unable to open filename '%s' "
"for reading (errno=%d)."), file, errno);
MKERROR(LOG_ERR, *error, NS_CONFIG_FILE, strdup(errstr), NULL);
return (NS_NOTFOUND);
}
emptyfile = 1;
lineno = 0;
for (; ; ) {
if ((linelen = read_line(fp, buffer, sizeof (buffer),
errstr)) < 0)
/* End of file */
break;
lineno++;
if (linelen == 0)
continue;
/* get rid of comment lines */
if (buffer[0] == '#')
continue;
emptyfile = 0;
name = NULL;
value = NULL;
__s_api_split_key_value(buffer, &name, &value);
if (name == NULL || value == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Missing Name or Value on line %d."),
lineno);
MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
strdup(errstr), NULL);
(void) fclose(fp);
return (NS_PARSE_ERR);
}
if (__s_api_get_versiontype(ptr, name, &i) != 0) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Illegal profile type on line %d."),
lineno);
MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
strdup(errstr), NULL);
(void) fclose(fp);
return (NS_PARSE_ERR);
}
if (!first && i == NS_LDAP_FILE_VERSION_P) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Illegal NS_LDAP_FILE_VERSION "
"on line %d."), lineno);
MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
strdup(errstr), NULL);
(void) fclose(fp);
return (NS_PARSE_ERR);
}
first = 0;
switch (__s_api_get_configtype(i)) {
case SERVERCONFIG:
case CLIENTCONFIG:
if (cred_file == 0) {
ret = __ns_ldap_setParamValue(ptr, i, value,
error);
if (ret != NS_SUCCESS) {
(void) fclose(fp);
return (ret);
}
} else if (i != NS_LDAP_FILE_VERSION_P) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Illegal entry in '%s' on "
"line %d"), file, lineno);
MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
strdup(errstr), NULL);
(void) fclose(fp);
return (NS_PARSE_ERR);
}
break;
case CREDCONFIG:
if (i == NS_LDAP_FILE_VERSION_P)
break;
if (cred_file) {
ret = __ns_ldap_setParamValue(ptr, i, value,
error);
if (ret != NS_SUCCESS) {
(void) fclose(fp);
return (ret);
}
} else {
(void) snprintf(errstr, sizeof (errstr),
gettext("Illegal entry in '%s' on "
"line %d"), file, lineno);
MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
strdup(errstr), NULL);
(void) fclose(fp);
return (NS_PARSE_ERR);
}
}
}
(void) fclose(fp);
if (!cred_file && emptyfile) {
/* Error in read_line */
(void) snprintf(errstr, sizeof (errstr),
gettext("Empty config file: '%s'"), file);
MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
NULL);
return (NS_PARSE_ERR);
}
if (linelen == -2) {
/* Error in read_line */
(void) snprintf(errstr, sizeof (errstr),
gettext("Line too long in '%s'"), file);
MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
NULL);
return (NS_PARSE_ERR);
}
return (NS_SUCCESS);
}
static
ns_ldap_return_code
set_attr(ns_config_t *config_struct,
char *attr_name,
char *attr_val,
ns_ldap_error_t **errorp)
{
ParamIndexType idx;
char errmsg[MAXERROR];
if (errorp == NULL) {
return (NS_LDAP_INVALID_PARAM);
}
*errorp = NULL;
/*
* This double call is made due to the presence of
* two sets of LDAP config. attribute names.
* An LDAP configuration can be obtained either from a server
* or from SMF. The former sends a DUA with attributes' names
* styled like "preferredServerList". But local configurations
* will have names inherited from the /var/ldap/ldap* files such as
* "NS_LDAP_SERVER_PREF".
* So, the standalone bits are able to process both sets of
* attributes' names.
*/
if (__s_api_get_profiletype(attr_name, &idx) < 0 &&
__s_api_get_versiontype(config_struct, attr_name, &idx) < 0) {
(void) snprintf(errmsg, sizeof (errmsg),
gettext("Ignoring unrecognized DUAProfile property: <%s>."),
attr_name);
MKERROR(LOG_INFO, *errorp, NS_LDAP_CONFIG, strdup(errmsg),
NULL);
(void) __ns_ldap_freeError(errorp);
return (NS_LDAP_SUCCESS);
}
return (__ns_ldap_setParamValue(config_struct, idx, attr_val, errorp));
}
/*
* This function creates a configuration which will be used
* for all LDAP requests in the Standalone mode.
*
* INPUT:
* config - a buffer returned by __ns_ldap_getConnectionInfo()'s
* dua_profile parameter.
*
*/
ns_config_t *
__s_api_create_config_door_str(char *config, ns_ldap_error_t **errorp)
{
char *attr, *attrName, *attrVal, *rest;
ns_config_t *configStruct = NULL;
char errmsg[MAXERROR];
if (config == NULL || errorp == NULL)
return (NULL);
if ((configStruct = __s_api_create_config()) == NULL) {
return (NULL);
}
*errorp = NULL;
attr = strtok_r(config, DOORLINESEP, &rest);
if (!attr) {
__s_api_destroy_config(configStruct);
(void) snprintf(errmsg, sizeof (errmsg),
gettext("DUAProfile received from the server"
" has bad format"));
MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL);
return (NULL);
}
do {
__s_api_split_key_value(attr, &attrName, &attrVal);
if (attrName == NULL || attrVal == NULL) {
__s_api_destroy_config(configStruct);
(void) snprintf(errmsg, sizeof (errmsg),
gettext("Attribute %s is not valid"), attr);
MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG,
strdup(errmsg), NULL);
return (NULL);
}
/* Get the version of the profile. */
if (strcasecmp(attrName, "objectclass") == 0) {
if (strcasecmp(attrVal, _PROFILE2_OBJECTCLASS) == 0) {
if (__ns_ldap_setParamValue(configStruct,
NS_LDAP_FILE_VERSION_P,
NS_LDAP_VERSION_2,
errorp) != NS_LDAP_SUCCESS) {
__s_api_destroy_config(configStruct);
return (NULL);
}
} else if (strcasecmp(attrVal,
_PROFILE1_OBJECTCLASS) == 0) {
if (__ns_ldap_setParamValue(configStruct,
NS_LDAP_FILE_VERSION_P,
NS_LDAP_VERSION_1,
errorp) != NS_LDAP_SUCCESS) {
__s_api_destroy_config(configStruct);
return (NULL);
}
}
continue;
}
if (set_attr(configStruct, attrName, attrVal, errorp) !=
NS_LDAP_SUCCESS) {
__s_api_destroy_config(configStruct);
return (NULL);
}
} while (attr = strtok_r(NULL, DOORLINESEP, &rest));
if (__s_api_crosscheck(configStruct, errmsg, B_FALSE, B_FALSE)
!= NS_SUCCESS) {
MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL);
__s_api_destroy_config(configStruct);
return (NULL);
}
return (configStruct);
}
/*
* Cache Manager side of configuration file loading
*/
ns_ldap_error_t *
__ns_ldap_LoadConfiguration()
{
ns_ldap_error_t *error = NULL;
ns_config_t *ptr = NULL;
char errstr[MAXERROR];
ns_parse_status ret;
ptr = __s_api_create_config();
if (ptr == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("__ns_ldap_LoadConfiguration: Out of memory."));
MKERROR(LOG_ERR, error, NS_CONFIG_NOTLOADED,
strdup(errstr), NULL);
return (error);
}
/* Load in Configuration file */
ret = read_file(ptr, 0, &error);
if (ret != NS_SUCCESS) {
__s_api_destroy_config(ptr);
return (error);
}
/* Load in Credential file */
ret = read_file(ptr, 1, &error);
if (ret != NS_SUCCESS) {
__s_api_destroy_config(ptr);
return (error);
}
if (__s_api_crosscheck(ptr, errstr, B_TRUE, B_TRUE) != NS_SUCCESS) {
__s_api_destroy_config(ptr);
MKERROR(LOG_ERR, error, NS_CONFIG_SYNTAX, strdup(errstr), NULL);
return (error);
}
__s_api_init_config(ptr);
return (NULL);
}
int
__print2buf(LineBuf *line, const char *toprint, char *sep)
{
int newsz = 0;
int newmax = 0;
char *str;
if (line == NULL)
return (-1);
newsz = strlen(toprint) + line->len + 1;
if (sep != NULL) {
newsz += strlen(sep);
}
if (line->alloc == 0 || newsz > line->alloc) {
/* Round up to next buffer and add 1 */
newmax = (((newsz+(BUFSIZ-1))/BUFSIZ)+1) * BUFSIZ;
if (line->alloc == 0)
line->str = (char *)calloc(newmax, 1);
else {
/*
* if realloc() returns NULL,
* the original buffer is untouched.
* It needs to be freed.
*/
str = (char *)realloc(line->str, newmax);
if (str == NULL) {
free(line->str);
line->str = NULL;
}
else
line->str = str;
}
line->alloc = newmax;
if (line->str == NULL) {
line->alloc = 0;
line->len = 0;
return (-1);
}
}
/* now add new 'toprint' data to buffer */
(void) strlcat(line->str, toprint, line->alloc);
if (sep != NULL) {
(void) strlcat(line->str, sep, line->alloc);
}
line->len = newsz;
return (0);
}
/*
* __ns_ldap_LoadDoorInfo is a routine used by the ldapcachemgr
* to create a configuration buffer to transmit back to a client
* domainname is transmitted to ldapcachemgr and ldapcachemgr uses
* it to select a configuration to transmit back. Otherwise it
* is essentially unused in sldap.
* If cred_only is not 0, then only the credentials for shadow
* update are taken care of.
*/
ns_ldap_error_t *
__ns_ldap_LoadDoorInfo(LineBuf *configinfo, char *domainname,
ns_config_t *new, int cred_only)
{
ns_config_t *ptr;
char errstr[MAXERROR];
ns_ldap_error_t *errorp;
char *str;
ParamIndexType i = 0;
int len;
ldap_config_out_t *cout;
/*
* If new is NULL, it outputs the flatten data of current default
* config, if it's non-NULL, it outputs the flatten data of a temporary
* config. It's used to compare the new config data with the current
* default config data.
*/
if (new == NULL)
ptr = __s_api_get_default_config();
else
ptr = new;
if (ptr == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("No configuration information available for %s."),
domainname == NULL ? "<no domain specified>" : domainname);
MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
strdup(errstr), NULL);
return (errorp);
}
(void) memset((char *)configinfo, 0, sizeof (LineBuf));
for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
if (cred_only) {
/* only exposed credential for shadow update */
if (i != NS_LDAP_ADMIN_BINDDN_P &&
i != NS_LDAP_ADMIN_BINDPASSWD_P)
continue;
} else {
/* credential for shadow update is not to be exposed */
if (i == NS_LDAP_ADMIN_BINDDN_P ||
i == NS_LDAP_ADMIN_BINDPASSWD_P)
continue;
}
str = __s_api_strValue(ptr, i, NS_DOOR_FMT);
if (str == NULL)
continue;
if (__print2buf(configinfo, str, DOORLINESEP)) {
(void) snprintf(errstr, sizeof (errstr),
gettext("__print2buf: Out of memory."));
MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
strdup(errstr), NULL);
__s_api_release_config(ptr);
free(str);
return (errorp);
}
free(str);
}
if (new == NULL)
__s_api_release_config(ptr);
/*
* The new interface of the configuration between ldap_cachemgr
* & libsldap contains a header structure ldap_config_out_t.
* The flatten configuration data configinfo->str is cloned
* to cout->config_str, configinfo->len is saved in
* cout->data_size and cout->cookie is set later after this function
* is returned in ldap_cachemgr.
* configinfo->str & configinfo->len are reused to save info of
* header + data.
* The format:
* [cookie|data_size|config_str .............]
*/
if (configinfo->str) {
len = sizeof (ldap_config_out_t) - sizeof (int) +
configinfo->len;
if ((cout = calloc(1, len)) == NULL) {
free(configinfo->str);
configinfo->str = NULL;
configinfo->len = 0;
(void) snprintf(errstr, sizeof (errstr),
gettext("calloc: Out of memory."));
MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
strdup(errstr), NULL);
return (errorp);
}
/*
* cout->cookie is set by the caller,
* which is in ldap_cachemgr.
*/
cout->data_size = configinfo->len;
(void) memcpy(cout->config_str, configinfo->str,
configinfo->len);
free(configinfo->str);
configinfo->str = (char *)cout;
configinfo->len = len;
}
return (NULL);
}
ns_ldap_error_t *
__ns_ldap_DumpLdif(char *filename)
{
ns_config_t *ptr;
char errstr[MAXERROR];
ns_ldap_error_t *errorp;
char *str;
FILE *fp;
ParamIndexType i = 0;
char *profile, *container, *base;
ptr = __s_api_get_default_config();
if (ptr == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("No configuration information available."));
MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
NULL);
return (errorp);
}
if (filename == NULL) {
fp = stdout;
} else {
fp = fopen(filename, "wF");
if (fp == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Unable to open filename %s for ldif "
"dump (errno=%d)."), filename, errno);
MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE,
strdup(errstr), NULL);
__s_api_release_config(ptr);
return (errorp);
}
(void) fchmod(fileno(fp), 0444);
}
if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ptype != CHARPTR ||
ptr->paramList[NS_LDAP_PROFILE_P].ns_ptype != CHARPTR) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Required BaseDN and/or Profile name "
"ldif fields not present"));
MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE, strdup(errstr),
NULL);
__s_api_release_config(ptr);
return (errorp);
}
profile = ptr->paramList[NS_LDAP_PROFILE_P].ns_pc;
base = ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_pc;
container = _PROFILE_CONTAINER;
/*
* Construct DN, but since this is the profile, there is no need
* to worry about mapping. The profile itself can not be mapped
*/
(void) fprintf(fp, "dn: cn=%s,ou=%s,%s\n", profile, container, base);
/* dump objectclass names */
if (ptr->version == NS_LDAP_V1) {
(void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n",
_PROFILE1_OBJECTCLASS);
} else {
(void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n",
_PROFILE2_OBJECTCLASS);
}
/* For each parameter - construct value */
for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
str = __s_api_strValue(ptr, i, NS_LDIF_FMT);
if (str == NULL)
continue;
/*
* don't dump binddn, bind password, admin binddn, admin
* bind password, enableShadowUpdate flag, or cert path
* as they are not part of version 2 profiles
*/
if ((i != NS_LDAP_BINDDN_P) &&
(i != NS_LDAP_BINDPASSWD_P) &&
(i != NS_LDAP_ADMIN_BINDDN_P) &&
(i != NS_LDAP_ADMIN_BINDPASSWD_P) &&
(i != NS_LDAP_ENABLE_SHADOW_UPDATE_P) &&
(i != NS_LDAP_HOST_CERTPATH_P))
(void) fprintf(fp, "%s\n", str);
free(str);
}
if (filename != NULL)
(void) fclose(fp);
__s_api_release_config(ptr);
return (NULL);
}
/*
* This routine can process the configuration and/or
* the credential files at the same time.
* files is char *[3] = { "config", "cred", NULL };
*/
static
ns_ldap_error_t *
__ns_ldap_DumpConfigFiles(char **files)
{
char *filename;
int fi;
int docred;
ns_config_t *ptr;
char *str;
char errstr[MAXERROR];
ParamIndexType i = 0;
FILE *fp;
int rc;
ns_ldap_error_t *errorp = NULL;
struct stat buf;
int cfgtype;
boolean_t file_export_error = B_FALSE;
ptr = __s_api_get_default_config();
if (ptr == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("No configuration information available."));
MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
NULL);
return (errorp);
}
for (fi = 0; fi < 2; fi++) {
docred = 0;
filename = files[fi];
if (filename == NULL)
continue;
if (fi == 1)
docred++;
rc = stat(filename, &buf);
fp = fopen(filename, "wF");
if (fp == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Unable to open filename %s"
" for configuration dump (%s)."),
filename, strerror(errno));
MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE,
strdup(errstr), NULL);
__s_api_release_config(ptr);
return (errorp);
}
if (rc == 0) {
if (fchmod(fileno(fp), buf.st_mode) != 0) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Unable to set permissions for file"
" %s for configuration dump (%s)."),
filename, strerror(errno));
(void) fclose(fp);
file_export_error = B_TRUE;
break;
}
} else {
if (fchmod(fileno(fp), 0400) != 0) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Unable to set permissions for file"
" %s for configuration dump (%s)."),
filename, strerror(errno));
(void) fclose(fp);
file_export_error = B_TRUE;
break;
}
}
if (fprintf(fp, "#\n# %s\n#\n", DONOTEDIT) < 0) {
(void) snprintf(errstr, sizeof (errstr), gettext(
"Writing to file %s for configuration dump failed "
"(%s)."), filename, strerror(errno));
file_export_error = B_TRUE;
}
/* assume VERSION is set and it outputs first */
/* For each parameter - construct value */
for (i = 0; !file_export_error && (i <= NS_LDAP_MAX_PIT_P);
i++) {
cfgtype = __s_api_get_configtype(i);
if ((docred == 0 && cfgtype == CREDCONFIG) ||
(docred == 1 && cfgtype != CREDCONFIG))
continue;
str = __s_api_strValue(ptr, i, NS_FILE_FMT);
if (str == NULL)
continue;
if (fprintf(fp, "%s\n", str) < 0) {
(void) snprintf(errstr, sizeof (errstr),
gettext("Writing to file %s for"
"configuration dump failed (%s)."),
filename, strerror(errno));
file_export_error = B_TRUE;
}
free(str);
}
if (fclose(fp) != 0) {
/* Break if error already hit */
if (file_export_error)
break;
(void) snprintf(errstr, sizeof (errstr), gettext(
"Writing to file %s for configuration dump failed "
"during file close (%s)."), filename,
strerror(errno));
file_export_error = B_TRUE;
break;
}
}
if (file_export_error) {
MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE,
strdup(errstr), NULL);
(void) unlink(filename);
}
__s_api_release_config(ptr);
return (errorp);
}
ns_ldap_error_t *
__ns_ldap_DumpConfiguration(char *file)
{
ns_ldap_error_t *ret;
char *files[3];
files[0] = NULL;
files[1] = NULL;
files[2] = NULL;
if (strcmp(file, NSCONFIGFILE) == 0) {
files[0] = file;
} else if (strcmp(file, NSCONFIGREFRESH) == 0) {
files[0] = file;
} else if (strcmp(file, NSCREDFILE) == 0) {
files[1] = file;
} else if (strcmp(file, NSCREDREFRESH) == 0) {
files[1] = file;
}
ret = __ns_ldap_DumpConfigFiles(files);
return (ret);
}
/*
* **************************************************************
* Misc Routines
* **************************************************************
*/
ns_config_t *
__ns_ldap_make_config(ns_ldap_result_t *result)
{
int l, m;
char val[BUFSIZE];
char *attrname;
ns_ldap_entry_t *entry;
ns_ldap_attr_t *attr;
char **attrval;
ParamIndexType index;
ns_config_t *ptr;
ns_ldap_error_t *error = NULL;
int prof_ver;
ns_config_t *curr_ptr = NULL;
char errstr[MAXERROR];
ns_ldap_error_t *errorp;
LineBuf buffer;
char *sepstr;
if (result == NULL)
return (NULL);
if (result->entries_count > 1) {
(void) snprintf(errstr, MAXERROR,
gettext("Configuration Error: More than one profile "
"found"));
MKERROR(LOG_ERR, errorp, NS_PARSE_ERR, strdup(errstr), NULL);
(void) __ns_ldap_freeError(&errorp);
return (NULL);
}
ptr = __s_api_create_config();
if (ptr == NULL)
return (NULL);
curr_ptr = __s_api_get_default_config();
if (curr_ptr == NULL) {
__s_api_destroy_config(ptr);
return (NULL);
}
/* Check to see if the profile is version 1 or version 2 */
prof_ver = 1;
entry = result->entry;
for (l = 0; l < entry->attr_count; l++) {
attr = entry->attr_pair[l];
attrname = attr->attrname;
if (attrname == NULL)
continue;
if (strcasecmp(attrname, "objectclass") == 0) {
for (m = 0; m < attr->value_count; m++) {
if (strcasecmp(_PROFILE2_OBJECTCLASS,
attr->attrvalue[m]) == 0) {
prof_ver = 2;
break;
}
}
}
}
/* update the configuration to accept v1 or v2 attributes */
if (prof_ver == 1) {
(void) strcpy(val, NS_LDAP_VERSION_1);
(void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P,
val, &error);
} else {
(void) strcpy(val, NS_LDAP_VERSION_2);
(void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P,
val, &error);
}
for (l = 0; l < entry->attr_count; l++) {
attr = entry->attr_pair[l];
attrname = attr->attrname;
if (attrname == NULL)
continue;
if (__s_api_get_profiletype(attrname, &index) != 0)
continue;
attrval = attr->attrvalue;
switch (index) {
case NS_LDAP_SEARCH_DN_P:
case NS_LDAP_SERVICE_SEARCH_DESC_P:
case NS_LDAP_ATTRIBUTEMAP_P:
case NS_LDAP_OBJECTCLASSMAP_P:
case NS_LDAP_SERVICE_CRED_LEVEL_P:
case NS_LDAP_SERVICE_AUTH_METHOD_P:
/* Multiple Value - insert 1 at a time */
for (m = 0; m < attr->value_count; m++) {
(void) __ns_ldap_setParamValue(ptr, index,
attrval[m], &error);
}
break;
default:
(void) memset((void *)&buffer, 0, sizeof (LineBuf));
/* Single or Multiple Value */
for (m = 0; m < attr->value_count; m++) {
sepstr = NULL;
if (m != attr->value_count - 1) {
sepstr = SPACESEP;
}
if (__print2buf(&buffer, attrval[m], sepstr))
goto makeconfigerror;
}
(void) __ns_ldap_setParamValue(ptr, index, buffer.str,
&error);
if (buffer.len > 0) {
free(buffer.str);
buffer.len = 0;
}
break;
}
}
if (ptr->version != NS_LDAP_V1) {
ParamIndexType i;
if (curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_ptype == CHARPTR) {
(void) __ns_ldap_setParamValue(ptr, NS_LDAP_BINDDN_P,
curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_pc,
&error);
}
if (curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ptype ==
CHARPTR) {
(void) __ns_ldap_setParamValue(ptr,
NS_LDAP_BINDPASSWD_P,
curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_pc,
&error);
}
i = NS_LDAP_ENABLE_SHADOW_UPDATE_P;
if (curr_ptr->paramList[i].ns_ptype == INT) {
char *valt;
valt = __s_get_shadowupdate_name(
curr_ptr->paramList[i].ns_i);
(void) __ns_ldap_setParamValue(ptr, i, valt, &error);
}
if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_ptype ==
CHARPTR) {
(void) __ns_ldap_setParamValue(ptr,
NS_LDAP_ADMIN_BINDDN_P,
curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_pc,
&error);
}
if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_ptype ==
CHARPTR) {
(void) __ns_ldap_setParamValue(ptr,
NS_LDAP_ADMIN_BINDPASSWD_P,
curr_ptr->
paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_pc,
&error);
}
if (curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_ptype ==
CHARPTR) {
(void) __ns_ldap_setParamValue(ptr,
NS_LDAP_HOST_CERTPATH_P,
curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_pc,
&error);
}
}
__s_api_release_config(curr_ptr);
return (ptr);
makeconfigerror:
if (buffer.len > 0)
free(buffer.str);
__s_api_debug_pause(LOG_ERR, NS_PARSE_ERR,
"__ns_ldap_make_config: Not enough memory");
return (NULL);
}
/*
* Download a profile into our internal structure. The calling application
* needs to DumpConfig() to save the information to NSCONFIGFILE and NSCREDFILE
* if desired.
*/
int
__ns_ldap_download(const char *profile, char *addr, char *baseDN,
ns_ldap_error_t **errorp)
{
char filter[BUFSIZE];
int rc;
ns_ldap_result_t *result = NULL;
ns_config_t *ptr = NULL;
ns_config_t *new_ptr = NULL;
char errstr[MAXERROR];
*errorp = NULL;
if (baseDN == NULL)
return (NS_LDAP_INVALID_PARAM);
ptr = __s_api_get_default_config();
if (ptr == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("No configuration information available."));
MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
NULL);
return (NS_LDAP_CONFIG);
}
rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SEARCH_BASEDN_P, baseDN,
errorp);
if (rc != NS_LDAP_SUCCESS) {
__s_api_release_config(ptr);
return (rc);
}
rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SERVERS_P, addr, errorp);
__s_api_release_config(ptr);
if (rc != NS_LDAP_SUCCESS)
return (rc);
(void) snprintf(filter, sizeof (filter), _PROFILE_FILTER,
_PROFILE1_OBJECTCLASS, _PROFILE2_OBJECTCLASS, profile);
rc = __ns_ldap_list(_PROFILE_CONTAINER, (const char *)filter,
NULL, NULL, NULL, 0, &result, errorp, NULL, NULL);
if (rc != NS_LDAP_SUCCESS)
return (rc);
new_ptr = __ns_ldap_make_config(result);
(void) __ns_ldap_freeResult(&result);
if (new_ptr == NULL)
return (NS_LDAP_OP_FAILED);
rc = __s_api_crosscheck(new_ptr, errstr, B_FALSE, B_FALSE);
if (rc != NS_LDAP_SUCCESS) {
__s_api_destroy_config(new_ptr);
MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
NULL);
return (NS_LDAP_CONFIG);
}
__s_api_init_config(new_ptr);
return (rc);
}
/*
* **************************************************************
* Configuration Printing Routines
* **************************************************************
*/
/*
* Yes the use of stdio is okay here because all we are doing is sending
* output to stdout. This would not be necessary if we could get to the
* configuration pointer outside this file.
*/
ns_ldap_error_t *
__ns_ldap_print_config(int verbose)
{
ns_config_t *ptr;
char errstr[MAXERROR];
ns_ldap_error_t *errorp;
char *str;
int i;
ptr = __s_api_get_default_config();
if (ptr == NULL) {
errorp = __ns_ldap_LoadConfiguration();
if (errorp != NULL)
return (errorp);
ptr = __s_api_get_default_config();
if (ptr == NULL) {
(void) snprintf(errstr, sizeof (errstr),
gettext("No configuration information."));
MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
strdup(errstr), NULL);
return (errorp);
}
}
if (verbose && (ptr->domainName != NULL)) {
(void) fputs("ptr->domainName ", stdout);
(void) fputs(ptr->domainName, stdout);
(void) putchar('\n');
}
/* For each parameter - construct value */
for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
/*
* Version 1 skipped this entry because:
*
* don't print default cache TTL for now since
* we don't store it in the ldap_client_file.
*/
if ((i == NS_LDAP_CACHETTL_P) && (ptr->version == NS_LDAP_V1))
continue;
/* the credential for shadow update is not to be exposed */
if (i == NS_LDAP_ADMIN_BINDDN_P ||
i == NS_LDAP_ADMIN_BINDPASSWD_P)
continue;
str = __s_api_strValue(ptr, i, NS_FILE_FMT);
if (str == NULL)
continue;
if (verbose)
(void) putchar('\t');
(void) fprintf(stdout, "%s\n", str);
free(str);
}
__s_api_release_config(ptr);
return (NULL);
}