summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsldap/common/ns_config.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libsldap/common/ns_config.c
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libsldap/common/ns_config.c')
-rw-r--r--usr/src/lib/libsldap/common/ns_config.c3664
1 files changed, 3664 insertions, 0 deletions
diff --git a/usr/src/lib/libsldap/common/ns_config.c b/usr/src/lib/libsldap/common/ns_config.c
new file mode 100644
index 0000000000..1e52104c6c
--- /dev/null
+++ b/usr/src/lib/libsldap/common/ns_config.c
@@ -0,0 +1,3664 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * libsldap - library side configuration components
+ * Routines to manage the config structure
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <libintl.h>
+#include <locale.h>
+#include <thread.h>
+#include <synch.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <crypt.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <sys/systeminfo.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <limits.h>
+#include "ns_sldap.h"
+#include "ns_internal.h"
+#include "ns_cache_door.h"
+
+#pragma fini(_free_config)
+
+static mutex_t ns_parse_lock = DEFAULTMUTEX;
+static mutex_t ns_loadrefresh_lock = DEFAULTMUTEX;
+static ns_config_t *current_config = NULL;
+
+static int cache_server = FALSE;
+
+/*
+ * Parameter Index Type validation routines
+ */
+static int
+__s_val_postime(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf);
+static int
+__s_val_basedn(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf);
+
+static int
+__s_val_binddn(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf);
+
+static int
+__s_val_bindpw(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf);
+
+static int
+__s_val_serverList(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf);
+
+/*
+ * Forward declarations
+ */
+
+static ns_parse_status
+verify_value(ns_config_t *cfg, char *name, char *value, char *errstr);
+
+static int
+set_default_value(ns_config_t *configptr, char *name, char *value,
+ ns_ldap_error_t **error);
+
+static void
+set_curr_config(ns_config_t *ptr);
+
+static int
+__door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error);
+
+static ns_config_t *
+SetDoorInfo(char *buffer, ns_ldap_error_t **errorp);
+
+static boolean_t
+timetorefresh(ns_config_t *cfg);
+
+static ns_config_t *
+LoadCacheConfiguration(ns_ldap_error_t **error);
+
+static void **
+dupParam(ns_param_t *ptr);
+
+static time_t
+conv_time(char *s);
+
+/*
+ * Structures used in enum <-> string mapping routines
+ */
+
+static ns_enum_map ns_auth_enum_v1[] = {
+ { ENUM2INT(NS_LDAP_EA_NONE), "NS_LDAP_AUTH_NONE" },
+ { ENUM2INT(NS_LDAP_EA_SIMPLE), "NS_LDAP_AUTH_SIMPLE" },
+ { ENUM2INT(NS_LDAP_EA_SASL_CRAM_MD5), "NS_LDAP_AUTH_SASL_CRAM_MD5" },
+ { -1, NULL },
+};
+
+static ns_enum_map ns_auth_enum_v2[] = {
+ { ENUM2INT(NS_LDAP_EA_NONE), "none" },
+ { ENUM2INT(NS_LDAP_EA_SIMPLE), "simple" },
+ { ENUM2INT(NS_LDAP_EA_SASL_CRAM_MD5), "sasl/CRAM-MD5" },
+ { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5), "sasl/DIGEST-MD5" },
+ { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5_INT),
+ "sasl/DIGEST-MD5:auth-int" },
+ { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5_CONF),
+ "sasl/DIGEST-MD5:auth-conf" },
+ { ENUM2INT(NS_LDAP_EA_SASL_EXTERNAL), "sasl/EXTERNAL" },
+ { ENUM2INT(NS_LDAP_EA_TLS_NONE), "tls:none" },
+ { ENUM2INT(NS_LDAP_EA_TLS_SIMPLE), "tls:simple" },
+ { ENUM2INT(NS_LDAP_EA_TLS_SASL_CRAM_MD5), "tls:sasl/CRAM-MD5" },
+ { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5), "tls:sasl/DIGEST-MD5" },
+ { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT),
+ "tls:sasl/DIGEST-MD5:auth-int" },
+ { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF),
+ "tls:sasl/DIGEST-MD5:auth-conf" },
+ { ENUM2INT(NS_LDAP_EA_TLS_SASL_EXTERNAL), "tls:sasl/EXTERNAL" },
+ { -1, NULL },
+};
+
+ /* V1 ONLY */
+static ns_enum_map ns_sec_enum_v1[] = {
+ { ENUM2INT(NS_LDAP_TLS_NONE), "NS_LDAP_SEC_NONE" },
+ { -1, NULL },
+};
+
+ /* V2 ONLY */
+static ns_enum_map ns_cred_enum_v2[] = {
+ { ENUM2INT(NS_LDAP_CRED_ANON), "anonymous" },
+ { ENUM2INT(NS_LDAP_CRED_PROXY), "proxy" },
+ { ENUM2INT(NS_LDAP_CRED_SELF), "self" },
+ { -1, NULL },
+};
+
+static ns_enum_map ns_ref_enum_v1[] = {
+ { ENUM2INT(NS_LDAP_FOLLOWREF), "NS_LDAP_FOLLOWREF" },
+ { ENUM2INT(NS_LDAP_NOREF), "NS_LDAP_NOREF" },
+ { -1, NULL },
+};
+
+static ns_enum_map ns_ref_enum_v2[] = {
+ { ENUM2INT(NS_LDAP_FOLLOWREF), "TRUE" },
+ { ENUM2INT(NS_LDAP_NOREF), "FALSE" },
+ { -1, NULL },
+};
+
+static ns_enum_map ns_scope_enum_v1[] = {
+ { ENUM2INT(NS_LDAP_SCOPE_BASE), "NS_LDAP_SCOPE_BASE" },
+ { ENUM2INT(NS_LDAP_SCOPE_ONELEVEL), "NS_LDAP_SCOPE_ONELEVEL" },
+ { ENUM2INT(NS_LDAP_SCOPE_SUBTREE), "NS_LDAP_SCOPE_SUBTREE" },
+ { -1, NULL },
+};
+
+static ns_enum_map ns_scope_enum_v2[] = {
+ { ENUM2INT(NS_LDAP_SCOPE_BASE), "base" },
+ { ENUM2INT(NS_LDAP_SCOPE_ONELEVEL), "one" },
+ { ENUM2INT(NS_LDAP_SCOPE_SUBTREE), "sub" },
+ { -1, NULL },
+};
+
+static ns_enum_map ns_pref_enum[] = {
+ { ENUM2INT(NS_LDAP_PREF_FALSE), "NS_LDAP_FALSE" },
+ { ENUM2INT(NS_LDAP_PREF_TRUE), "NS_LDAP_TRUE" },
+ { -1, NULL },
+};
+
+static int ns_def_auth_v1[] = {
+ ENUM2INT(NS_LDAP_EA_NONE),
+ 0
+};
+
+static int ns_def_auth_v2[] = {
+ ENUM2INT(NS_LDAP_EA_NONE),
+ 0
+};
+
+static int ns_def_cred_v1[] = {
+ ENUM2INT(NS_LDAP_CRED_PROXY),
+ 0
+};
+
+static int ns_def_cred_v2[] = {
+ ENUM2INT(NS_LDAP_CRED_ANON),
+ 0
+};
+
+/*
+ * The next macro places an integer in the first sizeof(int) bytes of a
+ * void pointer location. For 32-bit, it is the same as "(void *) i". It
+ * is used to solve a problem found during 64-bit testing. The problem
+ * was that for a configuration parameter such as NS_LDAP_SEARCH_REF_P,
+ * which is of type INT and has defined default value, an int
+ * variable(ns_param.ns_pu.i) defined inside an union(ns_pu) structure, is
+ * used to access the defined default value. This requires the default
+ * value to be in the first sizeof(int) bytes of the union element. If
+ * just using "(void *) intval" to declare the default value in the
+ * following defconfig[] structure, the intval data will be placed is the
+ * last sizeof(int) bytes. In which case, when accessing via ns_pu_i in
+ * a 64-bit system, ZERO will be returned as the default value, not the
+ * defined one.
+ *
+ * Note since amd64 is little-endian, the problem is not an issue.
+ * INT2VOIDPTR will just leave the data (i) unchanged.
+ */
+#if defined(__amd64)
+#define INT2VOIDPTR(i) (void *)i
+#else
+#define INT2VOIDPTR(i) \
+ (void *)(((long)(i))<<(8*(sizeof (void *) - sizeof (int))))
+#endif
+/*
+ * The default configuration table
+ * Version 1 entries are first, V2 entries follow.
+ */
+static ns_default_config defconfig[] = {
+ /* optional V1 profile */
+ {"NS_LDAP_FILE_VERSION", NS_LDAP_FILE_VERSION_P,
+ CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ NULL, /* No version number defined in V1 */
+ { CHARPTR, 0, (void *)NS_LDAP_VERSION_1 },
+ NULL, NULL },
+
+ /* ---------- V1 profile ---------- */
+ {"NS_LDAP_BINDDN", NS_LDAP_BINDDN_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ _P1_BINDDN,
+ { CHARPTR, 0, NULL },
+ __s_val_binddn, NULL },
+
+ {"NS_LDAP_BINDPASSWD", NS_LDAP_BINDPASSWD_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ _P1_BINDPASSWORD,
+ { CHARPTR, 0, NULL },
+ __s_val_bindpw, NULL },
+
+ {"NS_LDAP_SERVERS", NS_LDAP_SERVERS_P,
+ SERVERCONFIG, ARRAYCP, FALSE, NS_LDAP_V1,
+ _P1_SERVERS,
+ { ARRAYCP, 0, NULL },
+ __s_val_serverList, NULL },
+
+ {"NS_LDAP_SEARCH_BASEDN", NS_LDAP_SEARCH_BASEDN_P,
+ SERVERCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ _P1_SEARCHBASEDN,
+ { CHARPTR, 0, NULL },
+ __s_val_basedn, NULL },
+
+ {"NS_LDAP_AUTH", NS_LDAP_AUTH_P,
+ CLIENTCONFIG, ARRAYAUTH, FALSE, NS_LDAP_V1,
+ _P1_AUTHMETHOD,
+ { ARRAYAUTH, 1, (void *)&ns_def_auth_v1[0] },
+ NULL, ns_auth_enum_v1 },
+
+ {"NS_LDAP_TRANSPORT_SEC", NS_LDAP_TRANSPORT_SEC_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
+ _P1_TRANSPORTSECURITY,
+ { INT, 0, INT2VOIDPTR(NS_LDAP_TLS_NONE) },
+ NULL, ns_sec_enum_v1 },
+
+ {"NS_LDAP_SEARCH_REF", NS_LDAP_SEARCH_REF_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
+ _P1_SEARCHREFERRAL,
+ { INT, 0, INT2VOIDPTR(NS_LDAP_FOLLOWREF) },
+ NULL, ns_ref_enum_v1 },
+
+ {"NS_LDAP_DOMAIN", NS_LDAP_DOMAIN_P,
+ CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ NULL, /* not defined in the Profile */
+ { CHARPTR, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_EXP", NS_LDAP_EXP_P,
+ SERVERCONFIG, TIMET, TRUE, NS_LDAP_V1,
+ NULL, /* initialized by code to time+NS_LDAP_CACHETTL */
+ { INT, 0, 0 },
+ NULL, NULL },
+
+ {"NS_LDAP_CERT_PATH", NS_LDAP_CERT_PATH_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ _P1_CERTIFICATEPATH,
+ { CHARPTR, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_CERT_PASS", NS_LDAP_CERT_PASS_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ _P1_CERTIFICATEPASSWORD,
+ { CHARPTR, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_SEARCH_DN", NS_LDAP_SEARCH_DN_P,
+ CLIENTCONFIG, SSDLIST, FALSE, NS_LDAP_V1,
+ _P1_DATASEARCHDN,
+ { SSDLIST, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_SEARCH_SCOPE", NS_LDAP_SEARCH_SCOPE_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
+ _P1_SEARCHSCOPE,
+ { INT, 0, INT2VOIDPTR(NS_LDAP_SCOPE_ONELEVEL) },
+ NULL, ns_scope_enum_v1 },
+
+ {"NS_LDAP_SEARCH_TIME", NS_LDAP_SEARCH_TIME_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
+ _P1_SEARCHTIMELIMIT,
+ { INT, 0, INT2VOIDPTR(NS_DEFAULT_SEARCH_TIMEOUT) },
+ NULL, NULL },
+
+ {"NS_LDAP_SERVER_PREF", NS_LDAP_SERVER_PREF_P,
+ CLIENTCONFIG, ARRAYCP, FALSE, NS_LDAP_V1,
+ _P1_PREFERREDSERVER,
+ { ARRAYCP, 0, NULL },
+ __s_val_serverList, NULL },
+
+ {"NS_LDAP_PREF_ONLY", NS_LDAP_PREF_ONLY_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
+ _P1_PREFERREDSERVERONLY,
+ { INT, 0, INT2VOIDPTR(NS_LDAP_PREF_FALSE) },
+ NULL, ns_pref_enum },
+
+ {"NS_LDAP_CACHETTL", NS_LDAP_CACHETTL_P,
+ CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ _P1_CACHETTL,
+ { CHARPTR, 0, (void *)EXP_DEFAULT_TTL },
+ __s_val_postime, NULL },
+
+ {"NS_LDAP_PROFILE", NS_LDAP_PROFILE_P,
+ CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
+ _P_CN,
+ { CHARPTR, 0, (void *)DEFAULTCONFIGNAME },
+ NULL, NULL },
+
+ {"NS_LDAP_BIND_TIME", NS_LDAP_BIND_TIME_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
+ _P1_BINDTIMELIMIT,
+ { INT, 0, INT2VOIDPTR(NS_DEFAULT_BIND_TIMEOUT) },
+ NULL, NULL },
+
+ /* This configuration option is not visible in V1 */
+ {"NS_LDAP_CREDENTIAL_LEVEL", NS_LDAP_CREDENTIAL_LEVEL_P,
+ CLIENTCONFIG, ARRAYCRED, TRUE, NS_LDAP_V1,
+ NULL, /* No version defined in V1 */
+ { ARRAYCRED, 0, (void *)&ns_def_cred_v1[0] },
+ NULL, NULL },
+
+ /* ---------- V2 profile ---------- */
+ {"NS_LDAP_FILE_VERSION", NS_LDAP_FILE_VERSION_P,
+ CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ NULL, /* No version number defined in V1 */
+ { CHARPTR, 0, (void *)NS_LDAP_VERSION_2 },
+ NULL, NULL },
+
+ {"NS_LDAP_BINDDN", NS_LDAP_BINDDN_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ NULL, /* not defined in the Profile */
+ { CHARPTR, 0, NULL },
+ __s_val_binddn, NULL },
+ {"NS_LDAP_BINDPASSWD", NS_LDAP_BINDPASSWD_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ NULL, /* not defined in the Profile */
+ { CHARPTR, 0, NULL },
+ __s_val_bindpw, NULL },
+ {"NS_LDAP_EXP", NS_LDAP_EXP_P,
+ SERVERCONFIG, TIMET, TRUE, NS_LDAP_V2,
+ NULL, /* initialized by code to time+NS_LDAP_CACHETTL */
+ { INT, 0, 0 },
+ NULL, NULL },
+
+ {"NS_LDAP_SERVER_PREF", NS_LDAP_SERVER_PREF_P,
+ CLIENTCONFIG, SERVLIST, FALSE, NS_LDAP_V2,
+ _P2_PREFERREDSERVER,
+ { SERVLIST, 0, NULL },
+ __s_val_serverList, NULL },
+
+ {"NS_LDAP_SERVERS", NS_LDAP_SERVERS_P,
+ SERVERCONFIG, SERVLIST, FALSE, NS_LDAP_V2,
+ _P2_DEFAULTSERVER,
+ { SERVLIST, 0, NULL },
+ __s_val_serverList, NULL },
+
+ {"NS_LDAP_SEARCH_BASEDN", NS_LDAP_SEARCH_BASEDN_P,
+ SERVERCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ _P2_SEARCHBASEDN,
+ { CHARPTR, 0, NULL },
+ __s_val_basedn, NULL },
+
+ {"NS_LDAP_SEARCH_SCOPE", NS_LDAP_SEARCH_SCOPE_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V2,
+ _P2_SEARCHSCOPE,
+ { INT, 0, INT2VOIDPTR(NS_LDAP_SCOPE_ONELEVEL) },
+ NULL, ns_scope_enum_v2 },
+
+ {"NS_LDAP_AUTH", NS_LDAP_AUTH_P,
+ CLIENTCONFIG, ARRAYAUTH, FALSE, NS_LDAP_V2,
+ _P2_AUTHMETHOD,
+ { ARRAYAUTH, 2, (void *)&ns_def_auth_v2[0] },
+ NULL, ns_auth_enum_v2 },
+
+ {"NS_LDAP_CREDENTIAL_LEVEL", NS_LDAP_CREDENTIAL_LEVEL_P,
+ CLIENTCONFIG, ARRAYCRED, FALSE, NS_LDAP_V2,
+ _P2_CREDENTIALLEVEL,
+ { ARRAYCRED, 0, (void *)&ns_def_cred_v2[0] },
+ NULL, ns_cred_enum_v2 },
+
+ {"NS_LDAP_SERVICE_SEARCH_DESC", NS_LDAP_SERVICE_SEARCH_DESC_P,
+ CLIENTCONFIG, SSDLIST, FALSE, NS_LDAP_V2,
+ _P2_SERVICESEARCHDESC,
+ { SSDLIST, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_SEARCH_TIME", NS_LDAP_SEARCH_TIME_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V2,
+ _P2_SEARCHTIMELIMIT,
+ { INT, 0, INT2VOIDPTR(NS_DEFAULT_SEARCH_TIMEOUT) },
+ NULL, NULL },
+
+ {"NS_LDAP_BIND_TIME", NS_LDAP_BIND_TIME_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V2,
+ _P2_BINDTIMELIMIT,
+ { INT, 0, INT2VOIDPTR(NS_DEFAULT_BIND_TIMEOUT) },
+ NULL, NULL },
+
+ {"NS_LDAP_SEARCH_REF", NS_LDAP_SEARCH_REF_P,
+ CLIENTCONFIG, INT, TRUE, NS_LDAP_V2,
+ _P2_FOLLOWREFERRALS,
+ { INT, 0, INT2VOIDPTR(NS_LDAP_FOLLOWREF) },
+ NULL, ns_ref_enum_v2 },
+
+ {"NS_LDAP_CACHETTL", NS_LDAP_CACHETTL_P,
+ CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ _P2_PROFILETTL,
+ { CHARPTR, 0, (void *)EXP_DEFAULT_TTL },
+ __s_val_postime, NULL },
+
+ {"NS_LDAP_ATTRIBUTEMAP", NS_LDAP_ATTRIBUTEMAP_P,
+ CLIENTCONFIG, ATTRMAP, FALSE, NS_LDAP_V2,
+ _P2_ATTRIBUTEMAP,
+ { ATTRMAP, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_OBJECTCLASSMAP", NS_LDAP_OBJECTCLASSMAP_P,
+ CLIENTCONFIG, OBJMAP, FALSE, NS_LDAP_V2,
+ _P2_OBJECTCLASSMAP,
+ { OBJMAP, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_PROFILE", NS_LDAP_PROFILE_P,
+ CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ _P_CN,
+ { CHARPTR, 0, (void *)DEFAULTCONFIGNAME },
+ NULL, NULL },
+
+ {"NS_LDAP_SERVICE_AUTH_METHOD", NS_LDAP_SERVICE_AUTH_METHOD_P,
+ CLIENTCONFIG, SAMLIST, FALSE, NS_LDAP_V2,
+ _P2_SERVICEAUTHMETHOD,
+ { SAMLIST, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_SERVICE_CRED_LEVEL", NS_LDAP_SERVICE_CRED_LEVEL_P,
+ CLIENTCONFIG, SCLLIST, FALSE, NS_LDAP_V2,
+ _P2_SERVICECREDLEVEL,
+ { SCLLIST, 0, NULL },
+ NULL, NULL },
+
+ {"NS_LDAP_HOST_CERTPATH", NS_LDAP_HOST_CERTPATH_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ NULL, /* not defined in the Profile */
+ { CHARPTR, 0, (void *)NSLDAPDIRECTORY },
+ NULL, NULL },
+
+ /* array terminator [not an entry] */
+ {NULL, NS_LDAP_FILE_VERSION_P,
+ CLIENTCONFIG, NS_UNKNOWN, TRUE, NULL,
+ NULL,
+ { NS_UNKNOWN, 0, NULL },
+ NULL, NULL },
+};
+
+static char *
+__getdomainname()
+{
+ /*
+ * The sysinfo man page recommends using a buffer size
+ * of 257 bytes. MAXHOSTNAMELEN is 256. So add 1 here.
+ */
+ char buf[MAXHOSTNAMELEN + 1];
+ int status;
+
+ status = sysinfo(SI_SRPC_DOMAIN, buf, MAXHOSTNAMELEN);
+ if (status < 0)
+ return (NULL);
+ /* error: not enough space to hold returned value */
+ if (status > sizeof (buf))
+ return (NULL);
+ return (strdup(buf));
+}
+
+void
+__ns_ldap_setServer(int set)
+{
+ cache_server = set;
+}
+
+static boolean_t
+timetorefresh(ns_config_t *cfg)
+{
+ struct timeval tp;
+ static time_t expire = 0;
+
+ if (cfg == NULL || gettimeofday(&tp, NULL) == -1)
+ return (B_TRUE);
+
+ if (cfg->paramList[NS_LDAP_EXP_P].ns_ptype == TIMET)
+ expire = cfg->paramList[NS_LDAP_EXP_P].ns_tm;
+ else
+ return (B_TRUE);
+
+ return (expire != 0 && tp.tv_sec > expire);
+}
+
+int
+__s_get_enum_value(ns_config_t *ptr, char *value, ParamIndexType i)
+{
+ register ns_enum_map *mapp;
+ char *pstart = value;
+ char *pend;
+ int len;
+
+ if (pstart == NULL)
+ return (-1);
+
+ /* skip leading spaces */
+ while (*pstart == SPACETOK)
+ pstart++;
+ /* skip trailing spaces */
+ pend = pstart + strlen(pstart) - 1;
+ for (; pend >= pstart && *pend == SPACETOK; pend--);
+ len = pend - pstart + 1;
+ if (len == 0)
+ return (-1);
+
+ switch (i) {
+ case NS_LDAP_AUTH_P:
+ if (ptr->version == NS_LDAP_V1)
+ mapp = &ns_auth_enum_v1[0];
+ else
+ mapp = &ns_auth_enum_v2[0];
+ break;
+ case NS_LDAP_TRANSPORT_SEC_P:
+ return (-1);
+ case NS_LDAP_SEARCH_SCOPE_P:
+ if (ptr->version == NS_LDAP_V1)
+ mapp = &ns_scope_enum_v1[0];
+ else
+ mapp = &ns_scope_enum_v2[0];
+ break;
+ case NS_LDAP_SEARCH_REF_P:
+ if (ptr->version == NS_LDAP_V1)
+ mapp = &ns_ref_enum_v1[0];
+ else
+ mapp = &ns_ref_enum_v2[0];
+ break;
+ case NS_LDAP_PREF_ONLY_P:
+ mapp = &ns_pref_enum[0];
+ break;
+ case NS_LDAP_CREDENTIAL_LEVEL_P:
+ if (ptr->version == NS_LDAP_V1)
+ return (-1);
+ else
+ mapp = &ns_cred_enum_v2[0];
+ break;
+ case NS_LDAP_SERVICE_AUTH_METHOD_P:
+ mapp = &ns_auth_enum_v2[0];
+ break;
+ case NS_LDAP_SERVICE_CRED_LEVEL_P:
+ mapp = &ns_cred_enum_v2[0];
+ break;
+ default:
+ return (-1);
+ }
+
+ for (; mapp->name != NULL; mapp++) {
+ if (strncasecmp(pstart, mapp->name, len) == 0 &&
+ (strlen(mapp->name) == len)) {
+ return (mapp->value);
+ }
+ }
+ return (-1);
+}
+
+char *
+__s_get_auth_name(ns_config_t *ptr, AuthType_t type)
+{
+ register ns_enum_map *mapp;
+
+ if (ptr->version == NS_LDAP_V1)
+ mapp = &ns_auth_enum_v1[0];
+ else
+ mapp = &ns_auth_enum_v2[0];
+
+ for (; mapp->name != NULL; mapp++) {
+ if (type == INT2AUTHENUM(mapp->value)) {
+ return (mapp->name);
+ }
+ }
+ return ("Unknown AuthType_t type specified");
+}
+
+
+char *
+__s_get_security_name(ns_config_t *ptr, TlsType_t type)
+{
+ register ns_enum_map *mapp;
+
+ if (ptr->version == NS_LDAP_V1) {
+ mapp = &ns_sec_enum_v1[0];
+
+ for (; mapp->name != NULL; mapp++) {
+ if (type == INT2SECENUM(mapp->value)) {
+ return (mapp->name);
+ }
+ }
+ }
+ return ("Unknown TlsType_t type specified");
+}
+
+
+char *
+__s_get_scope_name(ns_config_t *ptr, ScopeType_t type)
+{
+ register ns_enum_map *mapp;
+
+ if (ptr->version == NS_LDAP_V1)
+ mapp = &ns_scope_enum_v1[0];
+ else
+ mapp = &ns_scope_enum_v2[0];
+
+ for (; mapp->name != NULL; mapp++) {
+ if (type == INT2SCOPEENUM(mapp->value)) {
+ return (mapp->name);
+ }
+ }
+ return ("Unknown ScopeType_t type specified");
+}
+
+
+char *
+__s_get_pref_name(PrefOnly_t type)
+{
+ register ns_enum_map *mapp = &ns_pref_enum[0];
+
+ for (; mapp->name != NULL; mapp++) {
+ if (type == INT2PREFONLYENUM(mapp->value)) {
+ return (mapp->name);
+ }
+ }
+ return ("Unknown PrefOnly_t type specified");
+}
+
+char *
+__s_get_searchref_name(ns_config_t *ptr, SearchRef_t type)
+{
+ register ns_enum_map *mapp;
+
+ if (ptr->version == NS_LDAP_V1)
+ mapp = &ns_ref_enum_v1[0];
+ else
+ mapp = &ns_ref_enum_v2[0];
+
+ for (; mapp->name != NULL; mapp++) {
+ if (type == INT2SEARCHREFENUM(mapp->value)) {
+ return (mapp->name);
+ }
+ }
+ return ("Unknown SearchRef_t type specified");
+}
+
+static char *
+__s_get_credlvl_name(ns_config_t *ptr, CredLevel_t type)
+{
+ register ns_enum_map *mapp;
+
+ if (ptr->version == NS_LDAP_V2) {
+ mapp = &ns_cred_enum_v2[0];
+ for (; mapp->name != NULL; mapp++) {
+ if (type == INT2CREDLEVELENUM(mapp->value)) {
+ return (mapp->name);
+ }
+ }
+ }
+ return ("Unknown CredLevel_t type specified");
+}
+
+static void
+destroy_param(ns_config_t *ptr, ParamIndexType type)
+{
+ int i, j;
+ char **ppc;
+
+ if (ptr == NULL)
+ return;
+
+ /*
+ * This routine is not lock protected because
+ * the config param it may be destroying is not
+ * necessarily THE config. Mutex protect elsewhere.
+ */
+ switch (ptr->paramList[type].ns_ptype) {
+ case CHARPTR:
+ if (ptr->paramList[type].ns_pc) {
+ free(ptr->paramList[type].ns_pc);
+ ptr->paramList[type].ns_pc = NULL;
+ }
+ break;
+ case SAMLIST:
+ case SCLLIST:
+ case SSDLIST:
+ case ARRAYCP:
+ case SERVLIST:
+ if (ptr->paramList[type].ns_ppc) {
+ ppc = ptr->paramList[type].ns_ppc;
+ j = ptr->paramList[type].ns_acnt;
+ for (i = 0; i < j && ppc[i] != NULL; i++) {
+ free((void *)ppc[i]);
+ }
+ free((void *)ppc);
+ ptr->paramList[type].ns_ppc = NULL;
+ }
+ break;
+ case ARRAYAUTH:
+ case ARRAYCRED:
+ if (ptr->paramList[type].ns_pi) {
+ free(ptr->paramList[type].ns_pi);
+ ptr->paramList[type].ns_pi = NULL;
+ }
+ break;
+ case INT:
+ ptr->paramList[type].ns_i = 0;
+ break;
+ case ATTRMAP:
+ break;
+ case OBJMAP:
+ break;
+ default:
+ break;
+ }
+ ptr->paramList[type].ns_ptype = NS_UNKNOWN;
+}
+
+static void
+destroy_config(ns_config_t *ptr)
+{
+ ParamIndexType i;
+
+ if (ptr != NULL) {
+ if (ptr->domainName != NULL)
+ free(ptr->domainName);
+ ptr->domainName = NULL;
+ for (i = 0; i <= LAST_VALUE; i++) {
+ destroy_param(ptr, i);
+ }
+ __s_api_destroy_hash(ptr);
+ free(ptr);
+ }
+}
+
+/*
+ * Marks the ns_config_t to be deleted and then releases it. (If no other
+ * caller is using, then __s_api_release_config will destroy it.)
+ *
+ * Note that __s_api_destroy_config should only be called if the caller has
+ * created the ns_config_t with __s_api_create_config (with the exception
+ * of set_curr_config). The ns_config_t should be private to the caller.
+ *
+ * This function should not be called with the current_config except by
+ * set_curr_config which locks ns_parse_lock to ensure that no thread
+ * will be waiting on current_config->config_mutex. This ensures that
+ * no caller with be waiting on cfg->config_mutex while it is being
+ * destroyed by __s_api_release_config.
+ */
+
+void
+__s_api_destroy_config(ns_config_t *cfg)
+{
+ if (cfg != NULL) {
+ (void) mutex_lock(&cfg->config_mutex);
+ cfg->delete = TRUE;
+ (void) mutex_unlock(&cfg->config_mutex);
+ __s_api_release_config(cfg);
+ }
+}
+
+
+/*
+ * Increment the configuration use count by one - assumes ns_parse_lock has
+ * been obtained
+ */
+
+static ns_config_t *
+get_curr_config_unlocked()
+{
+ ns_config_t *cfg;
+ ns_config_t *ret;
+
+ cfg = current_config;
+ ret = cfg;
+ if (cfg != NULL) {
+ (void) mutex_lock(&cfg->config_mutex);
+ if (cfg->delete)
+ ret = NULL;
+ else
+ cfg->nUse++;
+ (void) mutex_unlock(&cfg->config_mutex);
+ }
+ return (ret);
+}
+
+/*
+ * set_curr_config sets the current config to
+ * the specified ns_config_t. Note that this function
+ * is similar to the project private function __s_api_init_config
+ * except that it does not release the new ns_config_t
+ */
+
+static void
+set_curr_config(ns_config_t *ptr)
+{
+ ns_config_t *cfg;
+
+ (void) mutex_lock(&ns_parse_lock);
+ cfg = get_curr_config_unlocked();
+ if (cfg != ptr) {
+ __s_api_destroy_config(cfg);
+ current_config = ptr;
+ }
+ (void) mutex_unlock(&ns_parse_lock);
+}
+
+/*
+ * Decrements the ns_config_t usage count by one. Delete if delete flag
+ * is set and no other callers are using.
+ */
+
+void
+__s_api_release_config(ns_config_t *cfg)
+{
+ if (cfg != NULL) {
+ (void) mutex_lock(&cfg->config_mutex);
+ cfg->nUse--;
+ if (cfg->nUse == 0 && cfg->delete) {
+ destroy_config(cfg);
+ } else
+ (void) mutex_unlock(&cfg->config_mutex);
+ }
+}
+
+/*
+ * __s_api_init_config function destroys the previous configuration
+ * sets the new configuration and then releases it
+ */
+void
+__s_api_init_config(ns_config_t *ptr)
+{
+ set_curr_config(ptr);
+ __s_api_release_config(ptr);
+}
+
+
+/*
+ * Create an ns_config_t, set the usage count to one
+ */
+
+ns_config_t *
+__s_api_create_config(void)
+{
+ ns_config_t *ret;
+ ret = (ns_config_t *)calloc(1, sizeof (ns_config_t));
+ if (ret == NULL)
+ return (NULL);
+
+ ret->domainName = __getdomainname();
+ if (ret->domainName == NULL) {
+ free(ret);
+ return (NULL);
+ }
+ ret->version = NS_LDAP_V1;
+ (void) mutex_init(&ret->config_mutex, USYNC_THREAD, NULL);
+ ret->nUse = 1;
+ ret->delete = B_FALSE;
+ return (ret);
+}
+
+ns_config_t *
+__s_api_get_default_config(void)
+{
+ ns_config_t *cfg;
+
+ (void) mutex_lock(&ns_parse_lock);
+ cfg = get_curr_config_unlocked();
+ (void) mutex_unlock(&ns_parse_lock);
+
+ return (cfg);
+}
+
+static char *
+stripdup(const char *instr)
+{
+ char *pstart = (char *)instr;
+ char *pend, *ret;
+ int len;
+
+ if (pstart == NULL)
+ return (NULL);
+ /* remove leading spaces */
+ while (*pstart == SPACETOK)
+ pstart++;
+ /* remove trailing spaces */
+ pend = pstart + strlen(pstart) - 1;
+ for (; pend >= pstart && *pend == SPACETOK; pend--);
+ len = pend - pstart + 1;
+ if ((ret = malloc(len + 1)) == NULL)
+ return (NULL);
+ if (len != 0) {
+ (void) strncpy(ret, pstart, len);
+ }
+ ret[len] = '\0';
+ return (ret);
+}
+
+static boolean_t
+has_port(char **ppc, int cnt)
+{
+ int j;
+ const char *s;
+ const char *begin;
+
+ /*
+ * Don't check that address is legal - only determine
+ * if there is a port specified
+ */
+ if (ppc != NULL) {
+ for (j = 0; j < cnt; j++) {
+ begin = ppc[j];
+ s = begin + strlen(begin);
+ while (s >= begin) {
+ if (*s == ']')
+ break;
+ else if (*s == COLONTOK)
+ return (B_TRUE);
+ s--;
+ }
+ }
+ }
+ return (B_FALSE);
+}
+
+/*
+ * Note that __s_api_crosscheck is assumed to be called with an ns_config_t
+ * that is properly protected - so that it will not change during the
+ * duration of the call
+ */
+
+/* Size of errstr needs to be MAXERROR */
+ns_parse_status
+__s_api_crosscheck(ns_config_t *ptr, char *errstr, int check_dn)
+{
+ int value, j;
+ time_t tm;
+ const char *str, *str1;
+ boolean_t has_tls = B_FALSE;
+ boolean_t is_ok = B_TRUE;
+ int i, len, cnt;
+ const char *begin;
+ char **ppc;
+ int *pi;
+
+
+ if (ptr == NULL)
+ return (NS_SUCCESS);
+
+ /* check for no server specified */
+ if (ptr->paramList[NS_LDAP_SERVERS_P].ns_ppc == NULL) {
+ if (ptr->version == NS_LDAP_V1) {
+ str = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_SERVERS_P));
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: No entry for "
+ "'%s' found"), str);
+ return (NS_PARSE_ERR);
+ } else if (ptr->paramList[NS_LDAP_SERVER_PREF_P].ns_ppc ==
+ NULL) {
+ str = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_SERVERS_P));
+ str1 = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_SERVER_PREF_P));
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: "
+ "Neither '%s' nor '%s' is defined"), str, str1);
+ return (NS_PARSE_ERR);
+ }
+ }
+ if (ptr->paramList[NS_LDAP_CERT_PASS_P].ns_pc != NULL &&
+ ptr->paramList[NS_LDAP_CERT_PATH_P].ns_pc == NULL) {
+ str = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_CERT_PASS_P));
+ str1 = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_CERT_PATH_P));
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: %s specified "
+ "but no value for '%s' found"), str, str1);
+ return (NS_PARSE_ERR);
+ }
+ if (ptr->paramList[NS_LDAP_CERT_PASS_P].ns_pc == NULL &&
+ ptr->paramList[NS_LDAP_CERT_PATH_P].ns_pc != NULL) {
+ str = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_CERT_PATH_P));
+ str1 = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_CERT_PASS_P));
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: %s specified "
+ "but no value for '%s' found"), str, str1);
+ return (NS_PARSE_ERR);
+ }
+ /* check if search basedn has been specified */
+ if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ppc == NULL) {
+ str = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_SEARCH_BASEDN_P));
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: No entry for "
+ "'%s' found"), str);
+ return (NS_PARSE_ERR);
+ }
+
+ if (check_dn) {
+ /* check for auth value....passwd/bindn if necessary */
+
+ for (j = 0; ptr->paramList[NS_LDAP_AUTH_P].ns_pi != NULL &&
+ ptr->paramList[NS_LDAP_AUTH_P].ns_pi[j] != NULL; j++) {
+ value = ptr->paramList[NS_LDAP_AUTH_P].ns_pi[j];
+ switch (value) {
+ case NS_LDAP_EA_SIMPLE:
+ case NS_LDAP_EA_SASL_CRAM_MD5:
+ case NS_LDAP_EA_SASL_DIGEST_MD5:
+ case NS_LDAP_EA_SASL_DIGEST_MD5_INT:
+ case NS_LDAP_EA_SASL_DIGEST_MD5_CONF:
+ case NS_LDAP_EA_TLS_SIMPLE:
+ case NS_LDAP_EA_TLS_SASL_CRAM_MD5:
+ case NS_LDAP_EA_TLS_SASL_DIGEST_MD5:
+ case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT:
+ case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF:
+ if (ptr->paramList[NS_LDAP_BINDDN_P].ns_ppc == NULL) {
+ str = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_BINDDN_P));
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: No entry for "
+ "'%s' found"), str);
+ return (NS_PARSE_ERR);
+ }
+ if (ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ppc
+ == NULL) {
+ str = NULL_OR_STR(__s_api_get_configname(
+ NS_LDAP_BINDPASSWD_P));
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: No entry for "
+ "'%s' found"), str);
+ return (NS_PARSE_ERR);
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Check to see if port and tls are both configured. This is not
+ * supported until starttls is supported.
+ */
+
+ pi = ptr->paramList[NS_LDAP_AUTH_P].ns_pi;
+ if (pi != NULL) {
+ cnt = ptr->paramList[NS_LDAP_AUTH_P].ns_acnt;
+ for (j = 0; j < cnt && !has_tls; j++) {
+ has_tls = (pi[j] == NS_LDAP_EA_TLS_NONE) ||
+ (pi[j] == NS_LDAP_EA_TLS_SIMPLE) ||
+ (pi[j] == NS_LDAP_EA_TLS_SASL_CRAM_MD5) ||
+ (pi[j] == NS_LDAP_EA_TLS_SASL_DIGEST_MD5) ||
+ (pi[j] == NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT) ||
+ (pi[j] == NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF) ||
+ (pi[j] == NS_LDAP_EA_TLS_SASL_EXTERNAL);
+ }
+ }
+
+ ppc = ptr->paramList[NS_LDAP_SERVICE_AUTH_METHOD_P].ns_ppc;
+ if (!has_tls && ppc != NULL) {
+ cnt = ptr->paramList[NS_LDAP_SERVICE_AUTH_METHOD_P].ns_acnt;
+ for (j = 0; j < cnt && !has_tls; j++) {
+ begin = ppc[j];
+ /* skip over service tag */
+ if (begin != NULL)
+ begin = strchr(begin, ':');
+ if (!has_tls && begin != NULL) {
+ len = strlen(begin) - 3;
+ for (i = 0; i < len; i++)
+ if (strncasecmp(begin + i, "tls:", 4) == 0)
+ break;
+ has_tls = i < len;
+ }
+ }
+ }
+
+ if (has_tls) {
+ is_ok = !has_port(ptr->paramList[NS_LDAP_SERVERS_P].ns_ppc,
+ ptr->paramList[NS_LDAP_SERVERS_P].ns_acnt);
+ ppc = ptr->paramList[NS_LDAP_SERVER_PREF_P].ns_ppc;
+ if (is_ok)
+ is_ok = !has_port(ptr->paramList[NS_LDAP_SERVER_PREF_P].ns_ppc,
+ ptr->paramList[NS_LDAP_SERVER_PREF_P].ns_acnt);
+ }
+ if (!is_ok) {
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Configuration Error: "
+ "Cannot specify LDAP port with tls"));
+ return (NS_PARSE_ERR);
+ }
+
+ /*
+ * If NS_LDAP_CACHETTL is not specified,
+ * init NS_LDAP_EXP_P here. Otherwise,
+ * ldap_cachemgr will never refresh the profile.
+ * Set it to current time + default
+ * NS_LDAP_CACHETTL
+ */
+ if (ptr->paramList[NS_LDAP_CACHETTL_P].ns_pc == NULL) {
+ tm = conv_time(
+ defconfig[NS_LDAP_CACHETTL_P].defval.ns_pc);
+ ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET;
+ if (tm != 0) {
+ tm += time(NULL);
+ }
+ ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm;
+ }
+
+ return (NS_SUCCESS);
+}
+
+
+int
+__s_api_get_type(const char *value, ParamIndexType *type)
+{
+ int i;
+
+ for (i = 0; defconfig[i].name != NULL; i++) {
+ if (strcasecmp(defconfig[i].name, value) == 0) {
+ *type = defconfig[i].index;
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+/*
+ * Externally defined version of get_type.
+ * Includes extra error checking
+ */
+
+int
+__ns_ldap_getParamType(const char *value, ParamIndexType *type)
+{
+ if (value == NULL || type == NULL)
+ return (-1);
+ return (__s_api_get_type(value, type));
+}
+
+int
+__s_api_get_versiontype(ns_config_t *ptr, char *value, ParamIndexType *type)
+{
+ ns_version_t ver;
+ int i;
+
+ if (ptr == NULL)
+ return (-1);
+
+ ver = ptr->version;
+
+ for (i = 0; defconfig[i].name != NULL; i++) {
+ if (strcasecmp(defconfig[i].name, value) == 0) {
+ if (defconfig[i].version == ver) {
+ *type = defconfig[i].index;
+ return (0);
+ }
+ }
+ }
+ return (-1);
+}
+
+int
+__s_api_get_profiletype(char *value, ParamIndexType *type)
+{
+ int i;
+
+ for (i = 0; defconfig[i].name != NULL; i++) {
+ if (defconfig[i].profile_name == NULL)
+ continue;
+ if (strcasecmp(defconfig[i].profile_name, value) == 0) {
+ *type = defconfig[i].index;
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+int
+__s_api_get_configtype(ParamIndexType type)
+{
+ int i;
+
+ for (i = 0; defconfig[i].name != NULL; i++) {
+ if (defconfig[i].index == type) {
+ return (defconfig[i].config_type);
+ }
+ }
+ return (-1);
+}
+
+const char *
+__s_api_get_configname(ParamIndexType type)
+{
+ int i;
+
+ for (i = 0; defconfig[i].name != NULL; i++) {
+ if (defconfig[i].index == type) {
+ if (defconfig[i].name[0] == '\0')
+ return (NULL);
+ else
+ return (defconfig[i].name);
+ }
+ }
+ return (NULL);
+}
+
+static ns_default_config *
+get_defconfig(ns_config_t *ptr, ParamIndexType type)
+{
+ ns_version_t ver;
+ int i;
+
+ ver = ptr->version;
+
+ for (i = 0; defconfig[i].name != NULL; i++) {
+ if (defconfig[i].index == type &&
+ defconfig[i].version == ver) {
+ return (&defconfig[i]);
+ }
+ }
+ return (NULL);
+}
+
+static int
+set_default_value(ns_config_t *configptr, char *name,
+ char *value, ns_ldap_error_t **error)
+{
+ ParamIndexType i;
+ int ret;
+ char errstr[MAXERROR];
+
+ if (__s_api_get_type(name, &i) < 0) {
+ (void) snprintf(errstr, sizeof (errstr), gettext(
+ "Illegal type name (%s).\n"), name);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
+ NULL);
+ return (NS_LDAP_CONFIG);
+ }
+
+ if (i != NS_LDAP_SERVERS_P &&
+ i != NS_LDAP_SERVICE_AUTH_METHOD_P &&
+ i != NS_LDAP_SERVICE_CRED_LEVEL_P &&
+ i != NS_LDAP_SERVICE_SEARCH_DESC_P &&
+ i != NS_LDAP_SERVER_PREF_P &&
+ i != NS_LDAP_SEARCH_DN_P) {
+ if (configptr->paramList[i].ns_ptype != NS_UNKNOWN) {
+ destroy_param(configptr, i);
+ }
+ }
+
+ ret = __ns_ldap_setParamValue(configptr, i, value, error);
+ return (ret);
+}
+
+
+/*
+ * Initialize config to a default state
+ * By default leave configuration empty
+ * getParam will automatically get the
+ * appropriate default value if none exists
+ */
+
+void
+__ns_ldap_default_config()
+{
+ ns_config_t *ptr;
+
+ ptr = __s_api_create_config();
+ if (ptr == NULL)
+ return;
+
+ set_curr_config(ptr);
+ __s_api_release_config(ptr);
+}
+
+/*
+ * Get the current configuration pointer and return it.
+ * If necessary initialize or refresh the current
+ * configuration as applicable.
+ */
+
+ns_config_t *
+__s_api_loadrefresh_config()
+{
+ ns_config_t *cfg;
+ ns_config_t *new_cfg;
+ ns_ldap_error_t *errorp;
+
+ /* We want to refresh only one configuration at a time */
+ (void) mutex_lock(&ns_loadrefresh_lock);
+ cfg = __s_api_get_default_config();
+
+ /* (re)initialize configuration if necessary */
+ if (timetorefresh(cfg)) {
+ new_cfg = LoadCacheConfiguration(&errorp);
+ if (new_cfg != NULL) {
+ __s_api_release_config(cfg);
+ set_curr_config(new_cfg);
+ cfg = new_cfg;
+ }
+ if (errorp != NULL)
+ (void) __ns_ldap_freeError(&errorp);
+ }
+ (void) mutex_unlock(&ns_loadrefresh_lock);
+ return (cfg);
+}
+
+/*
+ * In general this routine is not very usefull. Individual routines can be
+ * created to do this job. Once that is done, this function can be removed.
+ * Size of errstr buffer needs to be MAXERROR.
+ */
+static ns_parse_status
+verify_value(ns_config_t *cfg, char *name, char *value, char *errstr)
+{
+ ParamIndexType index = 0;
+ int found = 0, j;
+ char *ptr = NULL, *strptr = NULL, buffer[BUFSIZE];
+ char *rest;
+ ns_default_config *def = NULL;
+
+ if (__s_api_get_type(name, &index) != 0) {
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Unknown keyword encountered '%s'."), name);
+ return (NS_PARSE_ERR);
+ }
+
+ def = get_defconfig(cfg, index);
+
+ /* eat up beginning quote, if any */
+ while (value != NULL && (*value == QUOTETOK || *value == SPACETOK))
+ value++;
+
+ /* eat up space/quote at end of value */
+ if (strlen(value) > 0)
+ ptr = value + strlen(value) - 1;
+ else
+ ptr = value;
+ for (; ptr != value && (*ptr == SPACETOK || *ptr == QUOTETOK); ptr--) {
+ *ptr = '\0';
+ }
+
+ switch (index) {
+ case NS_LDAP_EXP_P:
+ case NS_LDAP_CACHETTL_P:
+ case NS_LDAP_CERT_PATH_P:
+ case NS_LDAP_CERT_PASS_P:
+ case NS_LDAP_CERT_NICKNAME_P:
+ case NS_LDAP_BINDDN_P:
+ case NS_LDAP_BINDPASSWD_P:
+ case NS_LDAP_DOMAIN_P:
+ case NS_LDAP_SEARCH_BASEDN_P:
+ case NS_LDAP_SEARCH_TIME_P:
+ case NS_LDAP_PROFILE_P:
+ case NS_LDAP_AUTH_P:
+ case NS_LDAP_SEARCH_SCOPE_P:
+ case NS_LDAP_CREDENTIAL_LEVEL_P:
+ case NS_LDAP_SERVICE_SEARCH_DESC_P:
+ case NS_LDAP_BIND_TIME_P:
+ case NS_LDAP_ATTRIBUTEMAP_P:
+ case NS_LDAP_OBJECTCLASSMAP_P:
+ case NS_LDAP_SERVICE_AUTH_METHOD_P:
+ case NS_LDAP_SERVICE_CRED_LEVEL_P:
+ case NS_LDAP_HOST_CERTPATH_P:
+ break;
+ case NS_LDAP_SEARCH_DN_P:
+ /* depreciated because of service descriptors */
+ /* Parse as appropriate at descriptor create time */
+ break;
+ case NS_LDAP_FILE_VERSION_P:
+ if (value != NULL &&
+ strcasecmp(value, NS_LDAP_VERSION_1) != 0 &&
+ strcasecmp(value, NS_LDAP_VERSION_2) != 0) {
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Version mismatch, expected "
+ "cache version '%s' or '%s' but "
+ "encountered version '%s'."),
+ NS_LDAP_VERSION_1,
+ NS_LDAP_VERSION_2, value);
+ return (NS_PARSE_ERR);
+ }
+ break;
+ case NS_LDAP_SERVERS_P:
+ case NS_LDAP_SERVER_PREF_P:
+ (void) strcpy(buffer, value);
+ strptr = strtok_r(buffer, ",", &rest);
+ while (strptr != NULL) {
+ char *tmp = NULL;
+ tmp = stripdup(strptr);
+ if (tmp == NULL || (strchr(tmp, ' ') != NULL)) {
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Invalid parameter values "
+ "'%s' specified for keyword '%s'."),
+ tmp, name);
+ free(tmp);
+ return (NS_PARSE_ERR);
+ }
+ free(tmp);
+ strptr = strtok_r(NULL, ",", &rest);
+ }
+ break;
+ default:
+ found = 0; j = 0;
+ while (def->allowed != NULL &&
+ def->allowed[j].name != NULL && j < DEFMAX) {
+ if (strcmp(def->allowed[j].name,
+ value) == 0) {
+ found = 1;
+ break;
+ }
+ j++;
+ }
+ if (!found) {
+ (void) snprintf(errstr, MAXERROR,
+ gettext("Invalid option specified for "
+ "'%s' keyword. '%s' is not a recognized "
+ "keyword value."), name, value);
+ return (NS_PARSE_ERR);
+ }
+ }
+
+ return (NS_SUCCESS);
+}
+
+void
+__s_api_split_key_value(char *buffer, char **name, char **value)
+{
+ char *ptr;
+
+ *name = buffer;
+ /* split into name value pair */
+ if ((ptr = strchr(buffer, TOKENSEPARATOR)) != NULL) {
+ *ptr = '\0';
+ ptr++;
+ /* trim whitespace */
+ while (*ptr == SPACETOK)
+ ptr++;
+ *value = ptr;
+ }
+}
+
+/*
+ * Set a parameter value in a generic configuration structure
+ * Assume any necessary locks are in place. This routine would
+ * be better named: __ns_ldap_translateString2Param
+ *
+ * This routine translates external string format into internal
+ * param format and saves the result in the param table.
+ */
+int
+__ns_ldap_setParamValue(ns_config_t *ptr, const ParamIndexType type,
+ const void *data, ns_ldap_error_t **error)
+{
+ ns_default_config *def = NULL;
+ ns_param_t conf;
+ ns_mapping_t *map, *rmap;
+ int i, j, len;
+ char *cp, *cp2, *end;
+ char *tcp = NULL;
+ char errstr[2 * MAXERROR];
+ char tbuf[100], *ptbuf;
+ char *sid, *origA, **mapA;
+ char **attr;
+ time_t tm;
+ int free_memory, exitrc;
+ char **p;
+
+ /* Find ParamIndexType default configuration data */
+ def = get_defconfig(ptr, type);
+ if (def == NULL) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid ParamIndexType (%d)"), type);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
+ NULL);
+ return (NS_LDAP_CONFIG);
+ }
+
+ (void) memset(&conf, 0, sizeof (conf));
+
+ /* data is actually const char */
+ cp = (char *)data;
+
+ /* eat up beginning quote, if any */
+ while (cp && (*cp == QUOTETOK || *cp == SPACETOK))
+ cp++;
+
+ /* eat up space/quote at end of value */
+ end = cp2 = cp + strlen(cp) - 1;
+ for (; cp2 > cp && (*cp2 == SPACETOK || *cp2 == QUOTETOK); cp2--)
+ ;
+ /* data is const, must duplicate */
+ if (cp2 != end) {
+ tcp = (char *)calloc((int)(cp2 - cp + 2), sizeof (char));
+ if (tcp == NULL)
+ return (NS_LDAP_MEMORY);
+ end = cp2;
+ cp2 = tcp;
+ while (cp <= end) {
+ *cp2++ = *cp++;
+ }
+ *cp2 = '\0';
+ cp = tcp;
+ }
+
+ /* Parse data according to type */
+ switch (def->data_type) {
+ case INT:
+ switch (def->index) {
+ case NS_LDAP_PREF_ONLY_P:
+ case NS_LDAP_SEARCH_REF_P:
+ case NS_LDAP_SEARCH_SCOPE_P:
+ i = __s_get_enum_value(ptr, cp, def->index);
+ if (i < 0) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid %s (%d)"), def->name,
+ def->index);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ conf.ns_i = i;
+ break;
+ case NS_LDAP_TRANSPORT_SEC_P: /* ignore TRANSPORT_SEC */
+ break;
+ default:
+ cp2 = cp;
+ if ((*cp2 == '+') || (*cp2 == '-'))
+ cp2++;
+ for (/* empty */; *cp2; cp2++) {
+ if (isdigit(*cp2))
+ continue;
+
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid %s (%d)"), def->name,
+ def->index);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ i = atoi(cp);
+ conf.ns_i = i;
+ break;
+ }
+ break;
+ case TIMET:
+ /* Do nothing with a TIMET. Initialize it below */
+ break;
+ case CHARPTR:
+ conf.ns_pc = (char *)strdup(cp);
+ if (conf.ns_pc == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ break;
+ case SAMLIST:
+ /* first check to see if colon (:) is there */
+ if ((strchr(cp, COLONTOK)) == NULL) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid serviceAuthenticationMethod (%s)"),
+ cp);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ /* Appends an entry to the existing list */
+ if (ptr->paramList[type].ns_ptype != SAMLIST) {
+ conf.ns_ppc = (char **)calloc(2, sizeof (char *));
+ if (conf.ns_ppc == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = 1;
+ conf.ns_ppc[0] = (char *)strdup(cp);
+ if (conf.ns_ppc[0] == NULL) {
+ free(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ } else {
+ char *dp, *dpend;
+ int fnd = 0;
+
+ /* Attempt to replace if possible */
+ dpend = strchr(cp, COLONTOK);
+ len = dpend - cp;
+ dp = (char *)malloc(len+1);
+ if (dp == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ (void) strlcpy(dp, cp, len+1);
+ fnd = 0;
+ for (j = 0; j < ptr->paramList[type].ns_acnt; j++) {
+ dpend = strchr(ptr->paramList[type].ns_ppc[j],
+ COLONTOK);
+ if (dpend == NULL)
+ continue;
+ i = dpend - ptr->paramList[type].ns_ppc[j];
+ if (i != len)
+ continue;
+ if (strncmp(ptr->paramList[type].ns_ppc[j],
+ dp, len) == 0) {
+ conf.ns_acnt =
+ ptr->paramList[type].ns_acnt;
+ conf.ns_ppc =
+ ptr->paramList[type].ns_ppc;
+ ptr->paramList[type].ns_ppc = NULL;
+ free(conf.ns_ppc[j]);
+ conf.ns_ppc[j] = (char *)strdup(cp);
+ if (conf.ns_ppc[j] == NULL) {
+ free(dp);
+ __s_api_free2dArray
+ (conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ fnd = 1;
+ break;
+ }
+ }
+ free(dp);
+
+ if (fnd)
+ break; /* Replaced completed */
+
+ /* Append */
+ len = ptr->paramList[type].ns_acnt + 1;
+ if (len > 1) {
+ p = (char **)dupParam(&ptr->paramList[type]);
+ if (p == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ } else
+ p = NULL;
+ conf.ns_ppc =
+ (char **)realloc(p, (len+1) * sizeof (char *));
+ if (conf.ns_ppc == NULL) {
+ __s_api_free2dArray(p);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = len;
+ conf.ns_ppc[len-1] = (char *)strdup(cp);
+ if (conf.ns_ppc[len-1] == NULL) {
+ __s_api_free2dArray(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_ppc[len] = NULL;
+ }
+ break;
+ case SCLLIST:
+ /* first check to see if colon (:) is there */
+ if ((strchr(cp, COLONTOK)) == NULL) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid serviceCredentialLevel (%s)"),
+ cp);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ /* Appends an entry to the existing list */
+ if (ptr->paramList[type].ns_ptype != SCLLIST) {
+ conf.ns_ppc = (char **)calloc(2, sizeof (char *));
+ if (conf.ns_ppc == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = 1;
+ conf.ns_ppc[0] = (char *)strdup(cp);
+ if (conf.ns_ppc[0] == NULL) {
+ free(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ } else {
+ char *dp, *dpend;
+ int fnd = 0;
+
+ /* Attempt to replace if possible */
+ dpend = strchr(cp, COLONTOK);
+ len = dpend - cp;
+ dp = (char *)malloc(len+1);
+ if (dp == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ (void) strlcpy(dp, cp, len+1);
+ fnd = 0;
+ for (j = 0; j < ptr->paramList[type].ns_acnt; j++) {
+ dpend = strchr(ptr->paramList[type].ns_ppc[j],
+ COLONTOK);
+ if (dpend == NULL)
+ continue;
+ i = dpend - ptr->paramList[type].ns_ppc[j];
+ if (i != len)
+ continue;
+ if (strncmp(ptr->paramList[type].ns_ppc[j],
+ dp, len) == 0) {
+ conf.ns_acnt =
+ ptr->paramList[type].ns_acnt;
+ conf.ns_ppc =
+ ptr->paramList[type].ns_ppc;
+ ptr->paramList[type].ns_ppc = NULL;
+ free(conf.ns_ppc[j]);
+ conf.ns_ppc[j] = (char *)strdup(cp);
+ if (conf.ns_ppc[j] == NULL) {
+ free(dp);
+ __s_api_free2dArray
+ (conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ fnd = 1;
+ break;
+ }
+ }
+ free(dp);
+
+ if (fnd)
+ break; /* Replaced completed */
+
+ /* Append */
+ len = ptr->paramList[type].ns_acnt + 1;
+ if (len > 1) {
+ p = (char **)dupParam(&ptr->paramList[type]);
+ if (p == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ } else
+ p = NULL;
+ conf.ns_ppc =
+ (char **)realloc(p, (len+1) * sizeof (char *));
+ if (conf.ns_ppc == NULL) {
+ __s_api_free2dArray(p);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = len;
+ conf.ns_ppc[len-1] = (char *)strdup(cp);
+ if (conf.ns_ppc[len-1] == NULL) {
+ __s_api_free2dArray(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_ppc[len] = NULL;
+ }
+ break;
+ case SSDLIST:
+ /*
+ * first check to see if colon (:) is there,
+ * if so, make sure the serviceId is specified,
+ * i.e., colon is not the first character
+ */
+ if ((strchr(cp, COLONTOK)) == NULL || *cp == COLONTOK) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid serviceSearchDescriptor (%s)"),
+ cp);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ /* Appends an entry to the existing list */
+ if (ptr->paramList[type].ns_ptype != SSDLIST) {
+ conf.ns_ppc = (char **)calloc(2, sizeof (char *));
+ if (conf.ns_ppc == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = 1;
+ conf.ns_ppc[0] = (char *)strdup(cp);
+ if (conf.ns_ppc[0] == NULL) {
+ free(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ } else {
+ char *dp, *dpend;
+ int fnd = 0;
+
+ /* Attempt to replace if possible */
+ dpend = strchr(cp, COLONTOK);
+ len = dpend - cp;
+ dp = (char *)malloc(len+1);
+ if (dp == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ (void) strlcpy(dp, cp, len+1);
+ fnd = 0;
+ for (j = 0; j < ptr->paramList[type].ns_acnt; j++) {
+ dpend = strchr(ptr->paramList[type].ns_ppc[j],
+ COLONTOK);
+ if (dpend == NULL)
+ continue;
+ i = dpend - ptr->paramList[type].ns_ppc[j];
+ if (i != len)
+ continue;
+ if (strncmp(ptr->paramList[type].ns_ppc[j],
+ dp, len) == 0) {
+ conf.ns_acnt =
+ ptr->paramList[type].ns_acnt;
+ conf.ns_ppc =
+ ptr->paramList[type].ns_ppc;
+ ptr->paramList[type].ns_ppc = NULL;
+ free(conf.ns_ppc[j]);
+ conf.ns_ppc[j] = (char *)strdup(cp);
+ if (conf.ns_ppc[j] == NULL) {
+ free(dp);
+ __s_api_free2dArray
+ (conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ fnd = 1;
+ break;
+ }
+ }
+ free(dp);
+
+ if (fnd)
+ break; /* Replaced completed */
+
+ /* Append */
+ len = ptr->paramList[type].ns_acnt + 1;
+ if (len > 1) {
+ p = (char **)dupParam(&ptr->paramList[type]);
+ if (p == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ } else
+ p = NULL;
+ conf.ns_ppc =
+ (char **)realloc(p, (len+1) * sizeof (char *));
+ if (conf.ns_ppc == NULL) {
+ __s_api_free2dArray(p);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = len;
+ conf.ns_ppc[len-1] = (char *)strdup(cp);
+ if (conf.ns_ppc[len-1] == NULL) {
+ __s_api_free2dArray(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_ppc[len] = NULL;
+ }
+ break;
+ case ARRAYCP:
+ len = 0;
+ for (cp2 = cp; *cp2; cp2++) {
+ if (*cp2 == COMMATOK)
+ len++;
+ }
+ if (cp != cp2)
+ len++;
+ if (len == 0) {
+ conf.ns_ppc = (char **)NULL;
+ conf.ns_acnt = 0;
+ break;
+ }
+ conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *));
+ if (conf.ns_ppc == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = len;
+ i = 0;
+ for (cp2 = cp; *cp2; cp2++) {
+ if (*cp2 == COMMATOK) {
+ j = cp2 - cp + 1;
+ conf.ns_ppc[i] = (char *)malloc(j + 1);
+ if (conf.ns_ppc[i] == NULL) {
+ __s_api_free2dArray(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ (void) strlcpy(conf.ns_ppc[i], cp, j);
+ cp = cp2+1;
+ while (*cp == SPACETOK || *cp == COMMATOK)
+ cp++;
+ cp2 = cp - 1;
+ i++;
+ }
+ }
+ j = cp2 - cp + 1;
+ conf.ns_ppc[i] = (char *)malloc(j + 1);
+ if (conf.ns_ppc[i] == NULL) {
+ __s_api_free2dArray(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ (void) strlcpy(conf.ns_ppc[i], cp, j);
+ break;
+ case SERVLIST:
+ len = 0;
+ for (cp2 = cp; *cp2; cp2++) {
+ if (*cp2 == SPACETOK || *cp2 == COMMATOK) {
+ len++;
+ for (; *(cp2 + 1) == SPACETOK ||
+ *(cp2 +1) == COMMATOK; cp2++)
+ ;
+ }
+ }
+ if (cp != cp2)
+ len++;
+ if (len == 0) {
+ conf.ns_ppc = (char **)NULL;
+ conf.ns_acnt = 0;
+ break;
+ }
+ conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *));
+ if (conf.ns_ppc == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = len;
+ i = 0;
+ for (cp2 = cp; *cp2; cp2++) {
+ if (*cp2 == SPACETOK || *cp2 == COMMATOK) {
+ j = cp2 - cp + 1;
+ conf.ns_ppc[i] = (char *)malloc(j + 1);
+ if (conf.ns_ppc[i] == NULL) {
+ __s_api_free2dArray(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ (void) strlcpy(conf.ns_ppc[i], cp, j);
+ cp = cp2+1;
+ while (*cp == SPACETOK || *cp == COMMATOK)
+ cp++;
+ cp2 = cp - 1;
+ i++;
+ }
+ }
+ j = cp2 - cp + 1;
+ conf.ns_ppc[i] = (char *)malloc(j + 1);
+ if (conf.ns_ppc[i] == NULL) {
+ __s_api_free2dArray(conf.ns_ppc);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ (void) strlcpy(conf.ns_ppc[i], cp, j);
+ break;
+ case ARRAYAUTH:
+ len = 0;
+ for (cp2 = cp; *cp2; cp2++) {
+ if (*cp2 == SEMITOK || *cp2 == COMMATOK)
+ len++;
+ }
+ if (cp != cp2)
+ len++;
+ if (len == 0) {
+ conf.ns_pi = (int *)NULL;
+ conf.ns_acnt = 0;
+ break;
+ }
+ conf.ns_pi = (int *)calloc(len + 1, sizeof (int));
+ if (conf.ns_pi == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = len;
+ i = 0;
+ for (cp2 = cp; *cp2; cp2++) {
+ if (*cp2 == SEMITOK || *cp2 == COMMATOK) {
+ j = cp2 - cp + 1;
+ if (j > sizeof (tbuf)) {
+ j = -1;
+ ptbuf = cp;
+ } else {
+ (void) strlcpy(tbuf, cp, j);
+ j = __s_get_enum_value(ptr, tbuf,
+ def->index);
+ ptbuf = tbuf;
+ }
+ if (j < 0) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid authenticationMethod (%s)"),
+ ptbuf);
+ MKERROR(LOG_ERR, *error,
+ NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ free(conf.ns_pi);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ conf.ns_pi[i] = j;
+ cp = cp2+1;
+ i++;
+ }
+ }
+ j = cp2 - cp + 1;
+ if (j > sizeof (tbuf)) {
+ j = -1;
+ ptbuf = cp;
+ } else {
+ (void) strlcpy(tbuf, cp, j);
+ j = __s_get_enum_value(ptr, tbuf, def->index);
+ ptbuf = tbuf;
+ }
+ if (j < 0) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid authenticationMethod (%s)"), ptbuf);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ conf.ns_pi[i] = j;
+ break;
+ case ARRAYCRED:
+ len = 0;
+ for (cp2 = cp; *cp2; cp2++) {
+ if (*cp2 == SPACETOK)
+ len++;
+ }
+ if (cp != cp2)
+ len++;
+ if (len == 0) {
+ conf.ns_pi = (int *)NULL;
+ conf.ns_acnt = 0;
+ break;
+ }
+ conf.ns_pi = (int *)calloc(len + 1, sizeof (int));
+ if (conf.ns_pi == NULL) {
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_MEMORY);
+ }
+ conf.ns_acnt = len;
+ i = 0;
+ for (cp2 = cp; *cp2; cp2++) {
+ if (*cp2 == SPACETOK) {
+ j = cp2 - cp + 1;
+ if (j > sizeof (tbuf)) {
+ j = -1;
+ ptbuf = cp;
+ } else {
+ (void) strlcpy(tbuf, cp, j);
+ j = __s_get_enum_value(ptr, tbuf,
+ def->index);
+ ptbuf = tbuf;
+ }
+ if (j < 0) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid credentialLevel (%s)"),
+ ptbuf);
+ MKERROR(LOG_ERR, *error,
+ NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ free(conf.ns_pi);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ conf.ns_pi[i] = j;
+ cp = cp2+1;
+ i++;
+ }
+ }
+ j = cp2 - cp + 1;
+ if (j > sizeof (tbuf)) {
+ j = -1;
+ ptbuf = cp;
+ } else {
+ (void) strlcpy(tbuf, cp, j);
+ j = __s_get_enum_value(ptr, tbuf, def->index);
+ ptbuf = tbuf;
+ }
+ if (j < 0) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid credentialLevel (%s)"), ptbuf);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ conf.ns_pi[i] = j;
+ break;
+ case ATTRMAP:
+ case OBJMAP:
+ i = __s_api_parse_map(cp, &sid, &origA, &mapA);
+ if (i != NS_HASH_RC_SUCCESS) {
+ if (i == NS_HASH_RC_NO_MEMORY) {
+ exitrc = NS_LDAP_MEMORY;
+ } else {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: "
+ "invalid schema mapping (%s)"), cp);
+ exitrc = NS_LDAP_CONFIG;
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ }
+ if (tcp)
+ free(tcp);
+ return (exitrc);
+ }
+
+ /*
+ * Add reverse map first.
+ * There could be more than one.
+ */
+ for (attr = mapA; *attr; attr++) {
+
+ free_memory = 1;
+ exitrc = NS_LDAP_MEMORY;
+
+ rmap = (ns_mapping_t *)calloc(1,
+ sizeof (ns_mapping_t));
+ if (rmap) {
+ rmap->service = strdup(sid);
+ if (rmap->service) {
+ rmap->orig = strdup(*attr);
+ if (rmap->orig) {
+ rmap->map = (char **)calloc(2,
+ sizeof (char *));
+ if (rmap->map) {
+ (rmap->map)[0] =
+ strdup(origA);
+ if ((rmap->map)[0])
+ free_memory = 0;
+ }
+ }
+ }
+ }
+
+ if (free_memory == 0) {
+ if (def->data_type == ATTRMAP) {
+ rmap->type = NS_ATTR_MAP;
+ i = __s_api_add_map2hash(ptr,
+ NS_HASH_RAMAP, rmap);
+ } else {
+ rmap->type = NS_OBJ_MAP;
+ i = __s_api_add_map2hash(ptr,
+ NS_HASH_ROMAP, rmap);
+ }
+
+ if (i != NS_HASH_RC_SUCCESS) {
+ switch (i) {
+ case NS_HASH_RC_CONFIG_ERROR:
+ exitrc = NS_LDAP_INTERNAL;
+ (void) snprintf(errstr,
+ sizeof (errstr),
+ gettext(
+ "Unable to set value: "
+ "no configuration info "
+ "for schema map "
+ "update (%s)"), cp);
+ MKERROR(LOG_ERR, *error,
+ NS_LDAP_INTERNAL,
+ strdup(errstr),
+ NULL);
+ break;
+ case NS_HASH_RC_EXISTED:
+ exitrc = NS_LDAP_CONFIG;
+ (void) snprintf(errstr,
+ sizeof (errstr),
+ gettext(
+ "Unable to set value: "
+ "schema map "
+ "already existed for "
+ "(%s, %s)."),
+ *attr, origA);
+ MKERROR(LOG_ERR, *error,
+ NS_CONFIG_SYNTAX,
+ strdup(errstr),
+ NULL);
+ break;
+ case NS_HASH_RC_NO_MEMORY:
+ exitrc = NS_LDAP_MEMORY;
+ break;
+ }
+ free_memory = 1;
+ }
+ }
+
+ if (free_memory) {
+ if (tcp)
+ free(tcp);
+ free(sid);
+ free(origA);
+ __s_api_free2dArray(mapA);
+ if (rmap) {
+ if (rmap->service)
+ free(rmap->service);
+ if (rmap->orig)
+ free(rmap->orig);
+ if (rmap->map) {
+ if ((rmap->map)[0])
+ free((rmap->map)[0]);
+ free(rmap->map);
+ }
+ free(rmap);
+ }
+ return (exitrc);
+ }
+ }
+
+ /*
+ * For performance gain,
+ * add a "schema mapping existed" indicator
+ * for the given service if not already added.
+ * This dummy map needs not be removed, if
+ * the next real map add operation fails.
+ * since the caller, e.g. ldap_cachemgr.
+ * should exit anyway.
+ */
+ free_memory = 1;
+ exitrc = NS_LDAP_MEMORY;
+
+ map = (ns_mapping_t *)calloc(1,
+ sizeof (ns_mapping_t));
+ if (map) {
+ map->service = strdup(sid);
+ if (map->service) {
+ map->orig = strdup(
+ NS_HASH_SCHEMA_MAPPING_EXISTED);
+ if (map->orig) {
+ map->map = (char **)calloc(2,
+ sizeof (char *));
+ if (map->map) {
+ (map->map)[0] =
+ strdup(sid);
+ if ((map->map)[0])
+ free_memory = 0;
+ }
+ }
+ }
+ }
+
+ if (free_memory == 0) {
+ map->type = NS_ATTR_MAP;
+ /*
+ * add to reverse map,
+ * so that "ldapclient list"
+ * would not show it
+ */
+ i = __s_api_add_map2hash(ptr,
+ NS_HASH_RAMAP, map);
+
+ /*
+ * ignore "map already existed" error,
+ * just need one per service.
+ * Need however to free memory allocated
+ * for map.
+ */
+ if (i != NS_HASH_RC_SUCCESS &&
+ i != NS_HASH_RC_EXISTED) {
+ switch (i) {
+ case NS_HASH_RC_CONFIG_ERROR:
+ exitrc = NS_LDAP_INTERNAL;
+ (void) snprintf(errstr,
+ sizeof (errstr),
+ gettext(
+ "Unable to set value: "
+ "no configuration info "
+ "for schema map "
+ "update (%s)"), cp);
+ MKERROR(LOG_ERR, *error,
+ NS_LDAP_INTERNAL,
+ strdup(errstr),
+ NULL);
+ break;
+ case NS_HASH_RC_NO_MEMORY:
+ exitrc = NS_LDAP_MEMORY;
+ break;
+ }
+ free_memory = 1;
+ } else if (i == NS_HASH_RC_EXISTED) {
+ if (map->service)
+ free(map->service);
+ if (map->orig)
+ free(map->orig);
+ if (map->map) {
+ if ((map->map)[0])
+ free((map->map)[0]);
+ free(map->map);
+ }
+ free(map);
+ map = NULL;
+ }
+ }
+
+ if (free_memory) {
+ if (tcp)
+ free(tcp);
+ free(sid);
+ free(origA);
+ __s_api_free2dArray(mapA);
+ if (map) {
+ if (map->service)
+ free(map->service);
+ if (map->orig)
+ free(map->orig);
+ if (map->map) {
+ if ((map->map)[0])
+ free((map->map)[0]);
+ free(map->map);
+ }
+ free(map);
+ }
+ return (exitrc);
+ }
+
+ /*
+ * add the real schema map
+ */
+ free_memory = 1;
+ exitrc = NS_LDAP_MEMORY;
+ map = (ns_mapping_t *)calloc(1, sizeof (ns_mapping_t));
+ if (map) {
+ map->service = sid;
+ map->orig = origA;
+ map->map = mapA;
+
+ if (def->data_type == ATTRMAP) {
+ map->type = NS_ATTR_MAP;
+ i = __s_api_add_map2hash(ptr,
+ NS_HASH_AMAP, map);
+ } else {
+ map->type = NS_OBJ_MAP;
+ i = __s_api_add_map2hash(ptr,
+ NS_HASH_OMAP, map);
+ }
+
+ if (i != NS_HASH_RC_SUCCESS) {
+ switch (i) {
+ case NS_HASH_RC_CONFIG_ERROR:
+ exitrc = NS_LDAP_INTERNAL;
+ (void) snprintf(errstr,
+ sizeof (errstr),
+ gettext(
+ "Unable to set value: "
+ "no configuration info "
+ "for schema map "
+ "update (%s)"), cp);
+ MKERROR(LOG_ERR, *error,
+ NS_LDAP_INTERNAL,
+ strdup(errstr),
+ NULL);
+ break;
+ case NS_HASH_RC_EXISTED:
+ exitrc = NS_LDAP_CONFIG;
+ (void) snprintf(errstr,
+ sizeof (errstr),
+ gettext(
+ "Unable to set value: "
+ "schema map "
+ "already existed for "
+ "'%s'."), origA);
+ MKERROR(LOG_ERR, *error,
+ NS_CONFIG_SYNTAX,
+ strdup(errstr),
+ NULL);
+ break;
+ case NS_HASH_RC_NO_MEMORY:
+ exitrc = NS_LDAP_MEMORY;
+ break;
+ }
+ free_memory = 1;
+ } else
+ free_memory = 0;
+ }
+
+ if (free_memory) {
+ if (tcp)
+ free(tcp);
+ free(sid);
+ free(origA);
+ __s_api_free2dArray(mapA);
+ if (map)
+ free(map);
+ return (exitrc);
+ }
+
+ break;
+ default:
+ /* This should never happen. */
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set value: invalid configuration "
+ "type (%d)"), def->data_type);
+ MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
+ NULL);
+ if (tcp != NULL)
+ free(tcp);
+ return (NS_LDAP_CONFIG);
+ }
+ conf.ns_ptype = def->data_type;
+ if (tcp != NULL)
+ free(tcp);
+
+ /* Individually written verify routines here can replace */
+ /* verify_value. Verify conf (data) as appropriate here */
+ if (def->ns_verify != NULL) {
+ if ((*def->ns_verify)(type, def, &conf, errstr) != NS_SUCCESS) {
+ ns_param_t sav_conf;
+
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("%s"), errstr);
+ MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+
+ sav_conf = ptr->paramList[type];
+ ptr->paramList[type] = conf;
+ destroy_param(ptr, type);
+ ptr->paramList[type] = sav_conf;
+
+ return (NS_LDAP_CONFIG);
+ }
+ }
+
+ /* post evaluate the data */
+
+ /*
+ * if this is for setting a password,
+ * encrypt the password first.
+ * NOTE evalue() is smart and will just return
+ * the value passed if it is already encrypted.
+ *
+ * Init NS_LDAP_EXP_P here when CACHETTL is updated
+ */
+ if (type == NS_LDAP_BINDPASSWD_P) {
+ cp = conf.ns_pc;
+ cp2 = evalue((char *)cp);
+ conf.ns_pc = cp2;
+ free(cp);
+ cp = NULL;
+ } else if (type == NS_LDAP_FILE_VERSION_P) {
+ ptr->version = NS_LDAP_V1;
+ if (strcasecmp(conf.ns_pc, NS_LDAP_VERSION_2) == 0) {
+ ptr->version = NS_LDAP_V2;
+ }
+ } else if (type == NS_LDAP_CACHETTL_P) {
+ cp = conf.ns_pc;
+ tm = conv_time(cp);
+ ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET;
+ if (tm != 0) {
+ tm += time(NULL);
+ }
+ ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm;
+ }
+
+ /* Everything checks out move new values into param */
+ destroy_param(ptr, type);
+ /* Assign new/updated value into paramList */
+ ptr->paramList[type] = conf;
+
+ return (NS_LDAP_SUCCESS);
+}
+
+
+/*
+ * Set a parameter value in the 'config' configuration structure
+ * Lock as appropriate
+ */
+
+int
+__ns_ldap_setParam(const ParamIndexType type,
+ const void *data, ns_ldap_error_t **error)
+{
+ ns_ldap_error_t *errorp;
+ int ret;
+ char errstr[2 * MAXERROR];
+ ns_config_t *cfg;
+ ns_config_t *new_cfg;
+
+ /* We want to refresh only one configuration at a time */
+ (void) mutex_lock(&ns_loadrefresh_lock);
+ cfg = __s_api_get_default_config();
+
+ if (cache_server == TRUE) {
+ if (cfg == NULL) {
+ __ns_ldap_default_config();
+ cfg = __s_api_get_default_config();
+ if (cfg == NULL) {
+ (void) mutex_unlock(&ns_loadrefresh_lock);
+ return (NS_LDAP_MEMORY);
+ }
+ }
+ } else {
+ /*
+ * This code always return error here on client side,
+ * this needs to change once libsldap is used by more
+ * applications that need to set parameters.
+ */
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to set parameter from a client in "
+ "__ns_ldap_setParam()"));
+ MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX, strdup(errstr),
+ NULL);
+ if (cfg != NULL)
+ __s_api_release_config(cfg);
+ (void) mutex_unlock(&ns_loadrefresh_lock);
+ return (NS_LDAP_CONFIG);
+ }
+
+ /* (re)initialize configuration if necessary */
+ if (cache_server == FALSE && timetorefresh(cfg)) {
+ new_cfg = LoadCacheConfiguration(&errorp);
+ __s_api_release_config(cfg);
+ if (new_cfg == NULL) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to load configuration '%s' "
+ "('%s')."), NSCONFIGFILE,
+ errorp != NULL && errorp->message != NULL ?
+ errorp->message : "");
+ MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED,
+ strdup(errstr), NULL);
+ if (errorp != NULL)
+ (void) __ns_ldap_freeError(&errorp);
+ (void) mutex_unlock(&ns_loadrefresh_lock);
+ return (NS_LDAP_CONFIG);
+ }
+ set_curr_config(new_cfg);
+ cfg = new_cfg;
+ }
+ (void) mutex_unlock(&ns_loadrefresh_lock);
+
+ /* translate input and save in the parameter list */
+ ret = __ns_ldap_setParamValue(cfg, type, data, error);
+
+ __s_api_release_config(cfg);
+
+ return (ret);
+}
+
+
+/*
+ * Make a copy of a parameter entry
+ */
+
+static void **
+dupParam(ns_param_t *ptr)
+{
+ int count, i;
+ void **dupdata, *ret;
+ int *intptr;
+ char *cp, tmbuf[32];
+ static time_t expire = 0;
+ ns_auth_t *ap;
+
+ switch (ptr->ns_ptype) {
+ case ARRAYAUTH:
+ case ARRAYCRED:
+ case SAMLIST:
+ case SCLLIST:
+ case SSDLIST:
+ case SERVLIST:
+ case ARRAYCP:
+ count = ptr->ns_acnt;
+ if (count == 0)
+ return (NULL);
+ break;
+ case CHARPTR:
+ case INT:
+ case TIMET:
+ count = 1;
+ }
+
+ dupdata = (void **)calloc((count + 1), sizeof (void *));
+ if (dupdata == NULL)
+ return (NULL);
+
+ switch (ptr->ns_ptype) {
+ case ARRAYAUTH:
+ for (i = 0; i < count; i++) {
+ ap = __s_api_AuthEnumtoStruct(
+ (EnumAuthType_t)ptr->ns_pi[i]);
+ if (ap == NULL) {
+ free(dupdata);
+ return (NULL);
+ }
+ dupdata[i] = ap;
+ }
+ break;
+ case ARRAYCRED:
+ for (i = 0; i < count; i++) {
+ intptr = (int *)malloc(sizeof (int));
+ if (intptr == NULL) {
+ free(dupdata);
+ return (NULL);
+ }
+ dupdata[i] = (void *)intptr;
+ *intptr = ptr->ns_pi[i];
+ }
+ break;
+ case SAMLIST:
+ case SCLLIST:
+ case SSDLIST:
+ case SERVLIST:
+ case ARRAYCP:
+ for (i = 0; i < count; i++) {
+ ret = (void *)strdup(ptr->ns_ppc[i]);
+ if (ret == NULL) {
+ free(dupdata);
+ return (NULL);
+ }
+ dupdata[i] = ret;
+ }
+ break;
+ case CHARPTR:
+ if (ptr->ns_pc == NULL) {
+ free(dupdata);
+ return (NULL);
+ }
+ ret = (void *)strdup(ptr->ns_pc);
+ if (ret == NULL) {
+ free(dupdata);
+ return (NULL);
+ }
+ dupdata[0] = ret;
+ break;
+ case INT:
+ intptr = (int *)malloc(sizeof (int));
+ if (intptr == NULL) {
+ free(dupdata);
+ return (NULL);
+ }
+ *intptr = ptr->ns_i;
+ dupdata[0] = (void *)intptr;
+ break;
+ case TIMET:
+ expire = ptr->ns_tm;
+ tmbuf[31] = '\0';
+ cp = lltostr((long)expire, &tmbuf[31]);
+ ret = (void *)strdup(cp);
+ if (ret == NULL) {
+ free(dupdata);
+ return (NULL);
+ }
+ dupdata[0] = ret;
+ break;
+ }
+ return (dupdata);
+}
+
+int
+__ns_ldap_freeParam(void ***data)
+{
+ void **tmp;
+ int i = 0;
+
+ if (*data == NULL)
+ return (NS_LDAP_SUCCESS);
+
+ for (i = 0, tmp = *data; tmp[i] != NULL; i++)
+ free(tmp[i]);
+
+ free(*data);
+
+ *data = NULL;
+
+ return (NS_LDAP_SUCCESS);
+}
+
+/*
+ * Get the internal format for a parameter value. This
+ * routine makes a copy of an internal param value from
+ * the currently active parameter list and returns it.
+ */
+
+int
+__ns_ldap_getParam(const ParamIndexType Param,
+ void ***data, ns_ldap_error_t **error)
+{
+ char errstr[2 * MAXERROR];
+ ns_ldap_error_t *errorp;
+ ns_default_config *def;
+ ns_config_t *cfg;
+ ns_config_t *new_cfg;
+
+ if (data == NULL)
+ return (NS_LDAP_INVALID_PARAM);
+
+ *data = NULL;
+
+ /* We want to refresh only one configuration at a time */
+ (void) mutex_lock(&ns_loadrefresh_lock);
+ cfg = __s_api_get_default_config();
+
+ /* (re)initialize configuration if necessary */
+ if (cache_server == FALSE && timetorefresh(cfg)) {
+ new_cfg = LoadCacheConfiguration(&errorp);
+ __s_api_release_config(cfg);
+ if (new_cfg == NULL) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Unable to load configuration "
+ "'%s' ('%s')."),
+ NSCONFIGFILE,
+ errorp != NULL && errorp->message != NULL ?
+ errorp->message : "");
+ MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED,
+ strdup(errstr), NULL);
+ if (errorp != NULL)
+ (void) __ns_ldap_freeError(&errorp);
+ (void) mutex_unlock(&ns_loadrefresh_lock);
+ return (NS_LDAP_CONFIG);
+ }
+ set_curr_config(new_cfg);
+ cfg = new_cfg;
+ }
+ (void) mutex_unlock(&ns_loadrefresh_lock);
+
+ if (cfg == NULL) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("No configuration information available."));
+ MKERROR(LOG_ERR, *error, NS_CONFIG_NOTLOADED,
+ strdup(errstr), NULL);
+ return (NS_LDAP_CONFIG);
+ }
+
+ if (Param == NS_LDAP_DOMAIN_P) {
+ *data = (void **)calloc(2, sizeof (void *));
+ if (*data == NULL) {
+ __s_api_release_config(cfg);
+ return (NS_LDAP_MEMORY);
+ }
+ (*data)[0] = (void *)strdup(cfg->domainName);
+ if ((*data)[0] == NULL) {
+ free(*data);
+ __s_api_release_config(cfg);
+ return (NS_LDAP_MEMORY);
+ }
+ } else if (cfg->paramList[Param].ns_ptype == NS_UNKNOWN) {
+ /* get default */
+ def = get_defconfig(cfg, Param);
+ if (def != NULL)
+ *data = dupParam(&def->defval);
+ } else {
+ *data = dupParam(&(cfg->paramList[Param]));
+ }
+ __s_api_release_config(cfg);
+
+ return (NS_LDAP_SUCCESS);
+}
+
+/*
+ * This routine takes a parameter in internal format and
+ * translates it into a variety of string formats for various
+ * outputs (doors/file/ldif). This routine would be better
+ * named: __ns_ldap_translateParam2String
+ */
+
+char *
+__s_api_strValue(ns_config_t *cfg, char *str,
+ int bufsz, ParamIndexType index,
+ ns_strfmt_t fmt)
+{
+ ns_default_config *def = NULL;
+ ns_param_t *ptr;
+ ns_hash_t *hptr;
+ ns_mapping_t *mptr;
+ char ibuf[14], *buf;
+ char abuf[64], **cpp;
+ int alen, count, i, sz;
+ int seplen = strlen(COMMASEP) + strlen(DOORLINESEP);
+ int first;
+
+ if (cfg == NULL || str == NULL)
+ return (NULL);
+
+ /* NS_LDAP_EXP and TRANSPORT_SEC are not exported externally */
+ if (index == NS_LDAP_EXP_P || index == NS_LDAP_TRANSPORT_SEC_P)
+ return (NULL);
+
+ /* Return nothing if the value is the default */
+ if (cfg->paramList[index].ns_ptype == NS_UNKNOWN)
+ return (NULL);
+
+ ptr = &(cfg->paramList[index]);
+
+ abuf[0] = '\0';
+ alen = 0;
+
+ /* get default */
+ def = get_defconfig(cfg, index);
+ if (def == NULL)
+ return (NULL);
+
+ switch (fmt) {
+ case NS_DOOR_FMT:
+ (void) strlcpy(abuf, def->name, sizeof (abuf));
+ (void) strlcat(abuf, EQUALSEP, sizeof (abuf));
+ break;
+ case NS_FILE_FMT:
+ (void) strlcpy(abuf, def->name, sizeof (abuf));
+ (void) strlcat(abuf, EQUSPSEP, sizeof (abuf));
+ break;
+ case NS_LDIF_FMT:
+ /* If no LDIF attr exists ignore the entry */
+ if (def->profile_name == NULL)
+ return (NULL);
+ (void) strlcpy(abuf, def->profile_name, sizeof (abuf));
+ (void) strlcat(abuf, COLSPSEP, sizeof (abuf));
+ break;
+ default:
+ break;
+ }
+ alen = strlen(abuf);
+ if (alen > bufsz)
+ return (NULL);
+
+ buf = str;
+ (void) strlcpy(buf, abuf, bufsz);
+
+ switch (ptr->ns_ptype) {
+ case ARRAYAUTH:
+ count = ptr->ns_acnt;
+ sz = 0;
+ for (i = 0; i < count; i++) {
+ sz += strlen(__s_get_auth_name(cfg,
+ (AuthType_t)(ptr->ns_pi[i]))) + seplen;
+ }
+ sz = sz + alen + 1;
+ if (sz <= bufsz) {
+ buf = str;
+ } else {
+ buf = (char *)calloc(sz, sizeof (char));
+ if (buf == NULL)
+ return (NULL);
+ (void) strcpy(buf, abuf);
+ }
+ for (i = 0; i < count; i++) {
+ (void) strcat(buf,
+ __s_get_auth_name(cfg,
+ (AuthType_t)(ptr->ns_pi[i])));
+ if (i != count-1) {
+ if (cfg->version == NS_LDAP_V1)
+ (void) strcat(buf, COMMASEP);
+ else
+ (void) strcat(buf, SEMISEP);
+ }
+ }
+ break;
+ case ARRAYCRED:
+ count = ptr->ns_acnt;
+ sz = 0;
+ for (i = 0; i < count; i++) {
+ sz += strlen(__s_get_credlvl_name(cfg,
+ (CredLevel_t)ptr->ns_pi[i])) + seplen;
+ }
+ sz = sz + alen + 1;
+ if (sz <= bufsz) {
+ buf = str;
+ } else {
+ buf = (char *)calloc(sz, sizeof (char));
+ if (buf == NULL)
+ return (NULL);
+ (void) strcpy(buf, abuf);
+ }
+ for (i = 0; i < count; i++) {
+ (void) strcat(buf,
+ __s_get_credlvl_name(cfg,
+ (CredLevel_t)ptr->ns_pi[i]));
+ if (i != count-1) {
+ (void) strcat(buf, SPACESEP);
+ }
+ }
+ break;
+ case SAMLIST:
+ case SCLLIST:
+ case SSDLIST:
+ count = ptr->ns_acnt;
+ sz = 0;
+ for (i = 0; i < count; i++) {
+ sz += strlen(ptr->ns_ppc[i]) + seplen;
+ }
+ sz = sz + alen + 1;
+ /*
+ * We need to allocate buffer depending on the 'fmt' and
+ * on the number of ns_ptype's present(count) as we add
+ * name' or 'profile_name' and DOORLINESEP or new line
+ * char to the buffer - see below.
+ */
+ switch (fmt) {
+ case NS_LDIF_FMT:
+ sz += count * (strlen(def->profile_name)
+ + strlen(COLSPSEP) + strlen("\n"));
+ break;
+ case NS_FILE_FMT:
+ sz += count * (strlen(def->name)
+ + strlen(EQUALSEP) + strlen("\n"));
+ break;
+ case NS_DOOR_FMT:
+ sz += count * (strlen(def->name)
+ + strlen(EQUALSEP) + strlen(DOORLINESEP));
+ break;
+ }
+ if (sz <= bufsz) {
+ buf = str;
+ } else {
+ buf = (char *)calloc(sz, sizeof (char));
+ if (buf == NULL)
+ return (NULL);
+ (void) strcpy(buf, abuf);
+ }
+ for (i = 0; i < count; i++) {
+ (void) strcat(buf, ptr->ns_ppc[i]);
+ if (i != count-1) {
+ /* Separate items */
+ switch (fmt) {
+ case NS_DOOR_FMT:
+ (void) strcat(buf, DOORLINESEP);
+ (void) strcat(buf, def->name);
+ (void) strcat(buf, EQUALSEP);
+ break;
+ case NS_FILE_FMT:
+ (void) strcat(buf, "\n");
+ (void) strcat(buf, def->name);
+ (void) strcat(buf, EQUSPSEP);
+ break;
+ case NS_LDIF_FMT:
+ (void) strcat(buf, "\n");
+ (void) strcat(buf, def->profile_name);
+ (void) strcat(buf, COLSPSEP);
+ break;
+ }
+ }
+ }
+ break;
+ case ARRAYCP:
+ count = ptr->ns_acnt;
+ sz = 0;
+ for (i = 0; i < count; i++) {
+ sz += strlen(ptr->ns_ppc[i]) + seplen;
+ }
+ sz = sz + alen + 1;
+ if (sz <= bufsz) {
+ buf = str;
+ } else {
+ buf = (char *)calloc(sz, sizeof (char));
+ if (buf == NULL)
+ return (NULL);
+ (void) strcpy(buf, abuf);
+ }
+ for (i = 0; i < count; i++) {
+ (void) strcat(buf, ptr->ns_ppc[i]);
+ if (i != count-1) {
+ (void) strcat(buf, COMMASEP);
+ }
+ }
+ break;
+ case SERVLIST:
+ count = ptr->ns_acnt;
+ sz = 0;
+ for (i = 0; i < count; i++) {
+ sz += strlen(ptr->ns_ppc[i]) + seplen;
+ }
+ sz = sz + alen + 1;
+ if (sz <= bufsz) {
+ buf = str;
+ } else {
+ buf = (char *)calloc(sz, sizeof (char));
+ if (buf == NULL)
+ return (NULL);
+ (void) strcpy(buf, abuf);
+ }
+ for (i = 0; i < count; i++) {
+ (void) strcat(buf, ptr->ns_ppc[i]);
+ if (i != count-1) {
+ if (fmt == NS_LDIF_FMT)
+ (void) strcat(buf, SPACESEP);
+ else
+ (void) strcat(buf, COMMASEP);
+ }
+ }
+ break;
+ case CHARPTR:
+ if (ptr->ns_pc == NULL)
+ break;
+ sz = strlen(ptr->ns_pc) + alen + 1;
+ if (sz > bufsz) {
+ buf = (char *)calloc(sz, sizeof (char));
+ if (buf == NULL)
+ return (NULL);
+ (void) strcpy(buf, abuf);
+ }
+ (void) strcat(buf, ptr->ns_pc);
+ break;
+ case INT:
+ switch (def->index) {
+ case NS_LDAP_PREF_ONLY_P:
+ (void) strcat(buf,
+ __s_get_pref_name((PrefOnly_t)ptr->ns_i));
+ break;
+ case NS_LDAP_SEARCH_REF_P:
+ (void) strcat(buf,
+ __s_get_searchref_name(cfg,
+ (SearchRef_t)ptr->ns_i));
+ break;
+ case NS_LDAP_SEARCH_SCOPE_P:
+ (void) strcat(buf,
+ __s_get_scope_name(cfg,
+ (ScopeType_t)ptr->ns_i));
+ break;
+ default:
+ (void) snprintf(ibuf, sizeof (ibuf),
+ "%d", ptr->ns_i);
+ (void) strcat(buf, ibuf);
+ break;
+ }
+ break;
+ case ATTRMAP:
+ buf[0] = '\0';
+ first = 1;
+ for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) {
+ if (hptr->h_type != NS_HASH_AMAP) {
+ continue;
+ }
+ if (!first) {
+ if (fmt == NS_DOOR_FMT)
+ (void) strcat(buf, DOORLINESEP);
+ else
+ (void) strcat(buf, "\n");
+ }
+ mptr = hptr->h_map;
+ (void) strcat(buf, abuf);
+ (void) strcat(buf, mptr->service);
+ (void) strcat(buf, COLONSEP);
+ (void) strcat(buf, mptr->orig);
+ (void) strcat(buf, EQUALSEP);
+ for (cpp = mptr->map; cpp && *cpp; cpp++) {
+ if (cpp != mptr->map)
+ (void) strcat(buf, SPACESEP);
+ (void) strcat(buf, *cpp);
+ }
+ first = 0;
+ }
+ break;
+ case OBJMAP:
+ buf[0] = '\0';
+ first = 1;
+ for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) {
+ if (hptr->h_type != NS_HASH_OMAP) {
+ continue;
+ }
+ if (!first) {
+ if (fmt == NS_DOOR_FMT)
+ (void) strcat(buf, DOORLINESEP);
+ else
+ (void) strcat(buf, "\n");
+ }
+ mptr = hptr->h_map;
+ (void) strcat(buf, abuf);
+ (void) strcat(buf, mptr->service);
+ (void) strcat(buf, COLONSEP);
+ (void) strcat(buf, mptr->orig);
+ (void) strcat(buf, EQUALSEP);
+ for (cpp = mptr->map; cpp && *cpp; cpp++) {
+ if (cpp != mptr->map)
+ (void) strcat(buf, SPACESEP);
+ (void) strcat(buf, *cpp);
+ }
+ first = 0;
+ }
+ break;
+ }
+ return (buf);
+}
+
+static int
+__door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error)
+{
+ typedef union {
+ ldap_data_t s_d;
+ char s_b[DOORBUFFERSIZE];
+ } space_t;
+ space_t *space;
+
+ ldap_data_t *sptr;
+ int ndata;
+ int adata;
+ char errstr[MAXERROR];
+ char *domainname;
+
+ domainname = __getdomainname();
+ if (domainname == NULL || buffer == NULL || buflen == NULL ||
+ (strlen(domainname) >= (sizeof (space_t)
+ - sizeof (space->s_d.ldap_call.ldap_callnumber)))) {
+ return (NS_LDAP_OP_FAILED);
+ }
+
+ space = (space_t *)calloc(1, sizeof (space_t));
+ if (space == NULL)
+ return (NS_LDAP_OP_FAILED);
+
+ adata = (sizeof (ldap_call_t) + strlen(domainname) +1);
+ ndata = sizeof (space_t);
+ space->s_d.ldap_call.ldap_callnumber = GETLDAPCONFIGV1;
+ (void) strcpy(space->s_d.ldap_call.ldap_u.domainname, domainname);
+ free(domainname);
+ domainname = NULL;
+ sptr = &space->s_d;
+
+ switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
+ case SUCCESS:
+ break;
+ case NOTFOUND:
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Door call to "
+ "ldap_cachemgr failed - error: %d."),
+ space->s_d.ldap_ret.ldap_errno);
+ MKERROR(LOG_WARNING, *error, NS_CONFIG_CACHEMGR,
+ strdup(errstr), NULL);
+ free(space);
+ return (NS_LDAP_OP_FAILED);
+ default:
+ free(space);
+ return (NS_LDAP_OP_FAILED);
+ }
+
+ /* copy info from door call to buffer here */
+ *buflen = strlen(space->s_d.ldap_ret.ldap_u.config) + 1;
+ *buffer = calloc(*buflen, sizeof (char));
+ if (*buffer == NULL) {
+ free(space);
+ return (NS_LDAP_MEMORY);
+ }
+ (void) strcpy(*buffer, space->s_d.ldap_ret.ldap_u.config);
+
+ if (sptr != &space->s_d) {
+ (void) munmap((char *)sptr, ndata);
+ } else {
+ free(space);
+ space = NULL;
+ }
+ *error = NULL;
+
+ return (NS_LDAP_SUCCESS);
+}
+
+/*
+ * SetDoorInfo parses ldapcachemgr configuration information
+ * and verifies that the profile is version 1 or version 2 based.
+ * version 2 profiles must have a version number as the first profile
+ * attribute in the configuration.
+ */
+static ns_config_t *
+SetDoorInfo(char *buffer, ns_ldap_error_t **errorp)
+{
+ ns_config_t *ptr;
+ char errstr[MAXERROR], errbuf[MAXERROR];
+ char *name, *value, valbuf[BUFSIZE];
+ char *strptr;
+ char *rest;
+ char *bufptr = buffer;
+ ParamIndexType i;
+ int ret;
+ int first = 1;
+ int errfnd = 0;
+
+ if (errorp == NULL)
+ return (NULL);
+ *errorp = NULL;
+
+ ptr = __s_api_create_config();
+ if (ptr == NULL) {
+ return (NULL);
+ }
+
+ strptr = (char *)strtok_r(bufptr, DOORLINESEP, &rest);
+ for (; ; ) {
+ if (strptr == NULL)
+ break;
+ (void) strlcpy(valbuf, strptr, sizeof (valbuf));
+ __s_api_split_key_value(valbuf, &name, &value);
+ /* Use get_versiontype and check for V1 vs V2 prototypes */
+ if (__s_api_get_versiontype(ptr, name, &i) < 0) {
+ (void) snprintf(errstr, sizeof (errstr),
+ "%s (%s)\n",
+ gettext("Illegal profile entry "
+ "line in configuration."),
+ name);
+ errfnd++;
+ /* Write verify routines and get rid of verify_value here */
+ } else if (verify_value(ptr, name,
+ value, errbuf) != NS_SUCCESS) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("%s\n"), errbuf);
+ errfnd++;
+ } else if (!first && i == NS_LDAP_FILE_VERSION_P) {
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Illegal NS_LDAP_FILE_VERSION "
+ "line in configuration.\n"));
+ errfnd++;
+ }
+ if (errfnd) {
+ MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX,
+ strdup(errstr), NULL);
+ } else {
+ ret = set_default_value(ptr, name, value, errorp);
+ }
+ if (errfnd || ret != NS_SUCCESS) {
+ __s_api_destroy_config(ptr);
+ return (NULL);
+ }
+ first = 0;
+
+ strptr = (char *)strtok_r(NULL, DOORLINESEP, &rest);
+ }
+
+ if (__s_api_crosscheck(ptr, errstr, B_TRUE) != NS_SUCCESS) {
+ __s_api_destroy_config(ptr);
+ MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX, strdup(errstr),
+ NULL);
+ return (NULL);
+ }
+
+ return (ptr);
+}
+
+static ns_config_t *
+LoadCacheConfiguration(ns_ldap_error_t **error)
+{
+ char *buffer = NULL;
+ int buflen = 0;
+ int ret;
+ ns_config_t *cfg;
+
+ *error = NULL;
+ ret = __door_getldapconfig(&buffer, &buflen, error);
+
+ if (ret != NS_LDAP_SUCCESS) {
+ if (*error != NULL && (*error)->message != NULL)
+ syslog(LOG_WARNING, "libsldap: %s", (*error)->message);
+ return (NULL);
+ }
+
+ /* now convert from door format */
+ cfg = SetDoorInfo(buffer, error);
+ free(buffer);
+
+ if (cfg == NULL && *error != NULL && (*error)->message != NULL)
+ syslog(LOG_WARNING, "libsldap: %s", (*error)->message);
+ return (cfg);
+}
+
+/*
+ * converts the time string into seconds. The time string can be specified
+ * using one of the following time units:
+ * #s (# of seconds)
+ * #m (# of minutes)
+ * #h (# of hours)
+ * #d (# of days)
+ * #w (# of weeks)
+ * NOTE: you can only specify one the above. No combination of the above
+ * units is allowed. If no unit specified, it will default to "seconds".
+ */
+static time_t
+conv_time(char *s)
+{
+ time_t t;
+ char c;
+ int l, m;
+ long tot;
+
+ l = strlen(s);
+ if (l == 0)
+ return (0);
+ c = s[--l];
+ m = 0;
+ switch (c) {
+ case 'w': /* weeks */
+ m = 604800;
+ break;
+ case 'd': /* days */
+ m = 86400;
+ break;
+ case 'h': /* hours */
+ m = 3600;
+ break;
+ case 'm': /* minutes */
+ m = 60;
+ break;
+ case 's': /* seconds */
+ m = 1;
+ break;
+ /* the default case is set to "second" */
+ }
+ if (m != 0)
+ s[l] = '\0';
+ else
+ m = 1;
+ errno = 0;
+ tot = atol(s);
+ if ((0 == tot) && (EINVAL == errno))
+ return (0);
+ if (((LONG_MAX == tot) || (LONG_MIN == tot)) && (EINVAL == errno))
+ return (0);
+
+ tot = tot * m;
+ t = (time_t)tot;
+ return (t);
+}
+
+
+ns_auth_t *
+__s_api_AuthEnumtoStruct(const EnumAuthType_t i)
+{
+ ns_auth_t *ap;
+
+ ap = (ns_auth_t *)calloc(1, sizeof (ns_auth_t));
+ if (ap == NULL)
+ return (NULL);
+ switch (i) {
+ case NS_LDAP_EA_NONE:
+ break;
+ case NS_LDAP_EA_SIMPLE:
+ ap->type = NS_LDAP_AUTH_SIMPLE;
+ break;
+ case NS_LDAP_EA_SASL_CRAM_MD5:
+ ap->type = NS_LDAP_AUTH_SASL;
+ ap->saslmech = NS_LDAP_SASL_CRAM_MD5;
+ break;
+ case NS_LDAP_EA_SASL_DIGEST_MD5:
+ ap->type = NS_LDAP_AUTH_SASL;
+ ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
+ break;
+ case NS_LDAP_EA_SASL_DIGEST_MD5_INT:
+ ap->type = NS_LDAP_AUTH_SASL;
+ ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
+ ap->saslopt = NS_LDAP_SASLOPT_INT;
+ break;
+ case NS_LDAP_EA_SASL_DIGEST_MD5_CONF:
+ ap->type = NS_LDAP_AUTH_SASL;
+ ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
+ ap->saslopt = NS_LDAP_SASLOPT_PRIV;
+ break;
+ case NS_LDAP_EA_SASL_EXTERNAL:
+ ap->type = NS_LDAP_AUTH_SASL;
+ ap->saslmech = NS_LDAP_SASL_EXTERNAL;
+ break;
+ case NS_LDAP_EA_TLS_NONE:
+ ap->type = NS_LDAP_AUTH_TLS;
+ ap->tlstype = NS_LDAP_TLS_NONE;
+ break;
+ case NS_LDAP_EA_TLS_SIMPLE:
+ ap->type = NS_LDAP_AUTH_TLS;
+ ap->tlstype = NS_LDAP_TLS_SIMPLE;
+ break;
+ case NS_LDAP_EA_TLS_SASL_CRAM_MD5:
+ ap->type = NS_LDAP_AUTH_TLS;
+ ap->tlstype = NS_LDAP_TLS_SASL;
+ ap->saslmech = NS_LDAP_SASL_CRAM_MD5;
+ break;
+ case NS_LDAP_EA_TLS_SASL_DIGEST_MD5:
+ ap->type = NS_LDAP_AUTH_TLS;
+ ap->tlstype = NS_LDAP_TLS_SASL;
+ ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
+ break;
+ case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT:
+ ap->type = NS_LDAP_AUTH_TLS;
+ ap->tlstype = NS_LDAP_TLS_SASL;
+ ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
+ ap->saslopt = NS_LDAP_SASLOPT_INT;
+ break;
+ case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF:
+ ap->type = NS_LDAP_AUTH_TLS;
+ ap->tlstype = NS_LDAP_TLS_SASL;
+ ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
+ ap->saslopt = NS_LDAP_SASLOPT_PRIV;
+ break;
+ case NS_LDAP_EA_TLS_SASL_EXTERNAL:
+ ap->type = NS_LDAP_AUTH_TLS;
+ ap->tlstype = NS_LDAP_TLS_SASL;
+ ap->saslmech = NS_LDAP_SASL_EXTERNAL;
+ break;
+ default:
+ /* should never get here */
+ free(ap);
+ return (NULL);
+ }
+ return (ap);
+}
+
+
+/*
+ * Parameter Index Type validation routines
+ */
+
+/* Validate a positive integer */
+/* Size of errbuf needs to be MAXERROR */
+/* ARGSUSED */
+static int
+__s_val_postime(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf)
+{
+ char *cp;
+ long tot;
+
+ if (param && param->ns_ptype == CHARPTR && param->ns_pc) {
+ for (cp = param->ns_pc; cp && *cp; cp++) {
+ if (*cp >= '0' && *cp <= '9')
+ continue;
+ switch (*cp) {
+ case 'w': /* weeks */
+ case 'd': /* days */
+ case 'h': /* hours */
+ case 'm': /* minutes */
+ case 's': /* seconds */
+ if (*(cp+1) == '\0') {
+ break;
+ }
+ default:
+ (void) strcpy(errbuf, "Illegal time value");
+ return (NS_PARSE_ERR);
+ }
+ }
+ /* Valid form: [0-9][0-9]*[wdhms]* */
+ tot = atol(param->ns_pc); /* check overflow */
+ if (tot >= 0)
+ return (NS_SUCCESS);
+ }
+ (void) snprintf(errbuf, MAXERROR,
+ gettext("Illegal time value in %s"), def->name);
+ return (NS_PARSE_ERR);
+}
+
+
+/* Validate the Base DN */
+/* It can be empty (RootDSE request) or needs to have an '=' */
+/* Size of errbuf needs to be MAXERROR */
+/* ARGSUSED */
+static int
+__s_val_basedn(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf)
+{
+ if (param && param->ns_ptype == CHARPTR &&
+ i == NS_LDAP_SEARCH_BASEDN_P &&
+ ((param->ns_pc == NULL) || /* empty */
+ (*(param->ns_pc) == '\0') || /* empty */
+ (strchr(param->ns_pc, '=') != NULL))) /* '=' */
+ {
+ return (NS_SUCCESS);
+ }
+ (void) snprintf(errbuf, MAXERROR,
+ gettext("Non-existent or invalid DN in %s"),
+ def->name);
+ return (NS_PARSE_ERR);
+}
+
+
+/* Validate the serverList */
+/* For each server in list, check if valid IP or hostname */
+/* Size of errbuf needs to be MAXERROR */
+/* ARGSUSED */
+static int
+__s_val_serverList(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf)
+{
+ for (i = 0; i < param->ns_acnt; i++) {
+ if ((__s_api_isipv4(param->ns_ppc[i])) ||
+ (__s_api_isipv6(param->ns_ppc[i])) ||
+ (__s_api_ishost(param->ns_ppc[i]))) {
+ continue;
+ }
+ /* err */
+ (void) snprintf(errbuf, MAXERROR,
+ gettext("Invalid server (%s) in %s"),
+ param->ns_ppc[i], def->name);
+ return (NS_PARSE_ERR);
+ }
+
+ return (NS_SUCCESS);
+}
+
+
+/* Check for a BINDDN */
+/* It can not be empty and needs to have an '=' */
+/* Size of errbuf needs to be MAXERROR */
+/* ARGSUSED */
+static int
+__s_val_binddn(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf)
+{
+ if (param && param->ns_ptype == CHARPTR &&
+ i == NS_LDAP_BINDDN_P &&
+ ((param->ns_pc == NULL) ||
+ ((*(param->ns_pc) != '\0') &&
+ (strchr(param->ns_pc, '=') != NULL)))) {
+ return (NS_SUCCESS);
+ }
+ (void) snprintf(errbuf, MAXERROR,
+ gettext("NULL or invalid proxy bind DN"));
+ return (NS_PARSE_ERR);
+}
+
+
+/* Check for a BINDPASSWD */
+/* The string can not be NULL or empty */
+/* Size of errbuf needs to be MAXERROR */
+/* ARGSUSED */
+static int
+__s_val_bindpw(ParamIndexType i, ns_default_config *def,
+ ns_param_t *param, char *errbuf)
+{
+ if (param && param->ns_ptype == CHARPTR &&
+ i == NS_LDAP_BINDPASSWD_P &&
+ ((param->ns_pc == NULL) ||
+ (*(param->ns_pc) != '\0'))) {
+ return (NS_SUCCESS);
+ }
+ (void) snprintf(errbuf, MAXERROR,
+ gettext("NULL proxy bind password"));
+ return (NS_PARSE_ERR);
+}
+
+/*
+ * __s_get_hostcertpath returns either the configured host certificate path
+ * or, if none, the default host certificate path (/var/ldap). Note that this
+ * does not use __ns_ldap_getParam because it may be called during connection
+ * setup. This can fail due to insufficient memory.
+ */
+
+char *
+__s_get_hostcertpath(void)
+{
+ ns_config_t *cfg;
+ ns_param_t *param;
+ char *ret = NULL;
+
+ cfg = __s_api_get_default_config();
+ if (cfg != NULL) {
+ param = &cfg->paramList[NS_LDAP_HOST_CERTPATH_P];
+ if (param->ns_ptype == CHARPTR)
+ ret = strdup(param->ns_pc);
+ __s_api_release_config(cfg);
+ }
+ if (ret == NULL)
+ ret = strdup(NSLDAPDIRECTORY);
+ return (ret);
+}
+
+static void
+_free_config()
+{
+ if (current_config != NULL)
+ destroy_config(current_config);
+
+ current_config = NULL;
+}