dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libsldap / common / ns_config.c
blobacb37c0b0e191ee2c1ffca876ee431c16add02ac
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * libsldap - library side configuration components
28 * Routines to manage the config structure
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <string.h>
35 #include <strings.h>
36 #include <libintl.h>
37 #include <locale.h>
38 #include <thread.h>
39 #include <synch.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <ctype.h>
44 #include <crypt.h>
45 #include <arpa/inet.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <syslog.h>
49 #include <netdb.h>
50 #include <sys/systeminfo.h>
51 #include <sys/mman.h>
52 #include <sys/time.h>
53 #include <limits.h>
54 #include "ns_sldap.h"
55 #include "ns_internal.h"
56 #include "ns_cache_door.h"
57 #include "ns_connmgmt.h"
59 #pragma fini(__s_api_shutdown_conn_mgmt, \
60 _free_config, __ns_ldap_doorfd_close)
62 static mutex_t ns_parse_lock = DEFAULTMUTEX;
63 static mutex_t ns_loadrefresh_lock = DEFAULTMUTEX;
64 static ns_config_t *current_config = NULL;
66 static int cache_server = FALSE;
67 extern thread_key_t ns_cmgkey;
70 * Parameter Index Type validation routines
72 static int
73 __s_val_postime(ParamIndexType i, ns_default_config *def,
74 ns_param_t *param, char *errbuf);
75 static int
76 __s_val_basedn(ParamIndexType i, ns_default_config *def,
77 ns_param_t *param, char *errbuf);
79 static int
80 __s_val_binddn(ParamIndexType i, ns_default_config *def,
81 ns_param_t *param, char *errbuf);
83 static int
84 __s_val_bindpw(ParamIndexType i, ns_default_config *def,
85 ns_param_t *param, char *errbuf);
87 static int
88 __s_val_serverList(ParamIndexType i, ns_default_config *def,
89 ns_param_t *param, char *errbuf);
92 * Forward declarations
95 static ns_parse_status
96 verify_value(ns_config_t *cfg, char *name, char *value, char *errstr);
98 static int
99 set_default_value(ns_config_t *configptr, char *name, char *value,
100 ns_ldap_error_t **error);
102 static void
103 set_curr_config(ns_config_t *ptr);
105 static int
106 __door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error);
108 static ns_config_t *
109 SetDoorInfo(char *buffer, ns_ldap_error_t **errorp);
111 static boolean_t
112 timetorefresh(ns_config_t *cfg);
114 static ns_config_t *
115 LoadCacheConfiguration(ns_config_t *, ns_ldap_error_t **error);
117 static void **
118 dupParam(ns_param_t *ptr);
120 static time_t
121 conv_time(char *s);
124 * Structures used in enum <-> string mapping routines
127 static ns_enum_map ns_auth_enum_v1[] = {
128 { ENUM2INT(NS_LDAP_EA_NONE), "NS_LDAP_AUTH_NONE" },
129 { ENUM2INT(NS_LDAP_EA_SIMPLE), "NS_LDAP_AUTH_SIMPLE" },
130 { ENUM2INT(NS_LDAP_EA_SASL_CRAM_MD5), "NS_LDAP_AUTH_SASL_CRAM_MD5" },
131 { -1, NULL },
134 static ns_enum_map ns_auth_enum_v2[] = {
135 { ENUM2INT(NS_LDAP_EA_NONE), "none" },
136 { ENUM2INT(NS_LDAP_EA_SIMPLE), "simple" },
137 { ENUM2INT(NS_LDAP_EA_SASL_CRAM_MD5), "sasl/CRAM-MD5" },
138 { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5), "sasl/DIGEST-MD5" },
139 { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5_INT),
140 "sasl/DIGEST-MD5:auth-int" },
141 { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5_CONF),
142 "sasl/DIGEST-MD5:auth-conf" },
143 { ENUM2INT(NS_LDAP_EA_SASL_EXTERNAL), "sasl/EXTERNAL" },
144 { ENUM2INT(NS_LDAP_EA_SASL_GSSAPI), "sasl/GSSAPI" },
145 { ENUM2INT(NS_LDAP_EA_TLS_NONE), "tls:none" },
146 { ENUM2INT(NS_LDAP_EA_TLS_SIMPLE), "tls:simple" },
147 { ENUM2INT(NS_LDAP_EA_TLS_SASL_CRAM_MD5), "tls:sasl/CRAM-MD5" },
148 { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5), "tls:sasl/DIGEST-MD5" },
149 { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT),
150 "tls:sasl/DIGEST-MD5:auth-int" },
151 { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF),
152 "tls:sasl/DIGEST-MD5:auth-conf" },
153 { ENUM2INT(NS_LDAP_EA_TLS_SASL_EXTERNAL), "tls:sasl/EXTERNAL" },
154 { -1, NULL },
157 /* V1 ONLY */
158 static ns_enum_map ns_sec_enum_v1[] = {
159 { ENUM2INT(NS_LDAP_TLS_NONE), "NS_LDAP_SEC_NONE" },
160 { -1, NULL },
163 /* V2 ONLY */
164 static ns_enum_map ns_cred_enum_v2[] = {
165 { ENUM2INT(NS_LDAP_CRED_ANON), "anonymous" },
166 { ENUM2INT(NS_LDAP_CRED_PROXY), "proxy" },
167 { ENUM2INT(NS_LDAP_CRED_SELF), "self" },
168 { -1, NULL },
171 static ns_enum_map ns_ref_enum_v1[] = {
172 { ENUM2INT(NS_LDAP_FOLLOWREF), "NS_LDAP_FOLLOWREF" },
173 { ENUM2INT(NS_LDAP_NOREF), "NS_LDAP_NOREF" },
174 { -1, NULL },
177 static ns_enum_map ns_ref_enum_v2[] = {
178 { ENUM2INT(NS_LDAP_FOLLOWREF), "TRUE" },
179 { ENUM2INT(NS_LDAP_NOREF), "FALSE" },
180 { -1, NULL },
183 static ns_enum_map ns_scope_enum_v1[] = {
184 { ENUM2INT(NS_LDAP_SCOPE_BASE), "NS_LDAP_SCOPE_BASE" },
185 { ENUM2INT(NS_LDAP_SCOPE_ONELEVEL), "NS_LDAP_SCOPE_ONELEVEL" },
186 { ENUM2INT(NS_LDAP_SCOPE_SUBTREE), "NS_LDAP_SCOPE_SUBTREE" },
187 { -1, NULL },
190 static ns_enum_map ns_scope_enum_v2[] = {
191 { ENUM2INT(NS_LDAP_SCOPE_BASE), "base" },
192 { ENUM2INT(NS_LDAP_SCOPE_ONELEVEL), "one" },
193 { ENUM2INT(NS_LDAP_SCOPE_SUBTREE), "sub" },
194 { -1, NULL },
197 static ns_enum_map ns_pref_enum[] = {
198 { ENUM2INT(NS_LDAP_PREF_FALSE), "NS_LDAP_FALSE" },
199 { ENUM2INT(NS_LDAP_PREF_TRUE), "NS_LDAP_TRUE" },
200 { -1, NULL },
203 static ns_enum_map ns_shadow_update_enum[] = {
204 { ENUM2INT(NS_LDAP_ENABLE_SHADOW_UPDATE_FALSE), "FALSE" },
205 { ENUM2INT(NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE), "TRUE" },
206 { -1, NULL },
209 static int ns_def_auth_v1[] = {
210 ENUM2INT(NS_LDAP_EA_NONE),
214 static int ns_def_auth_v2[] = {
215 ENUM2INT(NS_LDAP_EA_NONE),
219 static int ns_def_cred_v1[] = {
220 ENUM2INT(NS_LDAP_CRED_PROXY),
224 static int ns_def_cred_v2[] = {
225 ENUM2INT(NS_LDAP_CRED_ANON),
230 * The next macro places an integer in the first sizeof(int) bytes of a
231 * void pointer location. For 32-bit, it is the same as "(void *) i". It
232 * is used to solve a problem found during 64-bit testing. The problem
233 * was that for a configuration parameter such as NS_LDAP_SEARCH_REF_P,
234 * which is of type INT and has defined default value, an int
235 * variable(ns_param.ns_pu.i) defined inside an union(ns_pu) structure, is
236 * used to access the defined default value. This requires the default
237 * value to be in the first sizeof(int) bytes of the union element. If
238 * just using "(void *) intval" to declare the default value in the
239 * following defconfig[] structure, the intval data will be placed is the
240 * last sizeof(int) bytes. In which case, when accessing via ns_pu_i in
241 * a 64-bit system, ZERO will be returned as the default value, not the
242 * defined one.
244 * Note since amd64 is little-endian, the problem is not an issue.
245 * INT2VOIDPTR will just leave the data (i) unchanged.
247 #if defined(__amd64)
248 #define INT2VOIDPTR(i) (void *)i
249 #else
250 #define INT2VOIDPTR(i) \
251 (void *)(((long)(i))<<(8*(sizeof (void *) - sizeof (int))))
252 #endif
254 * The default configuration table
255 * Version 1 entries are first, V2 entries follow.
257 static ns_default_config defconfig[] = {
258 /* optional V1 profile */
259 {"NS_LDAP_FILE_VERSION", NS_LDAP_FILE_VERSION_P,
260 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
261 NULL, /* No version number defined in V1 */
262 { CHARPTR, 0, (void *)NS_LDAP_VERSION_1 },
263 NULL, NULL },
265 /* ---------- V1 profile ---------- */
266 {"NS_LDAP_BINDDN", NS_LDAP_BINDDN_P,
267 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
268 _P1_BINDDN,
269 { CHARPTR, 0, NULL },
270 __s_val_binddn, NULL },
272 {"NS_LDAP_BINDPASSWD", NS_LDAP_BINDPASSWD_P,
273 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
274 _P1_BINDPASSWORD,
275 { CHARPTR, 0, NULL },
276 __s_val_bindpw, NULL },
278 {"NS_LDAP_SERVERS", NS_LDAP_SERVERS_P,
279 SERVERCONFIG, ARRAYCP, FALSE, NS_LDAP_V1,
280 _P1_SERVERS,
281 { ARRAYCP, 0, NULL },
282 __s_val_serverList, NULL },
284 {"NS_LDAP_SEARCH_BASEDN", NS_LDAP_SEARCH_BASEDN_P,
285 SERVERCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
286 _P1_SEARCHBASEDN,
287 { CHARPTR, 0, NULL },
288 __s_val_basedn, NULL },
290 {"NS_LDAP_AUTH", NS_LDAP_AUTH_P,
291 CLIENTCONFIG, ARRAYAUTH, FALSE, NS_LDAP_V1,
292 _P1_AUTHMETHOD,
293 { ARRAYAUTH, 1, (void *)&ns_def_auth_v1[0] },
294 NULL, ns_auth_enum_v1 },
296 {"NS_LDAP_TRANSPORT_SEC", NS_LDAP_TRANSPORT_SEC_P,
297 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
298 _P1_TRANSPORTSECURITY,
299 { INT, 0, INT2VOIDPTR(NS_LDAP_TLS_NONE) },
300 NULL, ns_sec_enum_v1 },
302 {"NS_LDAP_SEARCH_REF", NS_LDAP_SEARCH_REF_P,
303 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
304 _P1_SEARCHREFERRAL,
305 { INT, 0, INT2VOIDPTR(NS_LDAP_FOLLOWREF) },
306 NULL, ns_ref_enum_v1 },
308 {"NS_LDAP_DOMAIN", NS_LDAP_DOMAIN_P,
309 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
310 NULL, /* not defined in the Profile */
311 { CHARPTR, 0, NULL },
312 NULL, NULL },
314 {"NS_LDAP_EXP", NS_LDAP_EXP_P,
315 SERVERCONFIG, TIMET, TRUE, NS_LDAP_V1,
316 NULL, /* initialized by code to time+NS_LDAP_CACHETTL */
317 { INT, 0, 0 },
318 NULL, NULL },
320 {"NS_LDAP_CERT_PATH", NS_LDAP_CERT_PATH_P,
321 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
322 _P1_CERTIFICATEPATH,
323 { CHARPTR, 0, NULL },
324 NULL, NULL },
326 {"NS_LDAP_CERT_PASS", NS_LDAP_CERT_PASS_P,
327 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
328 _P1_CERTIFICATEPASSWORD,
329 { CHARPTR, 0, NULL },
330 NULL, NULL },
332 {"NS_LDAP_SEARCH_DN", NS_LDAP_SEARCH_DN_P,
333 CLIENTCONFIG, SSDLIST, FALSE, NS_LDAP_V1,
334 _P1_DATASEARCHDN,
335 { SSDLIST, 0, NULL },
336 NULL, NULL },
338 {"NS_LDAP_SEARCH_SCOPE", NS_LDAP_SEARCH_SCOPE_P,
339 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
340 _P1_SEARCHSCOPE,
341 { INT, 0, INT2VOIDPTR(NS_LDAP_SCOPE_ONELEVEL) },
342 NULL, ns_scope_enum_v1 },
344 {"NS_LDAP_SEARCH_TIME", NS_LDAP_SEARCH_TIME_P,
345 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
346 _P1_SEARCHTIMELIMIT,
347 { INT, 0, INT2VOIDPTR(NS_DEFAULT_SEARCH_TIMEOUT) },
348 NULL, NULL },
350 {"NS_LDAP_SERVER_PREF", NS_LDAP_SERVER_PREF_P,
351 CLIENTCONFIG, ARRAYCP, FALSE, NS_LDAP_V1,
352 _P1_PREFERREDSERVER,
353 { ARRAYCP, 0, NULL },
354 __s_val_serverList, NULL },
356 {"NS_LDAP_PREF_ONLY", NS_LDAP_PREF_ONLY_P,
357 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
358 _P1_PREFERREDSERVERONLY,
359 { INT, 0, INT2VOIDPTR(NS_LDAP_PREF_FALSE) },
360 NULL, ns_pref_enum },
362 {"NS_LDAP_CACHETTL", NS_LDAP_CACHETTL_P,
363 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
364 _P1_CACHETTL,
365 { CHARPTR, 0, (void *)EXP_DEFAULT_TTL },
366 __s_val_postime, NULL },
368 {"NS_LDAP_PROFILE", NS_LDAP_PROFILE_P,
369 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1,
370 _P_CN,
371 { CHARPTR, 0, (void *)DEFAULTCONFIGNAME },
372 NULL, NULL },
374 {"NS_LDAP_BIND_TIME", NS_LDAP_BIND_TIME_P,
375 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1,
376 _P1_BINDTIMELIMIT,
377 { INT, 0, INT2VOIDPTR(NS_DEFAULT_BIND_TIMEOUT) },
378 NULL, NULL },
380 /* This configuration option is not visible in V1 */
381 {"NS_LDAP_CREDENTIAL_LEVEL", NS_LDAP_CREDENTIAL_LEVEL_P,
382 CLIENTCONFIG, ARRAYCRED, TRUE, NS_LDAP_V1,
383 NULL, /* No version defined in V1 */
384 { ARRAYCRED, 0, (void *)&ns_def_cred_v1[0] },
385 NULL, NULL },
387 /* ---------- V2 profile ---------- */
388 {"NS_LDAP_FILE_VERSION", NS_LDAP_FILE_VERSION_P,
389 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
390 NULL, /* No version number defined in V1 */
391 { CHARPTR, 0, (void *)NS_LDAP_VERSION_2 },
392 NULL, NULL },
394 {"NS_LDAP_BINDDN", NS_LDAP_BINDDN_P,
395 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
396 NULL, /* not defined in the Profile */
397 { CHARPTR, 0, NULL },
398 __s_val_binddn, NULL },
400 {"NS_LDAP_BINDPASSWD", NS_LDAP_BINDPASSWD_P,
401 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
402 NULL, /* not defined in the Profile */
403 { CHARPTR, 0, NULL },
404 __s_val_bindpw, NULL },
406 {"NS_LDAP_ENABLE_SHADOW_UPDATE", NS_LDAP_ENABLE_SHADOW_UPDATE_P,
407 CREDCONFIG, INT, TRUE, NS_LDAP_V2,
408 NULL, /* not defined in the Profile */
409 { INT, 0, INT2VOIDPTR(NS_LDAP_ENABLE_SHADOW_UPDATE_FALSE) },
410 NULL, ns_shadow_update_enum },
412 {"NS_LDAP_ADMIN_BINDDN", NS_LDAP_ADMIN_BINDDN_P,
413 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
414 NULL, /* not defined in the Profile */
415 { CHARPTR, 0, NULL },
416 __s_val_binddn, NULL },
418 {"NS_LDAP_ADMIN_BINDPASSWD", NS_LDAP_ADMIN_BINDPASSWD_P,
419 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
420 NULL, /* not defined in the Profile */
421 { CHARPTR, 0, NULL },
422 __s_val_bindpw, NULL },
424 {"NS_LDAP_EXP", NS_LDAP_EXP_P,
425 SERVERCONFIG, TIMET, TRUE, NS_LDAP_V2,
426 NULL, /* initialized by code to time+NS_LDAP_CACHETTL */
427 { INT, 0, 0 },
428 NULL, NULL },
430 {"NS_LDAP_SERVER_PREF", NS_LDAP_SERVER_PREF_P,
431 CLIENTCONFIG, SERVLIST, FALSE, NS_LDAP_V2,
432 _P2_PREFERREDSERVER,
433 { SERVLIST, 0, NULL },
434 __s_val_serverList, NULL },
436 {"NS_LDAP_SERVERS", NS_LDAP_SERVERS_P,
437 SERVERCONFIG, SERVLIST, FALSE, NS_LDAP_V2,
438 _P2_DEFAULTSERVER,
439 { SERVLIST, 0, NULL },
440 __s_val_serverList, NULL },
442 {"NS_LDAP_SEARCH_BASEDN", NS_LDAP_SEARCH_BASEDN_P,
443 SERVERCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
444 _P2_SEARCHBASEDN,
445 { CHARPTR, 0, NULL },
446 __s_val_basedn, NULL },
448 {"NS_LDAP_SEARCH_SCOPE", NS_LDAP_SEARCH_SCOPE_P,
449 CLIENTCONFIG, INT, TRUE, NS_LDAP_V2,
450 _P2_SEARCHSCOPE,
451 { INT, 0, INT2VOIDPTR(NS_LDAP_SCOPE_ONELEVEL) },
452 NULL, ns_scope_enum_v2 },
454 {"NS_LDAP_AUTH", NS_LDAP_AUTH_P,
455 CLIENTCONFIG, ARRAYAUTH, FALSE, NS_LDAP_V2,
456 _P2_AUTHMETHOD,
457 { ARRAYAUTH, 2, (void *)&ns_def_auth_v2[0] },
458 NULL, ns_auth_enum_v2 },
460 {"NS_LDAP_CREDENTIAL_LEVEL", NS_LDAP_CREDENTIAL_LEVEL_P,
461 CLIENTCONFIG, ARRAYCRED, FALSE, NS_LDAP_V2,
462 _P2_CREDENTIALLEVEL,
463 { ARRAYCRED, 0, (void *)&ns_def_cred_v2[0] },
464 NULL, ns_cred_enum_v2 },
466 {"NS_LDAP_SERVICE_SEARCH_DESC", NS_LDAP_SERVICE_SEARCH_DESC_P,
467 CLIENTCONFIG, SSDLIST, FALSE, NS_LDAP_V2,
468 _P2_SERVICESEARCHDESC,
469 { SSDLIST, 0, NULL },
470 NULL, NULL },
472 {"NS_LDAP_SEARCH_TIME", NS_LDAP_SEARCH_TIME_P,
473 CLIENTCONFIG, INT, TRUE, NS_LDAP_V2,
474 _P2_SEARCHTIMELIMIT,
475 { INT, 0, INT2VOIDPTR(NS_DEFAULT_SEARCH_TIMEOUT) },
476 NULL, NULL },
478 {"NS_LDAP_BIND_TIME", NS_LDAP_BIND_TIME_P,
479 CLIENTCONFIG, INT, TRUE, NS_LDAP_V2,
480 _P2_BINDTIMELIMIT,
481 { INT, 0, INT2VOIDPTR(NS_DEFAULT_BIND_TIMEOUT) },
482 NULL, NULL },
484 {"NS_LDAP_SEARCH_REF", NS_LDAP_SEARCH_REF_P,
485 CLIENTCONFIG, INT, TRUE, NS_LDAP_V2,
486 _P2_FOLLOWREFERRALS,
487 { INT, 0, INT2VOIDPTR(NS_LDAP_FOLLOWREF) },
488 NULL, ns_ref_enum_v2 },
490 {"NS_LDAP_CACHETTL", NS_LDAP_CACHETTL_P,
491 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
492 _P2_PROFILETTL,
493 { CHARPTR, 0, (void *)EXP_DEFAULT_TTL },
494 __s_val_postime, NULL },
496 {"NS_LDAP_ATTRIBUTEMAP", NS_LDAP_ATTRIBUTEMAP_P,
497 CLIENTCONFIG, ATTRMAP, FALSE, NS_LDAP_V2,
498 _P2_ATTRIBUTEMAP,
499 { ATTRMAP, 0, NULL },
500 NULL, NULL },
502 {"NS_LDAP_OBJECTCLASSMAP", NS_LDAP_OBJECTCLASSMAP_P,
503 CLIENTCONFIG, OBJMAP, FALSE, NS_LDAP_V2,
504 _P2_OBJECTCLASSMAP,
505 { OBJMAP, 0, NULL },
506 NULL, NULL },
508 {"NS_LDAP_PROFILE", NS_LDAP_PROFILE_P,
509 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
510 _P_CN,
511 { CHARPTR, 0, (void *)DEFAULTCONFIGNAME },
512 NULL, NULL },
514 {"NS_LDAP_SERVICE_AUTH_METHOD", NS_LDAP_SERVICE_AUTH_METHOD_P,
515 CLIENTCONFIG, SAMLIST, FALSE, NS_LDAP_V2,
516 _P2_SERVICEAUTHMETHOD,
517 { SAMLIST, 0, NULL },
518 NULL, NULL },
520 {"NS_LDAP_SERVICE_CRED_LEVEL", NS_LDAP_SERVICE_CRED_LEVEL_P,
521 CLIENTCONFIG, SCLLIST, FALSE, NS_LDAP_V2,
522 _P2_SERVICECREDLEVEL,
523 { SCLLIST, 0, NULL },
524 NULL, NULL },
526 {"NS_LDAP_HOST_CERTPATH", NS_LDAP_HOST_CERTPATH_P,
527 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
528 NULL, /* not defined in the Profile */
529 { CHARPTR, 0, (void *)NSLDAPDIRECTORY },
530 NULL, NULL },
532 /* array terminator [not an entry] */
533 {NULL, NS_LDAP_FILE_VERSION_P,
534 CLIENTCONFIG, NS_UNKNOWN, TRUE, 0,
535 NULL,
536 { NS_UNKNOWN, 0, NULL },
537 NULL, NULL },
540 static char *
541 __getdomainname()
544 * The sysinfo man page recommends using a buffer size
545 * of 257 bytes. MAXHOSTNAMELEN is 256. So add 1 here.
547 char buf[MAXHOSTNAMELEN + 1];
548 int status;
550 status = sysinfo(SI_SRPC_DOMAIN, buf, MAXHOSTNAMELEN);
551 if (status < 0)
552 return (NULL);
553 /* error: not enough space to hold returned value */
554 if (status > sizeof (buf))
555 return (NULL);
556 return (strdup(buf));
559 void
560 __ns_ldap_setServer(int set)
562 cache_server = set;
565 static boolean_t
566 timetorefresh(ns_config_t *cfg)
568 struct timeval tp;
569 static time_t expire = 0;
571 if (cfg == NULL || gettimeofday(&tp, NULL) == -1)
572 return (B_TRUE);
574 if (cfg->paramList[NS_LDAP_EXP_P].ns_ptype == TIMET)
575 expire = cfg->paramList[NS_LDAP_EXP_P].ns_tm;
576 else
577 return (B_TRUE);
579 return (expire != 0 && tp.tv_sec > expire);
583 __s_get_enum_value(ns_config_t *ptr, char *value, ParamIndexType i)
585 register ns_enum_map *mapp;
586 char *pstart = value;
587 char *pend;
588 int len;
590 if (pstart == NULL)
591 return (-1);
593 /* skip leading spaces */
594 while (*pstart == SPACETOK)
595 pstart++;
596 /* skip trailing spaces */
597 pend = pstart + strlen(pstart) - 1;
598 for (; pend >= pstart && *pend == SPACETOK; pend--)
600 len = pend - pstart + 1;
601 if (len == 0)
602 return (-1);
604 switch (i) {
605 case NS_LDAP_AUTH_P:
606 if (ptr->version == NS_LDAP_V1)
607 mapp = &ns_auth_enum_v1[0];
608 else
609 mapp = &ns_auth_enum_v2[0];
610 break;
611 case NS_LDAP_TRANSPORT_SEC_P:
612 return (-1);
613 case NS_LDAP_SEARCH_SCOPE_P:
614 if (ptr->version == NS_LDAP_V1)
615 mapp = &ns_scope_enum_v1[0];
616 else
617 mapp = &ns_scope_enum_v2[0];
618 break;
619 case NS_LDAP_SEARCH_REF_P:
620 if (ptr->version == NS_LDAP_V1)
621 mapp = &ns_ref_enum_v1[0];
622 else
623 mapp = &ns_ref_enum_v2[0];
624 break;
625 case NS_LDAP_PREF_ONLY_P:
626 mapp = &ns_pref_enum[0];
627 break;
628 case NS_LDAP_ENABLE_SHADOW_UPDATE_P:
629 mapp = &ns_shadow_update_enum[0];
630 break;
631 case NS_LDAP_CREDENTIAL_LEVEL_P:
632 if (ptr->version == NS_LDAP_V1)
633 return (-1);
634 else
635 mapp = &ns_cred_enum_v2[0];
636 break;
637 case NS_LDAP_SERVICE_AUTH_METHOD_P:
638 mapp = &ns_auth_enum_v2[0];
639 break;
640 case NS_LDAP_SERVICE_CRED_LEVEL_P:
641 mapp = &ns_cred_enum_v2[0];
642 break;
643 default:
644 return (-1);
647 for (; mapp->name != NULL; mapp++) {
648 if (strncasecmp(pstart, mapp->name, len) == 0 &&
649 (strlen(mapp->name) == len)) {
650 return (mapp->value);
653 return (-1);
656 char *
657 __s_get_auth_name(ns_config_t *ptr, AuthType_t type)
659 register ns_enum_map *mapp;
661 if (ptr->version == NS_LDAP_V1)
662 mapp = &ns_auth_enum_v1[0];
663 else
664 mapp = &ns_auth_enum_v2[0];
666 for (; mapp->name != NULL; mapp++) {
667 if (type == INT2AUTHENUM(mapp->value)) {
668 return (mapp->name);
671 return ("Unknown AuthType_t type specified");
675 char *
676 __s_get_security_name(ns_config_t *ptr, TlsType_t type)
678 register ns_enum_map *mapp;
680 if (ptr->version == NS_LDAP_V1) {
681 mapp = &ns_sec_enum_v1[0];
683 for (; mapp->name != NULL; mapp++) {
684 if (type == INT2SECENUM(mapp->value)) {
685 return (mapp->name);
689 return ("Unknown TlsType_t type specified");
693 char *
694 __s_get_scope_name(ns_config_t *ptr, ScopeType_t type)
696 register ns_enum_map *mapp;
698 if (ptr->version == NS_LDAP_V1)
699 mapp = &ns_scope_enum_v1[0];
700 else
701 mapp = &ns_scope_enum_v2[0];
703 for (; mapp->name != NULL; mapp++) {
704 if (type == INT2SCOPEENUM(mapp->value)) {
705 return (mapp->name);
708 return ("Unknown ScopeType_t type specified");
712 char *
713 __s_get_pref_name(PrefOnly_t type)
715 register ns_enum_map *mapp = &ns_pref_enum[0];
717 for (; mapp->name != NULL; mapp++) {
718 if (type == INT2PREFONLYENUM(mapp->value)) {
719 return (mapp->name);
722 return ("Unknown PrefOnly_t type specified");
725 char *
726 __s_get_searchref_name(ns_config_t *ptr, SearchRef_t type)
728 register ns_enum_map *mapp;
730 if (ptr->version == NS_LDAP_V1)
731 mapp = &ns_ref_enum_v1[0];
732 else
733 mapp = &ns_ref_enum_v2[0];
735 for (; mapp->name != NULL; mapp++) {
736 if (type == INT2SEARCHREFENUM(mapp->value)) {
737 return (mapp->name);
740 return ("Unknown SearchRef_t type specified");
743 char *
744 __s_get_shadowupdate_name(enableShadowUpdate_t type)
746 register ns_enum_map *mapp;
748 mapp = &ns_shadow_update_enum[0];
750 for (; mapp->name != NULL; mapp++) {
751 if (type == INT2SHADOWUPDATENUM(mapp->value)) {
752 return (mapp->name);
755 return ("Unknown enableShadowUpdate_t type specified");
758 static char *
759 __s_get_credlvl_name(ns_config_t *ptr, CredLevel_t type)
761 register ns_enum_map *mapp;
763 if (ptr->version == NS_LDAP_V2) {
764 mapp = &ns_cred_enum_v2[0];
765 for (; mapp->name != NULL; mapp++) {
766 if (type == INT2CREDLEVELENUM(mapp->value)) {
767 return (mapp->name);
771 return ("Unknown CredLevel_t type specified");
774 static void
775 destroy_param(ns_config_t *ptr, ParamIndexType type)
777 int i, j;
778 char **ppc;
780 if (ptr == NULL)
781 return;
784 * This routine is not lock protected because
785 * the config param it may be destroying is not
786 * necessarily THE config. Mutex protect elsewhere.
788 switch (ptr->paramList[type].ns_ptype) {
789 case CHARPTR:
790 if (ptr->paramList[type].ns_pc) {
791 free(ptr->paramList[type].ns_pc);
792 ptr->paramList[type].ns_pc = NULL;
794 break;
795 case SAMLIST:
796 case SCLLIST:
797 case SSDLIST:
798 case ARRAYCP:
799 case SERVLIST:
800 if (ptr->paramList[type].ns_ppc) {
801 ppc = ptr->paramList[type].ns_ppc;
802 j = ptr->paramList[type].ns_acnt;
803 for (i = 0; i < j && ppc[i] != NULL; i++) {
804 free((void *)ppc[i]);
806 free((void *)ppc);
807 ptr->paramList[type].ns_ppc = NULL;
809 break;
810 case ARRAYAUTH:
811 case ARRAYCRED:
812 if (ptr->paramList[type].ns_pi) {
813 free(ptr->paramList[type].ns_pi);
814 ptr->paramList[type].ns_pi = NULL;
816 break;
817 case INT:
818 ptr->paramList[type].ns_i = 0;
819 break;
820 case ATTRMAP:
821 break;
822 case OBJMAP:
823 break;
824 default:
825 break;
827 ptr->paramList[type].ns_ptype = NS_UNKNOWN;
830 static void
831 destroy_config(ns_config_t *ptr)
833 ParamIndexType i;
835 if (ptr != NULL) {
836 if (ptr == current_config)
837 current_config = NULL;
838 free(ptr->domainName);
839 ptr->domainName = NULL;
840 for (i = 0; i <= LAST_VALUE; i++) {
841 destroy_param(ptr, i);
843 __s_api_destroy_hash(ptr);
844 free(ptr);
849 * Marks the ns_config_t to be deleted and then releases it. (If no other
850 * caller is using, then __s_api_release_config will destroy it.)
852 * Note that __s_api_destroy_config should only be called if the caller has
853 * created the ns_config_t with __s_api_create_config (with the exception
854 * of set_curr_config). The ns_config_t should be private to the caller.
856 * This function should not be called with the current_config except by
857 * set_curr_config which locks ns_parse_lock to ensure that no thread
858 * will be waiting on current_config->config_mutex. This ensures that
859 * no caller with be waiting on cfg->config_mutex while it is being
860 * destroyed by __s_api_release_config.
863 void
864 __s_api_destroy_config(ns_config_t *cfg)
866 if (cfg != NULL) {
867 (void) mutex_lock(&cfg->config_mutex);
868 cfg->delete = TRUE;
869 (void) mutex_unlock(&cfg->config_mutex);
870 __s_api_release_config(cfg);
876 * Increment the configuration use count by one - assumes ns_parse_lock has
877 * been obtained.
880 static ns_config_t *
881 get_curr_config_unlocked(ns_config_t *cfg, boolean_t global)
883 ns_config_t *ret;
885 ret = cfg;
886 if (cfg != NULL) {
887 (void) mutex_lock(&cfg->config_mutex);
889 * allow access to per connection management (non-global)
890 * config so operations on connection being closed can still
891 * be completed
893 if (cfg->delete && global == B_TRUE)
894 ret = NULL;
895 else
896 cfg->nUse++;
897 (void) mutex_unlock(&cfg->config_mutex);
899 return (ret);
903 * set_curr_config_global sets the current global config to the
904 * specified ns_config_t. Note that this function is similar
905 * to the project private function __s_api_init_config_global
906 * except that it does not release the new ns_config_t.
908 static void
909 set_curr_config_global(ns_config_t *ptr)
911 ns_config_t *cfg;
912 ns_config_t *cur_cfg;
914 (void) mutex_lock(&ns_parse_lock);
915 cur_cfg = current_config;
916 cfg = get_curr_config_unlocked(cur_cfg, B_TRUE);
917 if (cfg != ptr) {
918 __s_api_destroy_config(cfg);
919 current_config = ptr;
921 (void) mutex_unlock(&ns_parse_lock);
926 * set_curr_config sets the current config or the per connection
927 * management one to the specified ns_config_t. Note that this function
928 * is similar to the project private function __s_api_init_config
929 * except that it does not release the new ns_config_t. Also note
930 * that if there's no per connection management one to set, the
931 * global current config will be set.
934 static void
935 set_curr_config(ns_config_t *ptr)
937 ns_config_t *cfg;
938 ns_config_t *cur_cfg;
939 ns_conn_mgmt_t *cmg;
940 int rc;
942 rc = thr_getspecific(ns_cmgkey, (void **)&cmg);
944 /* set the per connection management config if possible */
945 if (rc == 0 && cmg != NULL && cmg->config != NULL) {
946 (void) mutex_lock(&cmg->cfg_lock);
947 cur_cfg = cmg->config;
948 cfg = get_curr_config_unlocked(cur_cfg, B_FALSE);
949 if (cfg != ptr) {
950 __s_api_destroy_config(cfg);
951 cmg->config = ptr;
953 (void) mutex_unlock(&cmg->cfg_lock);
954 return;
957 /* else set the global current config */
958 set_curr_config_global(ptr);
962 * Decrements the ns_config_t usage count by one. Delete if delete flag
963 * is set and no other callers are using.
966 void
967 __s_api_release_config(ns_config_t *cfg)
969 if (cfg != NULL) {
970 (void) mutex_lock(&cfg->config_mutex);
971 cfg->nUse--;
972 if (cfg->nUse == 0 && cfg->delete) {
973 destroy_config(cfg);
974 } else
975 (void) mutex_unlock(&cfg->config_mutex);
980 * __s_api_init_config function destroys the previous global configuration
981 * sets the new global configuration and then releases it
983 void
984 __s_api_init_config_global(ns_config_t *ptr)
986 set_curr_config_global(ptr);
987 __s_api_release_config(ptr);
991 * __s_api_init_config function destroys the previous configuration
992 * sets the new configuration and then releases it. The configuration
993 * may be the global one or the per connection management one.
995 void
996 __s_api_init_config(ns_config_t *ptr)
998 set_curr_config(ptr);
999 __s_api_release_config(ptr);
1004 * Create an ns_config_t, set the usage count to one
1007 ns_config_t *
1008 __s_api_create_config(void)
1010 ns_config_t *ret;
1011 ret = (ns_config_t *)calloc(1, sizeof (ns_config_t));
1012 if (ret == NULL)
1013 return (NULL);
1015 ret->domainName = __getdomainname();
1016 if (ret->domainName == NULL) {
1017 free(ret);
1018 return (NULL);
1020 ret->version = NS_LDAP_V1;
1021 (void) mutex_init(&ret->config_mutex, USYNC_THREAD, NULL);
1022 ret->nUse = 1;
1023 ret->delete = B_FALSE;
1024 return (ret);
1028 * __s_api_get_default_config_global returns the current global config
1030 ns_config_t *
1031 __s_api_get_default_config_global(void)
1033 ns_config_t *cfg;
1034 ns_config_t *cur_cfg;
1036 (void) mutex_lock(&ns_parse_lock);
1037 cur_cfg = current_config;
1038 cfg = get_curr_config_unlocked(cur_cfg, B_TRUE);
1039 (void) mutex_unlock(&ns_parse_lock);
1041 return (cfg);
1045 * __s_api_get_default_config returns the current global config or the
1046 * per connection management one.
1048 ns_config_t *
1049 __s_api_get_default_config(void)
1051 ns_config_t *cfg;
1052 ns_config_t *cur_cfg;
1053 ns_conn_mgmt_t *cmg;
1054 int rc;
1056 rc = thr_getspecific(ns_cmgkey, (void **)&cmg);
1058 /* get the per connection management config if available */
1059 if (rc == 0 && cmg != NULL && cmg->config != NULL) {
1060 (void) mutex_lock(&cmg->cfg_lock);
1061 cur_cfg = cmg->config;
1062 cfg = get_curr_config_unlocked(cur_cfg, B_FALSE);
1063 (void) mutex_unlock(&cmg->cfg_lock);
1064 return (cfg);
1067 /* else get the global current config */
1068 return (__s_api_get_default_config_global());
1071 static char *
1072 stripdup(const char *instr)
1074 char *pstart = (char *)instr;
1075 char *pend, *ret;
1076 int len;
1078 if (pstart == NULL)
1079 return (NULL);
1080 /* remove leading spaces */
1081 while (*pstart == SPACETOK)
1082 pstart++;
1083 /* remove trailing spaces */
1084 pend = pstart + strlen(pstart) - 1;
1085 for (; pend >= pstart && *pend == SPACETOK; pend--)
1087 len = pend - pstart + 1;
1088 if ((ret = malloc(len + 1)) == NULL)
1089 return (NULL);
1090 if (len != 0) {
1091 (void) strncpy(ret, pstart, len);
1093 ret[len] = '\0';
1094 return (ret);
1098 * Note that __s_api_crosscheck is assumed to be called with an ns_config_t
1099 * that is properly protected - so that it will not change during the
1100 * duration of the call
1103 /* Size of errstr needs to be MAXERROR */
1104 ns_parse_status
1105 __s_api_crosscheck(ns_config_t *ptr, char *errstr, int check_dn)
1107 int value, j;
1108 time_t tm;
1109 const char *str, *str1;
1110 int i, cnt;
1111 int self, gssapi;
1113 if (ptr == NULL)
1114 return (NS_SUCCESS);
1116 /* check for no server specified */
1117 if (ptr->paramList[NS_LDAP_SERVERS_P].ns_ppc == NULL) {
1118 if (ptr->version == NS_LDAP_V1) {
1119 str = NULL_OR_STR(__s_api_get_configname(
1120 NS_LDAP_SERVERS_P));
1121 (void) snprintf(errstr, MAXERROR,
1122 gettext("Configuration Error: No entry for "
1123 "'%s' found"), str);
1124 return (NS_PARSE_ERR);
1125 } else if (ptr->paramList[NS_LDAP_SERVER_PREF_P].ns_ppc ==
1126 NULL) {
1127 str = NULL_OR_STR(__s_api_get_configname(
1128 NS_LDAP_SERVERS_P));
1129 str1 = NULL_OR_STR(__s_api_get_configname(
1130 NS_LDAP_SERVER_PREF_P));
1131 (void) snprintf(errstr, MAXERROR,
1132 gettext("Configuration Error: "
1133 "Neither '%s' nor '%s' is defined"), str, str1);
1134 return (NS_PARSE_ERR);
1137 if (ptr->paramList[NS_LDAP_CERT_PASS_P].ns_pc != NULL &&
1138 ptr->paramList[NS_LDAP_CERT_PATH_P].ns_pc == NULL) {
1139 str = NULL_OR_STR(__s_api_get_configname(
1140 NS_LDAP_CERT_PASS_P));
1141 str1 = NULL_OR_STR(__s_api_get_configname(
1142 NS_LDAP_CERT_PATH_P));
1143 (void) snprintf(errstr, MAXERROR,
1144 gettext("Configuration Error: %s specified "
1145 "but no value for '%s' found"), str, str1);
1146 return (NS_PARSE_ERR);
1148 if (ptr->paramList[NS_LDAP_CERT_PASS_P].ns_pc == NULL &&
1149 ptr->paramList[NS_LDAP_CERT_PATH_P].ns_pc != NULL) {
1150 str = NULL_OR_STR(__s_api_get_configname(
1151 NS_LDAP_CERT_PATH_P));
1152 str1 = NULL_OR_STR(__s_api_get_configname(
1153 NS_LDAP_CERT_PASS_P));
1154 (void) snprintf(errstr, MAXERROR,
1155 gettext("Configuration Error: %s specified "
1156 "but no value for '%s' found"), str, str1);
1157 return (NS_PARSE_ERR);
1159 /* check if search basedn has been specified */
1160 if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ppc == NULL) {
1161 str = NULL_OR_STR(__s_api_get_configname(
1162 NS_LDAP_SEARCH_BASEDN_P));
1163 (void) snprintf(errstr, MAXERROR,
1164 gettext("Configuration Error: No entry for "
1165 "'%s' found"), str);
1166 return (NS_PARSE_ERR);
1169 if (check_dn) {
1170 /* check for auth value....passwd/bindn if necessary */
1172 for (j = 0; ptr->paramList[NS_LDAP_AUTH_P].ns_pi != NULL &&
1173 ptr->paramList[NS_LDAP_AUTH_P].ns_pi[j] != 0; j++) {
1174 value = ptr->paramList[NS_LDAP_AUTH_P].ns_pi[j];
1175 switch (value) {
1176 case NS_LDAP_EA_SIMPLE:
1177 case NS_LDAP_EA_SASL_CRAM_MD5:
1178 case NS_LDAP_EA_SASL_DIGEST_MD5:
1179 case NS_LDAP_EA_SASL_DIGEST_MD5_INT:
1180 case NS_LDAP_EA_SASL_DIGEST_MD5_CONF:
1181 case NS_LDAP_EA_TLS_SIMPLE:
1182 case NS_LDAP_EA_TLS_SASL_CRAM_MD5:
1183 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5:
1184 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT:
1185 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF:
1186 if (ptr->paramList[NS_LDAP_BINDDN_P].ns_ppc == NULL) {
1187 str = NULL_OR_STR(__s_api_get_configname(
1188 NS_LDAP_BINDDN_P));
1189 (void) snprintf(errstr, MAXERROR,
1190 gettext("Configuration Error: No entry for "
1191 "'%s' found"), str);
1192 return (NS_PARSE_ERR);
1194 if (ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ppc
1195 == NULL) {
1196 str = NULL_OR_STR(__s_api_get_configname(
1197 NS_LDAP_BINDPASSWD_P));
1198 (void) snprintf(errstr, MAXERROR,
1199 gettext("Configuration Error: No entry for "
1200 "'%s' found"), str);
1201 return (NS_PARSE_ERR);
1203 break;
1209 * If NS_LDAP_CACHETTL is not specified,
1210 * init NS_LDAP_EXP_P here. Otherwise,
1211 * ldap_cachemgr will never refresh the profile.
1212 * Set it to current time + default
1213 * NS_LDAP_CACHETTL
1215 if (ptr->paramList[NS_LDAP_CACHETTL_P].ns_pc == NULL) {
1216 tm = conv_time(
1217 defconfig[NS_LDAP_CACHETTL_P].defval.ns_pc);
1218 ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET;
1219 if (tm != 0) {
1220 tm += time(NULL);
1222 ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm;
1225 * If credential level self is defined, there should be
1226 * at least an auth method sasl/GSSAPI and vice versa.
1228 self = 0;
1229 cnt = ptr->paramList[NS_LDAP_CREDENTIAL_LEVEL_P].ns_acnt;
1230 for (i = 0; i < cnt; i++) {
1231 if (ptr->paramList[NS_LDAP_CREDENTIAL_LEVEL_P].ns_pi[i] ==
1232 NS_LDAP_CRED_SELF)
1233 self++;
1235 gssapi = 0;
1236 cnt = ptr->paramList[NS_LDAP_AUTH_P].ns_acnt;
1237 for (i = 0; i < cnt; i++) {
1238 if (ptr->paramList[NS_LDAP_AUTH_P].ns_pi[i] ==
1239 NS_LDAP_EA_SASL_GSSAPI)
1240 gssapi++;
1242 if (gssapi == 0 && self > 0) {
1243 (void) snprintf(errstr, MAXERROR,
1244 gettext("Configuration Error: "
1245 "Credential level self requires "
1246 "authentication method sasl/GSSAPI"));
1247 return (NS_PARSE_ERR);
1249 if (gssapi > 0 && self == 0) {
1250 (void) snprintf(errstr, MAXERROR,
1251 gettext("Configuration Error: "
1252 "Authentication method sasl/GSSAPI "
1253 "requires credential level self"));
1254 return (NS_PARSE_ERR);
1256 return (NS_SUCCESS);
1261 __s_api_get_type(const char *value, ParamIndexType *type)
1263 int i;
1265 for (i = 0; defconfig[i].name != NULL; i++) {
1266 if (strcasecmp(defconfig[i].name, value) == 0) {
1267 *type = defconfig[i].index;
1268 return (0);
1271 return (-1);
1275 * Externally defined version of get_type.
1276 * Includes extra error checking
1280 __ns_ldap_getParamType(const char *value, ParamIndexType *type)
1282 if (value == NULL || type == NULL)
1283 return (-1);
1284 return (__s_api_get_type(value, type));
1288 __s_api_get_versiontype(ns_config_t *ptr, char *value, ParamIndexType *type)
1290 ns_version_t ver;
1291 int i;
1293 if (ptr == NULL)
1294 return (-1);
1296 ver = ptr->version;
1298 for (i = 0; defconfig[i].name != NULL; i++) {
1299 if (strcasecmp(defconfig[i].name, value) == 0) {
1300 if (defconfig[i].version == ver) {
1301 *type = defconfig[i].index;
1302 return (0);
1306 return (-1);
1310 __s_api_get_profiletype(char *value, ParamIndexType *type)
1312 int i;
1314 for (i = 0; defconfig[i].name != NULL; i++) {
1315 if (defconfig[i].profile_name == NULL)
1316 continue;
1317 if (strcasecmp(defconfig[i].profile_name, value) == 0) {
1318 *type = defconfig[i].index;
1319 return (0);
1322 return (-1);
1326 __s_api_get_configtype(ParamIndexType type)
1328 int i;
1330 for (i = 0; defconfig[i].name != NULL; i++) {
1331 if (defconfig[i].index == type) {
1332 return (defconfig[i].config_type);
1335 return (-1);
1338 const char *
1339 __s_api_get_configname(ParamIndexType type)
1341 int i;
1343 for (i = 0; defconfig[i].name != NULL; i++) {
1344 if (defconfig[i].index == type) {
1345 if (defconfig[i].name[0] == '\0')
1346 return (NULL);
1347 else
1348 return (defconfig[i].name);
1351 return (NULL);
1354 static ns_default_config *
1355 get_defconfig(ns_config_t *ptr, ParamIndexType type)
1357 ns_version_t ver;
1358 int i;
1360 ver = ptr->version;
1362 for (i = 0; defconfig[i].name != NULL; i++) {
1363 if (defconfig[i].index == type &&
1364 defconfig[i].version == ver) {
1365 return (&defconfig[i]);
1368 return (NULL);
1371 static int
1372 set_default_value(ns_config_t *configptr, char *name,
1373 char *value, ns_ldap_error_t **error)
1375 ParamIndexType i;
1376 int ret;
1377 char errstr[MAXERROR];
1379 if (__s_api_get_type(name, &i) < 0) {
1380 (void) snprintf(errstr, sizeof (errstr), gettext(
1381 "Illegal type name (%s).\n"), name);
1382 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
1384 return (NS_LDAP_CONFIG);
1387 if (i != NS_LDAP_SERVERS_P &&
1388 i != NS_LDAP_SERVICE_AUTH_METHOD_P &&
1389 i != NS_LDAP_SERVICE_CRED_LEVEL_P &&
1390 i != NS_LDAP_SERVICE_SEARCH_DESC_P &&
1391 i != NS_LDAP_SERVER_PREF_P &&
1392 i != NS_LDAP_SEARCH_DN_P) {
1393 if (configptr->paramList[i].ns_ptype != NS_UNKNOWN) {
1394 destroy_param(configptr, i);
1398 ret = __ns_ldap_setParamValue(configptr, i, value, error);
1399 return (ret);
1404 * Initialize config to a default state
1405 * By default leave configuration empty
1406 * getParam will automatically get the
1407 * appropriate default value if none exists
1410 void
1411 __ns_ldap_default_config()
1413 ns_config_t *ptr;
1415 ptr = __s_api_create_config();
1416 if (ptr == NULL)
1417 return;
1419 set_curr_config(ptr);
1420 __s_api_release_config(ptr);
1424 * Get the current configuration pointer and return it.
1425 * If necessary initialize or refresh the current
1426 * configuration as applicable. If global is set, returns
1427 * the global one.
1430 static ns_config_t *
1431 loadrefresh_config(boolean_t global)
1433 ns_config_t *cfg;
1434 ns_config_t *new_cfg;
1435 ns_ldap_error_t *errorp;
1437 /* We want to refresh only one configuration at a time */
1438 (void) mutex_lock(&ns_loadrefresh_lock);
1439 if (global == B_TRUE)
1440 cfg = __s_api_get_default_config_global();
1441 else
1442 cfg = __s_api_get_default_config();
1444 /* (re)initialize configuration if necessary */
1445 if (!__s_api_isStandalone() && timetorefresh(cfg)) {
1446 new_cfg = LoadCacheConfiguration(cfg, &errorp);
1447 if (new_cfg != NULL && new_cfg != cfg) {
1448 __s_api_release_config(cfg);
1449 if (global == B_TRUE)
1450 set_curr_config_global(new_cfg);
1451 else
1452 set_curr_config(new_cfg);
1453 cfg = new_cfg;
1455 if (errorp != NULL)
1456 (void) __ns_ldap_freeError(&errorp);
1458 (void) mutex_unlock(&ns_loadrefresh_lock);
1459 return (cfg);
1463 * Get the current global configuration pointer and return it.
1464 * If necessary initialize or refresh the current
1465 * configuration as applicable.
1468 ns_config_t *
1469 __s_api_loadrefresh_config_global()
1471 return (loadrefresh_config(B_TRUE));
1475 * Get the current configuration pointer and return it.
1476 * If necessary initialize or refresh the current
1477 * configuration as applicable. The configuration may
1478 * be the global one or the per connection management one.
1481 ns_config_t *
1482 __s_api_loadrefresh_config()
1484 return (loadrefresh_config(B_FALSE));
1488 * In general this routine is not very usefull. Individual routines can be
1489 * created to do this job. Once that is done, this function can be removed.
1490 * Size of errstr buffer needs to be MAXERROR.
1492 static ns_parse_status
1493 verify_value(ns_config_t *cfg, char *name, char *value, char *errstr)
1495 ParamIndexType index = 0;
1496 int found = 0, j;
1497 char *ptr = NULL, *strptr = NULL, buffer[BUFSIZE];
1498 char *rest;
1499 ns_default_config *def = NULL;
1501 if (__s_api_get_type(name, &index) != 0) {
1502 (void) snprintf(errstr, MAXERROR,
1503 gettext("Unknown keyword encountered '%s'."), name);
1504 return (NS_PARSE_ERR);
1507 def = get_defconfig(cfg, index);
1509 /* eat up beginning quote, if any */
1510 while (value != NULL && (*value == QUOTETOK || *value == SPACETOK))
1511 value++;
1513 /* eat up space/quote at end of value */
1514 if (strlen(value) > 0)
1515 ptr = value + strlen(value) - 1;
1516 else
1517 ptr = value;
1518 for (; ptr != value && (*ptr == SPACETOK || *ptr == QUOTETOK); ptr--) {
1519 *ptr = '\0';
1522 switch (index) {
1523 case NS_LDAP_EXP_P:
1524 case NS_LDAP_CACHETTL_P:
1525 case NS_LDAP_CERT_PATH_P:
1526 case NS_LDAP_CERT_PASS_P:
1527 case NS_LDAP_CERT_NICKNAME_P:
1528 case NS_LDAP_BINDDN_P:
1529 case NS_LDAP_BINDPASSWD_P:
1530 case NS_LDAP_ADMIN_BINDDN_P:
1531 case NS_LDAP_ADMIN_BINDPASSWD_P:
1532 case NS_LDAP_DOMAIN_P:
1533 case NS_LDAP_SEARCH_BASEDN_P:
1534 case NS_LDAP_SEARCH_TIME_P:
1535 case NS_LDAP_PROFILE_P:
1536 case NS_LDAP_AUTH_P:
1537 case NS_LDAP_SEARCH_SCOPE_P:
1538 case NS_LDAP_CREDENTIAL_LEVEL_P:
1539 case NS_LDAP_SERVICE_SEARCH_DESC_P:
1540 case NS_LDAP_BIND_TIME_P:
1541 case NS_LDAP_ATTRIBUTEMAP_P:
1542 case NS_LDAP_OBJECTCLASSMAP_P:
1543 case NS_LDAP_SERVICE_AUTH_METHOD_P:
1544 case NS_LDAP_SERVICE_CRED_LEVEL_P:
1545 case NS_LDAP_HOST_CERTPATH_P:
1546 break;
1547 case NS_LDAP_SEARCH_DN_P:
1548 /* depreciated because of service descriptors */
1549 /* Parse as appropriate at descriptor create time */
1550 break;
1551 case NS_LDAP_FILE_VERSION_P:
1552 if (value != NULL &&
1553 strcasecmp(value, NS_LDAP_VERSION_1) != 0 &&
1554 strcasecmp(value, NS_LDAP_VERSION_2) != 0) {
1555 (void) snprintf(errstr, MAXERROR,
1556 gettext("Version mismatch, expected "
1557 "cache version '%s' or '%s' but "
1558 "encountered version '%s'."),
1559 NS_LDAP_VERSION_1,
1560 NS_LDAP_VERSION_2, value);
1561 return (NS_PARSE_ERR);
1563 break;
1564 case NS_LDAP_SERVERS_P:
1565 case NS_LDAP_SERVER_PREF_P:
1566 (void) strcpy(buffer, value);
1567 strptr = strtok_r(buffer, ",", &rest);
1568 while (strptr != NULL) {
1569 char *tmp = NULL;
1570 tmp = stripdup(strptr);
1571 if (tmp == NULL || (strchr(tmp, ' ') != NULL)) {
1572 (void) snprintf(errstr, MAXERROR,
1573 gettext("Invalid parameter values "
1574 "'%s' specified for keyword '%s'."),
1575 tmp, name);
1576 free(tmp);
1577 return (NS_PARSE_ERR);
1579 free(tmp);
1580 strptr = strtok_r(NULL, ",", &rest);
1582 break;
1583 default:
1584 found = 0; j = 0;
1585 while (def->allowed != NULL &&
1586 def->allowed[j].name != NULL && j < DEFMAX) {
1587 if (strcmp(def->allowed[j].name,
1588 value) == 0) {
1589 found = 1;
1590 break;
1592 j++;
1594 if (!found) {
1595 (void) snprintf(errstr, MAXERROR,
1596 gettext("Invalid option specified for "
1597 "'%s' keyword. '%s' is not a recognized "
1598 "keyword value."), name, value);
1599 return (NS_PARSE_ERR);
1603 return (NS_SUCCESS);
1606 void
1607 __s_api_split_key_value(char *buffer, char **name, char **value)
1609 char *ptr;
1611 *name = buffer;
1612 /* split into name value pair */
1613 if ((ptr = strchr(buffer, TOKENSEPARATOR)) != NULL) {
1614 *ptr = '\0';
1615 ptr++;
1616 /* trim whitespace */
1617 while (*ptr == SPACETOK)
1618 ptr++;
1619 *value = ptr;
1624 * Set a parameter value in a generic configuration structure
1625 * Assume any necessary locks are in place. This routine would
1626 * be better named: __ns_ldap_translateString2Param
1628 * This routine translates external string format into internal
1629 * param format and saves the result in the param table.
1632 __ns_ldap_setParamValue(ns_config_t *ptr, const ParamIndexType type,
1633 const void *data, ns_ldap_error_t **error)
1635 ns_default_config *def = NULL;
1636 ns_param_t conf;
1637 ns_mapping_t *map, *rmap;
1638 int i, j, len;
1639 char *cp, *cp2, *end;
1640 char *tcp = NULL;
1641 char errstr[2 * MAXERROR];
1642 char tbuf[100], *ptbuf;
1643 char *sid, *origA, **mapA;
1644 char **attr;
1645 time_t tm;
1646 int free_memory, exitrc;
1647 char **p;
1649 /* Find ParamIndexType default configuration data */
1650 def = get_defconfig(ptr, type);
1651 if (def == NULL) {
1652 (void) snprintf(errstr, sizeof (errstr),
1653 gettext("Unable to set value: "
1654 "invalid ParamIndexType (%d)"), type);
1655 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
1657 return (NS_LDAP_CONFIG);
1660 (void) memset(&conf, 0, sizeof (conf));
1662 /* data is actually const char */
1663 cp = (char *)data;
1665 /* eat up beginning quote, if any */
1666 while (cp && (*cp == QUOTETOK || *cp == SPACETOK))
1667 cp++;
1669 /* eat up space/quote at end of value */
1670 end = cp2 = cp + strlen(cp) - 1;
1671 for (; cp2 > cp && (*cp2 == SPACETOK || *cp2 == QUOTETOK); cp2--)
1673 /* data is const, must duplicate */
1674 if (cp2 != end) {
1675 tcp = (char *)calloc((int)(cp2 - cp + 2), sizeof (char));
1676 if (tcp == NULL)
1677 return (NS_LDAP_MEMORY);
1678 end = cp2;
1679 cp2 = tcp;
1680 while (cp <= end) {
1681 *cp2++ = *cp++;
1683 *cp2 = '\0';
1684 cp = tcp;
1687 /* Parse data according to type */
1688 switch (def->data_type) {
1689 case INT:
1690 switch (def->index) {
1691 case NS_LDAP_PREF_ONLY_P:
1692 case NS_LDAP_SEARCH_REF_P:
1693 case NS_LDAP_SEARCH_SCOPE_P:
1694 case NS_LDAP_ENABLE_SHADOW_UPDATE_P:
1695 i = __s_get_enum_value(ptr, cp, def->index);
1696 if (i < 0) {
1697 (void) snprintf(errstr, sizeof (errstr),
1698 gettext("Unable to set value: "
1699 "invalid %s (%d)"), def->name,
1700 def->index);
1701 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1702 strdup(errstr), 0);
1703 free(tcp);
1704 return (NS_LDAP_CONFIG);
1706 conf.ns_i = i;
1707 break;
1708 case NS_LDAP_TRANSPORT_SEC_P: /* ignore TRANSPORT_SEC */
1709 break;
1710 default:
1711 cp2 = cp;
1712 if ((*cp2 == '+') || (*cp2 == '-'))
1713 cp2++;
1714 for (/* empty */; *cp2; cp2++) {
1715 if (isdigit(*cp2))
1716 continue;
1718 (void) snprintf(errstr, sizeof (errstr),
1719 gettext("Unable to set value: "
1720 "invalid %s (%d)"), def->name,
1721 def->index);
1722 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1723 strdup(errstr), 0);
1724 free(tcp);
1725 return (NS_LDAP_CONFIG);
1727 i = atoi(cp);
1728 conf.ns_i = i;
1729 break;
1731 break;
1732 case TIMET:
1733 /* Do nothing with a TIMET. Initialize it below */
1734 break;
1735 case CHARPTR:
1736 conf.ns_pc = (char *)strdup(cp);
1737 if (conf.ns_pc == NULL) {
1738 free(tcp);
1739 return (NS_LDAP_MEMORY);
1741 break;
1742 case SAMLIST:
1743 /* first check to see if colon (:) is there */
1744 if ((strchr(cp, COLONTOK)) == NULL) {
1745 (void) snprintf(errstr, sizeof (errstr),
1746 gettext("Unable to set value: "
1747 "invalid serviceAuthenticationMethod (%s)"),
1748 cp);
1749 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1750 strdup(errstr), 0);
1751 free(tcp);
1752 return (NS_LDAP_CONFIG);
1754 /* Appends an entry to the existing list */
1755 if (ptr->paramList[type].ns_ptype != SAMLIST) {
1756 conf.ns_ppc = (char **)calloc(2, sizeof (char *));
1757 if (conf.ns_ppc == NULL) {
1758 free(tcp);
1759 return (NS_LDAP_MEMORY);
1761 conf.ns_acnt = 1;
1762 conf.ns_ppc[0] = (char *)strdup(cp);
1763 if (conf.ns_ppc[0] == NULL) {
1764 free(conf.ns_ppc);
1765 free(tcp);
1766 return (NS_LDAP_MEMORY);
1768 } else {
1769 char *dp, *dpend;
1770 int fnd = 0;
1772 /* Attempt to replace if possible */
1773 dpend = strchr(cp, COLONTOK);
1774 len = dpend - cp;
1775 dp = (char *)malloc(len+1);
1776 if (dp == NULL) {
1777 free(tcp);
1778 return (NS_LDAP_MEMORY);
1780 (void) strlcpy(dp, cp, len+1);
1781 fnd = 0;
1782 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) {
1783 dpend = strchr(ptr->paramList[type].ns_ppc[j],
1784 COLONTOK);
1785 if (dpend == NULL)
1786 continue;
1787 i = dpend - ptr->paramList[type].ns_ppc[j];
1788 if (i != len)
1789 continue;
1790 if (strncmp(ptr->paramList[type].ns_ppc[j],
1791 dp, len) == 0) {
1792 conf.ns_acnt =
1793 ptr->paramList[type].ns_acnt;
1794 conf.ns_ppc =
1795 ptr->paramList[type].ns_ppc;
1796 ptr->paramList[type].ns_ppc = NULL;
1797 free(conf.ns_ppc[j]);
1798 conf.ns_ppc[j] = (char *)strdup(cp);
1799 if (conf.ns_ppc[j] == NULL) {
1800 free(dp);
1801 __s_api_free2dArray
1802 (conf.ns_ppc);
1803 free(tcp);
1804 return (NS_LDAP_MEMORY);
1806 fnd = 1;
1807 break;
1810 free(dp);
1812 if (fnd)
1813 break; /* Replaced completed */
1815 /* Append */
1816 len = ptr->paramList[type].ns_acnt + 1;
1817 if (len > 1) {
1818 p = (char **)dupParam(&ptr->paramList[type]);
1819 if (p == NULL) {
1820 free(tcp);
1821 return (NS_LDAP_MEMORY);
1823 } else
1824 p = NULL;
1825 conf.ns_ppc =
1826 reallocarray(p, len + 1, sizeof (char *));
1827 if (conf.ns_ppc == NULL) {
1828 __s_api_free2dArray(p);
1829 free(tcp);
1830 return (NS_LDAP_MEMORY);
1832 conf.ns_acnt = len;
1833 conf.ns_ppc[len-1] = (char *)strdup(cp);
1834 if (conf.ns_ppc[len-1] == NULL) {
1835 __s_api_free2dArray(conf.ns_ppc);
1836 free(tcp);
1837 return (NS_LDAP_MEMORY);
1839 conf.ns_ppc[len] = NULL;
1841 break;
1842 case SCLLIST:
1843 /* first check to see if colon (:) is there */
1844 if ((strchr(cp, COLONTOK)) == NULL) {
1845 (void) snprintf(errstr, sizeof (errstr),
1846 gettext("Unable to set value: "
1847 "invalid serviceCredentialLevel (%s)"),
1848 cp);
1849 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1850 strdup(errstr), 0);
1851 free(tcp);
1852 return (NS_LDAP_CONFIG);
1854 /* Appends an entry to the existing list */
1855 if (ptr->paramList[type].ns_ptype != SCLLIST) {
1856 conf.ns_ppc = (char **)calloc(2, sizeof (char *));
1857 if (conf.ns_ppc == NULL) {
1858 free(tcp);
1859 return (NS_LDAP_MEMORY);
1861 conf.ns_acnt = 1;
1862 conf.ns_ppc[0] = (char *)strdup(cp);
1863 if (conf.ns_ppc[0] == NULL) {
1864 free(conf.ns_ppc);
1865 free(tcp);
1866 return (NS_LDAP_MEMORY);
1868 } else {
1869 char *dp, *dpend;
1870 int fnd = 0;
1872 /* Attempt to replace if possible */
1873 dpend = strchr(cp, COLONTOK);
1874 len = dpend - cp;
1875 dp = (char *)malloc(len+1);
1876 if (dp == NULL) {
1877 free(tcp);
1878 return (NS_LDAP_MEMORY);
1880 (void) strlcpy(dp, cp, len+1);
1881 fnd = 0;
1882 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) {
1883 dpend = strchr(ptr->paramList[type].ns_ppc[j],
1884 COLONTOK);
1885 if (dpend == NULL)
1886 continue;
1887 i = dpend - ptr->paramList[type].ns_ppc[j];
1888 if (i != len)
1889 continue;
1890 if (strncmp(ptr->paramList[type].ns_ppc[j],
1891 dp, len) == 0) {
1892 conf.ns_acnt =
1893 ptr->paramList[type].ns_acnt;
1894 conf.ns_ppc =
1895 ptr->paramList[type].ns_ppc;
1896 ptr->paramList[type].ns_ppc = NULL;
1897 free(conf.ns_ppc[j]);
1898 conf.ns_ppc[j] = (char *)strdup(cp);
1899 if (conf.ns_ppc[j] == NULL) {
1900 free(dp);
1901 __s_api_free2dArray
1902 (conf.ns_ppc);
1903 free(tcp);
1904 return (NS_LDAP_MEMORY);
1906 fnd = 1;
1907 break;
1910 free(dp);
1912 if (fnd)
1913 break; /* Replaced completed */
1915 /* Append */
1916 len = ptr->paramList[type].ns_acnt + 1;
1917 if (len > 1) {
1918 p = (char **)dupParam(&ptr->paramList[type]);
1919 if (p == NULL) {
1920 free(tcp);
1921 return (NS_LDAP_MEMORY);
1923 } else
1924 p = NULL;
1925 conf.ns_ppc =
1926 reallocarray(p, len + 1, sizeof (char *));
1927 if (conf.ns_ppc == NULL) {
1928 __s_api_free2dArray(p);
1929 free(tcp);
1930 return (NS_LDAP_MEMORY);
1932 conf.ns_acnt = len;
1933 conf.ns_ppc[len-1] = (char *)strdup(cp);
1934 if (conf.ns_ppc[len-1] == NULL) {
1935 __s_api_free2dArray(conf.ns_ppc);
1936 free(tcp);
1937 return (NS_LDAP_MEMORY);
1939 conf.ns_ppc[len] = NULL;
1941 break;
1942 case SSDLIST:
1944 * first check to see if colon (:) is there,
1945 * if so, make sure the serviceId is specified,
1946 * i.e., colon is not the first character
1948 if ((strchr(cp, COLONTOK)) == NULL || *cp == COLONTOK) {
1949 (void) snprintf(errstr, sizeof (errstr),
1950 gettext("Unable to set value: "
1951 "invalid serviceSearchDescriptor (%s)"),
1952 cp);
1953 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
1954 strdup(errstr), 0);
1955 free(tcp);
1956 return (NS_LDAP_CONFIG);
1958 /* Appends an entry to the existing list */
1959 if (ptr->paramList[type].ns_ptype != SSDLIST) {
1960 conf.ns_ppc = (char **)calloc(2, sizeof (char *));
1961 if (conf.ns_ppc == NULL) {
1962 free(tcp);
1963 return (NS_LDAP_MEMORY);
1965 conf.ns_acnt = 1;
1966 conf.ns_ppc[0] = (char *)strdup(cp);
1967 if (conf.ns_ppc[0] == NULL) {
1968 free(conf.ns_ppc);
1969 free(tcp);
1970 return (NS_LDAP_MEMORY);
1972 } else {
1973 char *dp, *dpend;
1974 int fnd = 0;
1976 /* Attempt to replace if possible */
1977 dpend = strchr(cp, COLONTOK);
1978 len = dpend - cp;
1979 dp = (char *)malloc(len+1);
1980 if (dp == NULL) {
1981 free(tcp);
1982 return (NS_LDAP_MEMORY);
1984 (void) strlcpy(dp, cp, len+1);
1985 fnd = 0;
1986 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) {
1987 dpend = strchr(ptr->paramList[type].ns_ppc[j],
1988 COLONTOK);
1989 if (dpend == NULL)
1990 continue;
1991 i = dpend - ptr->paramList[type].ns_ppc[j];
1992 if (i != len)
1993 continue;
1994 if (strncmp(ptr->paramList[type].ns_ppc[j],
1995 dp, len) == 0) {
1996 conf.ns_acnt =
1997 ptr->paramList[type].ns_acnt;
1998 conf.ns_ppc =
1999 ptr->paramList[type].ns_ppc;
2000 ptr->paramList[type].ns_ppc = NULL;
2001 free(conf.ns_ppc[j]);
2002 conf.ns_ppc[j] = (char *)strdup(cp);
2003 if (conf.ns_ppc[j] == NULL) {
2004 free(dp);
2005 __s_api_free2dArray
2006 (conf.ns_ppc);
2007 free(tcp);
2008 return (NS_LDAP_MEMORY);
2010 fnd = 1;
2011 break;
2014 free(dp);
2016 if (fnd)
2017 break; /* Replaced completed */
2019 /* Append */
2020 len = ptr->paramList[type].ns_acnt + 1;
2021 if (len > 1) {
2022 p = (char **)dupParam(&ptr->paramList[type]);
2023 if (p == NULL) {
2024 free(tcp);
2025 return (NS_LDAP_MEMORY);
2027 } else
2028 p = NULL;
2029 conf.ns_ppc =
2030 reallocarray(p, len + 1, sizeof (char *));
2031 if (conf.ns_ppc == NULL) {
2032 __s_api_free2dArray(p);
2033 free(tcp);
2034 return (NS_LDAP_MEMORY);
2036 conf.ns_acnt = len;
2037 conf.ns_ppc[len-1] = (char *)strdup(cp);
2038 if (conf.ns_ppc[len-1] == NULL) {
2039 __s_api_free2dArray(conf.ns_ppc);
2040 free(tcp);
2041 return (NS_LDAP_MEMORY);
2043 conf.ns_ppc[len] = NULL;
2045 break;
2046 case ARRAYCP:
2047 len = 0;
2048 for (cp2 = cp; *cp2; cp2++) {
2049 if (*cp2 == COMMATOK)
2050 len++;
2052 if (cp != cp2)
2053 len++;
2054 if (len == 0) {
2055 conf.ns_ppc = (char **)NULL;
2056 conf.ns_acnt = 0;
2057 break;
2059 conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *));
2060 if (conf.ns_ppc == NULL) {
2061 free(tcp);
2062 return (NS_LDAP_MEMORY);
2064 conf.ns_acnt = len;
2065 i = 0;
2066 for (cp2 = cp; *cp2; cp2++) {
2067 if (*cp2 == COMMATOK) {
2068 j = cp2 - cp + 1;
2069 conf.ns_ppc[i] = (char *)malloc(j + 1);
2070 if (conf.ns_ppc[i] == NULL) {
2071 __s_api_free2dArray(conf.ns_ppc);
2072 free(tcp);
2073 return (NS_LDAP_MEMORY);
2075 (void) strlcpy(conf.ns_ppc[i], cp, j);
2076 cp = cp2+1;
2077 while (*cp == SPACETOK || *cp == COMMATOK)
2078 cp++;
2079 cp2 = cp - 1;
2080 i++;
2083 j = cp2 - cp + 1;
2084 conf.ns_ppc[i] = (char *)malloc(j + 1);
2085 if (conf.ns_ppc[i] == NULL) {
2086 __s_api_free2dArray(conf.ns_ppc);
2087 free(tcp);
2088 return (NS_LDAP_MEMORY);
2090 (void) strlcpy(conf.ns_ppc[i], cp, j);
2091 break;
2092 case SERVLIST:
2093 len = 0;
2094 for (cp2 = cp; *cp2; cp2++) {
2095 if (*cp2 == SPACETOK || *cp2 == COMMATOK) {
2096 len++;
2097 for (; *(cp2 + 1) == SPACETOK ||
2098 *(cp2 +1) == COMMATOK; cp2++)
2102 if (cp != cp2)
2103 len++;
2104 if (len == 0) {
2105 conf.ns_ppc = (char **)NULL;
2106 conf.ns_acnt = 0;
2107 break;
2109 conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *));
2110 if (conf.ns_ppc == NULL) {
2111 free(tcp);
2112 return (NS_LDAP_MEMORY);
2114 conf.ns_acnt = len;
2115 i = 0;
2116 for (cp2 = cp; *cp2; cp2++) {
2117 if (*cp2 == SPACETOK || *cp2 == COMMATOK) {
2118 j = cp2 - cp + 1;
2119 conf.ns_ppc[i] = (char *)malloc(j + 1);
2120 if (conf.ns_ppc[i] == NULL) {
2121 __s_api_free2dArray(conf.ns_ppc);
2122 free(tcp);
2123 return (NS_LDAP_MEMORY);
2125 (void) strlcpy(conf.ns_ppc[i], cp, j);
2126 cp = cp2+1;
2127 while (*cp == SPACETOK || *cp == COMMATOK)
2128 cp++;
2129 cp2 = cp - 1;
2130 i++;
2133 j = cp2 - cp + 1;
2134 conf.ns_ppc[i] = (char *)malloc(j + 1);
2135 if (conf.ns_ppc[i] == NULL) {
2136 __s_api_free2dArray(conf.ns_ppc);
2137 free(tcp);
2138 return (NS_LDAP_MEMORY);
2140 (void) strlcpy(conf.ns_ppc[i], cp, j);
2141 break;
2142 case ARRAYAUTH:
2143 len = 0;
2144 for (cp2 = cp; *cp2; cp2++) {
2145 if (*cp2 == SEMITOK || *cp2 == COMMATOK)
2146 len++;
2148 if (cp != cp2)
2149 len++;
2150 if (len == 0) {
2151 conf.ns_pi = NULL;
2152 conf.ns_acnt = 0;
2153 break;
2155 conf.ns_pi = (int *)calloc(len + 1, sizeof (int));
2156 if (conf.ns_pi == NULL) {
2157 free(tcp);
2158 return (NS_LDAP_MEMORY);
2160 conf.ns_acnt = len;
2161 i = 0;
2162 for (cp2 = cp; *cp2; cp2++) {
2163 if (*cp2 == SEMITOK || *cp2 == COMMATOK) {
2164 j = cp2 - cp + 1;
2165 if (j > sizeof (tbuf)) {
2166 j = -1;
2167 ptbuf = cp;
2168 } else {
2169 (void) strlcpy(tbuf, cp, j);
2170 j = __s_get_enum_value(ptr, tbuf,
2171 def->index);
2172 ptbuf = tbuf;
2174 if (j < 0) {
2175 (void) snprintf(errstr, sizeof (errstr),
2176 gettext("Unable to set value: "
2177 "invalid "
2178 "authenticationMethod (%s)"),
2179 ptbuf);
2180 MKERROR(LOG_ERR, *error,
2181 NS_CONFIG_SYNTAX,
2182 strdup(errstr), 0);
2183 free(conf.ns_pi);
2184 free(tcp);
2185 return (NS_LDAP_CONFIG);
2187 conf.ns_pi[i] = j;
2188 cp = cp2+1;
2189 i++;
2192 j = cp2 - cp + 1;
2193 if (j > sizeof (tbuf)) {
2194 j = -1;
2195 ptbuf = cp;
2196 } else {
2197 (void) strlcpy(tbuf, cp, j);
2198 j = __s_get_enum_value(ptr, tbuf, def->index);
2199 ptbuf = tbuf;
2201 if (j < 0) {
2202 (void) snprintf(errstr, sizeof (errstr),
2203 gettext("Unable to set value: "
2204 "invalid authenticationMethod (%s)"), ptbuf);
2205 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
2206 strdup(errstr), 0);
2207 free(tcp);
2208 return (NS_LDAP_CONFIG);
2210 conf.ns_pi[i] = j;
2211 break;
2212 case ARRAYCRED:
2213 len = 0;
2214 for (cp2 = cp; *cp2; cp2++) {
2215 if (*cp2 == SPACETOK)
2216 len++;
2218 if (cp != cp2)
2219 len++;
2220 if (len == 0) {
2221 conf.ns_pi = NULL;
2222 conf.ns_acnt = 0;
2223 break;
2225 conf.ns_pi = (int *)calloc(len + 1, sizeof (int));
2226 if (conf.ns_pi == NULL) {
2227 free(tcp);
2228 return (NS_LDAP_MEMORY);
2230 conf.ns_acnt = len;
2231 i = 0;
2232 for (cp2 = cp; *cp2; cp2++) {
2233 if (*cp2 == SPACETOK) {
2234 j = cp2 - cp + 1;
2235 if (j > sizeof (tbuf)) {
2236 j = -1;
2237 ptbuf = cp;
2238 } else {
2239 (void) strlcpy(tbuf, cp, j);
2240 j = __s_get_enum_value(ptr, tbuf,
2241 def->index);
2242 ptbuf = tbuf;
2244 if (j < 0) {
2245 (void) snprintf(errstr, sizeof (errstr),
2246 gettext("Unable to set value: "
2247 "invalid credentialLevel (%s)"),
2248 ptbuf);
2249 MKERROR(LOG_ERR, *error,
2250 NS_CONFIG_SYNTAX,
2251 strdup(errstr), 0);
2252 free(conf.ns_pi);
2253 free(tcp);
2254 return (NS_LDAP_CONFIG);
2256 conf.ns_pi[i] = j;
2257 cp = cp2+1;
2258 i++;
2261 j = cp2 - cp + 1;
2262 if (j > sizeof (tbuf)) {
2263 j = -1;
2264 ptbuf = cp;
2265 } else {
2266 (void) strlcpy(tbuf, cp, j);
2267 j = __s_get_enum_value(ptr, tbuf, def->index);
2268 ptbuf = tbuf;
2270 if (j < 0) {
2271 (void) snprintf(errstr, sizeof (errstr),
2272 gettext("Unable to set value: "
2273 "invalid credentialLevel (%s)"), ptbuf);
2274 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
2275 strdup(errstr), 0);
2276 free(tcp);
2277 return (NS_LDAP_CONFIG);
2279 conf.ns_pi[i] = j;
2280 break;
2281 case ATTRMAP:
2282 case OBJMAP:
2283 i = __s_api_parse_map(cp, &sid, &origA, &mapA);
2284 if (i != NS_HASH_RC_SUCCESS) {
2285 if (i == NS_HASH_RC_NO_MEMORY) {
2286 exitrc = NS_LDAP_MEMORY;
2287 } else {
2288 (void) snprintf(errstr, sizeof (errstr),
2289 gettext("Unable to set value: "
2290 "invalid schema mapping (%s)"), cp);
2291 exitrc = NS_LDAP_CONFIG;
2292 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
2293 strdup(errstr), 0);
2295 free(tcp);
2296 return (exitrc);
2300 * Add reverse map first.
2301 * There could be more than one.
2303 for (attr = mapA; *attr; attr++) {
2305 free_memory = 1;
2306 exitrc = NS_LDAP_MEMORY;
2308 rmap = (ns_mapping_t *)calloc(1,
2309 sizeof (ns_mapping_t));
2310 if (rmap) {
2311 rmap->service = strdup(sid);
2312 if (rmap->service) {
2313 rmap->orig = strdup(*attr);
2314 if (rmap->orig) {
2315 rmap->map = (char **)calloc(2,
2316 sizeof (char *));
2317 if (rmap->map) {
2318 (rmap->map)[0] =
2319 strdup(origA);
2320 if ((rmap->map)[0])
2321 free_memory = 0;
2327 if (free_memory == 0) {
2328 if (def->data_type == ATTRMAP) {
2329 rmap->type = NS_ATTR_MAP;
2330 i = __s_api_add_map2hash(ptr,
2331 NS_HASH_RAMAP, rmap);
2332 } else {
2333 rmap->type = NS_OBJ_MAP;
2334 i = __s_api_add_map2hash(ptr,
2335 NS_HASH_ROMAP, rmap);
2338 if (i != NS_HASH_RC_SUCCESS) {
2339 switch (i) {
2340 case NS_HASH_RC_CONFIG_ERROR:
2341 exitrc = NS_LDAP_INTERNAL;
2342 (void) snprintf(errstr,
2343 sizeof (errstr),
2344 gettext(
2345 "Unable to set value: "
2346 "no configuration info "
2347 "for schema map "
2348 "update (%s)"), cp);
2349 MKERROR(LOG_ERR, *error,
2350 NS_LDAP_INTERNAL,
2351 strdup(errstr),
2353 break;
2354 case NS_HASH_RC_EXISTED:
2355 exitrc = NS_LDAP_CONFIG;
2356 (void) snprintf(errstr,
2357 sizeof (errstr),
2358 gettext(
2359 "Unable to set value: "
2360 "schema map "
2361 "already existed for "
2362 "(%s, %s)."),
2363 *attr, origA);
2364 MKERROR(LOG_ERR, *error,
2365 NS_CONFIG_SYNTAX,
2366 strdup(errstr),
2368 break;
2369 case NS_HASH_RC_NO_MEMORY:
2370 exitrc = NS_LDAP_MEMORY;
2371 break;
2373 free_memory = 1;
2377 if (free_memory) {
2378 free(tcp);
2379 free(sid);
2380 free(origA);
2381 __s_api_free2dArray(mapA);
2382 if (rmap) {
2383 free(rmap->service);
2384 free(rmap->orig);
2385 if (rmap->map) {
2386 free((rmap->map)[0]);
2387 free(rmap->map);
2389 free(rmap);
2391 return (exitrc);
2396 * For performance gain,
2397 * add a "schema mapping existed" indicator
2398 * for the given service if not already added.
2399 * This dummy map needs not be removed, if
2400 * the next real map add operation fails.
2401 * since the caller, e.g. ldap_cachemgr.
2402 * should exit anyway.
2404 free_memory = 1;
2405 exitrc = NS_LDAP_MEMORY;
2407 map = (ns_mapping_t *)calloc(1,
2408 sizeof (ns_mapping_t));
2409 if (map) {
2410 map->service = strdup(sid);
2411 if (map->service) {
2412 map->orig = strdup(
2413 NS_HASH_SCHEMA_MAPPING_EXISTED);
2414 if (map->orig) {
2415 map->map = (char **)calloc(2,
2416 sizeof (char *));
2417 if (map->map) {
2418 (map->map)[0] =
2419 strdup(sid);
2420 if ((map->map)[0])
2421 free_memory = 0;
2427 if (free_memory == 0) {
2428 map->type = NS_ATTR_MAP;
2430 * add to reverse map,
2431 * so that "ldapclient list"
2432 * would not show it
2434 i = __s_api_add_map2hash(ptr,
2435 NS_HASH_RAMAP, map);
2438 * ignore "map already existed" error,
2439 * just need one per service.
2440 * Need however to free memory allocated
2441 * for map.
2443 if (i != NS_HASH_RC_SUCCESS &&
2444 i != NS_HASH_RC_EXISTED) {
2445 switch (i) {
2446 case NS_HASH_RC_CONFIG_ERROR:
2447 exitrc = NS_LDAP_INTERNAL;
2448 (void) snprintf(errstr,
2449 sizeof (errstr),
2450 gettext(
2451 "Unable to set value: "
2452 "no configuration info "
2453 "for schema map "
2454 "update (%s)"), cp);
2455 MKERROR(LOG_ERR, *error,
2456 NS_LDAP_INTERNAL,
2457 strdup(errstr),
2459 break;
2460 case NS_HASH_RC_NO_MEMORY:
2461 exitrc = NS_LDAP_MEMORY;
2462 break;
2464 free_memory = 1;
2465 } else if (i == NS_HASH_RC_EXISTED) {
2466 free(map->service);
2467 free(map->orig);
2468 if (map->map) {
2469 free((map->map)[0]);
2470 free(map->map);
2472 free(map);
2473 map = NULL;
2477 if (free_memory) {
2478 free(tcp);
2479 free(sid);
2480 free(origA);
2481 __s_api_free2dArray(mapA);
2482 if (map) {
2483 free(map->service);
2484 free(map->orig);
2485 if (map->map) {
2486 free((map->map)[0]);
2487 free(map->map);
2489 free(map);
2491 return (exitrc);
2495 * add the real schema map
2497 free_memory = 1;
2498 exitrc = NS_LDAP_MEMORY;
2499 map = (ns_mapping_t *)calloc(1, sizeof (ns_mapping_t));
2500 if (map) {
2501 map->service = sid;
2502 map->orig = origA;
2503 map->map = mapA;
2505 if (def->data_type == ATTRMAP) {
2506 map->type = NS_ATTR_MAP;
2507 i = __s_api_add_map2hash(ptr,
2508 NS_HASH_AMAP, map);
2509 } else {
2510 map->type = NS_OBJ_MAP;
2511 i = __s_api_add_map2hash(ptr,
2512 NS_HASH_OMAP, map);
2515 if (i != NS_HASH_RC_SUCCESS) {
2516 switch (i) {
2517 case NS_HASH_RC_CONFIG_ERROR:
2518 exitrc = NS_LDAP_INTERNAL;
2519 (void) snprintf(errstr,
2520 sizeof (errstr),
2521 gettext(
2522 "Unable to set value: "
2523 "no configuration info "
2524 "for schema map "
2525 "update (%s)"), cp);
2526 MKERROR(LOG_ERR, *error,
2527 NS_LDAP_INTERNAL,
2528 strdup(errstr),
2530 break;
2531 case NS_HASH_RC_EXISTED:
2532 exitrc = NS_LDAP_CONFIG;
2533 (void) snprintf(errstr,
2534 sizeof (errstr),
2535 gettext(
2536 "Unable to set value: "
2537 "schema map "
2538 "already existed for "
2539 "'%s'."), origA);
2540 MKERROR(LOG_ERR, *error,
2541 NS_CONFIG_SYNTAX,
2542 strdup(errstr),
2544 break;
2545 case NS_HASH_RC_NO_MEMORY:
2546 exitrc = NS_LDAP_MEMORY;
2547 break;
2549 free_memory = 1;
2550 } else
2551 free_memory = 0;
2554 if (free_memory) {
2555 free(tcp);
2556 free(sid);
2557 free(origA);
2558 __s_api_free2dArray(mapA);
2559 free(map);
2560 return (exitrc);
2563 break;
2564 default:
2565 /* This should never happen. */
2566 (void) snprintf(errstr, sizeof (errstr),
2567 gettext("Unable to set value: invalid configuration "
2568 "type (%d)"), def->data_type);
2569 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
2571 free(tcp);
2572 return (NS_LDAP_CONFIG);
2574 conf.ns_ptype = def->data_type;
2575 free(tcp);
2577 /* Individually written verify routines here can replace */
2578 /* verify_value. Verify conf (data) as appropriate here */
2579 if (def->ns_verify != NULL) {
2580 if ((*def->ns_verify)(type, def, &conf, errstr) != NS_SUCCESS) {
2581 ns_param_t sav_conf;
2583 (void) snprintf(errstr, sizeof (errstr),
2584 gettext("%s"), errstr);
2585 MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX,
2586 strdup(errstr), 0);
2588 sav_conf = ptr->paramList[type];
2589 ptr->paramList[type] = conf;
2590 destroy_param(ptr, type);
2591 ptr->paramList[type] = sav_conf;
2593 return (NS_LDAP_CONFIG);
2597 /* post evaluate the data */
2600 * if this is for setting a password,
2601 * encrypt the password first.
2602 * NOTE evalue() is smart and will just return
2603 * the value passed if it is already encrypted.
2605 * Init NS_LDAP_EXP_P here when CACHETTL is updated
2607 if (type == NS_LDAP_BINDPASSWD_P ||
2608 type == NS_LDAP_ADMIN_BINDPASSWD_P) {
2609 cp = conf.ns_pc;
2610 cp2 = evalue((char *)cp);
2611 conf.ns_pc = cp2;
2612 free(cp);
2613 cp = NULL;
2614 } else if (type == NS_LDAP_FILE_VERSION_P) {
2615 ptr->version = NS_LDAP_V1;
2616 if (strcasecmp(conf.ns_pc, NS_LDAP_VERSION_2) == 0) {
2617 ptr->version = NS_LDAP_V2;
2619 } else if (type == NS_LDAP_CACHETTL_P) {
2620 cp = conf.ns_pc;
2621 tm = conv_time(cp);
2622 ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET;
2623 if (tm != 0) {
2624 tm += time(NULL);
2626 ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm;
2629 /* Everything checks out move new values into param */
2630 destroy_param(ptr, type);
2631 /* Assign new/updated value into paramList */
2632 ptr->paramList[type] = conf;
2634 return (NS_LDAP_SUCCESS);
2639 * Set a parameter value in the 'config' configuration structure
2640 * Lock as appropriate
2644 __ns_ldap_setParam(const ParamIndexType type,
2645 const void *data, ns_ldap_error_t **error)
2647 ns_ldap_error_t *errorp;
2648 int ret;
2649 char errstr[2 * MAXERROR];
2650 ns_config_t *cfg;
2651 ns_config_t *cfg_g = (ns_config_t *)-1;
2652 ns_config_t *new_cfg;
2653 boolean_t reinit_connmgmt = B_FALSE;
2655 /* We want to refresh only one configuration at a time */
2656 (void) mutex_lock(&ns_loadrefresh_lock);
2657 cfg = __s_api_get_default_config();
2659 if (cache_server == TRUE) {
2660 if (cfg == NULL) {
2661 __ns_ldap_default_config();
2662 cfg = __s_api_get_default_config();
2663 if (cfg == NULL) {
2664 (void) mutex_unlock(&ns_loadrefresh_lock);
2665 return (NS_LDAP_MEMORY);
2668 } else {
2670 * This code always return error here on client side,
2671 * this needs to change once libsldap is used by more
2672 * applications that need to set parameters.
2674 (void) snprintf(errstr, sizeof (errstr),
2675 gettext("Unable to set parameter from a client in "
2676 "__ns_ldap_setParam()"));
2677 MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX, strdup(errstr),
2679 if (cfg != NULL)
2680 __s_api_release_config(cfg);
2681 (void) mutex_unlock(&ns_loadrefresh_lock);
2682 return (NS_LDAP_CONFIG);
2685 /* (re)initialize configuration if necessary */
2686 if (!__s_api_isStandalone() &&
2687 cache_server == FALSE && timetorefresh(cfg))
2688 cfg_g = __s_api_get_default_config_global();
2689 /* only (re)initialize the global configuration */
2690 if (cfg == cfg_g) {
2691 if (cfg_g != NULL)
2692 __s_api_release_config(cfg_g);
2693 new_cfg = LoadCacheConfiguration(cfg, &errorp);
2694 if (new_cfg != cfg)
2695 __s_api_release_config(cfg);
2696 if (new_cfg == NULL) {
2697 (void) snprintf(errstr, sizeof (errstr),
2698 gettext("Unable to load configuration '%s' "
2699 "('%s')."), NSCONFIGFILE,
2700 errorp != NULL && errorp->message != NULL ?
2701 errorp->message : "");
2702 MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED,
2703 strdup(errstr), 0);
2704 if (errorp != NULL)
2705 (void) __ns_ldap_freeError(&errorp);
2706 (void) mutex_unlock(&ns_loadrefresh_lock);
2707 return (NS_LDAP_CONFIG);
2709 if (new_cfg != cfg) {
2710 set_curr_config_global(new_cfg);
2711 cfg = new_cfg;
2712 reinit_connmgmt = B_TRUE;
2715 (void) mutex_unlock(&ns_loadrefresh_lock);
2717 if (reinit_connmgmt == B_TRUE)
2718 __s_api_reinit_conn_mgmt_new_config(cfg);
2720 /* translate input and save in the parameter list */
2721 ret = __ns_ldap_setParamValue(cfg, type, data, error);
2723 __s_api_release_config(cfg);
2725 return (ret);
2730 * Make a copy of a parameter entry
2733 static void **
2734 dupParam(ns_param_t *ptr)
2736 int count, i;
2737 void **dupdata, *ret;
2738 int *intptr;
2739 char *cp, tmbuf[32];
2740 static time_t expire = 0;
2741 ns_auth_t *ap;
2743 switch (ptr->ns_ptype) {
2744 case ARRAYAUTH:
2745 case ARRAYCRED:
2746 case SAMLIST:
2747 case SCLLIST:
2748 case SSDLIST:
2749 case SERVLIST:
2750 case ARRAYCP:
2751 count = ptr->ns_acnt;
2752 if (count == 0)
2753 return (NULL);
2754 break;
2755 case CHARPTR:
2756 case INT:
2757 case TIMET:
2758 count = 1;
2761 dupdata = (void **)calloc((count + 1), sizeof (void *));
2762 if (dupdata == NULL)
2763 return (NULL);
2765 switch (ptr->ns_ptype) {
2766 case ARRAYAUTH:
2767 for (i = 0; i < count; i++) {
2768 ap = __s_api_AuthEnumtoStruct(
2769 (EnumAuthType_t)ptr->ns_pi[i]);
2770 if (ap == NULL) {
2771 free(dupdata);
2772 return (NULL);
2774 dupdata[i] = ap;
2776 break;
2777 case ARRAYCRED:
2778 for (i = 0; i < count; i++) {
2779 intptr = (int *)malloc(sizeof (int));
2780 if (intptr == NULL) {
2781 free(dupdata);
2782 return (NULL);
2784 dupdata[i] = (void *)intptr;
2785 *intptr = ptr->ns_pi[i];
2787 break;
2788 case SAMLIST:
2789 case SCLLIST:
2790 case SSDLIST:
2791 case SERVLIST:
2792 case ARRAYCP:
2793 for (i = 0; i < count; i++) {
2794 ret = (void *)strdup(ptr->ns_ppc[i]);
2795 if (ret == NULL) {
2796 free(dupdata);
2797 return (NULL);
2799 dupdata[i] = ret;
2801 break;
2802 case CHARPTR:
2803 if (ptr->ns_pc == NULL) {
2804 free(dupdata);
2805 return (NULL);
2807 ret = (void *)strdup(ptr->ns_pc);
2808 if (ret == NULL) {
2809 free(dupdata);
2810 return (NULL);
2812 dupdata[0] = ret;
2813 break;
2814 case INT:
2815 intptr = (int *)malloc(sizeof (int));
2816 if (intptr == NULL) {
2817 free(dupdata);
2818 return (NULL);
2820 *intptr = ptr->ns_i;
2821 dupdata[0] = (void *)intptr;
2822 break;
2823 case TIMET:
2824 expire = ptr->ns_tm;
2825 tmbuf[31] = '\0';
2826 cp = lltostr((long)expire, &tmbuf[31]);
2827 ret = (void *)strdup(cp);
2828 if (ret == NULL) {
2829 free(dupdata);
2830 return (NULL);
2832 dupdata[0] = ret;
2833 break;
2835 return (dupdata);
2839 __ns_ldap_freeParam(void ***data)
2841 void **tmp;
2842 int i = 0;
2844 if (*data == NULL)
2845 return (NS_LDAP_SUCCESS);
2847 for (i = 0, tmp = *data; tmp[i] != NULL; i++)
2848 free(tmp[i]);
2850 free(*data);
2852 *data = NULL;
2854 return (NS_LDAP_SUCCESS);
2858 * Get the internal format for a parameter value. This
2859 * routine makes a copy of an internal param value from
2860 * the currently active parameter list and returns it.
2864 __ns_ldap_getParam(const ParamIndexType Param,
2865 void ***data, ns_ldap_error_t **error)
2867 char errstr[2 * MAXERROR];
2868 ns_ldap_error_t *errorp;
2869 ns_default_config *def;
2870 ns_config_t *cfg;
2871 ns_config_t *cfg_g = (ns_config_t *)-1;
2872 ns_config_t *new_cfg;
2873 boolean_t reinit_connmgmt = B_FALSE;
2875 if (data == NULL)
2876 return (NS_LDAP_INVALID_PARAM);
2878 *data = NULL;
2880 /* We want to refresh only one configuration at a time */
2881 (void) mutex_lock(&ns_loadrefresh_lock);
2882 cfg = __s_api_get_default_config();
2884 /* (re)initialize configuration if necessary */
2885 if (!__s_api_isStandalone() &&
2886 cache_server == FALSE && timetorefresh(cfg))
2887 cfg_g = __s_api_get_default_config_global();
2888 /* only (re)initialize the global configuration */
2889 if (cfg == cfg_g) {
2890 if (cfg_g != NULL)
2891 __s_api_release_config(cfg_g);
2892 new_cfg = LoadCacheConfiguration(cfg, &errorp);
2893 if (new_cfg != cfg)
2894 __s_api_release_config(cfg);
2895 if (new_cfg == NULL) {
2896 (void) snprintf(errstr, sizeof (errstr),
2897 gettext("Unable to load configuration "
2898 "'%s' ('%s')."),
2899 NSCONFIGFILE,
2900 errorp != NULL && errorp->message != NULL ?
2901 errorp->message : "");
2902 MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED,
2903 strdup(errstr), 0);
2904 if (errorp != NULL)
2905 (void) __ns_ldap_freeError(&errorp);
2906 (void) mutex_unlock(&ns_loadrefresh_lock);
2907 return (NS_LDAP_CONFIG);
2909 if (new_cfg != cfg) {
2910 set_curr_config_global(new_cfg);
2911 cfg = new_cfg;
2912 reinit_connmgmt = B_TRUE;
2915 (void) mutex_unlock(&ns_loadrefresh_lock);
2917 if (reinit_connmgmt == B_TRUE)
2918 __s_api_reinit_conn_mgmt_new_config(cfg);
2920 if (cfg == NULL) {
2921 (void) snprintf(errstr, sizeof (errstr),
2922 gettext("No configuration information available."));
2923 MKERROR(LOG_ERR, *error, NS_CONFIG_NOTLOADED,
2924 strdup(errstr), 0);
2925 return (NS_LDAP_CONFIG);
2928 if (Param == NS_LDAP_DOMAIN_P) {
2929 *data = (void **)calloc(2, sizeof (void *));
2930 if (*data == NULL) {
2931 __s_api_release_config(cfg);
2932 return (NS_LDAP_MEMORY);
2934 (*data)[0] = (void *)strdup(cfg->domainName);
2935 if ((*data)[0] == NULL) {
2936 free(*data);
2937 __s_api_release_config(cfg);
2938 return (NS_LDAP_MEMORY);
2940 } else if (cfg->paramList[Param].ns_ptype == NS_UNKNOWN) {
2941 /* get default */
2942 def = get_defconfig(cfg, Param);
2943 if (def != NULL)
2944 *data = dupParam(&def->defval);
2945 } else {
2946 *data = dupParam(&(cfg->paramList[Param]));
2948 __s_api_release_config(cfg);
2950 return (NS_LDAP_SUCCESS);
2954 * This routine takes a parameter in internal format and
2955 * translates it into a variety of string formats for various
2956 * outputs (doors/file/ldif). This routine would be better
2957 * named: __ns_ldap_translateParam2String
2960 char *
2961 __s_api_strValue(ns_config_t *cfg, ParamIndexType index, ns_strfmt_t fmt)
2963 ns_default_config *def = NULL;
2964 ns_param_t *ptr;
2965 ns_hash_t *hptr;
2966 ns_mapping_t *mptr;
2967 char ibuf[14];
2968 char abuf[64], **cpp;
2969 int count, i;
2970 boolean_t first = B_TRUE;
2971 LineBuf lbuf;
2972 LineBuf *buffer = &lbuf;
2973 char *retstring;
2974 char *sepstr;
2976 if (cfg == NULL)
2977 return (NULL);
2979 /* NS_LDAP_EXP and TRANSPORT_SEC are not exported externally */
2980 if (index == NS_LDAP_EXP_P || index == NS_LDAP_TRANSPORT_SEC_P)
2981 return (NULL);
2983 /* Return nothing if the value is the default */
2984 if (cfg->paramList[index].ns_ptype == NS_UNKNOWN)
2985 return (NULL);
2987 (void) memset((char *)buffer, 0, sizeof (LineBuf));
2989 ptr = &(cfg->paramList[index]);
2991 abuf[0] = '\0';
2993 /* get default */
2994 def = get_defconfig(cfg, index);
2995 if (def == NULL)
2996 return (NULL);
2998 switch (fmt) {
2999 case NS_DOOR_FMT:
3000 (void) strlcpy(abuf, def->name, sizeof (abuf));
3001 (void) strlcat(abuf, EQUALSEP, sizeof (abuf));
3002 break;
3003 case NS_FILE_FMT:
3004 (void) strlcpy(abuf, def->name, sizeof (abuf));
3005 (void) strlcat(abuf, EQUSPSEP, sizeof (abuf));
3006 break;
3007 case NS_LDIF_FMT:
3008 /* If no LDIF attr exists ignore the entry */
3009 if (def->profile_name == NULL)
3010 return (NULL);
3011 (void) strlcpy(abuf, def->profile_name, sizeof (abuf));
3012 (void) strlcat(abuf, COLSPSEP, sizeof (abuf));
3013 break;
3014 default:
3015 break;
3018 if (__print2buf(buffer, abuf, NULL))
3019 goto strValueError;
3021 switch (ptr->ns_ptype) {
3022 case ARRAYAUTH:
3023 count = ptr->ns_acnt;
3024 for (i = 0; i < count; i++) {
3025 sepstr = NULL;
3026 if (i != count-1) {
3027 if (cfg->version == NS_LDAP_V1) {
3028 sepstr = COMMASEP;
3029 } else {
3030 sepstr = SEMISEP;
3033 if (__print2buf(buffer, __s_get_auth_name(cfg,
3034 (AuthType_t)(ptr->ns_pi[i])), sepstr))
3035 goto strValueError;
3037 break;
3038 case ARRAYCRED:
3039 count = ptr->ns_acnt;
3040 for (i = 0; i < count; i++) {
3041 sepstr = NULL;
3042 if (i != count-1) {
3043 sepstr = SPACESEP;
3045 if (__print2buf(buffer, __s_get_credlvl_name(cfg,
3046 (CredLevel_t)ptr->ns_pi[i]), sepstr))
3047 goto strValueError;
3049 break;
3050 case SAMLIST:
3051 case SCLLIST:
3052 case SSDLIST:
3053 count = ptr->ns_acnt;
3054 for (i = 0; i < count; i++) {
3055 if (__print2buf(buffer, ptr->ns_ppc[i], NULL))
3056 goto strValueError;
3058 if (i == count-1)
3059 continue;
3061 /* Separate items */
3062 switch (fmt) {
3063 case NS_DOOR_FMT:
3064 if (__print2buf(buffer, DOORLINESEP, NULL) ||
3065 __print2buf(buffer, def->name, EQUALSEP))
3066 goto strValueError;
3067 break;
3068 case NS_FILE_FMT:
3069 if (__print2buf(buffer, "\n", NULL) ||
3070 __print2buf(buffer, def->name, EQUSPSEP))
3071 goto strValueError;
3072 break;
3073 case NS_LDIF_FMT:
3074 if (__print2buf(buffer, "\n", NULL) ||
3075 __print2buf(buffer, def->profile_name,
3076 COLSPSEP))
3077 goto strValueError;
3078 break;
3081 break;
3082 case ARRAYCP:
3083 count = ptr->ns_acnt;
3084 for (i = 0; i < count; i++) {
3085 sepstr = NULL;
3086 if (i != count-1) {
3087 sepstr = COMMASEP;
3089 if (__print2buf(buffer, ptr->ns_ppc[i], sepstr))
3090 goto strValueError;
3092 break;
3093 case SERVLIST:
3094 count = ptr->ns_acnt;
3095 for (i = 0; i < count; i++) {
3096 sepstr = NULL;
3097 if (i != count-1) {
3098 if (fmt == NS_LDIF_FMT) {
3099 sepstr = SPACESEP;
3100 } else {
3101 sepstr = COMMASEP;
3104 if (__print2buf(buffer, ptr->ns_ppc[i], sepstr))
3105 goto strValueError;
3107 break;
3108 case CHARPTR:
3109 if (ptr->ns_pc == NULL)
3110 break;
3111 if (__print2buf(buffer, ptr->ns_pc, NULL))
3112 goto strValueError;
3113 break;
3114 case INT:
3115 switch (def->index) {
3116 case NS_LDAP_PREF_ONLY_P:
3117 if (__print2buf(buffer,
3118 __s_get_pref_name((PrefOnly_t)ptr->ns_i), NULL))
3119 goto strValueError;
3120 break;
3121 case NS_LDAP_SEARCH_REF_P:
3122 if (__print2buf(buffer, __s_get_searchref_name(cfg,
3123 (SearchRef_t)ptr->ns_i), NULL))
3124 goto strValueError;
3125 break;
3126 case NS_LDAP_SEARCH_SCOPE_P:
3127 if (__print2buf(buffer, __s_get_scope_name(cfg,
3128 (ScopeType_t)ptr->ns_i), NULL))
3129 goto strValueError;
3130 break;
3131 case NS_LDAP_ENABLE_SHADOW_UPDATE_P:
3132 if (__print2buf(buffer, __s_get_shadowupdate_name(
3133 (enableShadowUpdate_t)ptr->ns_i), NULL))
3134 goto strValueError;
3135 break;
3136 default:
3137 (void) snprintf(ibuf, sizeof (ibuf),
3138 "%d", ptr->ns_i);
3139 if (__print2buf(buffer, ibuf, NULL))
3140 goto strValueError;
3141 break;
3143 break;
3144 case ATTRMAP:
3145 for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) {
3146 if (hptr->h_type != NS_HASH_AMAP) {
3147 continue;
3149 if (!first) {
3150 /* print abuf as "separator" */
3151 if (fmt == NS_DOOR_FMT) {
3152 if (__print2buf(buffer, DOORLINESEP,
3153 abuf))
3154 goto strValueError;
3155 } else {
3156 if (__print2buf(buffer, "\n", abuf))
3157 goto strValueError;
3160 mptr = hptr->h_map;
3161 if (__print2buf(buffer, mptr->service, COLONSEP) ||
3162 __print2buf(buffer, mptr->orig, EQUALSEP))
3163 goto strValueError;
3164 for (cpp = mptr->map; cpp && *cpp; cpp++) {
3165 /* print *cpp as "separator" */
3166 sepstr = "";
3167 if (cpp != mptr->map)
3168 sepstr = SPACESEP;
3169 if (__print2buf(buffer, sepstr, *cpp))
3170 goto strValueError;
3172 first = B_FALSE;
3174 break;
3175 case OBJMAP:
3176 for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) {
3177 if (hptr->h_type != NS_HASH_OMAP) {
3178 continue;
3180 if (!first) {
3181 /* print abuf as "separator" */
3182 if (fmt == NS_DOOR_FMT) {
3183 if (__print2buf(buffer, DOORLINESEP,
3184 abuf))
3185 goto strValueError;
3186 } else {
3187 if (__print2buf(buffer, "\n", abuf))
3188 goto strValueError;
3191 mptr = hptr->h_map;
3192 if (__print2buf(buffer, mptr->service, COLONSEP) ||
3193 __print2buf(buffer, mptr->orig, EQUALSEP))
3194 goto strValueError;
3195 for (cpp = mptr->map; cpp && *cpp; cpp++) {
3196 /* print *cpp as "separator" */
3197 sepstr = "";
3198 if (cpp != mptr->map)
3199 sepstr = SPACESEP;
3200 if (__print2buf(buffer, sepstr, *cpp))
3201 goto strValueError;
3203 first = B_FALSE;
3205 break;
3208 retstring = buffer->str;
3209 return (retstring);
3211 strValueError:
3212 if (buffer->len > 0)
3213 free(buffer->str);
3214 return (NULL);
3217 /* shared by __door_getldapconfig() and __door_getadmincred() */
3219 __door_getconf(char **buffer, int *buflen, ns_ldap_error_t **error,
3220 int callnumber)
3222 typedef union {
3223 ldap_data_t s_d;
3224 char s_b[DOORBUFFERSIZE];
3225 } space_t;
3226 space_t *space;
3228 ldap_data_t *sptr;
3229 int ndata;
3230 int adata;
3231 char errstr[MAXERROR];
3232 char *domainname;
3233 ns_ldap_return_code retCode;
3234 ldap_config_out_t *cfghdr;
3236 *error = NULL;
3238 domainname = __getdomainname();
3239 if (domainname == NULL || buffer == NULL || buflen == NULL ||
3240 (strlen(domainname) >= (sizeof (space_t)
3241 - sizeof (space->s_d.ldap_call.ldap_callnumber)))) {
3242 return (NS_LDAP_OP_FAILED);
3245 space = (space_t *)calloc(1, sizeof (space_t));
3246 if (space == NULL)
3247 return (NS_LDAP_MEMORY);
3249 adata = (sizeof (ldap_call_t) + strlen(domainname) +1);
3250 ndata = sizeof (space_t);
3251 space->s_d.ldap_call.ldap_callnumber = callnumber;
3252 (void) strcpy(space->s_d.ldap_call.ldap_u.domainname, domainname);
3253 free(domainname);
3254 domainname = NULL;
3255 sptr = &space->s_d;
3257 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
3258 case NS_CACHE_SUCCESS:
3259 break;
3260 case NS_CACHE_NOTFOUND:
3261 (void) snprintf(errstr, sizeof (errstr),
3262 gettext("Door call to "
3263 "ldap_cachemgr failed - error: %d."),
3264 space->s_d.ldap_ret.ldap_errno);
3265 MKERROR(LOG_WARNING, *error, NS_CONFIG_CACHEMGR,
3266 strdup(errstr), 0);
3267 free(space);
3268 return (NS_LDAP_OP_FAILED);
3269 default:
3270 free(space);
3271 return (NS_LDAP_OP_FAILED);
3274 retCode = NS_LDAP_SUCCESS;
3276 /* copy info from door call to buffer here */
3277 cfghdr = &sptr->ldap_ret.ldap_u.config_str;
3278 *buflen = offsetof(ldap_config_out_t, config_str) +
3279 cfghdr->data_size + 1;
3280 *buffer = calloc(*buflen, sizeof (char));
3281 if (*buffer == NULL) {
3282 retCode = NS_LDAP_MEMORY;
3283 } else
3284 (void) memcpy(*buffer, cfghdr, *buflen - 1);
3286 if (sptr != &space->s_d) {
3287 (void) munmap((char *)sptr, ndata);
3289 free(space);
3291 return (retCode);
3294 static int
3295 __door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error)
3297 return (__door_getconf(buffer, buflen, error, GETLDAPCONFIGV1));
3301 * SetDoorInfoToUnixCred parses ldapcachemgr configuration information
3302 * for Admin credentials.
3305 SetDoorInfoToUnixCred(char *buffer, ns_ldap_error_t **errorp,
3306 UnixCred_t **cred)
3308 UnixCred_t *ptr;
3309 char errstr[MAXERROR];
3310 char *name, *value, valbuf[BUFSIZE];
3311 char *bufptr = buffer;
3312 char *strptr;
3313 char *rest;
3314 ParamIndexType index = 0;
3315 ldap_config_out_t *cfghdr;
3317 if (errorp == NULL || cred == NULL || *cred == NULL)
3318 return (NS_LDAP_INVALID_PARAM);
3319 *errorp = NULL;
3321 ptr = *cred;
3323 cfghdr = (ldap_config_out_t *)bufptr;
3324 bufptr = (char *)cfghdr->config_str;
3326 strptr = (char *)strtok_r(bufptr, DOORLINESEP, &rest);
3327 for (; ; ) {
3328 if (strptr == NULL)
3329 break;
3330 (void) strlcpy(valbuf, strptr, sizeof (valbuf));
3331 __s_api_split_key_value(valbuf, &name, &value);
3332 if (__ns_ldap_getParamType(name, &index) != 0) {
3333 (void) snprintf(errstr, MAXERROR,
3334 gettext("SetDoorInfoToUnixCred: "
3335 "Unknown keyword encountered '%s'."), name);
3336 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX,
3337 strdup(errstr), 0);
3338 return (NS_LDAP_CONFIG);
3340 switch (index) {
3341 case NS_LDAP_ADMIN_BINDDN_P:
3342 ptr->userID = (char *)strdup(value);
3343 break;
3344 case NS_LDAP_ADMIN_BINDPASSWD_P:
3345 ptr->passwd = (char *)strdup(value);
3346 break;
3347 default:
3348 (void) snprintf(errstr, MAXERROR,
3349 gettext("SetDoorInfoToUnixCred: "
3350 "Unknown index encountered '%d'."), index);
3351 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX,
3352 strdup(errstr), 0);
3353 return (NS_LDAP_CONFIG);
3355 strptr = (char *)strtok_r(NULL, DOORLINESEP, &rest);
3358 return (NS_LDAP_SUCCESS);
3362 * SetDoorInfo parses ldapcachemgr configuration information
3363 * and verifies that the profile is version 1 or version 2 based.
3364 * version 2 profiles must have a version number as the first profile
3365 * attribute in the configuration.
3367 static ns_config_t *
3368 SetDoorInfo(char *buffer, ns_ldap_error_t **errorp)
3370 ns_config_t *ptr;
3371 char errstr[MAXERROR], errbuf[MAXERROR];
3372 char *name, *value, valbuf[BUFSIZE];
3373 char *strptr;
3374 char *rest;
3375 char *bufptr = buffer;
3376 ParamIndexType i;
3377 int ret;
3378 int first = 1;
3379 int errfnd = 0;
3380 ldap_config_out_t *cfghdr;
3382 if (errorp == NULL)
3383 return (NULL);
3384 *errorp = NULL;
3386 ptr = __s_api_create_config();
3387 if (ptr == NULL) {
3388 return (NULL);
3391 /* get config cookie from the header */
3392 cfghdr = (ldap_config_out_t *)bufptr;
3393 ptr->config_cookie = cfghdr->cookie;
3394 bufptr = (char *)cfghdr->config_str;
3396 strptr = (char *)strtok_r(bufptr, DOORLINESEP, &rest);
3397 for (; ; ) {
3398 if (strptr == NULL)
3399 break;
3400 (void) strlcpy(valbuf, strptr, sizeof (valbuf));
3401 __s_api_split_key_value(valbuf, &name, &value);
3402 /* Use get_versiontype and check for V1 vs V2 prototypes */
3403 if (__s_api_get_versiontype(ptr, name, &i) < 0) {
3404 (void) snprintf(errstr, sizeof (errstr),
3405 "%s (%s)\n",
3406 gettext("Illegal profile entry "
3407 "line in configuration."),
3408 name);
3409 errfnd++;
3410 /* Write verify routines and get rid of verify_value here */
3411 } else if (verify_value(ptr, name,
3412 value, errbuf) != NS_SUCCESS) {
3413 (void) snprintf(errstr, sizeof (errstr),
3414 gettext("%s\n"), errbuf);
3415 errfnd++;
3416 } else if (!first && i == NS_LDAP_FILE_VERSION_P) {
3417 (void) snprintf(errstr, sizeof (errstr),
3418 gettext("Illegal NS_LDAP_FILE_VERSION "
3419 "line in configuration.\n"));
3420 errfnd++;
3422 if (errfnd) {
3423 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX,
3424 strdup(errstr), NULL);
3425 } else {
3426 ret = set_default_value(ptr, name, value, errorp);
3428 if (errfnd || ret != NS_SUCCESS) {
3429 __s_api_destroy_config(ptr);
3430 return (NULL);
3432 first = 0;
3434 strptr = (char *)strtok_r(NULL, DOORLINESEP, &rest);
3437 if (__s_api_crosscheck(ptr, errstr, B_TRUE) != NS_SUCCESS) {
3438 __s_api_destroy_config(ptr);
3439 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX, strdup(errstr),
3440 NULL);
3441 return (NULL);
3444 return (ptr);
3447 static ns_config_t *
3448 LoadCacheConfiguration(ns_config_t *oldcfg, ns_ldap_error_t **error)
3450 char *buffer = NULL;
3451 int buflen = 0;
3452 int ret;
3453 ns_config_t *cfg;
3454 ldap_config_out_t *cfghdr;
3455 ldap_get_chg_cookie_t old_cookie;
3456 ldap_get_chg_cookie_t new_cookie;
3458 *error = NULL;
3459 ret = __door_getldapconfig(&buffer, &buflen, error);
3461 if (ret != NS_LDAP_SUCCESS) {
3462 if (*error != NULL && (*error)->message != NULL)
3463 syslog(LOG_WARNING, "libsldap: %s", (*error)->message);
3464 return (NULL);
3467 /* No need to reload configuration if config cookie is the same */
3468 cfghdr = (ldap_config_out_t *)buffer;
3469 new_cookie = cfghdr->cookie;
3470 if (oldcfg != NULL)
3471 old_cookie = oldcfg->config_cookie;
3473 if (oldcfg != NULL && old_cookie.mgr_pid == new_cookie.mgr_pid &&
3474 old_cookie.seq_num == new_cookie.seq_num) {
3475 free(buffer);
3476 return (oldcfg);
3479 /* now convert from door format */
3480 cfg = SetDoorInfo(buffer, error);
3481 free(buffer);
3483 if (cfg == NULL && *error != NULL && (*error)->message != NULL)
3484 syslog(LOG_WARNING, "libsldap: %s", (*error)->message);
3485 return (cfg);
3489 * converts the time string into seconds. The time string can be specified
3490 * using one of the following time units:
3491 * #s (# of seconds)
3492 * #m (# of minutes)
3493 * #h (# of hours)
3494 * #d (# of days)
3495 * #w (# of weeks)
3496 * NOTE: you can only specify one the above. No combination of the above
3497 * units is allowed. If no unit specified, it will default to "seconds".
3499 static time_t
3500 conv_time(char *s)
3502 time_t t;
3503 char c;
3504 int l, m;
3505 long tot;
3507 l = strlen(s);
3508 if (l == 0)
3509 return (0);
3510 c = s[--l];
3511 m = 0;
3512 switch (c) {
3513 case 'w': /* weeks */
3514 m = 604800;
3515 break;
3516 case 'd': /* days */
3517 m = 86400;
3518 break;
3519 case 'h': /* hours */
3520 m = 3600;
3521 break;
3522 case 'm': /* minutes */
3523 m = 60;
3524 break;
3525 case 's': /* seconds */
3526 m = 1;
3527 break;
3528 /* the default case is set to "second" */
3530 if (m != 0)
3531 s[l] = '\0';
3532 else
3533 m = 1;
3534 errno = 0;
3535 tot = atol(s);
3536 if ((0 == tot) && (EINVAL == errno))
3537 return (0);
3538 if (((LONG_MAX == tot) || (LONG_MIN == tot)) && (EINVAL == errno))
3539 return (0);
3541 tot = tot * m;
3542 t = (time_t)tot;
3543 return (t);
3547 ns_auth_t *
3548 __s_api_AuthEnumtoStruct(const EnumAuthType_t i)
3550 ns_auth_t *ap;
3552 ap = (ns_auth_t *)calloc(1, sizeof (ns_auth_t));
3553 if (ap == NULL)
3554 return (NULL);
3555 switch (i) {
3556 case NS_LDAP_EA_NONE:
3557 break;
3558 case NS_LDAP_EA_SIMPLE:
3559 ap->type = NS_LDAP_AUTH_SIMPLE;
3560 break;
3561 case NS_LDAP_EA_SASL_CRAM_MD5:
3562 ap->type = NS_LDAP_AUTH_SASL;
3563 ap->saslmech = NS_LDAP_SASL_CRAM_MD5;
3564 break;
3565 case NS_LDAP_EA_SASL_DIGEST_MD5:
3566 ap->type = NS_LDAP_AUTH_SASL;
3567 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
3568 break;
3569 case NS_LDAP_EA_SASL_DIGEST_MD5_INT:
3570 ap->type = NS_LDAP_AUTH_SASL;
3571 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
3572 ap->saslopt = NS_LDAP_SASLOPT_INT;
3573 break;
3574 case NS_LDAP_EA_SASL_DIGEST_MD5_CONF:
3575 ap->type = NS_LDAP_AUTH_SASL;
3576 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
3577 ap->saslopt = NS_LDAP_SASLOPT_PRIV;
3578 break;
3579 case NS_LDAP_EA_SASL_EXTERNAL:
3580 ap->type = NS_LDAP_AUTH_SASL;
3581 ap->saslmech = NS_LDAP_SASL_EXTERNAL;
3582 break;
3583 case NS_LDAP_EA_SASL_GSSAPI:
3584 ap->type = NS_LDAP_AUTH_SASL;
3585 ap->saslmech = NS_LDAP_SASL_GSSAPI;
3586 ap->saslopt = NS_LDAP_SASLOPT_INT |
3587 NS_LDAP_SASLOPT_PRIV;
3588 break;
3589 case NS_LDAP_EA_TLS_NONE:
3590 ap->type = NS_LDAP_AUTH_TLS;
3591 ap->tlstype = NS_LDAP_TLS_NONE;
3592 break;
3593 case NS_LDAP_EA_TLS_SIMPLE:
3594 ap->type = NS_LDAP_AUTH_TLS;
3595 ap->tlstype = NS_LDAP_TLS_SIMPLE;
3596 break;
3597 case NS_LDAP_EA_TLS_SASL_CRAM_MD5:
3598 ap->type = NS_LDAP_AUTH_TLS;
3599 ap->tlstype = NS_LDAP_TLS_SASL;
3600 ap->saslmech = NS_LDAP_SASL_CRAM_MD5;
3601 break;
3602 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5:
3603 ap->type = NS_LDAP_AUTH_TLS;
3604 ap->tlstype = NS_LDAP_TLS_SASL;
3605 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
3606 break;
3607 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT:
3608 ap->type = NS_LDAP_AUTH_TLS;
3609 ap->tlstype = NS_LDAP_TLS_SASL;
3610 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
3611 ap->saslopt = NS_LDAP_SASLOPT_INT;
3612 break;
3613 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF:
3614 ap->type = NS_LDAP_AUTH_TLS;
3615 ap->tlstype = NS_LDAP_TLS_SASL;
3616 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5;
3617 ap->saslopt = NS_LDAP_SASLOPT_PRIV;
3618 break;
3619 case NS_LDAP_EA_TLS_SASL_EXTERNAL:
3620 ap->type = NS_LDAP_AUTH_TLS;
3621 ap->tlstype = NS_LDAP_TLS_SASL;
3622 ap->saslmech = NS_LDAP_SASL_EXTERNAL;
3623 break;
3624 default:
3625 /* should never get here */
3626 free(ap);
3627 return (NULL);
3629 return (ap);
3634 * Parameter Index Type validation routines
3637 /* Validate a positive integer */
3638 /* Size of errbuf needs to be MAXERROR */
3639 /* ARGSUSED */
3640 static int
3641 __s_val_postime(ParamIndexType i, ns_default_config *def,
3642 ns_param_t *param, char *errbuf)
3644 char *cp;
3645 long tot;
3647 if (param && param->ns_ptype == CHARPTR && param->ns_pc) {
3648 for (cp = param->ns_pc; cp && *cp; cp++) {
3649 if (*cp >= '0' && *cp <= '9')
3650 continue;
3651 switch (*cp) {
3652 case 'w': /* weeks */
3653 case 'd': /* days */
3654 case 'h': /* hours */
3655 case 'm': /* minutes */
3656 case 's': /* seconds */
3657 if (*(cp+1) == '\0') {
3658 break;
3660 default:
3661 (void) strcpy(errbuf, "Illegal time value");
3662 return (NS_PARSE_ERR);
3665 /* Valid form: [0-9][0-9]*[wdhms]* */
3666 tot = atol(param->ns_pc); /* check overflow */
3667 if (tot >= 0)
3668 return (NS_SUCCESS);
3670 (void) snprintf(errbuf, MAXERROR,
3671 gettext("Illegal time value in %s"), def->name);
3672 return (NS_PARSE_ERR);
3676 /* Validate the Base DN */
3677 /* It can be empty (RootDSE request) or needs to have an '=' */
3678 /* Size of errbuf needs to be MAXERROR */
3679 /* ARGSUSED */
3680 static int
3681 __s_val_basedn(ParamIndexType i, ns_default_config *def,
3682 ns_param_t *param, char *errbuf)
3684 if (param && param->ns_ptype == CHARPTR &&
3685 i == NS_LDAP_SEARCH_BASEDN_P &&
3686 ((param->ns_pc == NULL) || /* empty */
3687 (*(param->ns_pc) == '\0') || /* empty */
3688 (strchr(param->ns_pc, '=') != NULL))) /* '=' */
3690 return (NS_SUCCESS);
3692 (void) snprintf(errbuf, MAXERROR,
3693 gettext("Non-existent or invalid DN in %s"),
3694 def->name);
3695 return (NS_PARSE_ERR);
3699 /* Validate the serverList */
3700 /* For each server in list, check if valid IP or hostname */
3701 /* Size of errbuf needs to be MAXERROR */
3702 /* ARGSUSED */
3703 static int
3704 __s_val_serverList(ParamIndexType i, ns_default_config *def,
3705 ns_param_t *param, char *errbuf)
3707 for (i = 0; i < param->ns_acnt; i++) {
3708 if ((__s_api_isipv4(param->ns_ppc[i])) ||
3709 (__s_api_isipv6(param->ns_ppc[i])) ||
3710 (__s_api_ishost(param->ns_ppc[i]))) {
3711 continue;
3713 /* err */
3714 (void) snprintf(errbuf, MAXERROR,
3715 gettext("Invalid server (%s) in %s"),
3716 param->ns_ppc[i], def->name);
3717 return (NS_PARSE_ERR);
3720 return (NS_SUCCESS);
3724 /* Check for a BINDDN */
3725 /* It can not be empty and needs to have an '=' */
3726 /* Size of errbuf needs to be MAXERROR */
3727 /* ARGSUSED */
3728 static int
3729 __s_val_binddn(ParamIndexType i, ns_default_config *def,
3730 ns_param_t *param, char *errbuf)
3732 char *dntype;
3734 if (param && param->ns_ptype == CHARPTR &&
3735 (i == NS_LDAP_BINDDN_P || i == NS_LDAP_ADMIN_BINDDN_P) &&
3736 ((param->ns_pc == NULL) ||
3737 ((*(param->ns_pc) != '\0') &&
3738 (strchr(param->ns_pc, '=') != NULL)))) {
3739 return (NS_SUCCESS);
3741 if (i == NS_LDAP_BINDDN_P)
3742 dntype = "proxy";
3743 else
3744 dntype = "update";
3745 (void) snprintf(errbuf, MAXERROR,
3746 gettext("NULL or invalid %s bind DN"), dntype);
3747 return (NS_PARSE_ERR);
3751 /* Check for a BINDPASSWD */
3752 /* The string can not be NULL or empty */
3753 /* Size of errbuf needs to be MAXERROR */
3754 /* ARGSUSED */
3755 static int
3756 __s_val_bindpw(ParamIndexType i, ns_default_config *def,
3757 ns_param_t *param, char *errbuf)
3759 char *pwtype;
3761 if (param && param->ns_ptype == CHARPTR &&
3762 (i == NS_LDAP_BINDPASSWD_P || i == NS_LDAP_ADMIN_BINDPASSWD_P) &&
3763 ((param->ns_pc == NULL) ||
3764 (*(param->ns_pc) != '\0'))) {
3765 return (NS_SUCCESS);
3767 if (i == NS_LDAP_BINDPASSWD_P)
3768 pwtype = "proxy";
3769 else
3770 pwtype = "admin";
3771 (void) snprintf(errbuf, MAXERROR,
3772 gettext("NULL %s bind password"), pwtype);
3773 return (NS_PARSE_ERR);
3777 * __s_get_hostcertpath returns either the configured host certificate path
3778 * or, if none, the default host certificate path (/var/ldap). Note that this
3779 * does not use __ns_ldap_getParam because it may be called during connection
3780 * setup. This can fail due to insufficient memory.
3783 char *
3784 __s_get_hostcertpath(void)
3786 ns_config_t *cfg;
3787 ns_param_t *param;
3788 char *ret = NULL;
3790 cfg = __s_api_get_default_config();
3791 if (cfg != NULL) {
3792 param = &cfg->paramList[NS_LDAP_HOST_CERTPATH_P];
3793 if (param->ns_ptype == CHARPTR)
3794 ret = strdup(param->ns_pc);
3795 __s_api_release_config(cfg);
3797 if (ret == NULL)
3798 ret = strdup(NSLDAPDIRECTORY);
3799 return (ret);
3802 static void
3803 _free_config()
3805 if (current_config != NULL)
3806 destroy_config(current_config);
3808 current_config = NULL;