1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * libsldap - library side configuration components 28 * Routines to manage the config structure 29 */ 30 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" 58 59 #pragma fini(__s_api_shutdown_conn_mgmt, \ 60 _free_config, __ns_ldap_doorfd_close) 61 62 static mutex_t ns_parse_lock = DEFAULTMUTEX; 63 static mutex_t ns_loadrefresh_lock = DEFAULTMUTEX; 64 static ns_config_t *current_config = NULL; 65 66 static int cache_server = FALSE; 67 extern thread_key_t ns_cmgkey; 68 69 /* 70 * Parameter Index Type validation routines 71 */ 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); 78 79 static int 80 __s_val_binddn(ParamIndexType i, ns_default_config *def, 81 ns_param_t *param, char *errbuf); 82 83 static int 84 __s_val_bindpw(ParamIndexType i, ns_default_config *def, 85 ns_param_t *param, char *errbuf); 86 87 static int 88 __s_val_serverList(ParamIndexType i, ns_default_config *def, 89 ns_param_t *param, char *errbuf); 90 91 /* 92 * Forward declarations 93 */ 94 95 static ns_parse_status 96 verify_value(ns_config_t *cfg, char *name, char *value, char *errstr); 97 98 static int 99 set_default_value(ns_config_t *configptr, char *name, char *value, 100 ns_ldap_error_t **error); 101 102 static void 103 set_curr_config(ns_config_t *ptr); 104 105 static int 106 __door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error); 107 108 static ns_config_t * 109 SetDoorInfo(char *buffer, ns_ldap_error_t **errorp); 110 111 static boolean_t 112 timetorefresh(ns_config_t *cfg); 113 114 static ns_config_t * 115 LoadCacheConfiguration(ns_config_t *, ns_ldap_error_t **error); 116 117 static void ** 118 dupParam(ns_param_t *ptr); 119 120 static time_t 121 conv_time(char *s); 122 123 /* 124 * Structures used in enum <-> string mapping routines 125 */ 126 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 }, 132 }; 133 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 }, 155 }; 156 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 }, 161 }; 162 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 }, 169 }; 170 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 }, 175 }; 176 177 static ns_enum_map ns_ref_enum_v2[] = { 178 { ENUM2INT(NS_LDAP_FOLLOWREF), "TRUE" }, 179 { ENUM2INT(NS_LDAP_NOREF), "FALSE" }, 180 { -1, NULL }, 181 }; 182 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 }, 188 }; 189 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 }, 195 }; 196 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 }, 201 }; 202 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 }, 207 }; 208 209 static int ns_def_auth_v1[] = { 210 ENUM2INT(NS_LDAP_EA_NONE), 211 0 212 }; 213 214 static int ns_def_auth_v2[] = { 215 ENUM2INT(NS_LDAP_EA_NONE), 216 0 217 }; 218 219 static int ns_def_cred_v1[] = { 220 ENUM2INT(NS_LDAP_CRED_PROXY), 221 0 222 }; 223 224 static int ns_def_cred_v2[] = { 225 ENUM2INT(NS_LDAP_CRED_ANON), 226 0 227 }; 228 229 /* 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. 243 * 244 * Note since amd64 is little-endian, the problem is not an issue. 245 * INT2VOIDPTR will just leave the data (i) unchanged. 246 */ 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 253 /* 254 * The default configuration table 255 * Version 1 entries are first, V2 entries follow. 256 */ 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 }, 264 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 }, 271 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 }, 277 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 }, 283 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 }, 289 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 }, 295 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 }, 301 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 }, 307 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 }, 313 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 }, 319 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 }, 325 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 }, 331 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 }, 337 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 }, 343 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 }, 349 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 }, 355 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 }, 361 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 }, 367 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 }, 373 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 }, 379 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 }, 386 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 }, 393 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 }, 399 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 }, 405 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 }, 411 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 }, 417 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 }, 423 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 }, 429 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 }, 435 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 }, 441 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 }, 447 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 }, 453 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 }, 459 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 }, 465 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 }, 471 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 }, 477 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 }, 483 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 }, 489 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 }, 495 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 }, 501 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 }, 507 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 }, 513 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 }, 519 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 }, 525 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 }, 531 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 }, 538 }; 539 540 static char * 541 __getdomainname() 542 { 543 /* 544 * The sysinfo man page recommends using a buffer size 545 * of 257 bytes. MAXHOSTNAMELEN is 256. So add 1 here. 546 */ 547 char buf[MAXHOSTNAMELEN + 1]; 548 int status; 549 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)); 557 } 558 559 void 560 __ns_ldap_setServer(int set) 561 { 562 cache_server = set; 563 } 564 565 static boolean_t 566 timetorefresh(ns_config_t *cfg) 567 { 568 struct timeval tp; 569 static time_t expire = 0; 570 571 if (cfg == NULL || gettimeofday(&tp, NULL) == -1) 572 return (B_TRUE); 573 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); 578 579 return (expire != 0 && tp.tv_sec > expire); 580 } 581 582 int 583 __s_get_enum_value(ns_config_t *ptr, char *value, ParamIndexType i) 584 { 585 register ns_enum_map *mapp; 586 char *pstart = value; 587 char *pend; 588 int len; 589 590 if (pstart == NULL) 591 return (-1); 592 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--) 599 ; 600 len = pend - pstart + 1; 601 if (len == 0) 602 return (-1); 603 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); 645 } 646 647 for (; mapp->name != NULL; mapp++) { 648 if (strncasecmp(pstart, mapp->name, len) == 0 && 649 (strlen(mapp->name) == len)) { 650 return (mapp->value); 651 } 652 } 653 return (-1); 654 } 655 656 char * 657 __s_get_auth_name(ns_config_t *ptr, AuthType_t type) 658 { 659 register ns_enum_map *mapp; 660 661 if (ptr->version == NS_LDAP_V1) 662 mapp = &ns_auth_enum_v1[0]; 663 else 664 mapp = &ns_auth_enum_v2[0]; 665 666 for (; mapp->name != NULL; mapp++) { 667 if (type == INT2AUTHENUM(mapp->value)) { 668 return (mapp->name); 669 } 670 } 671 return ("Unknown AuthType_t type specified"); 672 } 673 674 675 char * 676 __s_get_security_name(ns_config_t *ptr, TlsType_t type) 677 { 678 register ns_enum_map *mapp; 679 680 if (ptr->version == NS_LDAP_V1) { 681 mapp = &ns_sec_enum_v1[0]; 682 683 for (; mapp->name != NULL; mapp++) { 684 if (type == INT2SECENUM(mapp->value)) { 685 return (mapp->name); 686 } 687 } 688 } 689 return ("Unknown TlsType_t type specified"); 690 } 691 692 693 char * 694 __s_get_scope_name(ns_config_t *ptr, ScopeType_t type) 695 { 696 register ns_enum_map *mapp; 697 698 if (ptr->version == NS_LDAP_V1) 699 mapp = &ns_scope_enum_v1[0]; 700 else 701 mapp = &ns_scope_enum_v2[0]; 702 703 for (; mapp->name != NULL; mapp++) { 704 if (type == INT2SCOPEENUM(mapp->value)) { 705 return (mapp->name); 706 } 707 } 708 return ("Unknown ScopeType_t type specified"); 709 } 710 711 712 char * 713 __s_get_pref_name(PrefOnly_t type) 714 { 715 register ns_enum_map *mapp = &ns_pref_enum[0]; 716 717 for (; mapp->name != NULL; mapp++) { 718 if (type == INT2PREFONLYENUM(mapp->value)) { 719 return (mapp->name); 720 } 721 } 722 return ("Unknown PrefOnly_t type specified"); 723 } 724 725 char * 726 __s_get_searchref_name(ns_config_t *ptr, SearchRef_t type) 727 { 728 register ns_enum_map *mapp; 729 730 if (ptr->version == NS_LDAP_V1) 731 mapp = &ns_ref_enum_v1[0]; 732 else 733 mapp = &ns_ref_enum_v2[0]; 734 735 for (; mapp->name != NULL; mapp++) { 736 if (type == INT2SEARCHREFENUM(mapp->value)) { 737 return (mapp->name); 738 } 739 } 740 return ("Unknown SearchRef_t type specified"); 741 } 742 743 char * 744 __s_get_shadowupdate_name(enableShadowUpdate_t type) 745 { 746 register ns_enum_map *mapp; 747 748 mapp = &ns_shadow_update_enum[0]; 749 750 for (; mapp->name != NULL; mapp++) { 751 if (type == INT2SHADOWUPDATENUM(mapp->value)) { 752 return (mapp->name); 753 } 754 } 755 return ("Unknown enableShadowUpdate_t type specified"); 756 } 757 758 static char * 759 __s_get_credlvl_name(ns_config_t *ptr, CredLevel_t type) 760 { 761 register ns_enum_map *mapp; 762 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); 768 } 769 } 770 } 771 return ("Unknown CredLevel_t type specified"); 772 } 773 774 static void 775 destroy_param(ns_config_t *ptr, ParamIndexType type) 776 { 777 int i, j; 778 char **ppc; 779 780 if (ptr == NULL) 781 return; 782 783 /* 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. 787 */ 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; 793 } 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]); 805 } 806 free((void *)ppc); 807 ptr->paramList[type].ns_ppc = NULL; 808 } 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; 815 } 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; 826 } 827 ptr->paramList[type].ns_ptype = NS_UNKNOWN; 828 } 829 830 static void 831 destroy_config(ns_config_t *ptr) 832 { 833 ParamIndexType i; 834 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); 842 } 843 __s_api_destroy_hash(ptr); 844 free(ptr); 845 } 846 } 847 848 /* 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.) 851 * 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. 855 * 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. 861 */ 862 863 void 864 __s_api_destroy_config(ns_config_t *cfg) 865 { 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); 871 } 872 } 873 874 875 /* 876 * Increment the configuration use count by one - assumes ns_parse_lock has 877 * been obtained. 878 */ 879 880 static ns_config_t * 881 get_curr_config_unlocked(ns_config_t *cfg, boolean_t global) 882 { 883 ns_config_t *ret; 884 885 ret = cfg; 886 if (cfg != NULL) { 887 (void) mutex_lock(&cfg->config_mutex); 888 /* 889 * allow access to per connection management (non-global) 890 * config so operations on connection being closed can still 891 * be completed 892 */ 893 if (cfg->delete && global == B_TRUE) 894 ret = NULL; 895 else 896 cfg->nUse++; 897 (void) mutex_unlock(&cfg->config_mutex); 898 } 899 return (ret); 900 } 901 902 /* 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. 907 */ 908 static void 909 set_curr_config_global(ns_config_t *ptr) 910 { 911 ns_config_t *cfg; 912 ns_config_t *cur_cfg; 913 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; 920 } 921 (void) mutex_unlock(&ns_parse_lock); 922 } 923 924 925 /* 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. 932 */ 933 934 static void 935 set_curr_config(ns_config_t *ptr) 936 { 937 ns_config_t *cfg; 938 ns_config_t *cur_cfg; 939 ns_conn_mgmt_t *cmg; 940 int rc; 941 942 rc = thr_getspecific(ns_cmgkey, (void **)&cmg); 943 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; 952 } 953 (void) mutex_unlock(&cmg->cfg_lock); 954 return; 955 } 956 957 /* else set the global current config */ 958 set_curr_config_global(ptr); 959 } 960 961 /* 962 * Decrements the ns_config_t usage count by one. Delete if delete flag 963 * is set and no other callers are using. 964 */ 965 966 void 967 __s_api_release_config(ns_config_t *cfg) 968 { 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); 976 } 977 } 978 979 /* 980 * __s_api_init_config function destroys the previous global configuration 981 * sets the new global configuration and then releases it 982 */ 983 void 984 __s_api_init_config_global(ns_config_t *ptr) 985 { 986 set_curr_config_global(ptr); 987 __s_api_release_config(ptr); 988 } 989 990 /* 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. 994 */ 995 void 996 __s_api_init_config(ns_config_t *ptr) 997 { 998 set_curr_config(ptr); 999 __s_api_release_config(ptr); 1000 } 1001 1002 1003 /* 1004 * Create an ns_config_t, set the usage count to one 1005 */ 1006 1007 ns_config_t * 1008 __s_api_create_config(void) 1009 { 1010 ns_config_t *ret; 1011 ret = (ns_config_t *)calloc(1, sizeof (ns_config_t)); 1012 if (ret == NULL) 1013 return (NULL); 1014 1015 ret->domainName = __getdomainname(); 1016 if (ret->domainName == NULL) { 1017 free(ret); 1018 return (NULL); 1019 } 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); 1025 } 1026 1027 /* 1028 * __s_api_get_default_config_global returns the current global config 1029 */ 1030 ns_config_t * 1031 __s_api_get_default_config_global(void) 1032 { 1033 ns_config_t *cfg; 1034 ns_config_t *cur_cfg; 1035 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); 1040 1041 return (cfg); 1042 } 1043 1044 /* 1045 * __s_api_get_default_config returns the current global config or the 1046 * per connection management one. 1047 */ 1048 ns_config_t * 1049 __s_api_get_default_config(void) 1050 { 1051 ns_config_t *cfg; 1052 ns_config_t *cur_cfg; 1053 ns_conn_mgmt_t *cmg; 1054 int rc; 1055 1056 rc = thr_getspecific(ns_cmgkey, (void **)&cmg); 1057 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); 1065 } 1066 1067 /* else get the global current config */ 1068 return (__s_api_get_default_config_global()); 1069 } 1070 1071 static char * 1072 stripdup(const char *instr) 1073 { 1074 char *pstart = (char *)instr; 1075 char *pend, *ret; 1076 int len; 1077 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--) 1086 ; 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); 1092 } 1093 ret[len] = '\0'; 1094 return (ret); 1095 } 1096 1097 /* 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 1101 */ 1102 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) 1106 { 1107 int value, j; 1108 time_t tm; 1109 const char *str, *str1; 1110 int i, cnt; 1111 int self, gssapi; 1112 1113 if (ptr == NULL) 1114 return (NS_SUCCESS); 1115 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); 1135 } 1136 } 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); 1147 } 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); 1158 } 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); 1167 } 1168 1169 if (check_dn) { 1170 /* check for auth value....passwd/bindn if necessary */ 1171 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); 1193 } 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); 1202 } 1203 break; 1204 } 1205 } 1206 } 1207 1208 /* 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 1214 */ 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); 1221 } 1222 ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm; 1223 } 1224 /* 1225 * If credential level self is defined, there should be 1226 * at least an auth method sasl/GSSAPI and vice versa. 1227 */ 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++; 1234 } 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++; 1241 } 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); 1248 } 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); 1255 } 1256 return (NS_SUCCESS); 1257 } 1258 1259 1260 int 1261 __s_api_get_type(const char *value, ParamIndexType *type) 1262 { 1263 int i; 1264 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); 1269 } 1270 } 1271 return (-1); 1272 } 1273 1274 /* 1275 * Externally defined version of get_type. 1276 * Includes extra error checking 1277 */ 1278 1279 int 1280 __ns_ldap_getParamType(const char *value, ParamIndexType *type) 1281 { 1282 if (value == NULL || type == NULL) 1283 return (-1); 1284 return (__s_api_get_type(value, type)); 1285 } 1286 1287 int 1288 __s_api_get_versiontype(ns_config_t *ptr, char *value, ParamIndexType *type) 1289 { 1290 ns_version_t ver; 1291 int i; 1292 1293 if (ptr == NULL) 1294 return (-1); 1295 1296 ver = ptr->version; 1297 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); 1303 } 1304 } 1305 } 1306 return (-1); 1307 } 1308 1309 int 1310 __s_api_get_profiletype(char *value, ParamIndexType *type) 1311 { 1312 int i; 1313 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); 1320 } 1321 } 1322 return (-1); 1323 } 1324 1325 int 1326 __s_api_get_configtype(ParamIndexType type) 1327 { 1328 int i; 1329 1330 for (i = 0; defconfig[i].name != NULL; i++) { 1331 if (defconfig[i].index == type) { 1332 return (defconfig[i].config_type); 1333 } 1334 } 1335 return (-1); 1336 } 1337 1338 const char * 1339 __s_api_get_configname(ParamIndexType type) 1340 { 1341 int i; 1342 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); 1349 } 1350 } 1351 return (NULL); 1352 } 1353 1354 static ns_default_config * 1355 get_defconfig(ns_config_t *ptr, ParamIndexType type) 1356 { 1357 ns_version_t ver; 1358 int i; 1359 1360 ver = ptr->version; 1361 1362 for (i = 0; defconfig[i].name != NULL; i++) { 1363 if (defconfig[i].index == type && 1364 defconfig[i].version == ver) { 1365 return (&defconfig[i]); 1366 } 1367 } 1368 return (NULL); 1369 } 1370 1371 static int 1372 set_default_value(ns_config_t *configptr, char *name, 1373 char *value, ns_ldap_error_t **error) 1374 { 1375 ParamIndexType i; 1376 int ret; 1377 char errstr[MAXERROR]; 1378 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), 1383 NS_LDAP_MEMORY); 1384 return (NS_LDAP_CONFIG); 1385 } 1386 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); 1395 } 1396 } 1397 1398 ret = __ns_ldap_setParamValue(configptr, i, value, error); 1399 return (ret); 1400 } 1401 1402 1403 /* 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 1408 */ 1409 1410 void 1411 __ns_ldap_default_config() 1412 { 1413 ns_config_t *ptr; 1414 1415 ptr = __s_api_create_config(); 1416 if (ptr == NULL) 1417 return; 1418 1419 set_curr_config(ptr); 1420 __s_api_release_config(ptr); 1421 } 1422 1423 /* 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. 1428 */ 1429 1430 static ns_config_t * 1431 loadrefresh_config(boolean_t global) 1432 { 1433 ns_config_t *cfg; 1434 ns_config_t *new_cfg; 1435 ns_ldap_error_t *errorp; 1436 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(); 1443 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; 1454 } 1455 if (errorp != NULL) 1456 (void) __ns_ldap_freeError(&errorp); 1457 } 1458 (void) mutex_unlock(&ns_loadrefresh_lock); 1459 return (cfg); 1460 } 1461 1462 /* 1463 * Get the current global configuration pointer and return it. 1464 * If necessary initialize or refresh the current 1465 * configuration as applicable. 1466 */ 1467 1468 ns_config_t * 1469 __s_api_loadrefresh_config_global() 1470 { 1471 return (loadrefresh_config(B_TRUE)); 1472 } 1473 1474 /* 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. 1479 */ 1480 1481 ns_config_t * 1482 __s_api_loadrefresh_config() 1483 { 1484 return (loadrefresh_config(B_FALSE)); 1485 } 1486 1487 /* 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. 1491 */ 1492 static ns_parse_status 1493 verify_value(ns_config_t *cfg, char *name, char *value, char *errstr) 1494 { 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; 1500 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); 1505 } 1506 1507 def = get_defconfig(cfg, index); 1508 1509 /* eat up beginning quote, if any */ 1510 while (value != NULL && (*value == QUOTETOK || *value == SPACETOK)) 1511 value++; 1512 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'; 1520 } 1521 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); 1562 } 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); 1578 } 1579 free(tmp); 1580 strptr = strtok_r(NULL, ",", &rest); 1581 } 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; 1591 } 1592 j++; 1593 } 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); 1600 } 1601 } 1602 1603 return (NS_SUCCESS); 1604 } 1605 1606 void 1607 __s_api_split_key_value(char *buffer, char **name, char **value) 1608 { 1609 char *ptr; 1610 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; 1620 } 1621 } 1622 1623 /* 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 1627 * 1628 * This routine translates external string format into internal 1629 * param format and saves the result in the param table. 1630 */ 1631 int 1632 __ns_ldap_setParamValue(ns_config_t *ptr, const ParamIndexType type, 1633 const void *data, ns_ldap_error_t **error) 1634 { 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; 1648 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), 1656 NS_LDAP_MEMORY); 1657 return (NS_LDAP_CONFIG); 1658 } 1659 1660 (void) memset(&conf, 0, sizeof (conf)); 1661 1662 /* data is actually const char */ 1663 cp = (char *)data; 1664 1665 /* eat up beginning quote, if any */ 1666 while (cp && (*cp == QUOTETOK || *cp == SPACETOK)) 1667 cp++; 1668 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--) 1672 ; 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++; 1682 } 1683 *cp2 = '\0'; 1684 cp = tcp; 1685 } 1686 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), NS_LDAP_MEMORY); 1703 if (tcp != NULL) 1704 free(tcp); 1705 return (NS_LDAP_CONFIG); 1706 } 1707 conf.ns_i = i; 1708 break; 1709 case NS_LDAP_TRANSPORT_SEC_P: /* ignore TRANSPORT_SEC */ 1710 break; 1711 default: 1712 cp2 = cp; 1713 if ((*cp2 == '+') || (*cp2 == '-')) 1714 cp2++; 1715 for (/* empty */; *cp2; cp2++) { 1716 if (isdigit(*cp2)) 1717 continue; 1718 1719 (void) snprintf(errstr, sizeof (errstr), 1720 gettext("Unable to set value: " 1721 "invalid %s (%d)"), def->name, 1722 def->index); 1723 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1724 strdup(errstr), NS_LDAP_MEMORY); 1725 if (tcp != NULL) 1726 free(tcp); 1727 return (NS_LDAP_CONFIG); 1728 } 1729 i = atoi(cp); 1730 conf.ns_i = i; 1731 break; 1732 } 1733 break; 1734 case TIMET: 1735 /* Do nothing with a TIMET. Initialize it below */ 1736 break; 1737 case CHARPTR: 1738 conf.ns_pc = (char *)strdup(cp); 1739 if (conf.ns_pc == NULL) { 1740 if (tcp != NULL) 1741 free(tcp); 1742 return (NS_LDAP_MEMORY); 1743 } 1744 break; 1745 case SAMLIST: 1746 /* first check to see if colon (:) is there */ 1747 if ((strchr(cp, COLONTOK)) == NULL) { 1748 (void) snprintf(errstr, sizeof (errstr), 1749 gettext("Unable to set value: " 1750 "invalid serviceAuthenticationMethod (%s)"), 1751 cp); 1752 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1753 strdup(errstr), NS_LDAP_MEMORY); 1754 if (tcp != NULL) 1755 free(tcp); 1756 return (NS_LDAP_CONFIG); 1757 } 1758 /* Appends an entry to the existing list */ 1759 if (ptr->paramList[type].ns_ptype != SAMLIST) { 1760 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1761 if (conf.ns_ppc == NULL) { 1762 if (tcp != NULL) 1763 free(tcp); 1764 return (NS_LDAP_MEMORY); 1765 } 1766 conf.ns_acnt = 1; 1767 conf.ns_ppc[0] = (char *)strdup(cp); 1768 if (conf.ns_ppc[0] == NULL) { 1769 free(conf.ns_ppc); 1770 if (tcp != NULL) 1771 free(tcp); 1772 return (NS_LDAP_MEMORY); 1773 } 1774 } else { 1775 char *dp, *dpend; 1776 int fnd = 0; 1777 1778 /* Attempt to replace if possible */ 1779 dpend = strchr(cp, COLONTOK); 1780 len = dpend - cp; 1781 dp = (char *)malloc(len+1); 1782 if (dp == NULL) { 1783 if (tcp != NULL) 1784 free(tcp); 1785 return (NS_LDAP_MEMORY); 1786 } 1787 (void) strlcpy(dp, cp, len+1); 1788 fnd = 0; 1789 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 1790 dpend = strchr(ptr->paramList[type].ns_ppc[j], 1791 COLONTOK); 1792 if (dpend == NULL) 1793 continue; 1794 i = dpend - ptr->paramList[type].ns_ppc[j]; 1795 if (i != len) 1796 continue; 1797 if (strncmp(ptr->paramList[type].ns_ppc[j], 1798 dp, len) == 0) { 1799 conf.ns_acnt = 1800 ptr->paramList[type].ns_acnt; 1801 conf.ns_ppc = 1802 ptr->paramList[type].ns_ppc; 1803 ptr->paramList[type].ns_ppc = NULL; 1804 free(conf.ns_ppc[j]); 1805 conf.ns_ppc[j] = (char *)strdup(cp); 1806 if (conf.ns_ppc[j] == NULL) { 1807 free(dp); 1808 __s_api_free2dArray 1809 (conf.ns_ppc); 1810 if (tcp != NULL) 1811 free(tcp); 1812 return (NS_LDAP_MEMORY); 1813 } 1814 fnd = 1; 1815 break; 1816 } 1817 } 1818 free(dp); 1819 1820 if (fnd) 1821 break; /* Replaced completed */ 1822 1823 /* Append */ 1824 len = ptr->paramList[type].ns_acnt + 1; 1825 if (len > 1) { 1826 p = (char **)dupParam(&ptr->paramList[type]); 1827 if (p == NULL) { 1828 if (tcp != NULL) 1829 free(tcp); 1830 return (NS_LDAP_MEMORY); 1831 } 1832 } else 1833 p = NULL; 1834 conf.ns_ppc = 1835 (char **)realloc(p, (len+1) * sizeof (char *)); 1836 if (conf.ns_ppc == NULL) { 1837 __s_api_free2dArray(p); 1838 if (tcp != NULL) 1839 free(tcp); 1840 return (NS_LDAP_MEMORY); 1841 } 1842 conf.ns_acnt = len; 1843 conf.ns_ppc[len-1] = (char *)strdup(cp); 1844 if (conf.ns_ppc[len-1] == NULL) { 1845 __s_api_free2dArray(conf.ns_ppc); 1846 if (tcp != NULL) 1847 free(tcp); 1848 return (NS_LDAP_MEMORY); 1849 } 1850 conf.ns_ppc[len] = NULL; 1851 } 1852 break; 1853 case SCLLIST: 1854 /* first check to see if colon (:) is there */ 1855 if ((strchr(cp, COLONTOK)) == NULL) { 1856 (void) snprintf(errstr, sizeof (errstr), 1857 gettext("Unable to set value: " 1858 "invalid serviceCredentialLevel (%s)"), 1859 cp); 1860 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1861 strdup(errstr), NS_LDAP_MEMORY); 1862 if (tcp != NULL) 1863 free(tcp); 1864 return (NS_LDAP_CONFIG); 1865 } 1866 /* Appends an entry to the existing list */ 1867 if (ptr->paramList[type].ns_ptype != SCLLIST) { 1868 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1869 if (conf.ns_ppc == NULL) { 1870 if (tcp != NULL) 1871 free(tcp); 1872 return (NS_LDAP_MEMORY); 1873 } 1874 conf.ns_acnt = 1; 1875 conf.ns_ppc[0] = (char *)strdup(cp); 1876 if (conf.ns_ppc[0] == NULL) { 1877 free(conf.ns_ppc); 1878 if (tcp != NULL) 1879 free(tcp); 1880 return (NS_LDAP_MEMORY); 1881 } 1882 } else { 1883 char *dp, *dpend; 1884 int fnd = 0; 1885 1886 /* Attempt to replace if possible */ 1887 dpend = strchr(cp, COLONTOK); 1888 len = dpend - cp; 1889 dp = (char *)malloc(len+1); 1890 if (dp == NULL) { 1891 if (tcp != NULL) 1892 free(tcp); 1893 return (NS_LDAP_MEMORY); 1894 } 1895 (void) strlcpy(dp, cp, len+1); 1896 fnd = 0; 1897 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 1898 dpend = strchr(ptr->paramList[type].ns_ppc[j], 1899 COLONTOK); 1900 if (dpend == NULL) 1901 continue; 1902 i = dpend - ptr->paramList[type].ns_ppc[j]; 1903 if (i != len) 1904 continue; 1905 if (strncmp(ptr->paramList[type].ns_ppc[j], 1906 dp, len) == 0) { 1907 conf.ns_acnt = 1908 ptr->paramList[type].ns_acnt; 1909 conf.ns_ppc = 1910 ptr->paramList[type].ns_ppc; 1911 ptr->paramList[type].ns_ppc = NULL; 1912 free(conf.ns_ppc[j]); 1913 conf.ns_ppc[j] = (char *)strdup(cp); 1914 if (conf.ns_ppc[j] == NULL) { 1915 free(dp); 1916 __s_api_free2dArray 1917 (conf.ns_ppc); 1918 if (tcp != NULL) 1919 free(tcp); 1920 return (NS_LDAP_MEMORY); 1921 } 1922 fnd = 1; 1923 break; 1924 } 1925 } 1926 free(dp); 1927 1928 if (fnd) 1929 break; /* Replaced completed */ 1930 1931 /* Append */ 1932 len = ptr->paramList[type].ns_acnt + 1; 1933 if (len > 1) { 1934 p = (char **)dupParam(&ptr->paramList[type]); 1935 if (p == NULL) { 1936 if (tcp != NULL) 1937 free(tcp); 1938 return (NS_LDAP_MEMORY); 1939 } 1940 } else 1941 p = NULL; 1942 conf.ns_ppc = 1943 (char **)realloc(p, (len+1) * sizeof (char *)); 1944 if (conf.ns_ppc == NULL) { 1945 __s_api_free2dArray(p); 1946 if (tcp != NULL) 1947 free(tcp); 1948 return (NS_LDAP_MEMORY); 1949 } 1950 conf.ns_acnt = len; 1951 conf.ns_ppc[len-1] = (char *)strdup(cp); 1952 if (conf.ns_ppc[len-1] == NULL) { 1953 __s_api_free2dArray(conf.ns_ppc); 1954 if (tcp != NULL) 1955 free(tcp); 1956 return (NS_LDAP_MEMORY); 1957 } 1958 conf.ns_ppc[len] = NULL; 1959 } 1960 break; 1961 case SSDLIST: 1962 /* 1963 * first check to see if colon (:) is there, 1964 * if so, make sure the serviceId is specified, 1965 * i.e., colon is not the first character 1966 */ 1967 if ((strchr(cp, COLONTOK)) == NULL || *cp == COLONTOK) { 1968 (void) snprintf(errstr, sizeof (errstr), 1969 gettext("Unable to set value: " 1970 "invalid serviceSearchDescriptor (%s)"), 1971 cp); 1972 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1973 strdup(errstr), NS_LDAP_MEMORY); 1974 if (tcp != NULL) 1975 free(tcp); 1976 return (NS_LDAP_CONFIG); 1977 } 1978 /* Appends an entry to the existing list */ 1979 if (ptr->paramList[type].ns_ptype != SSDLIST) { 1980 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1981 if (conf.ns_ppc == NULL) { 1982 if (tcp != NULL) 1983 free(tcp); 1984 return (NS_LDAP_MEMORY); 1985 } 1986 conf.ns_acnt = 1; 1987 conf.ns_ppc[0] = (char *)strdup(cp); 1988 if (conf.ns_ppc[0] == NULL) { 1989 free(conf.ns_ppc); 1990 if (tcp != NULL) 1991 free(tcp); 1992 return (NS_LDAP_MEMORY); 1993 } 1994 } else { 1995 char *dp, *dpend; 1996 int fnd = 0; 1997 1998 /* Attempt to replace if possible */ 1999 dpend = strchr(cp, COLONTOK); 2000 len = dpend - cp; 2001 dp = (char *)malloc(len+1); 2002 if (dp == NULL) { 2003 if (tcp != NULL) 2004 free(tcp); 2005 return (NS_LDAP_MEMORY); 2006 } 2007 (void) strlcpy(dp, cp, len+1); 2008 fnd = 0; 2009 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 2010 dpend = strchr(ptr->paramList[type].ns_ppc[j], 2011 COLONTOK); 2012 if (dpend == NULL) 2013 continue; 2014 i = dpend - ptr->paramList[type].ns_ppc[j]; 2015 if (i != len) 2016 continue; 2017 if (strncmp(ptr->paramList[type].ns_ppc[j], 2018 dp, len) == 0) { 2019 conf.ns_acnt = 2020 ptr->paramList[type].ns_acnt; 2021 conf.ns_ppc = 2022 ptr->paramList[type].ns_ppc; 2023 ptr->paramList[type].ns_ppc = NULL; 2024 free(conf.ns_ppc[j]); 2025 conf.ns_ppc[j] = (char *)strdup(cp); 2026 if (conf.ns_ppc[j] == NULL) { 2027 free(dp); 2028 __s_api_free2dArray 2029 (conf.ns_ppc); 2030 if (tcp != NULL) 2031 free(tcp); 2032 return (NS_LDAP_MEMORY); 2033 } 2034 fnd = 1; 2035 break; 2036 } 2037 } 2038 free(dp); 2039 2040 if (fnd) 2041 break; /* Replaced completed */ 2042 2043 /* Append */ 2044 len = ptr->paramList[type].ns_acnt + 1; 2045 if (len > 1) { 2046 p = (char **)dupParam(&ptr->paramList[type]); 2047 if (p == NULL) { 2048 if (tcp != NULL) 2049 free(tcp); 2050 return (NS_LDAP_MEMORY); 2051 } 2052 } else 2053 p = NULL; 2054 conf.ns_ppc = 2055 (char **)realloc(p, (len+1) * sizeof (char *)); 2056 if (conf.ns_ppc == NULL) { 2057 __s_api_free2dArray(p); 2058 if (tcp != NULL) 2059 free(tcp); 2060 return (NS_LDAP_MEMORY); 2061 } 2062 conf.ns_acnt = len; 2063 conf.ns_ppc[len-1] = (char *)strdup(cp); 2064 if (conf.ns_ppc[len-1] == NULL) { 2065 __s_api_free2dArray(conf.ns_ppc); 2066 if (tcp != NULL) 2067 free(tcp); 2068 return (NS_LDAP_MEMORY); 2069 } 2070 conf.ns_ppc[len] = NULL; 2071 } 2072 break; 2073 case ARRAYCP: 2074 len = 0; 2075 for (cp2 = cp; *cp2; cp2++) { 2076 if (*cp2 == COMMATOK) 2077 len++; 2078 } 2079 if (cp != cp2) 2080 len++; 2081 if (len == 0) { 2082 conf.ns_ppc = (char **)NULL; 2083 conf.ns_acnt = 0; 2084 break; 2085 } 2086 conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *)); 2087 if (conf.ns_ppc == NULL) { 2088 if (tcp != NULL) 2089 free(tcp); 2090 return (NS_LDAP_MEMORY); 2091 } 2092 conf.ns_acnt = len; 2093 i = 0; 2094 for (cp2 = cp; *cp2; cp2++) { 2095 if (*cp2 == COMMATOK) { 2096 j = cp2 - cp + 1; 2097 conf.ns_ppc[i] = (char *)malloc(j + 1); 2098 if (conf.ns_ppc[i] == NULL) { 2099 __s_api_free2dArray(conf.ns_ppc); 2100 if (tcp != NULL) 2101 free(tcp); 2102 return (NS_LDAP_MEMORY); 2103 } 2104 (void) strlcpy(conf.ns_ppc[i], cp, j); 2105 cp = cp2+1; 2106 while (*cp == SPACETOK || *cp == COMMATOK) 2107 cp++; 2108 cp2 = cp - 1; 2109 i++; 2110 } 2111 } 2112 j = cp2 - cp + 1; 2113 conf.ns_ppc[i] = (char *)malloc(j + 1); 2114 if (conf.ns_ppc[i] == NULL) { 2115 __s_api_free2dArray(conf.ns_ppc); 2116 if (tcp != NULL) 2117 free(tcp); 2118 return (NS_LDAP_MEMORY); 2119 } 2120 (void) strlcpy(conf.ns_ppc[i], cp, j); 2121 break; 2122 case SERVLIST: 2123 len = 0; 2124 for (cp2 = cp; *cp2; cp2++) { 2125 if (*cp2 == SPACETOK || *cp2 == COMMATOK) { 2126 len++; 2127 for (; *(cp2 + 1) == SPACETOK || 2128 *(cp2 +1) == COMMATOK; cp2++) 2129 ; 2130 } 2131 } 2132 if (cp != cp2) 2133 len++; 2134 if (len == 0) { 2135 conf.ns_ppc = (char **)NULL; 2136 conf.ns_acnt = 0; 2137 break; 2138 } 2139 conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *)); 2140 if (conf.ns_ppc == NULL) { 2141 if (tcp != NULL) 2142 free(tcp); 2143 return (NS_LDAP_MEMORY); 2144 } 2145 conf.ns_acnt = len; 2146 i = 0; 2147 for (cp2 = cp; *cp2; cp2++) { 2148 if (*cp2 == SPACETOK || *cp2 == COMMATOK) { 2149 j = cp2 - cp + 1; 2150 conf.ns_ppc[i] = (char *)malloc(j + 1); 2151 if (conf.ns_ppc[i] == NULL) { 2152 __s_api_free2dArray(conf.ns_ppc); 2153 if (tcp != NULL) 2154 free(tcp); 2155 return (NS_LDAP_MEMORY); 2156 } 2157 (void) strlcpy(conf.ns_ppc[i], cp, j); 2158 cp = cp2+1; 2159 while (*cp == SPACETOK || *cp == COMMATOK) 2160 cp++; 2161 cp2 = cp - 1; 2162 i++; 2163 } 2164 } 2165 j = cp2 - cp + 1; 2166 conf.ns_ppc[i] = (char *)malloc(j + 1); 2167 if (conf.ns_ppc[i] == NULL) { 2168 __s_api_free2dArray(conf.ns_ppc); 2169 if (tcp != NULL) 2170 free(tcp); 2171 return (NS_LDAP_MEMORY); 2172 } 2173 (void) strlcpy(conf.ns_ppc[i], cp, j); 2174 break; 2175 case ARRAYAUTH: 2176 len = 0; 2177 for (cp2 = cp; *cp2; cp2++) { 2178 if (*cp2 == SEMITOK || *cp2 == COMMATOK) 2179 len++; 2180 } 2181 if (cp != cp2) 2182 len++; 2183 if (len == 0) { 2184 conf.ns_pi = (int *)NULL; 2185 conf.ns_acnt = 0; 2186 break; 2187 } 2188 conf.ns_pi = (int *)calloc(len + 1, sizeof (int)); 2189 if (conf.ns_pi == NULL) { 2190 if (tcp != NULL) 2191 free(tcp); 2192 return (NS_LDAP_MEMORY); 2193 } 2194 conf.ns_acnt = len; 2195 i = 0; 2196 for (cp2 = cp; *cp2; cp2++) { 2197 if (*cp2 == SEMITOK || *cp2 == COMMATOK) { 2198 j = cp2 - cp + 1; 2199 if (j > sizeof (tbuf)) { 2200 j = -1; 2201 ptbuf = cp; 2202 } else { 2203 (void) strlcpy(tbuf, cp, j); 2204 j = __s_get_enum_value(ptr, tbuf, 2205 def->index); 2206 ptbuf = tbuf; 2207 } 2208 if (j < 0) { 2209 (void) snprintf(errstr, sizeof (errstr), 2210 gettext("Unable to set value: " 2211 "invalid " 2212 "authenticationMethod (%s)"), 2213 ptbuf); 2214 MKERROR(LOG_ERR, *error, 2215 NS_CONFIG_SYNTAX, 2216 strdup(errstr), NS_LDAP_MEMORY); 2217 free(conf.ns_pi); 2218 if (tcp != NULL) 2219 free(tcp); 2220 return (NS_LDAP_CONFIG); 2221 } 2222 conf.ns_pi[i] = j; 2223 cp = cp2+1; 2224 i++; 2225 } 2226 } 2227 j = cp2 - cp + 1; 2228 if (j > sizeof (tbuf)) { 2229 j = -1; 2230 ptbuf = cp; 2231 } else { 2232 (void) strlcpy(tbuf, cp, j); 2233 j = __s_get_enum_value(ptr, tbuf, def->index); 2234 ptbuf = tbuf; 2235 } 2236 if (j < 0) { 2237 (void) snprintf(errstr, sizeof (errstr), 2238 gettext("Unable to set value: " 2239 "invalid authenticationMethod (%s)"), ptbuf); 2240 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2241 strdup(errstr), NS_LDAP_MEMORY); 2242 if (tcp != NULL) 2243 free(tcp); 2244 return (NS_LDAP_CONFIG); 2245 } 2246 conf.ns_pi[i] = j; 2247 break; 2248 case ARRAYCRED: 2249 len = 0; 2250 for (cp2 = cp; *cp2; cp2++) { 2251 if (*cp2 == SPACETOK) 2252 len++; 2253 } 2254 if (cp != cp2) 2255 len++; 2256 if (len == 0) { 2257 conf.ns_pi = (int *)NULL; 2258 conf.ns_acnt = 0; 2259 break; 2260 } 2261 conf.ns_pi = (int *)calloc(len + 1, sizeof (int)); 2262 if (conf.ns_pi == NULL) { 2263 if (tcp != NULL) 2264 free(tcp); 2265 return (NS_LDAP_MEMORY); 2266 } 2267 conf.ns_acnt = len; 2268 i = 0; 2269 for (cp2 = cp; *cp2; cp2++) { 2270 if (*cp2 == SPACETOK) { 2271 j = cp2 - cp + 1; 2272 if (j > sizeof (tbuf)) { 2273 j = -1; 2274 ptbuf = cp; 2275 } else { 2276 (void) strlcpy(tbuf, cp, j); 2277 j = __s_get_enum_value(ptr, tbuf, 2278 def->index); 2279 ptbuf = tbuf; 2280 } 2281 if (j < 0) { 2282 (void) snprintf(errstr, sizeof (errstr), 2283 gettext("Unable to set value: " 2284 "invalid credentialLevel (%s)"), 2285 ptbuf); 2286 MKERROR(LOG_ERR, *error, 2287 NS_CONFIG_SYNTAX, 2288 strdup(errstr), NS_LDAP_MEMORY); 2289 free(conf.ns_pi); 2290 if (tcp != NULL) 2291 free(tcp); 2292 return (NS_LDAP_CONFIG); 2293 } 2294 conf.ns_pi[i] = j; 2295 cp = cp2+1; 2296 i++; 2297 } 2298 } 2299 j = cp2 - cp + 1; 2300 if (j > sizeof (tbuf)) { 2301 j = -1; 2302 ptbuf = cp; 2303 } else { 2304 (void) strlcpy(tbuf, cp, j); 2305 j = __s_get_enum_value(ptr, tbuf, def->index); 2306 ptbuf = tbuf; 2307 } 2308 if (j < 0) { 2309 (void) snprintf(errstr, sizeof (errstr), 2310 gettext("Unable to set value: " 2311 "invalid credentialLevel (%s)"), ptbuf); 2312 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2313 strdup(errstr), NS_LDAP_MEMORY); 2314 if (tcp != NULL) 2315 free(tcp); 2316 return (NS_LDAP_CONFIG); 2317 } 2318 conf.ns_pi[i] = j; 2319 break; 2320 case ATTRMAP: 2321 case OBJMAP: 2322 i = __s_api_parse_map(cp, &sid, &origA, &mapA); 2323 if (i != NS_HASH_RC_SUCCESS) { 2324 if (i == NS_HASH_RC_NO_MEMORY) { 2325 exitrc = NS_LDAP_MEMORY; 2326 } else { 2327 (void) snprintf(errstr, sizeof (errstr), 2328 gettext("Unable to set value: " 2329 "invalid schema mapping (%s)"), cp); 2330 exitrc = NS_LDAP_CONFIG; 2331 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2332 strdup(errstr), NS_LDAP_MEMORY); 2333 } 2334 if (tcp) 2335 free(tcp); 2336 return (exitrc); 2337 } 2338 2339 /* 2340 * Add reverse map first. 2341 * There could be more than one. 2342 */ 2343 for (attr = mapA; *attr; attr++) { 2344 2345 free_memory = 1; 2346 exitrc = NS_LDAP_MEMORY; 2347 2348 rmap = (ns_mapping_t *)calloc(1, 2349 sizeof (ns_mapping_t)); 2350 if (rmap) { 2351 rmap->service = strdup(sid); 2352 if (rmap->service) { 2353 rmap->orig = strdup(*attr); 2354 if (rmap->orig) { 2355 rmap->map = (char **)calloc(2, 2356 sizeof (char *)); 2357 if (rmap->map) { 2358 (rmap->map)[0] = 2359 strdup(origA); 2360 if ((rmap->map)[0]) 2361 free_memory = 0; 2362 } 2363 } 2364 } 2365 } 2366 2367 if (free_memory == 0) { 2368 if (def->data_type == ATTRMAP) { 2369 rmap->type = NS_ATTR_MAP; 2370 i = __s_api_add_map2hash(ptr, 2371 NS_HASH_RAMAP, rmap); 2372 } else { 2373 rmap->type = NS_OBJ_MAP; 2374 i = __s_api_add_map2hash(ptr, 2375 NS_HASH_ROMAP, rmap); 2376 } 2377 2378 if (i != NS_HASH_RC_SUCCESS) { 2379 switch (i) { 2380 case NS_HASH_RC_CONFIG_ERROR: 2381 exitrc = NS_LDAP_INTERNAL; 2382 (void) snprintf(errstr, 2383 sizeof (errstr), 2384 gettext( 2385 "Unable to set value: " 2386 "no configuration info " 2387 "for schema map " 2388 "update (%s)"), cp); 2389 MKERROR(LOG_ERR, *error, 2390 NS_LDAP_INTERNAL, 2391 strdup(errstr), 2392 NS_LDAP_MEMORY); 2393 break; 2394 case NS_HASH_RC_EXISTED: 2395 exitrc = NS_LDAP_CONFIG; 2396 (void) snprintf(errstr, 2397 sizeof (errstr), 2398 gettext( 2399 "Unable to set value: " 2400 "schema map " 2401 "already existed for " 2402 "(%s, %s)."), 2403 *attr, origA); 2404 MKERROR(LOG_ERR, *error, 2405 NS_CONFIG_SYNTAX, 2406 strdup(errstr), 2407 NS_LDAP_MEMORY); 2408 break; 2409 case NS_HASH_RC_NO_MEMORY: 2410 exitrc = NS_LDAP_MEMORY; 2411 break; 2412 } 2413 free_memory = 1; 2414 } 2415 } 2416 2417 if (free_memory) { 2418 if (tcp) 2419 free(tcp); 2420 free(sid); 2421 free(origA); 2422 __s_api_free2dArray(mapA); 2423 if (rmap) { 2424 if (rmap->service) 2425 free(rmap->service); 2426 if (rmap->orig) 2427 free(rmap->orig); 2428 if (rmap->map) { 2429 if ((rmap->map)[0]) 2430 free((rmap->map)[0]); 2431 free(rmap->map); 2432 } 2433 free(rmap); 2434 } 2435 return (exitrc); 2436 } 2437 } 2438 2439 /* 2440 * For performance gain, 2441 * add a "schema mapping existed" indicator 2442 * for the given service if not already added. 2443 * This dummy map needs not be removed, if 2444 * the next real map add operation fails. 2445 * since the caller, e.g. ldap_cachemgr. 2446 * should exit anyway. 2447 */ 2448 free_memory = 1; 2449 exitrc = NS_LDAP_MEMORY; 2450 2451 map = (ns_mapping_t *)calloc(1, 2452 sizeof (ns_mapping_t)); 2453 if (map) { 2454 map->service = strdup(sid); 2455 if (map->service) { 2456 map->orig = strdup( 2457 NS_HASH_SCHEMA_MAPPING_EXISTED); 2458 if (map->orig) { 2459 map->map = (char **)calloc(2, 2460 sizeof (char *)); 2461 if (map->map) { 2462 (map->map)[0] = 2463 strdup(sid); 2464 if ((map->map)[0]) 2465 free_memory = 0; 2466 } 2467 } 2468 } 2469 } 2470 2471 if (free_memory == 0) { 2472 map->type = NS_ATTR_MAP; 2473 /* 2474 * add to reverse map, 2475 * so that "ldapclient list" 2476 * would not show it 2477 */ 2478 i = __s_api_add_map2hash(ptr, 2479 NS_HASH_RAMAP, map); 2480 2481 /* 2482 * ignore "map already existed" error, 2483 * just need one per service. 2484 * Need however to free memory allocated 2485 * for map. 2486 */ 2487 if (i != NS_HASH_RC_SUCCESS && 2488 i != NS_HASH_RC_EXISTED) { 2489 switch (i) { 2490 case NS_HASH_RC_CONFIG_ERROR: 2491 exitrc = NS_LDAP_INTERNAL; 2492 (void) snprintf(errstr, 2493 sizeof (errstr), 2494 gettext( 2495 "Unable to set value: " 2496 "no configuration info " 2497 "for schema map " 2498 "update (%s)"), cp); 2499 MKERROR(LOG_ERR, *error, 2500 NS_LDAP_INTERNAL, 2501 strdup(errstr), 2502 NS_LDAP_MEMORY); 2503 break; 2504 case NS_HASH_RC_NO_MEMORY: 2505 exitrc = NS_LDAP_MEMORY; 2506 break; 2507 } 2508 free_memory = 1; 2509 } else if (i == NS_HASH_RC_EXISTED) { 2510 if (map->service) 2511 free(map->service); 2512 if (map->orig) 2513 free(map->orig); 2514 if (map->map) { 2515 if ((map->map)[0]) 2516 free((map->map)[0]); 2517 free(map->map); 2518 } 2519 free(map); 2520 map = NULL; 2521 } 2522 } 2523 2524 if (free_memory) { 2525 if (tcp) 2526 free(tcp); 2527 free(sid); 2528 free(origA); 2529 __s_api_free2dArray(mapA); 2530 if (map) { 2531 if (map->service) 2532 free(map->service); 2533 if (map->orig) 2534 free(map->orig); 2535 if (map->map) { 2536 if ((map->map)[0]) 2537 free((map->map)[0]); 2538 free(map->map); 2539 } 2540 free(map); 2541 } 2542 return (exitrc); 2543 } 2544 2545 /* 2546 * add the real schema map 2547 */ 2548 free_memory = 1; 2549 exitrc = NS_LDAP_MEMORY; 2550 map = (ns_mapping_t *)calloc(1, sizeof (ns_mapping_t)); 2551 if (map) { 2552 map->service = sid; 2553 map->orig = origA; 2554 map->map = mapA; 2555 2556 if (def->data_type == ATTRMAP) { 2557 map->type = NS_ATTR_MAP; 2558 i = __s_api_add_map2hash(ptr, 2559 NS_HASH_AMAP, map); 2560 } else { 2561 map->type = NS_OBJ_MAP; 2562 i = __s_api_add_map2hash(ptr, 2563 NS_HASH_OMAP, map); 2564 } 2565 2566 if (i != NS_HASH_RC_SUCCESS) { 2567 switch (i) { 2568 case NS_HASH_RC_CONFIG_ERROR: 2569 exitrc = NS_LDAP_INTERNAL; 2570 (void) snprintf(errstr, 2571 sizeof (errstr), 2572 gettext( 2573 "Unable to set value: " 2574 "no configuration info " 2575 "for schema map " 2576 "update (%s)"), cp); 2577 MKERROR(LOG_ERR, *error, 2578 NS_LDAP_INTERNAL, 2579 strdup(errstr), 2580 NS_LDAP_MEMORY); 2581 break; 2582 case NS_HASH_RC_EXISTED: 2583 exitrc = NS_LDAP_CONFIG; 2584 (void) snprintf(errstr, 2585 sizeof (errstr), 2586 gettext( 2587 "Unable to set value: " 2588 "schema map " 2589 "already existed for " 2590 "'%s'."), origA); 2591 MKERROR(LOG_ERR, *error, 2592 NS_CONFIG_SYNTAX, 2593 strdup(errstr), 2594 NS_LDAP_MEMORY); 2595 break; 2596 case NS_HASH_RC_NO_MEMORY: 2597 exitrc = NS_LDAP_MEMORY; 2598 break; 2599 } 2600 free_memory = 1; 2601 } else 2602 free_memory = 0; 2603 } 2604 2605 if (free_memory) { 2606 if (tcp) 2607 free(tcp); 2608 free(sid); 2609 free(origA); 2610 __s_api_free2dArray(mapA); 2611 if (map) 2612 free(map); 2613 return (exitrc); 2614 } 2615 2616 break; 2617 default: 2618 /* This should never happen. */ 2619 (void) snprintf(errstr, sizeof (errstr), 2620 gettext("Unable to set value: invalid configuration " 2621 "type (%d)"), def->data_type); 2622 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 2623 NS_LDAP_MEMORY); 2624 if (tcp != NULL) 2625 free(tcp); 2626 return (NS_LDAP_CONFIG); 2627 } 2628 conf.ns_ptype = def->data_type; 2629 if (tcp != NULL) 2630 free(tcp); 2631 2632 /* Individually written verify routines here can replace */ 2633 /* verify_value. Verify conf (data) as appropriate here */ 2634 if (def->ns_verify != NULL) { 2635 if ((*def->ns_verify)(type, def, &conf, errstr) != NS_SUCCESS) { 2636 ns_param_t sav_conf; 2637 2638 MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX, 2639 strdup(errstr), NS_LDAP_MEMORY); 2640 2641 sav_conf = ptr->paramList[type]; 2642 ptr->paramList[type] = conf; 2643 destroy_param(ptr, type); 2644 ptr->paramList[type] = sav_conf; 2645 2646 return (NS_LDAP_CONFIG); 2647 } 2648 } 2649 2650 /* post evaluate the data */ 2651 2652 /* 2653 * if this is for setting a password, 2654 * encrypt the password first. 2655 * NOTE evalue() is smart and will just return 2656 * the value passed if it is already encrypted. 2657 * 2658 * Init NS_LDAP_EXP_P here when CACHETTL is updated 2659 */ 2660 if (type == NS_LDAP_BINDPASSWD_P || 2661 type == NS_LDAP_ADMIN_BINDPASSWD_P) { 2662 cp = conf.ns_pc; 2663 cp2 = evalue((char *)cp); 2664 conf.ns_pc = cp2; 2665 free(cp); 2666 cp = NULL; 2667 } else if (type == NS_LDAP_FILE_VERSION_P) { 2668 ptr->version = NS_LDAP_V1; 2669 if (strcasecmp(conf.ns_pc, NS_LDAP_VERSION_2) == 0) { 2670 ptr->version = NS_LDAP_V2; 2671 } 2672 } else if (type == NS_LDAP_CACHETTL_P) { 2673 cp = conf.ns_pc; 2674 tm = conv_time(cp); 2675 ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET; 2676 if (tm != 0) { 2677 tm += time(NULL); 2678 } 2679 ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm; 2680 } 2681 2682 /* Everything checks out move new values into param */ 2683 destroy_param(ptr, type); 2684 /* Assign new/updated value into paramList */ 2685 ptr->paramList[type] = conf; 2686 2687 return (NS_LDAP_SUCCESS); 2688 } 2689 2690 2691 /* 2692 * Set a parameter value in the 'config' configuration structure 2693 * Lock as appropriate 2694 */ 2695 2696 int 2697 __ns_ldap_setParam(const ParamIndexType type, 2698 const void *data, ns_ldap_error_t **error) 2699 { 2700 ns_ldap_error_t *errorp; 2701 int ret; 2702 char errstr[2 * MAXERROR]; 2703 ns_config_t *cfg; 2704 ns_config_t *cfg_g = (ns_config_t *)-1; 2705 ns_config_t *new_cfg; 2706 boolean_t reinit_connmgmt = B_FALSE; 2707 2708 /* We want to refresh only one configuration at a time */ 2709 (void) mutex_lock(&ns_loadrefresh_lock); 2710 cfg = __s_api_get_default_config(); 2711 2712 if (cache_server == TRUE) { 2713 if (cfg == NULL) { 2714 __ns_ldap_default_config(); 2715 cfg = __s_api_get_default_config(); 2716 if (cfg == NULL) { 2717 (void) mutex_unlock(&ns_loadrefresh_lock); 2718 return (NS_LDAP_MEMORY); 2719 } 2720 } 2721 } else { 2722 /* 2723 * This code always return error here on client side, 2724 * this needs to change once libsldap is used by more 2725 * applications that need to set parameters. 2726 */ 2727 (void) snprintf(errstr, sizeof (errstr), 2728 gettext("Unable to set parameter from a client in " 2729 "__ns_ldap_setParam()")); 2730 MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX, strdup(errstr), 2731 NS_LDAP_MEMORY); 2732 if (cfg != NULL) 2733 __s_api_release_config(cfg); 2734 (void) mutex_unlock(&ns_loadrefresh_lock); 2735 return (NS_LDAP_CONFIG); 2736 } 2737 2738 /* (re)initialize configuration if necessary */ 2739 if (!__s_api_isStandalone() && 2740 cache_server == FALSE && timetorefresh(cfg)) 2741 cfg_g = __s_api_get_default_config_global(); 2742 /* only (re)initialize the global configuration */ 2743 if (cfg == cfg_g) { 2744 if (cfg_g != NULL) 2745 __s_api_release_config(cfg_g); 2746 new_cfg = LoadCacheConfiguration(cfg, &errorp); 2747 if (new_cfg != cfg) 2748 __s_api_release_config(cfg); 2749 if (new_cfg == NULL) { 2750 (void) snprintf(errstr, sizeof (errstr), 2751 gettext("Unable to load configuration '%s' " 2752 "('%s')."), NSCONFIGFILE, 2753 errorp != NULL && errorp->message != NULL ? 2754 errorp->message : ""); 2755 MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED, 2756 strdup(errstr), NS_LDAP_MEMORY); 2757 if (errorp != NULL) 2758 (void) __ns_ldap_freeError(&errorp); 2759 (void) mutex_unlock(&ns_loadrefresh_lock); 2760 return (NS_LDAP_CONFIG); 2761 } 2762 if (new_cfg != cfg) { 2763 set_curr_config_global(new_cfg); 2764 cfg = new_cfg; 2765 reinit_connmgmt = B_TRUE; 2766 } 2767 } 2768 (void) mutex_unlock(&ns_loadrefresh_lock); 2769 2770 if (reinit_connmgmt == B_TRUE) 2771 __s_api_reinit_conn_mgmt_new_config(cfg); 2772 2773 /* translate input and save in the parameter list */ 2774 ret = __ns_ldap_setParamValue(cfg, type, data, error); 2775 2776 __s_api_release_config(cfg); 2777 2778 return (ret); 2779 } 2780 2781 2782 /* 2783 * Make a copy of a parameter entry 2784 */ 2785 2786 static void ** 2787 dupParam(ns_param_t *ptr) 2788 { 2789 int count, i; 2790 void **dupdata, *ret; 2791 int *intptr; 2792 char *cp, tmbuf[32]; 2793 static time_t expire = 0; 2794 ns_auth_t *ap; 2795 2796 switch (ptr->ns_ptype) { 2797 case ARRAYAUTH: 2798 case ARRAYCRED: 2799 case SAMLIST: 2800 case SCLLIST: 2801 case SSDLIST: 2802 case SERVLIST: 2803 case ARRAYCP: 2804 count = ptr->ns_acnt; 2805 if (count == 0) 2806 return (NULL); 2807 break; 2808 case CHARPTR: 2809 case INT: 2810 case TIMET: 2811 count = 1; 2812 } 2813 2814 dupdata = (void **)calloc((count + 1), sizeof (void *)); 2815 if (dupdata == NULL) 2816 return (NULL); 2817 2818 switch (ptr->ns_ptype) { 2819 case ARRAYAUTH: 2820 for (i = 0; i < count; i++) { 2821 ap = __s_api_AuthEnumtoStruct( 2822 (EnumAuthType_t)ptr->ns_pi[i]); 2823 if (ap == NULL) { 2824 free(dupdata); 2825 return (NULL); 2826 } 2827 dupdata[i] = ap; 2828 } 2829 break; 2830 case ARRAYCRED: 2831 for (i = 0; i < count; i++) { 2832 intptr = (int *)malloc(sizeof (int)); 2833 if (intptr == NULL) { 2834 free(dupdata); 2835 return (NULL); 2836 } 2837 dupdata[i] = (void *)intptr; 2838 *intptr = ptr->ns_pi[i]; 2839 } 2840 break; 2841 case SAMLIST: 2842 case SCLLIST: 2843 case SSDLIST: 2844 case SERVLIST: 2845 case ARRAYCP: 2846 for (i = 0; i < count; i++) { 2847 ret = (void *)strdup(ptr->ns_ppc[i]); 2848 if (ret == NULL) { 2849 free(dupdata); 2850 return (NULL); 2851 } 2852 dupdata[i] = ret; 2853 } 2854 break; 2855 case CHARPTR: 2856 if (ptr->ns_pc == NULL) { 2857 free(dupdata); 2858 return (NULL); 2859 } 2860 ret = (void *)strdup(ptr->ns_pc); 2861 if (ret == NULL) { 2862 free(dupdata); 2863 return (NULL); 2864 } 2865 dupdata[0] = ret; 2866 break; 2867 case INT: 2868 intptr = (int *)malloc(sizeof (int)); 2869 if (intptr == NULL) { 2870 free(dupdata); 2871 return (NULL); 2872 } 2873 *intptr = ptr->ns_i; 2874 dupdata[0] = (void *)intptr; 2875 break; 2876 case TIMET: 2877 expire = ptr->ns_tm; 2878 tmbuf[31] = '\0'; 2879 cp = lltostr((long)expire, &tmbuf[31]); 2880 ret = (void *)strdup(cp); 2881 if (ret == NULL) { 2882 free(dupdata); 2883 return (NULL); 2884 } 2885 dupdata[0] = ret; 2886 break; 2887 } 2888 return (dupdata); 2889 } 2890 2891 int 2892 __ns_ldap_freeParam(void ***data) 2893 { 2894 void **tmp; 2895 int i = 0; 2896 2897 if (*data == NULL) 2898 return (NS_LDAP_SUCCESS); 2899 2900 for (i = 0, tmp = *data; tmp[i] != NULL; i++) 2901 free(tmp[i]); 2902 2903 free(*data); 2904 2905 *data = NULL; 2906 2907 return (NS_LDAP_SUCCESS); 2908 } 2909 2910 /* 2911 * Get the internal format for a parameter value. This 2912 * routine makes a copy of an internal param value from 2913 * the currently active parameter list and returns it. 2914 */ 2915 2916 int 2917 __ns_ldap_getParam(const ParamIndexType Param, 2918 void ***data, ns_ldap_error_t **error) 2919 { 2920 char errstr[2 * MAXERROR]; 2921 ns_ldap_error_t *errorp; 2922 ns_default_config *def; 2923 ns_config_t *cfg; 2924 ns_config_t *cfg_g = (ns_config_t *)-1; 2925 ns_config_t *new_cfg; 2926 boolean_t reinit_connmgmt = B_FALSE; 2927 2928 if (data == NULL) 2929 return (NS_LDAP_INVALID_PARAM); 2930 2931 *data = NULL; 2932 2933 /* We want to refresh only one configuration at a time */ 2934 (void) mutex_lock(&ns_loadrefresh_lock); 2935 cfg = __s_api_get_default_config(); 2936 2937 /* (re)initialize configuration if necessary */ 2938 if (!__s_api_isStandalone() && 2939 cache_server == FALSE && timetorefresh(cfg)) 2940 cfg_g = __s_api_get_default_config_global(); 2941 /* only (re)initialize the global configuration */ 2942 if (cfg == cfg_g) { 2943 if (cfg_g != NULL) 2944 __s_api_release_config(cfg_g); 2945 new_cfg = LoadCacheConfiguration(cfg, &errorp); 2946 if (new_cfg != cfg) 2947 __s_api_release_config(cfg); 2948 if (new_cfg == NULL) { 2949 (void) snprintf(errstr, sizeof (errstr), 2950 gettext("Unable to load configuration " 2951 "'%s' ('%s')."), 2952 NSCONFIGFILE, 2953 errorp != NULL && errorp->message != NULL ? 2954 errorp->message : ""); 2955 MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED, 2956 strdup(errstr), NS_LDAP_MEMORY); 2957 if (errorp != NULL) 2958 (void) __ns_ldap_freeError(&errorp); 2959 (void) mutex_unlock(&ns_loadrefresh_lock); 2960 return (NS_LDAP_CONFIG); 2961 } 2962 if (new_cfg != cfg) { 2963 set_curr_config_global(new_cfg); 2964 cfg = new_cfg; 2965 reinit_connmgmt = B_TRUE; 2966 } 2967 } 2968 (void) mutex_unlock(&ns_loadrefresh_lock); 2969 2970 if (reinit_connmgmt == B_TRUE) 2971 __s_api_reinit_conn_mgmt_new_config(cfg); 2972 2973 if (cfg == NULL) { 2974 (void) snprintf(errstr, sizeof (errstr), 2975 gettext("No configuration information available.")); 2976 MKERROR(LOG_ERR, *error, NS_CONFIG_NOTLOADED, 2977 strdup(errstr), NS_LDAP_MEMORY); 2978 return (NS_LDAP_CONFIG); 2979 } 2980 2981 if (Param == NS_LDAP_DOMAIN_P) { 2982 *data = (void **)calloc(2, sizeof (void *)); 2983 if (*data == NULL) { 2984 __s_api_release_config(cfg); 2985 return (NS_LDAP_MEMORY); 2986 } 2987 (*data)[0] = (void *)strdup(cfg->domainName); 2988 if ((*data)[0] == NULL) { 2989 free(*data); 2990 __s_api_release_config(cfg); 2991 return (NS_LDAP_MEMORY); 2992 } 2993 } else if (cfg->paramList[Param].ns_ptype == NS_UNKNOWN) { 2994 /* get default */ 2995 def = get_defconfig(cfg, Param); 2996 if (def != NULL) 2997 *data = dupParam(&def->defval); 2998 } else { 2999 *data = dupParam(&(cfg->paramList[Param])); 3000 } 3001 __s_api_release_config(cfg); 3002 3003 return (NS_LDAP_SUCCESS); 3004 } 3005 3006 /* 3007 * This routine takes a parameter in internal format and 3008 * translates it into a variety of string formats for various 3009 * outputs (doors/file/ldif). This routine would be better 3010 * named: __ns_ldap_translateParam2String 3011 */ 3012 3013 char * 3014 __s_api_strValue(ns_config_t *cfg, ParamIndexType index, ns_strfmt_t fmt) 3015 { 3016 ns_default_config *def = NULL; 3017 ns_param_t *ptr; 3018 ns_hash_t *hptr; 3019 ns_mapping_t *mptr; 3020 char ibuf[14]; 3021 char abuf[64], **cpp; 3022 int count, i; 3023 boolean_t first = B_TRUE; 3024 LineBuf lbuf; 3025 LineBuf *buffer = &lbuf; 3026 char *retstring; 3027 char *sepstr; 3028 3029 if (cfg == NULL) 3030 return (NULL); 3031 3032 /* NS_LDAP_EXP and TRANSPORT_SEC are not exported externally */ 3033 if (index == NS_LDAP_EXP_P || index == NS_LDAP_TRANSPORT_SEC_P) 3034 return (NULL); 3035 3036 /* Return nothing if the value is the default */ 3037 if (cfg->paramList[index].ns_ptype == NS_UNKNOWN) 3038 return (NULL); 3039 3040 (void) memset((char *)buffer, 0, sizeof (LineBuf)); 3041 3042 ptr = &(cfg->paramList[index]); 3043 3044 abuf[0] = '\0'; 3045 3046 /* get default */ 3047 def = get_defconfig(cfg, index); 3048 if (def == NULL) 3049 return (NULL); 3050 3051 switch (fmt) { 3052 case NS_DOOR_FMT: 3053 (void) strlcpy(abuf, def->name, sizeof (abuf)); 3054 (void) strlcat(abuf, EQUALSEP, sizeof (abuf)); 3055 break; 3056 case NS_FILE_FMT: 3057 (void) strlcpy(abuf, def->name, sizeof (abuf)); 3058 (void) strlcat(abuf, EQUSPSEP, sizeof (abuf)); 3059 break; 3060 case NS_LDIF_FMT: 3061 /* If no LDIF attr exists ignore the entry */ 3062 if (def->profile_name == NULL) 3063 return (NULL); 3064 (void) strlcpy(abuf, def->profile_name, sizeof (abuf)); 3065 (void) strlcat(abuf, COLSPSEP, sizeof (abuf)); 3066 break; 3067 default: 3068 break; 3069 } 3070 3071 if (__print2buf(buffer, abuf, NULL)) 3072 goto strValueError; 3073 3074 switch (ptr->ns_ptype) { 3075 case ARRAYAUTH: 3076 count = ptr->ns_acnt; 3077 for (i = 0; i < count; i++) { 3078 sepstr = NULL; 3079 if (i != count-1) { 3080 if (cfg->version == NS_LDAP_V1) { 3081 sepstr = COMMASEP; 3082 } else { 3083 sepstr = SEMISEP; 3084 } 3085 } 3086 if (__print2buf(buffer, __s_get_auth_name(cfg, 3087 (AuthType_t)(ptr->ns_pi[i])), sepstr)) 3088 goto strValueError; 3089 } 3090 break; 3091 case ARRAYCRED: 3092 count = ptr->ns_acnt; 3093 for (i = 0; i < count; i++) { 3094 sepstr = NULL; 3095 if (i != count-1) { 3096 sepstr = SPACESEP; 3097 } 3098 if (__print2buf(buffer, __s_get_credlvl_name(cfg, 3099 (CredLevel_t)ptr->ns_pi[i]), sepstr)) 3100 goto strValueError; 3101 } 3102 break; 3103 case SAMLIST: 3104 case SCLLIST: 3105 case SSDLIST: 3106 count = ptr->ns_acnt; 3107 for (i = 0; i < count; i++) { 3108 if (__print2buf(buffer, ptr->ns_ppc[i], NULL)) 3109 goto strValueError; 3110 3111 if (i == count-1) 3112 continue; 3113 3114 /* Separate items */ 3115 switch (fmt) { 3116 case NS_DOOR_FMT: 3117 if (__print2buf(buffer, DOORLINESEP, NULL) || 3118 __print2buf(buffer, def->name, EQUALSEP)) 3119 goto strValueError; 3120 break; 3121 case NS_FILE_FMT: 3122 if (__print2buf(buffer, "\n", NULL) || 3123 __print2buf(buffer, def->name, EQUSPSEP)) 3124 goto strValueError; 3125 break; 3126 case NS_LDIF_FMT: 3127 if (__print2buf(buffer, "\n", NULL) || 3128 __print2buf(buffer, def->profile_name, 3129 COLSPSEP)) 3130 goto strValueError; 3131 break; 3132 } 3133 } 3134 break; 3135 case ARRAYCP: 3136 count = ptr->ns_acnt; 3137 for (i = 0; i < count; i++) { 3138 sepstr = NULL; 3139 if (i != count-1) { 3140 sepstr = COMMASEP; 3141 } 3142 if (__print2buf(buffer, ptr->ns_ppc[i], sepstr)) 3143 goto strValueError; 3144 } 3145 break; 3146 case SERVLIST: 3147 count = ptr->ns_acnt; 3148 for (i = 0; i < count; i++) { 3149 sepstr = NULL; 3150 if (i != count-1) { 3151 if (fmt == NS_LDIF_FMT) { 3152 sepstr = SPACESEP; 3153 } else { 3154 sepstr = COMMASEP; 3155 } 3156 } 3157 if (__print2buf(buffer, ptr->ns_ppc[i], sepstr)) 3158 goto strValueError; 3159 } 3160 break; 3161 case CHARPTR: 3162 if (ptr->ns_pc == NULL) 3163 break; 3164 if (__print2buf(buffer, ptr->ns_pc, NULL)) 3165 goto strValueError; 3166 break; 3167 case INT: 3168 switch (def->index) { 3169 case NS_LDAP_PREF_ONLY_P: 3170 if (__print2buf(buffer, 3171 __s_get_pref_name((PrefOnly_t)ptr->ns_i), NULL)) 3172 goto strValueError; 3173 break; 3174 case NS_LDAP_SEARCH_REF_P: 3175 if (__print2buf(buffer, __s_get_searchref_name(cfg, 3176 (SearchRef_t)ptr->ns_i), NULL)) 3177 goto strValueError; 3178 break; 3179 case NS_LDAP_SEARCH_SCOPE_P: 3180 if (__print2buf(buffer, __s_get_scope_name(cfg, 3181 (ScopeType_t)ptr->ns_i), NULL)) 3182 goto strValueError; 3183 break; 3184 case NS_LDAP_ENABLE_SHADOW_UPDATE_P: 3185 if (__print2buf(buffer, __s_get_shadowupdate_name( 3186 (enableShadowUpdate_t)ptr->ns_i), NULL)) 3187 goto strValueError; 3188 break; 3189 default: 3190 (void) snprintf(ibuf, sizeof (ibuf), 3191 "%d", ptr->ns_i); 3192 if (__print2buf(buffer, ibuf, NULL)) 3193 goto strValueError; 3194 break; 3195 } 3196 break; 3197 case ATTRMAP: 3198 for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) { 3199 if (hptr->h_type != NS_HASH_AMAP) { 3200 continue; 3201 } 3202 if (!first) { 3203 /* print abuf as "separator" */ 3204 if (fmt == NS_DOOR_FMT) { 3205 if (__print2buf(buffer, DOORLINESEP, 3206 abuf)) 3207 goto strValueError; 3208 } else { 3209 if (__print2buf(buffer, "\n", abuf)) 3210 goto strValueError; 3211 } 3212 } 3213 mptr = hptr->h_map; 3214 if (__print2buf(buffer, mptr->service, COLONSEP) || 3215 __print2buf(buffer, mptr->orig, EQUALSEP)) 3216 goto strValueError; 3217 for (cpp = mptr->map; cpp && *cpp; cpp++) { 3218 /* print *cpp as "separator" */ 3219 sepstr = ""; 3220 if (cpp != mptr->map) 3221 sepstr = SPACESEP; 3222 if (__print2buf(buffer, sepstr, *cpp)) 3223 goto strValueError; 3224 } 3225 first = B_FALSE; 3226 } 3227 break; 3228 case OBJMAP: 3229 for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) { 3230 if (hptr->h_type != NS_HASH_OMAP) { 3231 continue; 3232 } 3233 if (!first) { 3234 /* print abuf as "separator" */ 3235 if (fmt == NS_DOOR_FMT) { 3236 if (__print2buf(buffer, DOORLINESEP, 3237 abuf)) 3238 goto strValueError; 3239 } else { 3240 if (__print2buf(buffer, "\n", abuf)) 3241 goto strValueError; 3242 } 3243 } 3244 mptr = hptr->h_map; 3245 if (__print2buf(buffer, mptr->service, COLONSEP) || 3246 __print2buf(buffer, mptr->orig, EQUALSEP)) 3247 goto strValueError; 3248 for (cpp = mptr->map; cpp && *cpp; cpp++) { 3249 /* print *cpp as "separator" */ 3250 sepstr = ""; 3251 if (cpp != mptr->map) 3252 sepstr = SPACESEP; 3253 if (__print2buf(buffer, sepstr, *cpp)) 3254 goto strValueError; 3255 } 3256 first = B_FALSE; 3257 } 3258 break; 3259 } 3260 3261 retstring = buffer->str; 3262 return (retstring); 3263 3264 strValueError: 3265 if (buffer->len > 0) 3266 free(buffer->str); 3267 return (NULL); 3268 } 3269 3270 /* shared by __door_getldapconfig() and __door_getadmincred() */ 3271 int 3272 __door_getconf(char **buffer, int *buflen, ns_ldap_error_t **error, 3273 int callnumber) 3274 { 3275 typedef union { 3276 ldap_data_t s_d; 3277 char s_b[DOORBUFFERSIZE]; 3278 } space_t; 3279 space_t *space; 3280 3281 ldap_data_t *sptr; 3282 int ndata; 3283 int adata; 3284 char errstr[MAXERROR]; 3285 char *domainname; 3286 ns_ldap_return_code retCode; 3287 ldap_config_out_t *cfghdr; 3288 3289 *error = NULL; 3290 3291 domainname = __getdomainname(); 3292 if (domainname == NULL || buffer == NULL || buflen == NULL || 3293 (strlen(domainname) >= (sizeof (space_t) 3294 - sizeof (space->s_d.ldap_call.ldap_callnumber)))) { 3295 return (NS_LDAP_OP_FAILED); 3296 } 3297 3298 space = (space_t *)calloc(1, sizeof (space_t)); 3299 if (space == NULL) 3300 return (NS_LDAP_MEMORY); 3301 3302 adata = (sizeof (ldap_call_t) + strlen(domainname) +1); 3303 ndata = sizeof (space_t); 3304 space->s_d.ldap_call.ldap_callnumber = callnumber; 3305 (void) strcpy(space->s_d.ldap_call.ldap_u.domainname, domainname); 3306 free(domainname); 3307 domainname = NULL; 3308 sptr = &space->s_d; 3309 3310 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) { 3311 case NS_CACHE_SUCCESS: 3312 break; 3313 case NS_CACHE_NOTFOUND: 3314 (void) snprintf(errstr, sizeof (errstr), 3315 gettext("Door call to " 3316 "ldap_cachemgr failed - error: %d."), 3317 space->s_d.ldap_ret.ldap_errno); 3318 MKERROR(LOG_WARNING, *error, NS_CONFIG_CACHEMGR, 3319 strdup(errstr), NS_LDAP_MEMORY); 3320 free(space); 3321 return (NS_LDAP_OP_FAILED); 3322 default: 3323 free(space); 3324 return (NS_LDAP_OP_FAILED); 3325 } 3326 3327 retCode = NS_LDAP_SUCCESS; 3328 3329 /* copy info from door call to buffer here */ 3330 cfghdr = &sptr->ldap_ret.ldap_u.config_str; 3331 *buflen = offsetof(ldap_config_out_t, config_str) + 3332 cfghdr->data_size + 1; 3333 *buffer = calloc(*buflen, sizeof (char)); 3334 if (*buffer == NULL) { 3335 retCode = NS_LDAP_MEMORY; 3336 } else 3337 (void) memcpy(*buffer, cfghdr, *buflen - 1); 3338 3339 if (sptr != &space->s_d) { 3340 (void) munmap((char *)sptr, ndata); 3341 } 3342 free(space); 3343 3344 return (retCode); 3345 } 3346 3347 static int 3348 __door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error) 3349 { 3350 return (__door_getconf(buffer, buflen, error, GETLDAPCONFIGV1)); 3351 } 3352 3353 /* 3354 * SetDoorInfoToUnixCred parses ldapcachemgr configuration information 3355 * for Admin credentials. 3356 */ 3357 int 3358 SetDoorInfoToUnixCred(char *buffer, ns_ldap_error_t **errorp, 3359 UnixCred_t **cred) 3360 { 3361 UnixCred_t *ptr; 3362 char errstr[MAXERROR]; 3363 char *name, *value, valbuf[BUFSIZE]; 3364 char *bufptr = buffer; 3365 char *strptr; 3366 char *rest; 3367 ParamIndexType index = 0; 3368 ldap_config_out_t *cfghdr; 3369 3370 if (errorp == NULL || cred == NULL || *cred == NULL) 3371 return (NS_LDAP_INVALID_PARAM); 3372 *errorp = NULL; 3373 3374 ptr = *cred; 3375 3376 cfghdr = (ldap_config_out_t *)bufptr; 3377 bufptr = (char *)cfghdr->config_str; 3378 3379 strptr = (char *)strtok_r(bufptr, DOORLINESEP, &rest); 3380 for (; ; ) { 3381 if (strptr == NULL) 3382 break; 3383 (void) strlcpy(valbuf, strptr, sizeof (valbuf)); 3384 __s_api_split_key_value(valbuf, &name, &value); 3385 if (__ns_ldap_getParamType(name, &index) != 0) { 3386 (void) snprintf(errstr, MAXERROR, 3387 gettext("SetDoorInfoToUnixCred: " 3388 "Unknown keyword encountered '%s'."), name); 3389 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX, 3390 strdup(errstr), NS_LDAP_MEMORY); 3391 return (NS_LDAP_CONFIG); 3392 } 3393 switch (index) { 3394 case NS_LDAP_ADMIN_BINDDN_P: 3395 ptr->userID = (char *)strdup(value); 3396 break; 3397 case NS_LDAP_ADMIN_BINDPASSWD_P: 3398 ptr->passwd = (char *)strdup(value); 3399 break; 3400 default: 3401 (void) snprintf(errstr, MAXERROR, 3402 gettext("SetDoorInfoToUnixCred: " 3403 "Unknown index encountered '%d'."), index); 3404 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX, 3405 strdup(errstr), NS_LDAP_MEMORY); 3406 return (NS_LDAP_CONFIG); 3407 } 3408 strptr = (char *)strtok_r(NULL, DOORLINESEP, &rest); 3409 } 3410 3411 return (NS_LDAP_SUCCESS); 3412 } 3413 3414 /* 3415 * SetDoorInfo parses ldapcachemgr configuration information 3416 * and verifies that the profile is version 1 or version 2 based. 3417 * version 2 profiles must have a version number as the first profile 3418 * attribute in the configuration. 3419 */ 3420 static ns_config_t * 3421 SetDoorInfo(char *buffer, ns_ldap_error_t **errorp) 3422 { 3423 ns_config_t *ptr; 3424 char errstr[MAXERROR], errbuf[MAXERROR]; 3425 char *name, *value, valbuf[BUFSIZE]; 3426 char *strptr; 3427 char *rest; 3428 char *bufptr = buffer; 3429 ParamIndexType i; 3430 int ret; 3431 int first = 1; 3432 int errfnd = 0; 3433 ldap_config_out_t *cfghdr; 3434 3435 if (errorp == NULL) 3436 return (NULL); 3437 *errorp = NULL; 3438 3439 ptr = __s_api_create_config(); 3440 if (ptr == NULL) { 3441 return (NULL); 3442 } 3443 3444 /* get config cookie from the header */ 3445 cfghdr = (ldap_config_out_t *)bufptr; 3446 ptr->config_cookie = cfghdr->cookie; 3447 bufptr = (char *)cfghdr->config_str; 3448 3449 strptr = (char *)strtok_r(bufptr, DOORLINESEP, &rest); 3450 for (; ; ) { 3451 if (strptr == NULL) 3452 break; 3453 (void) strlcpy(valbuf, strptr, sizeof (valbuf)); 3454 __s_api_split_key_value(valbuf, &name, &value); 3455 /* Use get_versiontype and check for V1 vs V2 prototypes */ 3456 if (__s_api_get_versiontype(ptr, name, &i) < 0) { 3457 (void) snprintf(errstr, sizeof (errstr), 3458 "%s (%s)\n", 3459 gettext("Illegal profile entry " 3460 "line in configuration."), 3461 name); 3462 errfnd++; 3463 /* Write verify routines and get rid of verify_value here */ 3464 } else if (verify_value(ptr, name, 3465 value, errbuf) != NS_SUCCESS) { 3466 (void) snprintf(errstr, sizeof (errstr), 3467 gettext("%s\n"), errbuf); 3468 errfnd++; 3469 } else if (!first && i == NS_LDAP_FILE_VERSION_P) { 3470 (void) snprintf(errstr, sizeof (errstr), 3471 gettext("Illegal NS_LDAP_FILE_VERSION " 3472 "line in configuration.\n")); 3473 errfnd++; 3474 } 3475 if (errfnd) { 3476 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX, 3477 strdup(errstr), NULL); 3478 } else { 3479 ret = set_default_value(ptr, name, value, errorp); 3480 } 3481 if (errfnd || ret != NS_SUCCESS) { 3482 __s_api_destroy_config(ptr); 3483 return (NULL); 3484 } 3485 first = 0; 3486 3487 strptr = (char *)strtok_r(NULL, DOORLINESEP, &rest); 3488 } 3489 3490 if (__s_api_crosscheck(ptr, errstr, B_TRUE) != NS_SUCCESS) { 3491 __s_api_destroy_config(ptr); 3492 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX, strdup(errstr), 3493 NULL); 3494 return (NULL); 3495 } 3496 3497 return (ptr); 3498 } 3499 3500 static ns_config_t * 3501 LoadCacheConfiguration(ns_config_t *oldcfg, ns_ldap_error_t **error) 3502 { 3503 char *buffer = NULL; 3504 int buflen = 0; 3505 int ret; 3506 ns_config_t *cfg; 3507 ldap_config_out_t *cfghdr; 3508 ldap_get_chg_cookie_t old_cookie; 3509 ldap_get_chg_cookie_t new_cookie; 3510 3511 *error = NULL; 3512 ret = __door_getldapconfig(&buffer, &buflen, error); 3513 3514 if (ret != NS_LDAP_SUCCESS) { 3515 if (*error != NULL && (*error)->message != NULL) 3516 syslog(LOG_WARNING, "libsldap: %s", (*error)->message); 3517 return (NULL); 3518 } 3519 3520 /* No need to reload configuration if config cookie is the same */ 3521 cfghdr = (ldap_config_out_t *)buffer; 3522 new_cookie = cfghdr->cookie; 3523 if (oldcfg != NULL) 3524 old_cookie = oldcfg->config_cookie; 3525 3526 if (oldcfg != NULL && old_cookie.mgr_pid == new_cookie.mgr_pid && 3527 old_cookie.seq_num == new_cookie.seq_num) { 3528 free(buffer); 3529 return (oldcfg); 3530 } 3531 3532 /* now convert from door format */ 3533 cfg = SetDoorInfo(buffer, error); 3534 free(buffer); 3535 3536 if (cfg == NULL && *error != NULL && (*error)->message != NULL) 3537 syslog(LOG_WARNING, "libsldap: %s", (*error)->message); 3538 return (cfg); 3539 } 3540 3541 /* 3542 * converts the time string into seconds. The time string can be specified 3543 * using one of the following time units: 3544 * #s (# of seconds) 3545 * #m (# of minutes) 3546 * #h (# of hours) 3547 * #d (# of days) 3548 * #w (# of weeks) 3549 * NOTE: you can only specify one the above. No combination of the above 3550 * units is allowed. If no unit specified, it will default to "seconds". 3551 */ 3552 static time_t 3553 conv_time(char *s) 3554 { 3555 time_t t; 3556 char c; 3557 int l, m; 3558 long tot; 3559 3560 l = strlen(s); 3561 if (l == 0) 3562 return (0); 3563 c = s[--l]; 3564 m = 0; 3565 switch (c) { 3566 case 'w': /* weeks */ 3567 m = 604800; 3568 break; 3569 case 'd': /* days */ 3570 m = 86400; 3571 break; 3572 case 'h': /* hours */ 3573 m = 3600; 3574 break; 3575 case 'm': /* minutes */ 3576 m = 60; 3577 break; 3578 case 's': /* seconds */ 3579 m = 1; 3580 break; 3581 /* the default case is set to "second" */ 3582 } 3583 if (m != 0) 3584 s[l] = '\0'; 3585 else 3586 m = 1; 3587 errno = 0; 3588 tot = atol(s); 3589 if ((0 == tot) && (EINVAL == errno)) 3590 return (0); 3591 if (((LONG_MAX == tot) || (LONG_MIN == tot)) && (EINVAL == errno)) 3592 return (0); 3593 3594 tot = tot * m; 3595 t = (time_t)tot; 3596 return (t); 3597 } 3598 3599 3600 ns_auth_t * 3601 __s_api_AuthEnumtoStruct(const EnumAuthType_t i) 3602 { 3603 ns_auth_t *ap; 3604 3605 ap = (ns_auth_t *)calloc(1, sizeof (ns_auth_t)); 3606 if (ap == NULL) 3607 return (NULL); 3608 switch (i) { 3609 case NS_LDAP_EA_NONE: 3610 break; 3611 case NS_LDAP_EA_SIMPLE: 3612 ap->type = NS_LDAP_AUTH_SIMPLE; 3613 break; 3614 case NS_LDAP_EA_SASL_CRAM_MD5: 3615 ap->type = NS_LDAP_AUTH_SASL; 3616 ap->saslmech = NS_LDAP_SASL_CRAM_MD5; 3617 break; 3618 case NS_LDAP_EA_SASL_DIGEST_MD5: 3619 ap->type = NS_LDAP_AUTH_SASL; 3620 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3621 break; 3622 case NS_LDAP_EA_SASL_DIGEST_MD5_INT: 3623 ap->type = NS_LDAP_AUTH_SASL; 3624 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3625 ap->saslopt = NS_LDAP_SASLOPT_INT; 3626 break; 3627 case NS_LDAP_EA_SASL_DIGEST_MD5_CONF: 3628 ap->type = NS_LDAP_AUTH_SASL; 3629 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3630 ap->saslopt = NS_LDAP_SASLOPT_PRIV; 3631 break; 3632 case NS_LDAP_EA_SASL_EXTERNAL: 3633 ap->type = NS_LDAP_AUTH_SASL; 3634 ap->saslmech = NS_LDAP_SASL_EXTERNAL; 3635 break; 3636 case NS_LDAP_EA_SASL_GSSAPI: 3637 ap->type = NS_LDAP_AUTH_SASL; 3638 ap->saslmech = NS_LDAP_SASL_GSSAPI; 3639 ap->saslopt = NS_LDAP_SASLOPT_INT | 3640 NS_LDAP_SASLOPT_PRIV; 3641 break; 3642 case NS_LDAP_EA_TLS_NONE: 3643 ap->type = NS_LDAP_AUTH_TLS; 3644 ap->tlstype = NS_LDAP_TLS_NONE; 3645 break; 3646 case NS_LDAP_EA_TLS_SIMPLE: 3647 ap->type = NS_LDAP_AUTH_TLS; 3648 ap->tlstype = NS_LDAP_TLS_SIMPLE; 3649 break; 3650 case NS_LDAP_EA_TLS_SASL_CRAM_MD5: 3651 ap->type = NS_LDAP_AUTH_TLS; 3652 ap->tlstype = NS_LDAP_TLS_SASL; 3653 ap->saslmech = NS_LDAP_SASL_CRAM_MD5; 3654 break; 3655 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5: 3656 ap->type = NS_LDAP_AUTH_TLS; 3657 ap->tlstype = NS_LDAP_TLS_SASL; 3658 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3659 break; 3660 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT: 3661 ap->type = NS_LDAP_AUTH_TLS; 3662 ap->tlstype = NS_LDAP_TLS_SASL; 3663 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3664 ap->saslopt = NS_LDAP_SASLOPT_INT; 3665 break; 3666 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF: 3667 ap->type = NS_LDAP_AUTH_TLS; 3668 ap->tlstype = NS_LDAP_TLS_SASL; 3669 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3670 ap->saslopt = NS_LDAP_SASLOPT_PRIV; 3671 break; 3672 case NS_LDAP_EA_TLS_SASL_EXTERNAL: 3673 ap->type = NS_LDAP_AUTH_TLS; 3674 ap->tlstype = NS_LDAP_TLS_SASL; 3675 ap->saslmech = NS_LDAP_SASL_EXTERNAL; 3676 break; 3677 default: 3678 /* should never get here */ 3679 free(ap); 3680 return (NULL); 3681 } 3682 return (ap); 3683 } 3684 3685 3686 /* 3687 * Parameter Index Type validation routines 3688 */ 3689 3690 /* Validate a positive integer */ 3691 /* Size of errbuf needs to be MAXERROR */ 3692 /* ARGSUSED */ 3693 static int 3694 __s_val_postime(ParamIndexType i, ns_default_config *def, 3695 ns_param_t *param, char *errbuf) 3696 { 3697 char *cp; 3698 long tot; 3699 3700 if (param && param->ns_ptype == CHARPTR && param->ns_pc) { 3701 for (cp = param->ns_pc; cp && *cp; cp++) { 3702 if (*cp >= '0' && *cp <= '9') 3703 continue; 3704 switch (*cp) { 3705 case 'w': /* weeks */ 3706 case 'd': /* days */ 3707 case 'h': /* hours */ 3708 case 'm': /* minutes */ 3709 case 's': /* seconds */ 3710 if (*(cp+1) == '\0') { 3711 break; 3712 } 3713 /* FALLTHROUGH */ 3714 default: 3715 (void) strcpy(errbuf, "Illegal time value"); 3716 return (NS_PARSE_ERR); 3717 } 3718 } 3719 /* Valid form: [0-9][0-9]*[wdhms]* */ 3720 tot = atol(param->ns_pc); /* check overflow */ 3721 if (tot >= 0) 3722 return (NS_SUCCESS); 3723 } 3724 (void) snprintf(errbuf, MAXERROR, 3725 gettext("Illegal time value in %s"), def->name); 3726 return (NS_PARSE_ERR); 3727 } 3728 3729 3730 /* Validate the Base DN */ 3731 /* It can be empty (RootDSE request) or needs to have an '=' */ 3732 /* Size of errbuf needs to be MAXERROR */ 3733 /* ARGSUSED */ 3734 static int 3735 __s_val_basedn(ParamIndexType i, ns_default_config *def, 3736 ns_param_t *param, char *errbuf) 3737 { 3738 if (param && param->ns_ptype == CHARPTR && 3739 i == NS_LDAP_SEARCH_BASEDN_P && 3740 ((param->ns_pc == NULL) || /* empty */ 3741 (*(param->ns_pc) == '\0') || /* empty */ 3742 (strchr(param->ns_pc, '=') != NULL))) /* '=' */ 3743 { 3744 return (NS_SUCCESS); 3745 } 3746 (void) snprintf(errbuf, MAXERROR, 3747 gettext("Non-existent or invalid DN in %s"), 3748 def->name); 3749 return (NS_PARSE_ERR); 3750 } 3751 3752 3753 /* Validate the serverList */ 3754 /* For each server in list, check if valid IP or hostname */ 3755 /* Size of errbuf needs to be MAXERROR */ 3756 /* ARGSUSED */ 3757 static int 3758 __s_val_serverList(ParamIndexType i, ns_default_config *def, 3759 ns_param_t *param, char *errbuf) 3760 { 3761 for (i = 0; i < param->ns_acnt; i++) { 3762 if ((__s_api_isipv4(param->ns_ppc[i])) || 3763 (__s_api_isipv6(param->ns_ppc[i])) || 3764 (__s_api_ishost(param->ns_ppc[i]))) { 3765 continue; 3766 } 3767 /* err */ 3768 (void) snprintf(errbuf, MAXERROR, 3769 gettext("Invalid server (%s) in %s"), 3770 param->ns_ppc[i], def->name); 3771 return (NS_PARSE_ERR); 3772 } 3773 3774 return (NS_SUCCESS); 3775 } 3776 3777 3778 /* Check for a BINDDN */ 3779 /* It can not be empty and needs to have an '=' */ 3780 /* Size of errbuf needs to be MAXERROR */ 3781 /* ARGSUSED */ 3782 static int 3783 __s_val_binddn(ParamIndexType i, ns_default_config *def, 3784 ns_param_t *param, char *errbuf) 3785 { 3786 char *dntype; 3787 3788 if (param && param->ns_ptype == CHARPTR && 3789 (i == NS_LDAP_BINDDN_P || i == NS_LDAP_ADMIN_BINDDN_P) && 3790 ((param->ns_pc == NULL) || 3791 ((*(param->ns_pc) != '\0') && 3792 (strchr(param->ns_pc, '=') != NULL)))) { 3793 return (NS_SUCCESS); 3794 } 3795 if (i == NS_LDAP_BINDDN_P) 3796 dntype = "proxy"; 3797 else 3798 dntype = "update"; 3799 (void) snprintf(errbuf, MAXERROR, 3800 gettext("NULL or invalid %s bind DN"), dntype); 3801 return (NS_PARSE_ERR); 3802 } 3803 3804 3805 /* Check for a BINDPASSWD */ 3806 /* The string can not be NULL or empty */ 3807 /* Size of errbuf needs to be MAXERROR */ 3808 /* ARGSUSED */ 3809 static int 3810 __s_val_bindpw(ParamIndexType i, ns_default_config *def, 3811 ns_param_t *param, char *errbuf) 3812 { 3813 char *pwtype; 3814 3815 if (param && param->ns_ptype == CHARPTR && 3816 (i == NS_LDAP_BINDPASSWD_P || i == NS_LDAP_ADMIN_BINDPASSWD_P) && 3817 ((param->ns_pc == NULL) || 3818 (*(param->ns_pc) != '\0'))) { 3819 return (NS_SUCCESS); 3820 } 3821 if (i == NS_LDAP_BINDPASSWD_P) 3822 pwtype = "proxy"; 3823 else 3824 pwtype = "admin"; 3825 (void) snprintf(errbuf, MAXERROR, 3826 gettext("NULL %s bind password"), pwtype); 3827 return (NS_PARSE_ERR); 3828 } 3829 3830 /* 3831 * __s_get_hostcertpath returns either the configured host certificate path 3832 * or, if none, the default host certificate path (/var/ldap). Note that this 3833 * does not use __ns_ldap_getParam because it may be called during connection 3834 * setup. This can fail due to insufficient memory. 3835 */ 3836 3837 char * 3838 __s_get_hostcertpath(void) 3839 { 3840 ns_config_t *cfg; 3841 ns_param_t *param; 3842 char *ret = NULL; 3843 3844 cfg = __s_api_get_default_config(); 3845 if (cfg != NULL) { 3846 param = &cfg->paramList[NS_LDAP_HOST_CERTPATH_P]; 3847 if (param->ns_ptype == CHARPTR) 3848 ret = strdup(param->ns_pc); 3849 __s_api_release_config(cfg); 3850 } 3851 if (ret == NULL) 3852 ret = strdup(NSLDAPDIRECTORY); 3853 return (ret); 3854 } 3855 3856 static void 3857 _free_config() 3858 { 3859 if (current_config != NULL) 3860 destroy_config(current_config); 3861 3862 current_config = NULL; 3863 } 3864