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, NULL, 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 if (ptr->domainName != NULL) 839 free(ptr->domainName); 840 ptr->domainName = NULL; 841 for (i = 0; i <= LAST_VALUE; i++) { 842 destroy_param(ptr, i); 843 } 844 __s_api_destroy_hash(ptr); 845 free(ptr); 846 } 847 } 848 849 /* 850 * Marks the ns_config_t to be deleted and then releases it. (If no other 851 * caller is using, then __s_api_release_config will destroy it.) 852 * 853 * Note that __s_api_destroy_config should only be called if the caller has 854 * created the ns_config_t with __s_api_create_config (with the exception 855 * of set_curr_config). The ns_config_t should be private to the caller. 856 * 857 * This function should not be called with the current_config except by 858 * set_curr_config which locks ns_parse_lock to ensure that no thread 859 * will be waiting on current_config->config_mutex. This ensures that 860 * no caller with be waiting on cfg->config_mutex while it is being 861 * destroyed by __s_api_release_config. 862 */ 863 864 void 865 __s_api_destroy_config(ns_config_t *cfg) 866 { 867 if (cfg != NULL) { 868 (void) mutex_lock(&cfg->config_mutex); 869 cfg->delete = TRUE; 870 (void) mutex_unlock(&cfg->config_mutex); 871 __s_api_release_config(cfg); 872 } 873 } 874 875 876 /* 877 * Increment the configuration use count by one - assumes ns_parse_lock has 878 * been obtained. 879 */ 880 881 static ns_config_t * 882 get_curr_config_unlocked(ns_config_t *cfg, boolean_t global) 883 { 884 ns_config_t *ret; 885 886 ret = cfg; 887 if (cfg != NULL) { 888 (void) mutex_lock(&cfg->config_mutex); 889 /* 890 * allow access to per connection management (non-global) 891 * config so operations on connection being closed can still 892 * be completed 893 */ 894 if (cfg->delete && global == B_TRUE) 895 ret = NULL; 896 else 897 cfg->nUse++; 898 (void) mutex_unlock(&cfg->config_mutex); 899 } 900 return (ret); 901 } 902 903 /* 904 * set_curr_config_global sets the current global config to the 905 * specified ns_config_t. Note that this function is similar 906 * to the project private function __s_api_init_config_global 907 * except that it does not release the new ns_config_t. 908 */ 909 static void 910 set_curr_config_global(ns_config_t *ptr) 911 { 912 ns_config_t *cfg; 913 ns_config_t *cur_cfg; 914 915 (void) mutex_lock(&ns_parse_lock); 916 cur_cfg = current_config; 917 cfg = get_curr_config_unlocked(cur_cfg, B_TRUE); 918 if (cfg != ptr) { 919 __s_api_destroy_config(cfg); 920 current_config = ptr; 921 } 922 (void) mutex_unlock(&ns_parse_lock); 923 } 924 925 926 /* 927 * set_curr_config sets the current config or the per connection 928 * management one to the specified ns_config_t. Note that this function 929 * is similar to the project private function __s_api_init_config 930 * except that it does not release the new ns_config_t. Also note 931 * that if there's no per connection management one to set, the 932 * global current config will be set. 933 */ 934 935 static void 936 set_curr_config(ns_config_t *ptr) 937 { 938 ns_config_t *cfg; 939 ns_config_t *cur_cfg; 940 ns_conn_mgmt_t *cmg; 941 int rc; 942 943 rc = thr_getspecific(ns_cmgkey, (void **)&cmg); 944 945 /* set the per connection management config if possible */ 946 if (rc == 0 && cmg != NULL && cmg->config != NULL) { 947 (void) mutex_lock(&cmg->cfg_lock); 948 cur_cfg = cmg->config; 949 cfg = get_curr_config_unlocked(cur_cfg, B_FALSE); 950 if (cfg != ptr) { 951 __s_api_destroy_config(cfg); 952 cmg->config = ptr; 953 } 954 (void) mutex_unlock(&cmg->cfg_lock); 955 return; 956 } 957 958 /* else set the global current config */ 959 set_curr_config_global(ptr); 960 } 961 962 /* 963 * Decrements the ns_config_t usage count by one. Delete if delete flag 964 * is set and no other callers are using. 965 */ 966 967 void 968 __s_api_release_config(ns_config_t *cfg) 969 { 970 if (cfg != NULL) { 971 (void) mutex_lock(&cfg->config_mutex); 972 cfg->nUse--; 973 if (cfg->nUse == 0 && cfg->delete) { 974 destroy_config(cfg); 975 } else 976 (void) mutex_unlock(&cfg->config_mutex); 977 } 978 } 979 980 /* 981 * __s_api_init_config function destroys the previous global configuration 982 * sets the new global configuration and then releases it 983 */ 984 void 985 __s_api_init_config_global(ns_config_t *ptr) 986 { 987 set_curr_config_global(ptr); 988 __s_api_release_config(ptr); 989 } 990 991 /* 992 * __s_api_init_config function destroys the previous configuration 993 * sets the new configuration and then releases it. The configuration 994 * may be the global one or the per connection management one. 995 */ 996 void 997 __s_api_init_config(ns_config_t *ptr) 998 { 999 set_curr_config(ptr); 1000 __s_api_release_config(ptr); 1001 } 1002 1003 1004 /* 1005 * Create an ns_config_t, set the usage count to one 1006 */ 1007 1008 ns_config_t * 1009 __s_api_create_config(void) 1010 { 1011 ns_config_t *ret; 1012 ret = (ns_config_t *)calloc(1, sizeof (ns_config_t)); 1013 if (ret == NULL) 1014 return (NULL); 1015 1016 ret->domainName = __getdomainname(); 1017 if (ret->domainName == NULL) { 1018 free(ret); 1019 return (NULL); 1020 } 1021 ret->version = NS_LDAP_V1; 1022 (void) mutex_init(&ret->config_mutex, USYNC_THREAD, NULL); 1023 ret->nUse = 1; 1024 ret->delete = B_FALSE; 1025 return (ret); 1026 } 1027 1028 /* 1029 * __s_api_get_default_config_global returns the current global config 1030 */ 1031 ns_config_t * 1032 __s_api_get_default_config_global(void) 1033 { 1034 ns_config_t *cfg; 1035 ns_config_t *cur_cfg; 1036 1037 (void) mutex_lock(&ns_parse_lock); 1038 cur_cfg = current_config; 1039 cfg = get_curr_config_unlocked(cur_cfg, B_TRUE); 1040 (void) mutex_unlock(&ns_parse_lock); 1041 1042 return (cfg); 1043 } 1044 1045 /* 1046 * __s_api_get_default_config returns the current global config or the 1047 * per connection management one. 1048 */ 1049 ns_config_t * 1050 __s_api_get_default_config(void) 1051 { 1052 ns_config_t *cfg; 1053 ns_config_t *cur_cfg; 1054 ns_conn_mgmt_t *cmg; 1055 int rc; 1056 1057 rc = thr_getspecific(ns_cmgkey, (void **)&cmg); 1058 1059 /* get the per connection management config if available */ 1060 if (rc == 0 && cmg != NULL && cmg->config != NULL) { 1061 (void) mutex_lock(&cmg->cfg_lock); 1062 cur_cfg = cmg->config; 1063 cfg = get_curr_config_unlocked(cur_cfg, B_FALSE); 1064 (void) mutex_unlock(&cmg->cfg_lock); 1065 return (cfg); 1066 } 1067 1068 /* else get the global current config */ 1069 return (__s_api_get_default_config_global()); 1070 } 1071 1072 static char * 1073 stripdup(const char *instr) 1074 { 1075 char *pstart = (char *)instr; 1076 char *pend, *ret; 1077 int len; 1078 1079 if (pstart == NULL) 1080 return (NULL); 1081 /* remove leading spaces */ 1082 while (*pstart == SPACETOK) 1083 pstart++; 1084 /* remove trailing spaces */ 1085 pend = pstart + strlen(pstart) - 1; 1086 for (; pend >= pstart && *pend == SPACETOK; pend--) 1087 ; 1088 len = pend - pstart + 1; 1089 if ((ret = malloc(len + 1)) == NULL) 1090 return (NULL); 1091 if (len != 0) { 1092 (void) strncpy(ret, pstart, len); 1093 } 1094 ret[len] = '\0'; 1095 return (ret); 1096 } 1097 1098 /* 1099 * Note that __s_api_crosscheck is assumed to be called with an ns_config_t 1100 * that is properly protected - so that it will not change during the 1101 * duration of the call 1102 */ 1103 1104 /* Size of errstr needs to be MAXERROR */ 1105 ns_parse_status 1106 __s_api_crosscheck(ns_config_t *ptr, char *errstr, int check_dn) 1107 { 1108 int value, j; 1109 time_t tm; 1110 const char *str, *str1; 1111 int i, cnt; 1112 int self, gssapi; 1113 1114 if (ptr == NULL) 1115 return (NS_SUCCESS); 1116 1117 /* check for no server specified */ 1118 if (ptr->paramList[NS_LDAP_SERVERS_P].ns_ppc == NULL) { 1119 if (ptr->version == NS_LDAP_V1) { 1120 str = NULL_OR_STR(__s_api_get_configname( 1121 NS_LDAP_SERVERS_P)); 1122 (void) snprintf(errstr, MAXERROR, 1123 gettext("Configuration Error: No entry for " 1124 "'%s' found"), str); 1125 return (NS_PARSE_ERR); 1126 } else if (ptr->paramList[NS_LDAP_SERVER_PREF_P].ns_ppc == 1127 NULL) { 1128 str = NULL_OR_STR(__s_api_get_configname( 1129 NS_LDAP_SERVERS_P)); 1130 str1 = NULL_OR_STR(__s_api_get_configname( 1131 NS_LDAP_SERVER_PREF_P)); 1132 (void) snprintf(errstr, MAXERROR, 1133 gettext("Configuration Error: " 1134 "Neither '%s' nor '%s' is defined"), str, str1); 1135 return (NS_PARSE_ERR); 1136 } 1137 } 1138 if (ptr->paramList[NS_LDAP_CERT_PASS_P].ns_pc != NULL && 1139 ptr->paramList[NS_LDAP_CERT_PATH_P].ns_pc == NULL) { 1140 str = NULL_OR_STR(__s_api_get_configname( 1141 NS_LDAP_CERT_PASS_P)); 1142 str1 = NULL_OR_STR(__s_api_get_configname( 1143 NS_LDAP_CERT_PATH_P)); 1144 (void) snprintf(errstr, MAXERROR, 1145 gettext("Configuration Error: %s specified " 1146 "but no value for '%s' found"), str, str1); 1147 return (NS_PARSE_ERR); 1148 } 1149 if (ptr->paramList[NS_LDAP_CERT_PASS_P].ns_pc == NULL && 1150 ptr->paramList[NS_LDAP_CERT_PATH_P].ns_pc != NULL) { 1151 str = NULL_OR_STR(__s_api_get_configname( 1152 NS_LDAP_CERT_PATH_P)); 1153 str1 = NULL_OR_STR(__s_api_get_configname( 1154 NS_LDAP_CERT_PASS_P)); 1155 (void) snprintf(errstr, MAXERROR, 1156 gettext("Configuration Error: %s specified " 1157 "but no value for '%s' found"), str, str1); 1158 return (NS_PARSE_ERR); 1159 } 1160 /* check if search basedn has been specified */ 1161 if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ppc == NULL) { 1162 str = NULL_OR_STR(__s_api_get_configname( 1163 NS_LDAP_SEARCH_BASEDN_P)); 1164 (void) snprintf(errstr, MAXERROR, 1165 gettext("Configuration Error: No entry for " 1166 "'%s' found"), str); 1167 return (NS_PARSE_ERR); 1168 } 1169 1170 if (check_dn) { 1171 /* check for auth value....passwd/bindn if necessary */ 1172 1173 for (j = 0; ptr->paramList[NS_LDAP_AUTH_P].ns_pi != NULL && 1174 ptr->paramList[NS_LDAP_AUTH_P].ns_pi[j] != NULL; j++) { 1175 value = ptr->paramList[NS_LDAP_AUTH_P].ns_pi[j]; 1176 switch (value) { 1177 case NS_LDAP_EA_SIMPLE: 1178 case NS_LDAP_EA_SASL_CRAM_MD5: 1179 case NS_LDAP_EA_SASL_DIGEST_MD5: 1180 case NS_LDAP_EA_SASL_DIGEST_MD5_INT: 1181 case NS_LDAP_EA_SASL_DIGEST_MD5_CONF: 1182 case NS_LDAP_EA_TLS_SIMPLE: 1183 case NS_LDAP_EA_TLS_SASL_CRAM_MD5: 1184 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5: 1185 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT: 1186 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF: 1187 if (ptr->paramList[NS_LDAP_BINDDN_P].ns_ppc == NULL) { 1188 str = NULL_OR_STR(__s_api_get_configname( 1189 NS_LDAP_BINDDN_P)); 1190 (void) snprintf(errstr, MAXERROR, 1191 gettext("Configuration Error: No entry for " 1192 "'%s' found"), str); 1193 return (NS_PARSE_ERR); 1194 } 1195 if (ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ppc 1196 == NULL) { 1197 str = NULL_OR_STR(__s_api_get_configname( 1198 NS_LDAP_BINDPASSWD_P)); 1199 (void) snprintf(errstr, MAXERROR, 1200 gettext("Configuration Error: No entry for " 1201 "'%s' found"), str); 1202 return (NS_PARSE_ERR); 1203 } 1204 break; 1205 } 1206 } 1207 } 1208 1209 /* 1210 * If NS_LDAP_CACHETTL is not specified, 1211 * init NS_LDAP_EXP_P here. Otherwise, 1212 * ldap_cachemgr will never refresh the profile. 1213 * Set it to current time + default 1214 * NS_LDAP_CACHETTL 1215 */ 1216 if (ptr->paramList[NS_LDAP_CACHETTL_P].ns_pc == NULL) { 1217 tm = conv_time( 1218 defconfig[NS_LDAP_CACHETTL_P].defval.ns_pc); 1219 ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET; 1220 if (tm != 0) { 1221 tm += time(NULL); 1222 } 1223 ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm; 1224 } 1225 /* 1226 * If credential level self is defined, there should be 1227 * at least an auth method sasl/GSSAPI and vice versa. 1228 */ 1229 self = 0; 1230 cnt = ptr->paramList[NS_LDAP_CREDENTIAL_LEVEL_P].ns_acnt; 1231 for (i = 0; i < cnt; i++) { 1232 if (ptr->paramList[NS_LDAP_CREDENTIAL_LEVEL_P].ns_pi[i] == 1233 NS_LDAP_CRED_SELF) 1234 self++; 1235 } 1236 gssapi = 0; 1237 cnt = ptr->paramList[NS_LDAP_AUTH_P].ns_acnt; 1238 for (i = 0; i < cnt; i++) { 1239 if (ptr->paramList[NS_LDAP_AUTH_P].ns_pi[i] == 1240 NS_LDAP_EA_SASL_GSSAPI) 1241 gssapi++; 1242 } 1243 if (gssapi == 0 && self > 0) { 1244 (void) snprintf(errstr, MAXERROR, 1245 gettext("Configuration Error: " 1246 "Credential level self requires " 1247 "authentication method sasl/GSSAPI")); 1248 return (NS_PARSE_ERR); 1249 } 1250 if (gssapi > 0 && self == 0) { 1251 (void) snprintf(errstr, MAXERROR, 1252 gettext("Configuration Error: " 1253 "Authentication method sasl/GSSAPI " 1254 "requires credential level self")); 1255 return (NS_PARSE_ERR); 1256 } 1257 return (NS_SUCCESS); 1258 } 1259 1260 1261 int 1262 __s_api_get_type(const char *value, ParamIndexType *type) 1263 { 1264 int i; 1265 1266 for (i = 0; defconfig[i].name != NULL; i++) { 1267 if (strcasecmp(defconfig[i].name, value) == 0) { 1268 *type = defconfig[i].index; 1269 return (0); 1270 } 1271 } 1272 return (-1); 1273 } 1274 1275 /* 1276 * Externally defined version of get_type. 1277 * Includes extra error checking 1278 */ 1279 1280 int 1281 __ns_ldap_getParamType(const char *value, ParamIndexType *type) 1282 { 1283 if (value == NULL || type == NULL) 1284 return (-1); 1285 return (__s_api_get_type(value, type)); 1286 } 1287 1288 int 1289 __s_api_get_versiontype(ns_config_t *ptr, char *value, ParamIndexType *type) 1290 { 1291 ns_version_t ver; 1292 int i; 1293 1294 if (ptr == NULL) 1295 return (-1); 1296 1297 ver = ptr->version; 1298 1299 for (i = 0; defconfig[i].name != NULL; i++) { 1300 if (strcasecmp(defconfig[i].name, value) == 0) { 1301 if (defconfig[i].version == ver) { 1302 *type = defconfig[i].index; 1303 return (0); 1304 } 1305 } 1306 } 1307 return (-1); 1308 } 1309 1310 int 1311 __s_api_get_profiletype(char *value, ParamIndexType *type) 1312 { 1313 int i; 1314 1315 for (i = 0; defconfig[i].name != NULL; i++) { 1316 if (defconfig[i].profile_name == NULL) 1317 continue; 1318 if (strcasecmp(defconfig[i].profile_name, value) == 0) { 1319 *type = defconfig[i].index; 1320 return (0); 1321 } 1322 } 1323 return (-1); 1324 } 1325 1326 int 1327 __s_api_get_configtype(ParamIndexType type) 1328 { 1329 int i; 1330 1331 for (i = 0; defconfig[i].name != NULL; i++) { 1332 if (defconfig[i].index == type) { 1333 return (defconfig[i].config_type); 1334 } 1335 } 1336 return (-1); 1337 } 1338 1339 const char * 1340 __s_api_get_configname(ParamIndexType type) 1341 { 1342 int i; 1343 1344 for (i = 0; defconfig[i].name != NULL; i++) { 1345 if (defconfig[i].index == type) { 1346 if (defconfig[i].name[0] == '\0') 1347 return (NULL); 1348 else 1349 return (defconfig[i].name); 1350 } 1351 } 1352 return (NULL); 1353 } 1354 1355 static ns_default_config * 1356 get_defconfig(ns_config_t *ptr, ParamIndexType type) 1357 { 1358 ns_version_t ver; 1359 int i; 1360 1361 ver = ptr->version; 1362 1363 for (i = 0; defconfig[i].name != NULL; i++) { 1364 if (defconfig[i].index == type && 1365 defconfig[i].version == ver) { 1366 return (&defconfig[i]); 1367 } 1368 } 1369 return (NULL); 1370 } 1371 1372 static int 1373 set_default_value(ns_config_t *configptr, char *name, 1374 char *value, ns_ldap_error_t **error) 1375 { 1376 ParamIndexType i; 1377 int ret; 1378 char errstr[MAXERROR]; 1379 1380 if (__s_api_get_type(name, &i) < 0) { 1381 (void) snprintf(errstr, sizeof (errstr), gettext( 1382 "Illegal type name (%s).\n"), name); 1383 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 1384 NULL); 1385 return (NS_LDAP_CONFIG); 1386 } 1387 1388 if (i != NS_LDAP_SERVERS_P && 1389 i != NS_LDAP_SERVICE_AUTH_METHOD_P && 1390 i != NS_LDAP_SERVICE_CRED_LEVEL_P && 1391 i != NS_LDAP_SERVICE_SEARCH_DESC_P && 1392 i != NS_LDAP_SERVER_PREF_P && 1393 i != NS_LDAP_SEARCH_DN_P) { 1394 if (configptr->paramList[i].ns_ptype != NS_UNKNOWN) { 1395 destroy_param(configptr, i); 1396 } 1397 } 1398 1399 ret = __ns_ldap_setParamValue(configptr, i, value, error); 1400 return (ret); 1401 } 1402 1403 1404 /* 1405 * Initialize config to a default state 1406 * By default leave configuration empty 1407 * getParam will automatically get the 1408 * appropriate default value if none exists 1409 */ 1410 1411 void 1412 __ns_ldap_default_config() 1413 { 1414 ns_config_t *ptr; 1415 1416 ptr = __s_api_create_config(); 1417 if (ptr == NULL) 1418 return; 1419 1420 set_curr_config(ptr); 1421 __s_api_release_config(ptr); 1422 } 1423 1424 /* 1425 * Get the current configuration pointer and return it. 1426 * If necessary initialize or refresh the current 1427 * configuration as applicable. If global is set, returns 1428 * the global one. 1429 */ 1430 1431 static ns_config_t * 1432 loadrefresh_config(boolean_t global) 1433 { 1434 ns_config_t *cfg; 1435 ns_config_t *new_cfg; 1436 ns_ldap_error_t *errorp; 1437 1438 /* We want to refresh only one configuration at a time */ 1439 (void) mutex_lock(&ns_loadrefresh_lock); 1440 if (global == B_TRUE) 1441 cfg = __s_api_get_default_config_global(); 1442 else 1443 cfg = __s_api_get_default_config(); 1444 1445 /* (re)initialize configuration if necessary */ 1446 if (!__s_api_isStandalone() && timetorefresh(cfg)) { 1447 new_cfg = LoadCacheConfiguration(cfg, &errorp); 1448 if (new_cfg != NULL && new_cfg != cfg) { 1449 __s_api_release_config(cfg); 1450 if (global == B_TRUE) 1451 set_curr_config_global(new_cfg); 1452 else 1453 set_curr_config(new_cfg); 1454 cfg = new_cfg; 1455 } 1456 if (errorp != NULL) 1457 (void) __ns_ldap_freeError(&errorp); 1458 } 1459 (void) mutex_unlock(&ns_loadrefresh_lock); 1460 return (cfg); 1461 } 1462 1463 /* 1464 * Get the current global configuration pointer and return it. 1465 * If necessary initialize or refresh the current 1466 * configuration as applicable. 1467 */ 1468 1469 ns_config_t * 1470 __s_api_loadrefresh_config_global() 1471 { 1472 return (loadrefresh_config(B_TRUE)); 1473 } 1474 1475 /* 1476 * Get the current configuration pointer and return it. 1477 * If necessary initialize or refresh the current 1478 * configuration as applicable. The configuration may 1479 * be the global one or the per connection management one. 1480 */ 1481 1482 ns_config_t * 1483 __s_api_loadrefresh_config() 1484 { 1485 return (loadrefresh_config(B_FALSE)); 1486 } 1487 1488 /* 1489 * In general this routine is not very usefull. Individual routines can be 1490 * created to do this job. Once that is done, this function can be removed. 1491 * Size of errstr buffer needs to be MAXERROR. 1492 */ 1493 static ns_parse_status 1494 verify_value(ns_config_t *cfg, char *name, char *value, char *errstr) 1495 { 1496 ParamIndexType index = 0; 1497 int found = 0, j; 1498 char *ptr = NULL, *strptr = NULL, buffer[BUFSIZE]; 1499 char *rest; 1500 ns_default_config *def = NULL; 1501 1502 if (__s_api_get_type(name, &index) != 0) { 1503 (void) snprintf(errstr, MAXERROR, 1504 gettext("Unknown keyword encountered '%s'."), name); 1505 return (NS_PARSE_ERR); 1506 } 1507 1508 def = get_defconfig(cfg, index); 1509 1510 /* eat up beginning quote, if any */ 1511 while (value != NULL && (*value == QUOTETOK || *value == SPACETOK)) 1512 value++; 1513 1514 /* eat up space/quote at end of value */ 1515 if (strlen(value) > 0) 1516 ptr = value + strlen(value) - 1; 1517 else 1518 ptr = value; 1519 for (; ptr != value && (*ptr == SPACETOK || *ptr == QUOTETOK); ptr--) { 1520 *ptr = '\0'; 1521 } 1522 1523 switch (index) { 1524 case NS_LDAP_EXP_P: 1525 case NS_LDAP_CACHETTL_P: 1526 case NS_LDAP_CERT_PATH_P: 1527 case NS_LDAP_CERT_PASS_P: 1528 case NS_LDAP_CERT_NICKNAME_P: 1529 case NS_LDAP_BINDDN_P: 1530 case NS_LDAP_BINDPASSWD_P: 1531 case NS_LDAP_ADMIN_BINDDN_P: 1532 case NS_LDAP_ADMIN_BINDPASSWD_P: 1533 case NS_LDAP_DOMAIN_P: 1534 case NS_LDAP_SEARCH_BASEDN_P: 1535 case NS_LDAP_SEARCH_TIME_P: 1536 case NS_LDAP_PROFILE_P: 1537 case NS_LDAP_AUTH_P: 1538 case NS_LDAP_SEARCH_SCOPE_P: 1539 case NS_LDAP_CREDENTIAL_LEVEL_P: 1540 case NS_LDAP_SERVICE_SEARCH_DESC_P: 1541 case NS_LDAP_BIND_TIME_P: 1542 case NS_LDAP_ATTRIBUTEMAP_P: 1543 case NS_LDAP_OBJECTCLASSMAP_P: 1544 case NS_LDAP_SERVICE_AUTH_METHOD_P: 1545 case NS_LDAP_SERVICE_CRED_LEVEL_P: 1546 case NS_LDAP_HOST_CERTPATH_P: 1547 break; 1548 case NS_LDAP_SEARCH_DN_P: 1549 /* depreciated because of service descriptors */ 1550 /* Parse as appropriate at descriptor create time */ 1551 break; 1552 case NS_LDAP_FILE_VERSION_P: 1553 if (value != NULL && 1554 strcasecmp(value, NS_LDAP_VERSION_1) != 0 && 1555 strcasecmp(value, NS_LDAP_VERSION_2) != 0) { 1556 (void) snprintf(errstr, MAXERROR, 1557 gettext("Version mismatch, expected " 1558 "cache version '%s' or '%s' but " 1559 "encountered version '%s'."), 1560 NS_LDAP_VERSION_1, 1561 NS_LDAP_VERSION_2, value); 1562 return (NS_PARSE_ERR); 1563 } 1564 break; 1565 case NS_LDAP_SERVERS_P: 1566 case NS_LDAP_SERVER_PREF_P: 1567 (void) strcpy(buffer, value); 1568 strptr = strtok_r(buffer, ",", &rest); 1569 while (strptr != NULL) { 1570 char *tmp = NULL; 1571 tmp = stripdup(strptr); 1572 if (tmp == NULL || (strchr(tmp, ' ') != NULL)) { 1573 (void) snprintf(errstr, MAXERROR, 1574 gettext("Invalid parameter values " 1575 "'%s' specified for keyword '%s'."), 1576 tmp, name); 1577 free(tmp); 1578 return (NS_PARSE_ERR); 1579 } 1580 free(tmp); 1581 strptr = strtok_r(NULL, ",", &rest); 1582 } 1583 break; 1584 default: 1585 found = 0; j = 0; 1586 while (def->allowed != NULL && 1587 def->allowed[j].name != NULL && j < DEFMAX) { 1588 if (strcmp(def->allowed[j].name, 1589 value) == 0) { 1590 found = 1; 1591 break; 1592 } 1593 j++; 1594 } 1595 if (!found) { 1596 (void) snprintf(errstr, MAXERROR, 1597 gettext("Invalid option specified for " 1598 "'%s' keyword. '%s' is not a recognized " 1599 "keyword value."), name, value); 1600 return (NS_PARSE_ERR); 1601 } 1602 } 1603 1604 return (NS_SUCCESS); 1605 } 1606 1607 void 1608 __s_api_split_key_value(char *buffer, char **name, char **value) 1609 { 1610 char *ptr; 1611 1612 *name = buffer; 1613 /* split into name value pair */ 1614 if ((ptr = strchr(buffer, TOKENSEPARATOR)) != NULL) { 1615 *ptr = '\0'; 1616 ptr++; 1617 /* trim whitespace */ 1618 while (*ptr == SPACETOK) 1619 ptr++; 1620 *value = ptr; 1621 } 1622 } 1623 1624 /* 1625 * Set a parameter value in a generic configuration structure 1626 * Assume any necessary locks are in place. This routine would 1627 * be better named: __ns_ldap_translateString2Param 1628 * 1629 * This routine translates external string format into internal 1630 * param format and saves the result in the param table. 1631 */ 1632 int 1633 __ns_ldap_setParamValue(ns_config_t *ptr, const ParamIndexType type, 1634 const void *data, ns_ldap_error_t **error) 1635 { 1636 ns_default_config *def = NULL; 1637 ns_param_t conf; 1638 ns_mapping_t *map, *rmap; 1639 int i, j, len; 1640 char *cp, *cp2, *end; 1641 char *tcp = NULL; 1642 char errstr[2 * MAXERROR]; 1643 char tbuf[100], *ptbuf; 1644 char *sid, *origA, **mapA; 1645 char **attr; 1646 time_t tm; 1647 int free_memory, exitrc; 1648 char **p; 1649 1650 /* Find ParamIndexType default configuration data */ 1651 def = get_defconfig(ptr, type); 1652 if (def == NULL) { 1653 (void) snprintf(errstr, sizeof (errstr), 1654 gettext("Unable to set value: " 1655 "invalid ParamIndexType (%d)"), type); 1656 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 1657 NULL); 1658 return (NS_LDAP_CONFIG); 1659 } 1660 1661 (void) memset(&conf, 0, sizeof (conf)); 1662 1663 /* data is actually const char */ 1664 cp = (char *)data; 1665 1666 /* eat up beginning quote, if any */ 1667 while (cp && (*cp == QUOTETOK || *cp == SPACETOK)) 1668 cp++; 1669 1670 /* eat up space/quote at end of value */ 1671 end = cp2 = cp + strlen(cp) - 1; 1672 for (; cp2 > cp && (*cp2 == SPACETOK || *cp2 == QUOTETOK); cp2--) 1673 ; 1674 /* data is const, must duplicate */ 1675 if (cp2 != end) { 1676 tcp = (char *)calloc((int)(cp2 - cp + 2), sizeof (char)); 1677 if (tcp == NULL) 1678 return (NS_LDAP_MEMORY); 1679 end = cp2; 1680 cp2 = tcp; 1681 while (cp <= end) { 1682 *cp2++ = *cp++; 1683 } 1684 *cp2 = '\0'; 1685 cp = tcp; 1686 } 1687 1688 /* Parse data according to type */ 1689 switch (def->data_type) { 1690 case INT: 1691 switch (def->index) { 1692 case NS_LDAP_PREF_ONLY_P: 1693 case NS_LDAP_SEARCH_REF_P: 1694 case NS_LDAP_SEARCH_SCOPE_P: 1695 case NS_LDAP_ENABLE_SHADOW_UPDATE_P: 1696 i = __s_get_enum_value(ptr, cp, def->index); 1697 if (i < 0) { 1698 (void) snprintf(errstr, sizeof (errstr), 1699 gettext("Unable to set value: " 1700 "invalid %s (%d)"), def->name, 1701 def->index); 1702 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1703 strdup(errstr), NULL); 1704 if (tcp != NULL) 1705 free(tcp); 1706 return (NS_LDAP_CONFIG); 1707 } 1708 conf.ns_i = i; 1709 break; 1710 case NS_LDAP_TRANSPORT_SEC_P: /* ignore TRANSPORT_SEC */ 1711 break; 1712 default: 1713 cp2 = cp; 1714 if ((*cp2 == '+') || (*cp2 == '-')) 1715 cp2++; 1716 for (/* empty */; *cp2; cp2++) { 1717 if (isdigit(*cp2)) 1718 continue; 1719 1720 (void) snprintf(errstr, sizeof (errstr), 1721 gettext("Unable to set value: " 1722 "invalid %s (%d)"), def->name, 1723 def->index); 1724 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1725 strdup(errstr), NULL); 1726 if (tcp != NULL) 1727 free(tcp); 1728 return (NS_LDAP_CONFIG); 1729 } 1730 i = atoi(cp); 1731 conf.ns_i = i; 1732 break; 1733 } 1734 break; 1735 case TIMET: 1736 /* Do nothing with a TIMET. Initialize it below */ 1737 break; 1738 case CHARPTR: 1739 conf.ns_pc = (char *)strdup(cp); 1740 if (conf.ns_pc == NULL) { 1741 if (tcp != NULL) 1742 free(tcp); 1743 return (NS_LDAP_MEMORY); 1744 } 1745 break; 1746 case SAMLIST: 1747 /* first check to see if colon (:) is there */ 1748 if ((strchr(cp, COLONTOK)) == NULL) { 1749 (void) snprintf(errstr, sizeof (errstr), 1750 gettext("Unable to set value: " 1751 "invalid serviceAuthenticationMethod (%s)"), 1752 cp); 1753 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1754 strdup(errstr), NULL); 1755 if (tcp != NULL) 1756 free(tcp); 1757 return (NS_LDAP_CONFIG); 1758 } 1759 /* Appends an entry to the existing list */ 1760 if (ptr->paramList[type].ns_ptype != SAMLIST) { 1761 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1762 if (conf.ns_ppc == NULL) { 1763 if (tcp != NULL) 1764 free(tcp); 1765 return (NS_LDAP_MEMORY); 1766 } 1767 conf.ns_acnt = 1; 1768 conf.ns_ppc[0] = (char *)strdup(cp); 1769 if (conf.ns_ppc[0] == NULL) { 1770 free(conf.ns_ppc); 1771 if (tcp != NULL) 1772 free(tcp); 1773 return (NS_LDAP_MEMORY); 1774 } 1775 } else { 1776 char *dp, *dpend; 1777 int fnd = 0; 1778 1779 /* Attempt to replace if possible */ 1780 dpend = strchr(cp, COLONTOK); 1781 len = dpend - cp; 1782 dp = (char *)malloc(len+1); 1783 if (dp == NULL) { 1784 if (tcp != NULL) 1785 free(tcp); 1786 return (NS_LDAP_MEMORY); 1787 } 1788 (void) strlcpy(dp, cp, len+1); 1789 fnd = 0; 1790 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 1791 dpend = strchr(ptr->paramList[type].ns_ppc[j], 1792 COLONTOK); 1793 if (dpend == NULL) 1794 continue; 1795 i = dpend - ptr->paramList[type].ns_ppc[j]; 1796 if (i != len) 1797 continue; 1798 if (strncmp(ptr->paramList[type].ns_ppc[j], 1799 dp, len) == 0) { 1800 conf.ns_acnt = 1801 ptr->paramList[type].ns_acnt; 1802 conf.ns_ppc = 1803 ptr->paramList[type].ns_ppc; 1804 ptr->paramList[type].ns_ppc = NULL; 1805 free(conf.ns_ppc[j]); 1806 conf.ns_ppc[j] = (char *)strdup(cp); 1807 if (conf.ns_ppc[j] == NULL) { 1808 free(dp); 1809 __s_api_free2dArray 1810 (conf.ns_ppc); 1811 if (tcp != NULL) 1812 free(tcp); 1813 return (NS_LDAP_MEMORY); 1814 } 1815 fnd = 1; 1816 break; 1817 } 1818 } 1819 free(dp); 1820 1821 if (fnd) 1822 break; /* Replaced completed */ 1823 1824 /* Append */ 1825 len = ptr->paramList[type].ns_acnt + 1; 1826 if (len > 1) { 1827 p = (char **)dupParam(&ptr->paramList[type]); 1828 if (p == NULL) { 1829 if (tcp != NULL) 1830 free(tcp); 1831 return (NS_LDAP_MEMORY); 1832 } 1833 } else 1834 p = NULL; 1835 conf.ns_ppc = 1836 (char **)realloc(p, (len+1) * sizeof (char *)); 1837 if (conf.ns_ppc == NULL) { 1838 __s_api_free2dArray(p); 1839 if (tcp != NULL) 1840 free(tcp); 1841 return (NS_LDAP_MEMORY); 1842 } 1843 conf.ns_acnt = len; 1844 conf.ns_ppc[len-1] = (char *)strdup(cp); 1845 if (conf.ns_ppc[len-1] == NULL) { 1846 __s_api_free2dArray(conf.ns_ppc); 1847 if (tcp != NULL) 1848 free(tcp); 1849 return (NS_LDAP_MEMORY); 1850 } 1851 conf.ns_ppc[len] = NULL; 1852 } 1853 break; 1854 case SCLLIST: 1855 /* first check to see if colon (:) is there */ 1856 if ((strchr(cp, COLONTOK)) == NULL) { 1857 (void) snprintf(errstr, sizeof (errstr), 1858 gettext("Unable to set value: " 1859 "invalid serviceCredentialLevel (%s)"), 1860 cp); 1861 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1862 strdup(errstr), NULL); 1863 if (tcp != NULL) 1864 free(tcp); 1865 return (NS_LDAP_CONFIG); 1866 } 1867 /* Appends an entry to the existing list */ 1868 if (ptr->paramList[type].ns_ptype != SCLLIST) { 1869 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1870 if (conf.ns_ppc == NULL) { 1871 if (tcp != NULL) 1872 free(tcp); 1873 return (NS_LDAP_MEMORY); 1874 } 1875 conf.ns_acnt = 1; 1876 conf.ns_ppc[0] = (char *)strdup(cp); 1877 if (conf.ns_ppc[0] == NULL) { 1878 free(conf.ns_ppc); 1879 if (tcp != NULL) 1880 free(tcp); 1881 return (NS_LDAP_MEMORY); 1882 } 1883 } else { 1884 char *dp, *dpend; 1885 int fnd = 0; 1886 1887 /* Attempt to replace if possible */ 1888 dpend = strchr(cp, COLONTOK); 1889 len = dpend - cp; 1890 dp = (char *)malloc(len+1); 1891 if (dp == NULL) { 1892 if (tcp != NULL) 1893 free(tcp); 1894 return (NS_LDAP_MEMORY); 1895 } 1896 (void) strlcpy(dp, cp, len+1); 1897 fnd = 0; 1898 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 1899 dpend = strchr(ptr->paramList[type].ns_ppc[j], 1900 COLONTOK); 1901 if (dpend == NULL) 1902 continue; 1903 i = dpend - ptr->paramList[type].ns_ppc[j]; 1904 if (i != len) 1905 continue; 1906 if (strncmp(ptr->paramList[type].ns_ppc[j], 1907 dp, len) == 0) { 1908 conf.ns_acnt = 1909 ptr->paramList[type].ns_acnt; 1910 conf.ns_ppc = 1911 ptr->paramList[type].ns_ppc; 1912 ptr->paramList[type].ns_ppc = NULL; 1913 free(conf.ns_ppc[j]); 1914 conf.ns_ppc[j] = (char *)strdup(cp); 1915 if (conf.ns_ppc[j] == NULL) { 1916 free(dp); 1917 __s_api_free2dArray 1918 (conf.ns_ppc); 1919 if (tcp != NULL) 1920 free(tcp); 1921 return (NS_LDAP_MEMORY); 1922 } 1923 fnd = 1; 1924 break; 1925 } 1926 } 1927 free(dp); 1928 1929 if (fnd) 1930 break; /* Replaced completed */ 1931 1932 /* Append */ 1933 len = ptr->paramList[type].ns_acnt + 1; 1934 if (len > 1) { 1935 p = (char **)dupParam(&ptr->paramList[type]); 1936 if (p == NULL) { 1937 if (tcp != NULL) 1938 free(tcp); 1939 return (NS_LDAP_MEMORY); 1940 } 1941 } else 1942 p = NULL; 1943 conf.ns_ppc = 1944 (char **)realloc(p, (len+1) * sizeof (char *)); 1945 if (conf.ns_ppc == NULL) { 1946 __s_api_free2dArray(p); 1947 if (tcp != NULL) 1948 free(tcp); 1949 return (NS_LDAP_MEMORY); 1950 } 1951 conf.ns_acnt = len; 1952 conf.ns_ppc[len-1] = (char *)strdup(cp); 1953 if (conf.ns_ppc[len-1] == NULL) { 1954 __s_api_free2dArray(conf.ns_ppc); 1955 if (tcp != NULL) 1956 free(tcp); 1957 return (NS_LDAP_MEMORY); 1958 } 1959 conf.ns_ppc[len] = NULL; 1960 } 1961 break; 1962 case SSDLIST: 1963 /* 1964 * first check to see if colon (:) is there, 1965 * if so, make sure the serviceId is specified, 1966 * i.e., colon is not the first character 1967 */ 1968 if ((strchr(cp, COLONTOK)) == NULL || *cp == COLONTOK) { 1969 (void) snprintf(errstr, sizeof (errstr), 1970 gettext("Unable to set value: " 1971 "invalid serviceSearchDescriptor (%s)"), 1972 cp); 1973 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1974 strdup(errstr), NULL); 1975 if (tcp != NULL) 1976 free(tcp); 1977 return (NS_LDAP_CONFIG); 1978 } 1979 /* Appends an entry to the existing list */ 1980 if (ptr->paramList[type].ns_ptype != SSDLIST) { 1981 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1982 if (conf.ns_ppc == NULL) { 1983 if (tcp != NULL) 1984 free(tcp); 1985 return (NS_LDAP_MEMORY); 1986 } 1987 conf.ns_acnt = 1; 1988 conf.ns_ppc[0] = (char *)strdup(cp); 1989 if (conf.ns_ppc[0] == NULL) { 1990 free(conf.ns_ppc); 1991 if (tcp != NULL) 1992 free(tcp); 1993 return (NS_LDAP_MEMORY); 1994 } 1995 } else { 1996 char *dp, *dpend; 1997 int fnd = 0; 1998 1999 /* Attempt to replace if possible */ 2000 dpend = strchr(cp, COLONTOK); 2001 len = dpend - cp; 2002 dp = (char *)malloc(len+1); 2003 if (dp == NULL) { 2004 if (tcp != NULL) 2005 free(tcp); 2006 return (NS_LDAP_MEMORY); 2007 } 2008 (void) strlcpy(dp, cp, len+1); 2009 fnd = 0; 2010 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 2011 dpend = strchr(ptr->paramList[type].ns_ppc[j], 2012 COLONTOK); 2013 if (dpend == NULL) 2014 continue; 2015 i = dpend - ptr->paramList[type].ns_ppc[j]; 2016 if (i != len) 2017 continue; 2018 if (strncmp(ptr->paramList[type].ns_ppc[j], 2019 dp, len) == 0) { 2020 conf.ns_acnt = 2021 ptr->paramList[type].ns_acnt; 2022 conf.ns_ppc = 2023 ptr->paramList[type].ns_ppc; 2024 ptr->paramList[type].ns_ppc = NULL; 2025 free(conf.ns_ppc[j]); 2026 conf.ns_ppc[j] = (char *)strdup(cp); 2027 if (conf.ns_ppc[j] == NULL) { 2028 free(dp); 2029 __s_api_free2dArray 2030 (conf.ns_ppc); 2031 if (tcp != NULL) 2032 free(tcp); 2033 return (NS_LDAP_MEMORY); 2034 } 2035 fnd = 1; 2036 break; 2037 } 2038 } 2039 free(dp); 2040 2041 if (fnd) 2042 break; /* Replaced completed */ 2043 2044 /* Append */ 2045 len = ptr->paramList[type].ns_acnt + 1; 2046 if (len > 1) { 2047 p = (char **)dupParam(&ptr->paramList[type]); 2048 if (p == NULL) { 2049 if (tcp != NULL) 2050 free(tcp); 2051 return (NS_LDAP_MEMORY); 2052 } 2053 } else 2054 p = NULL; 2055 conf.ns_ppc = 2056 (char **)realloc(p, (len+1) * sizeof (char *)); 2057 if (conf.ns_ppc == NULL) { 2058 __s_api_free2dArray(p); 2059 if (tcp != NULL) 2060 free(tcp); 2061 return (NS_LDAP_MEMORY); 2062 } 2063 conf.ns_acnt = len; 2064 conf.ns_ppc[len-1] = (char *)strdup(cp); 2065 if (conf.ns_ppc[len-1] == NULL) { 2066 __s_api_free2dArray(conf.ns_ppc); 2067 if (tcp != NULL) 2068 free(tcp); 2069 return (NS_LDAP_MEMORY); 2070 } 2071 conf.ns_ppc[len] = NULL; 2072 } 2073 break; 2074 case ARRAYCP: 2075 len = 0; 2076 for (cp2 = cp; *cp2; cp2++) { 2077 if (*cp2 == COMMATOK) 2078 len++; 2079 } 2080 if (cp != cp2) 2081 len++; 2082 if (len == 0) { 2083 conf.ns_ppc = (char **)NULL; 2084 conf.ns_acnt = 0; 2085 break; 2086 } 2087 conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *)); 2088 if (conf.ns_ppc == NULL) { 2089 if (tcp != NULL) 2090 free(tcp); 2091 return (NS_LDAP_MEMORY); 2092 } 2093 conf.ns_acnt = len; 2094 i = 0; 2095 for (cp2 = cp; *cp2; cp2++) { 2096 if (*cp2 == COMMATOK) { 2097 j = cp2 - cp + 1; 2098 conf.ns_ppc[i] = (char *)malloc(j + 1); 2099 if (conf.ns_ppc[i] == NULL) { 2100 __s_api_free2dArray(conf.ns_ppc); 2101 if (tcp != NULL) 2102 free(tcp); 2103 return (NS_LDAP_MEMORY); 2104 } 2105 (void) strlcpy(conf.ns_ppc[i], cp, j); 2106 cp = cp2+1; 2107 while (*cp == SPACETOK || *cp == COMMATOK) 2108 cp++; 2109 cp2 = cp - 1; 2110 i++; 2111 } 2112 } 2113 j = cp2 - cp + 1; 2114 conf.ns_ppc[i] = (char *)malloc(j + 1); 2115 if (conf.ns_ppc[i] == NULL) { 2116 __s_api_free2dArray(conf.ns_ppc); 2117 if (tcp != NULL) 2118 free(tcp); 2119 return (NS_LDAP_MEMORY); 2120 } 2121 (void) strlcpy(conf.ns_ppc[i], cp, j); 2122 break; 2123 case SERVLIST: 2124 len = 0; 2125 for (cp2 = cp; *cp2; cp2++) { 2126 if (*cp2 == SPACETOK || *cp2 == COMMATOK) { 2127 len++; 2128 for (; *(cp2 + 1) == SPACETOK || 2129 *(cp2 +1) == COMMATOK; cp2++) 2130 ; 2131 } 2132 } 2133 if (cp != cp2) 2134 len++; 2135 if (len == 0) { 2136 conf.ns_ppc = (char **)NULL; 2137 conf.ns_acnt = 0; 2138 break; 2139 } 2140 conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *)); 2141 if (conf.ns_ppc == NULL) { 2142 if (tcp != NULL) 2143 free(tcp); 2144 return (NS_LDAP_MEMORY); 2145 } 2146 conf.ns_acnt = len; 2147 i = 0; 2148 for (cp2 = cp; *cp2; cp2++) { 2149 if (*cp2 == SPACETOK || *cp2 == COMMATOK) { 2150 j = cp2 - cp + 1; 2151 conf.ns_ppc[i] = (char *)malloc(j + 1); 2152 if (conf.ns_ppc[i] == NULL) { 2153 __s_api_free2dArray(conf.ns_ppc); 2154 if (tcp != NULL) 2155 free(tcp); 2156 return (NS_LDAP_MEMORY); 2157 } 2158 (void) strlcpy(conf.ns_ppc[i], cp, j); 2159 cp = cp2+1; 2160 while (*cp == SPACETOK || *cp == COMMATOK) 2161 cp++; 2162 cp2 = cp - 1; 2163 i++; 2164 } 2165 } 2166 j = cp2 - cp + 1; 2167 conf.ns_ppc[i] = (char *)malloc(j + 1); 2168 if (conf.ns_ppc[i] == NULL) { 2169 __s_api_free2dArray(conf.ns_ppc); 2170 if (tcp != NULL) 2171 free(tcp); 2172 return (NS_LDAP_MEMORY); 2173 } 2174 (void) strlcpy(conf.ns_ppc[i], cp, j); 2175 break; 2176 case ARRAYAUTH: 2177 len = 0; 2178 for (cp2 = cp; *cp2; cp2++) { 2179 if (*cp2 == SEMITOK || *cp2 == COMMATOK) 2180 len++; 2181 } 2182 if (cp != cp2) 2183 len++; 2184 if (len == 0) { 2185 conf.ns_pi = (int *)NULL; 2186 conf.ns_acnt = 0; 2187 break; 2188 } 2189 conf.ns_pi = (int *)calloc(len + 1, sizeof (int)); 2190 if (conf.ns_pi == NULL) { 2191 if (tcp != NULL) 2192 free(tcp); 2193 return (NS_LDAP_MEMORY); 2194 } 2195 conf.ns_acnt = len; 2196 i = 0; 2197 for (cp2 = cp; *cp2; cp2++) { 2198 if (*cp2 == SEMITOK || *cp2 == COMMATOK) { 2199 j = cp2 - cp + 1; 2200 if (j > sizeof (tbuf)) { 2201 j = -1; 2202 ptbuf = cp; 2203 } else { 2204 (void) strlcpy(tbuf, cp, j); 2205 j = __s_get_enum_value(ptr, tbuf, 2206 def->index); 2207 ptbuf = tbuf; 2208 } 2209 if (j < 0) { 2210 (void) snprintf(errstr, sizeof (errstr), 2211 gettext("Unable to set value: " 2212 "invalid " 2213 "authenticationMethod (%s)"), 2214 ptbuf); 2215 MKERROR(LOG_ERR, *error, 2216 NS_CONFIG_SYNTAX, 2217 strdup(errstr), NULL); 2218 free(conf.ns_pi); 2219 if (tcp != NULL) 2220 free(tcp); 2221 return (NS_LDAP_CONFIG); 2222 } 2223 conf.ns_pi[i] = j; 2224 cp = cp2+1; 2225 i++; 2226 } 2227 } 2228 j = cp2 - cp + 1; 2229 if (j > sizeof (tbuf)) { 2230 j = -1; 2231 ptbuf = cp; 2232 } else { 2233 (void) strlcpy(tbuf, cp, j); 2234 j = __s_get_enum_value(ptr, tbuf, def->index); 2235 ptbuf = tbuf; 2236 } 2237 if (j < 0) { 2238 (void) snprintf(errstr, sizeof (errstr), 2239 gettext("Unable to set value: " 2240 "invalid authenticationMethod (%s)"), ptbuf); 2241 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2242 strdup(errstr), NULL); 2243 if (tcp != NULL) 2244 free(tcp); 2245 return (NS_LDAP_CONFIG); 2246 } 2247 conf.ns_pi[i] = j; 2248 break; 2249 case ARRAYCRED: 2250 len = 0; 2251 for (cp2 = cp; *cp2; cp2++) { 2252 if (*cp2 == SPACETOK) 2253 len++; 2254 } 2255 if (cp != cp2) 2256 len++; 2257 if (len == 0) { 2258 conf.ns_pi = (int *)NULL; 2259 conf.ns_acnt = 0; 2260 break; 2261 } 2262 conf.ns_pi = (int *)calloc(len + 1, sizeof (int)); 2263 if (conf.ns_pi == NULL) { 2264 if (tcp != NULL) 2265 free(tcp); 2266 return (NS_LDAP_MEMORY); 2267 } 2268 conf.ns_acnt = len; 2269 i = 0; 2270 for (cp2 = cp; *cp2; cp2++) { 2271 if (*cp2 == SPACETOK) { 2272 j = cp2 - cp + 1; 2273 if (j > sizeof (tbuf)) { 2274 j = -1; 2275 ptbuf = cp; 2276 } else { 2277 (void) strlcpy(tbuf, cp, j); 2278 j = __s_get_enum_value(ptr, tbuf, 2279 def->index); 2280 ptbuf = tbuf; 2281 } 2282 if (j < 0) { 2283 (void) snprintf(errstr, sizeof (errstr), 2284 gettext("Unable to set value: " 2285 "invalid credentialLevel (%s)"), 2286 ptbuf); 2287 MKERROR(LOG_ERR, *error, 2288 NS_CONFIG_SYNTAX, 2289 strdup(errstr), NULL); 2290 free(conf.ns_pi); 2291 if (tcp != NULL) 2292 free(tcp); 2293 return (NS_LDAP_CONFIG); 2294 } 2295 conf.ns_pi[i] = j; 2296 cp = cp2+1; 2297 i++; 2298 } 2299 } 2300 j = cp2 - cp + 1; 2301 if (j > sizeof (tbuf)) { 2302 j = -1; 2303 ptbuf = cp; 2304 } else { 2305 (void) strlcpy(tbuf, cp, j); 2306 j = __s_get_enum_value(ptr, tbuf, def->index); 2307 ptbuf = tbuf; 2308 } 2309 if (j < 0) { 2310 (void) snprintf(errstr, sizeof (errstr), 2311 gettext("Unable to set value: " 2312 "invalid credentialLevel (%s)"), ptbuf); 2313 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2314 strdup(errstr), NULL); 2315 if (tcp != NULL) 2316 free(tcp); 2317 return (NS_LDAP_CONFIG); 2318 } 2319 conf.ns_pi[i] = j; 2320 break; 2321 case ATTRMAP: 2322 case OBJMAP: 2323 i = __s_api_parse_map(cp, &sid, &origA, &mapA); 2324 if (i != NS_HASH_RC_SUCCESS) { 2325 if (i == NS_HASH_RC_NO_MEMORY) { 2326 exitrc = NS_LDAP_MEMORY; 2327 } else { 2328 (void) snprintf(errstr, sizeof (errstr), 2329 gettext("Unable to set value: " 2330 "invalid schema mapping (%s)"), cp); 2331 exitrc = NS_LDAP_CONFIG; 2332 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2333 strdup(errstr), NULL); 2334 } 2335 if (tcp) 2336 free(tcp); 2337 return (exitrc); 2338 } 2339 2340 /* 2341 * Add reverse map first. 2342 * There could be more than one. 2343 */ 2344 for (attr = mapA; *attr; attr++) { 2345 2346 free_memory = 1; 2347 exitrc = NS_LDAP_MEMORY; 2348 2349 rmap = (ns_mapping_t *)calloc(1, 2350 sizeof (ns_mapping_t)); 2351 if (rmap) { 2352 rmap->service = strdup(sid); 2353 if (rmap->service) { 2354 rmap->orig = strdup(*attr); 2355 if (rmap->orig) { 2356 rmap->map = (char **)calloc(2, 2357 sizeof (char *)); 2358 if (rmap->map) { 2359 (rmap->map)[0] = 2360 strdup(origA); 2361 if ((rmap->map)[0]) 2362 free_memory = 0; 2363 } 2364 } 2365 } 2366 } 2367 2368 if (free_memory == 0) { 2369 if (def->data_type == ATTRMAP) { 2370 rmap->type = NS_ATTR_MAP; 2371 i = __s_api_add_map2hash(ptr, 2372 NS_HASH_RAMAP, rmap); 2373 } else { 2374 rmap->type = NS_OBJ_MAP; 2375 i = __s_api_add_map2hash(ptr, 2376 NS_HASH_ROMAP, rmap); 2377 } 2378 2379 if (i != NS_HASH_RC_SUCCESS) { 2380 switch (i) { 2381 case NS_HASH_RC_CONFIG_ERROR: 2382 exitrc = NS_LDAP_INTERNAL; 2383 (void) snprintf(errstr, 2384 sizeof (errstr), 2385 gettext( 2386 "Unable to set value: " 2387 "no configuration info " 2388 "for schema map " 2389 "update (%s)"), cp); 2390 MKERROR(LOG_ERR, *error, 2391 NS_LDAP_INTERNAL, 2392 strdup(errstr), 2393 NULL); 2394 break; 2395 case NS_HASH_RC_EXISTED: 2396 exitrc = NS_LDAP_CONFIG; 2397 (void) snprintf(errstr, 2398 sizeof (errstr), 2399 gettext( 2400 "Unable to set value: " 2401 "schema map " 2402 "already existed for " 2403 "(%s, %s)."), 2404 *attr, origA); 2405 MKERROR(LOG_ERR, *error, 2406 NS_CONFIG_SYNTAX, 2407 strdup(errstr), 2408 NULL); 2409 break; 2410 case NS_HASH_RC_NO_MEMORY: 2411 exitrc = NS_LDAP_MEMORY; 2412 break; 2413 } 2414 free_memory = 1; 2415 } 2416 } 2417 2418 if (free_memory) { 2419 if (tcp) 2420 free(tcp); 2421 free(sid); 2422 free(origA); 2423 __s_api_free2dArray(mapA); 2424 if (rmap) { 2425 if (rmap->service) 2426 free(rmap->service); 2427 if (rmap->orig) 2428 free(rmap->orig); 2429 if (rmap->map) { 2430 if ((rmap->map)[0]) 2431 free((rmap->map)[0]); 2432 free(rmap->map); 2433 } 2434 free(rmap); 2435 } 2436 return (exitrc); 2437 } 2438 } 2439 2440 /* 2441 * For performance gain, 2442 * add a "schema mapping existed" indicator 2443 * for the given service if not already added. 2444 * This dummy map needs not be removed, if 2445 * the next real map add operation fails. 2446 * since the caller, e.g. ldap_cachemgr. 2447 * should exit anyway. 2448 */ 2449 free_memory = 1; 2450 exitrc = NS_LDAP_MEMORY; 2451 2452 map = (ns_mapping_t *)calloc(1, 2453 sizeof (ns_mapping_t)); 2454 if (map) { 2455 map->service = strdup(sid); 2456 if (map->service) { 2457 map->orig = strdup( 2458 NS_HASH_SCHEMA_MAPPING_EXISTED); 2459 if (map->orig) { 2460 map->map = (char **)calloc(2, 2461 sizeof (char *)); 2462 if (map->map) { 2463 (map->map)[0] = 2464 strdup(sid); 2465 if ((map->map)[0]) 2466 free_memory = 0; 2467 } 2468 } 2469 } 2470 } 2471 2472 if (free_memory == 0) { 2473 map->type = NS_ATTR_MAP; 2474 /* 2475 * add to reverse map, 2476 * so that "ldapclient list" 2477 * would not show it 2478 */ 2479 i = __s_api_add_map2hash(ptr, 2480 NS_HASH_RAMAP, map); 2481 2482 /* 2483 * ignore "map already existed" error, 2484 * just need one per service. 2485 * Need however to free memory allocated 2486 * for map. 2487 */ 2488 if (i != NS_HASH_RC_SUCCESS && 2489 i != NS_HASH_RC_EXISTED) { 2490 switch (i) { 2491 case NS_HASH_RC_CONFIG_ERROR: 2492 exitrc = NS_LDAP_INTERNAL; 2493 (void) snprintf(errstr, 2494 sizeof (errstr), 2495 gettext( 2496 "Unable to set value: " 2497 "no configuration info " 2498 "for schema map " 2499 "update (%s)"), cp); 2500 MKERROR(LOG_ERR, *error, 2501 NS_LDAP_INTERNAL, 2502 strdup(errstr), 2503 NULL); 2504 break; 2505 case NS_HASH_RC_NO_MEMORY: 2506 exitrc = NS_LDAP_MEMORY; 2507 break; 2508 } 2509 free_memory = 1; 2510 } else if (i == NS_HASH_RC_EXISTED) { 2511 if (map->service) 2512 free(map->service); 2513 if (map->orig) 2514 free(map->orig); 2515 if (map->map) { 2516 if ((map->map)[0]) 2517 free((map->map)[0]); 2518 free(map->map); 2519 } 2520 free(map); 2521 map = NULL; 2522 } 2523 } 2524 2525 if (free_memory) { 2526 if (tcp) 2527 free(tcp); 2528 free(sid); 2529 free(origA); 2530 __s_api_free2dArray(mapA); 2531 if (map) { 2532 if (map->service) 2533 free(map->service); 2534 if (map->orig) 2535 free(map->orig); 2536 if (map->map) { 2537 if ((map->map)[0]) 2538 free((map->map)[0]); 2539 free(map->map); 2540 } 2541 free(map); 2542 } 2543 return (exitrc); 2544 } 2545 2546 /* 2547 * add the real schema map 2548 */ 2549 free_memory = 1; 2550 exitrc = NS_LDAP_MEMORY; 2551 map = (ns_mapping_t *)calloc(1, sizeof (ns_mapping_t)); 2552 if (map) { 2553 map->service = sid; 2554 map->orig = origA; 2555 map->map = mapA; 2556 2557 if (def->data_type == ATTRMAP) { 2558 map->type = NS_ATTR_MAP; 2559 i = __s_api_add_map2hash(ptr, 2560 NS_HASH_AMAP, map); 2561 } else { 2562 map->type = NS_OBJ_MAP; 2563 i = __s_api_add_map2hash(ptr, 2564 NS_HASH_OMAP, map); 2565 } 2566 2567 if (i != NS_HASH_RC_SUCCESS) { 2568 switch (i) { 2569 case NS_HASH_RC_CONFIG_ERROR: 2570 exitrc = NS_LDAP_INTERNAL; 2571 (void) snprintf(errstr, 2572 sizeof (errstr), 2573 gettext( 2574 "Unable to set value: " 2575 "no configuration info " 2576 "for schema map " 2577 "update (%s)"), cp); 2578 MKERROR(LOG_ERR, *error, 2579 NS_LDAP_INTERNAL, 2580 strdup(errstr), 2581 NULL); 2582 break; 2583 case NS_HASH_RC_EXISTED: 2584 exitrc = NS_LDAP_CONFIG; 2585 (void) snprintf(errstr, 2586 sizeof (errstr), 2587 gettext( 2588 "Unable to set value: " 2589 "schema map " 2590 "already existed for " 2591 "'%s'."), origA); 2592 MKERROR(LOG_ERR, *error, 2593 NS_CONFIG_SYNTAX, 2594 strdup(errstr), 2595 NULL); 2596 break; 2597 case NS_HASH_RC_NO_MEMORY: 2598 exitrc = NS_LDAP_MEMORY; 2599 break; 2600 } 2601 free_memory = 1; 2602 } else 2603 free_memory = 0; 2604 } 2605 2606 if (free_memory) { 2607 if (tcp) 2608 free(tcp); 2609 free(sid); 2610 free(origA); 2611 __s_api_free2dArray(mapA); 2612 if (map) 2613 free(map); 2614 return (exitrc); 2615 } 2616 2617 break; 2618 default: 2619 /* This should never happen. */ 2620 (void) snprintf(errstr, sizeof (errstr), 2621 gettext("Unable to set value: invalid configuration " 2622 "type (%d)"), def->data_type); 2623 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 2624 NULL); 2625 if (tcp != NULL) 2626 free(tcp); 2627 return (NS_LDAP_CONFIG); 2628 } 2629 conf.ns_ptype = def->data_type; 2630 if (tcp != NULL) 2631 free(tcp); 2632 2633 /* Individually written verify routines here can replace */ 2634 /* verify_value. Verify conf (data) as appropriate here */ 2635 if (def->ns_verify != NULL) { 2636 if ((*def->ns_verify)(type, def, &conf, errstr) != NS_SUCCESS) { 2637 ns_param_t sav_conf; 2638 2639 (void) snprintf(errstr, sizeof (errstr), 2640 gettext("%s"), errstr); 2641 MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX, 2642 strdup(errstr), NULL); 2643 2644 sav_conf = ptr->paramList[type]; 2645 ptr->paramList[type] = conf; 2646 destroy_param(ptr, type); 2647 ptr->paramList[type] = sav_conf; 2648 2649 return (NS_LDAP_CONFIG); 2650 } 2651 } 2652 2653 /* post evaluate the data */ 2654 2655 /* 2656 * if this is for setting a password, 2657 * encrypt the password first. 2658 * NOTE evalue() is smart and will just return 2659 * the value passed if it is already encrypted. 2660 * 2661 * Init NS_LDAP_EXP_P here when CACHETTL is updated 2662 */ 2663 if (type == NS_LDAP_BINDPASSWD_P || 2664 type == NS_LDAP_ADMIN_BINDPASSWD_P) { 2665 cp = conf.ns_pc; 2666 cp2 = evalue((char *)cp); 2667 conf.ns_pc = cp2; 2668 free(cp); 2669 cp = NULL; 2670 } else if (type == NS_LDAP_FILE_VERSION_P) { 2671 ptr->version = NS_LDAP_V1; 2672 if (strcasecmp(conf.ns_pc, NS_LDAP_VERSION_2) == 0) { 2673 ptr->version = NS_LDAP_V2; 2674 } 2675 } else if (type == NS_LDAP_CACHETTL_P) { 2676 cp = conf.ns_pc; 2677 tm = conv_time(cp); 2678 ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET; 2679 if (tm != 0) { 2680 tm += time(NULL); 2681 } 2682 ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm; 2683 } 2684 2685 /* Everything checks out move new values into param */ 2686 destroy_param(ptr, type); 2687 /* Assign new/updated value into paramList */ 2688 ptr->paramList[type] = conf; 2689 2690 return (NS_LDAP_SUCCESS); 2691 } 2692 2693 2694 /* 2695 * Set a parameter value in the 'config' configuration structure 2696 * Lock as appropriate 2697 */ 2698 2699 int 2700 __ns_ldap_setParam(const ParamIndexType type, 2701 const void *data, ns_ldap_error_t **error) 2702 { 2703 ns_ldap_error_t *errorp; 2704 int ret; 2705 char errstr[2 * MAXERROR]; 2706 ns_config_t *cfg; 2707 ns_config_t *cfg_g = (ns_config_t *)-1; 2708 ns_config_t *new_cfg; 2709 boolean_t reinit_connmgmt = B_FALSE; 2710 2711 /* We want to refresh only one configuration at a time */ 2712 (void) mutex_lock(&ns_loadrefresh_lock); 2713 cfg = __s_api_get_default_config(); 2714 2715 if (cache_server == TRUE) { 2716 if (cfg == NULL) { 2717 __ns_ldap_default_config(); 2718 cfg = __s_api_get_default_config(); 2719 if (cfg == NULL) { 2720 (void) mutex_unlock(&ns_loadrefresh_lock); 2721 return (NS_LDAP_MEMORY); 2722 } 2723 } 2724 } else { 2725 /* 2726 * This code always return error here on client side, 2727 * this needs to change once libsldap is used by more 2728 * applications that need to set parameters. 2729 */ 2730 (void) snprintf(errstr, sizeof (errstr), 2731 gettext("Unable to set parameter from a client in " 2732 "__ns_ldap_setParam()")); 2733 MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX, strdup(errstr), 2734 NULL); 2735 if (cfg != NULL) 2736 __s_api_release_config(cfg); 2737 (void) mutex_unlock(&ns_loadrefresh_lock); 2738 return (NS_LDAP_CONFIG); 2739 } 2740 2741 /* (re)initialize configuration if necessary */ 2742 if (!__s_api_isStandalone() && 2743 cache_server == FALSE && timetorefresh(cfg)) 2744 cfg_g = __s_api_get_default_config_global(); 2745 /* only (re)initialize the global configuration */ 2746 if (cfg == cfg_g) { 2747 if (cfg_g != NULL) 2748 __s_api_release_config(cfg_g); 2749 new_cfg = LoadCacheConfiguration(cfg, &errorp); 2750 if (new_cfg != cfg) 2751 __s_api_release_config(cfg); 2752 if (new_cfg == NULL) { 2753 (void) snprintf(errstr, sizeof (errstr), 2754 gettext("Unable to load configuration '%s' " 2755 "('%s')."), NSCONFIGFILE, 2756 errorp != NULL && errorp->message != NULL ? 2757 errorp->message : ""); 2758 MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED, 2759 strdup(errstr), NULL); 2760 if (errorp != NULL) 2761 (void) __ns_ldap_freeError(&errorp); 2762 (void) mutex_unlock(&ns_loadrefresh_lock); 2763 return (NS_LDAP_CONFIG); 2764 } 2765 if (new_cfg != cfg) { 2766 set_curr_config_global(new_cfg); 2767 cfg = new_cfg; 2768 reinit_connmgmt = B_TRUE; 2769 } 2770 } 2771 (void) mutex_unlock(&ns_loadrefresh_lock); 2772 2773 if (reinit_connmgmt == B_TRUE) 2774 __s_api_reinit_conn_mgmt_new_config(cfg); 2775 2776 /* translate input and save in the parameter list */ 2777 ret = __ns_ldap_setParamValue(cfg, type, data, error); 2778 2779 __s_api_release_config(cfg); 2780 2781 return (ret); 2782 } 2783 2784 2785 /* 2786 * Make a copy of a parameter entry 2787 */ 2788 2789 static void ** 2790 dupParam(ns_param_t *ptr) 2791 { 2792 int count, i; 2793 void **dupdata, *ret; 2794 int *intptr; 2795 char *cp, tmbuf[32]; 2796 static time_t expire = 0; 2797 ns_auth_t *ap; 2798 2799 switch (ptr->ns_ptype) { 2800 case ARRAYAUTH: 2801 case ARRAYCRED: 2802 case SAMLIST: 2803 case SCLLIST: 2804 case SSDLIST: 2805 case SERVLIST: 2806 case ARRAYCP: 2807 count = ptr->ns_acnt; 2808 if (count == 0) 2809 return (NULL); 2810 break; 2811 case CHARPTR: 2812 case INT: 2813 case TIMET: 2814 count = 1; 2815 } 2816 2817 dupdata = (void **)calloc((count + 1), sizeof (void *)); 2818 if (dupdata == NULL) 2819 return (NULL); 2820 2821 switch (ptr->ns_ptype) { 2822 case ARRAYAUTH: 2823 for (i = 0; i < count; i++) { 2824 ap = __s_api_AuthEnumtoStruct( 2825 (EnumAuthType_t)ptr->ns_pi[i]); 2826 if (ap == NULL) { 2827 free(dupdata); 2828 return (NULL); 2829 } 2830 dupdata[i] = ap; 2831 } 2832 break; 2833 case ARRAYCRED: 2834 for (i = 0; i < count; i++) { 2835 intptr = (int *)malloc(sizeof (int)); 2836 if (intptr == NULL) { 2837 free(dupdata); 2838 return (NULL); 2839 } 2840 dupdata[i] = (void *)intptr; 2841 *intptr = ptr->ns_pi[i]; 2842 } 2843 break; 2844 case SAMLIST: 2845 case SCLLIST: 2846 case SSDLIST: 2847 case SERVLIST: 2848 case ARRAYCP: 2849 for (i = 0; i < count; i++) { 2850 ret = (void *)strdup(ptr->ns_ppc[i]); 2851 if (ret == NULL) { 2852 free(dupdata); 2853 return (NULL); 2854 } 2855 dupdata[i] = ret; 2856 } 2857 break; 2858 case CHARPTR: 2859 if (ptr->ns_pc == NULL) { 2860 free(dupdata); 2861 return (NULL); 2862 } 2863 ret = (void *)strdup(ptr->ns_pc); 2864 if (ret == NULL) { 2865 free(dupdata); 2866 return (NULL); 2867 } 2868 dupdata[0] = ret; 2869 break; 2870 case INT: 2871 intptr = (int *)malloc(sizeof (int)); 2872 if (intptr == NULL) { 2873 free(dupdata); 2874 return (NULL); 2875 } 2876 *intptr = ptr->ns_i; 2877 dupdata[0] = (void *)intptr; 2878 break; 2879 case TIMET: 2880 expire = ptr->ns_tm; 2881 tmbuf[31] = '\0'; 2882 cp = lltostr((long)expire, &tmbuf[31]); 2883 ret = (void *)strdup(cp); 2884 if (ret == NULL) { 2885 free(dupdata); 2886 return (NULL); 2887 } 2888 dupdata[0] = ret; 2889 break; 2890 } 2891 return (dupdata); 2892 } 2893 2894 int 2895 __ns_ldap_freeParam(void ***data) 2896 { 2897 void **tmp; 2898 int i = 0; 2899 2900 if (*data == NULL) 2901 return (NS_LDAP_SUCCESS); 2902 2903 for (i = 0, tmp = *data; tmp[i] != NULL; i++) 2904 free(tmp[i]); 2905 2906 free(*data); 2907 2908 *data = NULL; 2909 2910 return (NS_LDAP_SUCCESS); 2911 } 2912 2913 /* 2914 * Get the internal format for a parameter value. This 2915 * routine makes a copy of an internal param value from 2916 * the currently active parameter list and returns it. 2917 */ 2918 2919 int 2920 __ns_ldap_getParam(const ParamIndexType Param, 2921 void ***data, ns_ldap_error_t **error) 2922 { 2923 char errstr[2 * MAXERROR]; 2924 ns_ldap_error_t *errorp; 2925 ns_default_config *def; 2926 ns_config_t *cfg; 2927 ns_config_t *cfg_g = (ns_config_t *)-1; 2928 ns_config_t *new_cfg; 2929 boolean_t reinit_connmgmt = B_FALSE; 2930 2931 if (data == NULL) 2932 return (NS_LDAP_INVALID_PARAM); 2933 2934 *data = NULL; 2935 2936 /* We want to refresh only one configuration at a time */ 2937 (void) mutex_lock(&ns_loadrefresh_lock); 2938 cfg = __s_api_get_default_config(); 2939 2940 /* (re)initialize configuration if necessary */ 2941 if (!__s_api_isStandalone() && 2942 cache_server == FALSE && timetorefresh(cfg)) 2943 cfg_g = __s_api_get_default_config_global(); 2944 /* only (re)initialize the global configuration */ 2945 if (cfg == cfg_g) { 2946 if (cfg_g != NULL) 2947 __s_api_release_config(cfg_g); 2948 new_cfg = LoadCacheConfiguration(cfg, &errorp); 2949 if (new_cfg != cfg) 2950 __s_api_release_config(cfg); 2951 if (new_cfg == NULL) { 2952 (void) snprintf(errstr, sizeof (errstr), 2953 gettext("Unable to load configuration " 2954 "'%s' ('%s')."), 2955 NSCONFIGFILE, 2956 errorp != NULL && errorp->message != NULL ? 2957 errorp->message : ""); 2958 MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED, 2959 strdup(errstr), NULL); 2960 if (errorp != NULL) 2961 (void) __ns_ldap_freeError(&errorp); 2962 (void) mutex_unlock(&ns_loadrefresh_lock); 2963 return (NS_LDAP_CONFIG); 2964 } 2965 if (new_cfg != cfg) { 2966 set_curr_config_global(new_cfg); 2967 cfg = new_cfg; 2968 reinit_connmgmt = B_TRUE; 2969 } 2970 } 2971 (void) mutex_unlock(&ns_loadrefresh_lock); 2972 2973 if (reinit_connmgmt == B_TRUE) 2974 __s_api_reinit_conn_mgmt_new_config(cfg); 2975 2976 if (cfg == NULL) { 2977 (void) snprintf(errstr, sizeof (errstr), 2978 gettext("No configuration information available.")); 2979 MKERROR(LOG_ERR, *error, NS_CONFIG_NOTLOADED, 2980 strdup(errstr), NULL); 2981 return (NS_LDAP_CONFIG); 2982 } 2983 2984 if (Param == NS_LDAP_DOMAIN_P) { 2985 *data = (void **)calloc(2, sizeof (void *)); 2986 if (*data == NULL) { 2987 __s_api_release_config(cfg); 2988 return (NS_LDAP_MEMORY); 2989 } 2990 (*data)[0] = (void *)strdup(cfg->domainName); 2991 if ((*data)[0] == NULL) { 2992 free(*data); 2993 __s_api_release_config(cfg); 2994 return (NS_LDAP_MEMORY); 2995 } 2996 } else if (cfg->paramList[Param].ns_ptype == NS_UNKNOWN) { 2997 /* get default */ 2998 def = get_defconfig(cfg, Param); 2999 if (def != NULL) 3000 *data = dupParam(&def->defval); 3001 } else { 3002 *data = dupParam(&(cfg->paramList[Param])); 3003 } 3004 __s_api_release_config(cfg); 3005 3006 return (NS_LDAP_SUCCESS); 3007 } 3008 3009 /* 3010 * This routine takes a parameter in internal format and 3011 * translates it into a variety of string formats for various 3012 * outputs (doors/file/ldif). This routine would be better 3013 * named: __ns_ldap_translateParam2String 3014 */ 3015 3016 char * 3017 __s_api_strValue(ns_config_t *cfg, ParamIndexType index, ns_strfmt_t fmt) 3018 { 3019 ns_default_config *def = NULL; 3020 ns_param_t *ptr; 3021 ns_hash_t *hptr; 3022 ns_mapping_t *mptr; 3023 char ibuf[14]; 3024 char abuf[64], **cpp; 3025 int count, i; 3026 boolean_t first = B_TRUE; 3027 LineBuf lbuf; 3028 LineBuf *buffer = &lbuf; 3029 char *retstring; 3030 char *sepstr; 3031 3032 if (cfg == NULL) 3033 return (NULL); 3034 3035 /* NS_LDAP_EXP and TRANSPORT_SEC are not exported externally */ 3036 if (index == NS_LDAP_EXP_P || index == NS_LDAP_TRANSPORT_SEC_P) 3037 return (NULL); 3038 3039 /* Return nothing if the value is the default */ 3040 if (cfg->paramList[index].ns_ptype == NS_UNKNOWN) 3041 return (NULL); 3042 3043 (void) memset((char *)buffer, 0, sizeof (LineBuf)); 3044 3045 ptr = &(cfg->paramList[index]); 3046 3047 abuf[0] = '\0'; 3048 3049 /* get default */ 3050 def = get_defconfig(cfg, index); 3051 if (def == NULL) 3052 return (NULL); 3053 3054 switch (fmt) { 3055 case NS_DOOR_FMT: 3056 (void) strlcpy(abuf, def->name, sizeof (abuf)); 3057 (void) strlcat(abuf, EQUALSEP, sizeof (abuf)); 3058 break; 3059 case NS_FILE_FMT: 3060 (void) strlcpy(abuf, def->name, sizeof (abuf)); 3061 (void) strlcat(abuf, EQUSPSEP, sizeof (abuf)); 3062 break; 3063 case NS_LDIF_FMT: 3064 /* If no LDIF attr exists ignore the entry */ 3065 if (def->profile_name == NULL) 3066 return (NULL); 3067 (void) strlcpy(abuf, def->profile_name, sizeof (abuf)); 3068 (void) strlcat(abuf, COLSPSEP, sizeof (abuf)); 3069 break; 3070 default: 3071 break; 3072 } 3073 3074 if (__print2buf(buffer, abuf, NULL)) 3075 goto strValueError; 3076 3077 switch (ptr->ns_ptype) { 3078 case ARRAYAUTH: 3079 count = ptr->ns_acnt; 3080 for (i = 0; i < count; i++) { 3081 sepstr = NULL; 3082 if (i != count-1) { 3083 if (cfg->version == NS_LDAP_V1) { 3084 sepstr = COMMASEP; 3085 } else { 3086 sepstr = SEMISEP; 3087 } 3088 } 3089 if (__print2buf(buffer, __s_get_auth_name(cfg, 3090 (AuthType_t)(ptr->ns_pi[i])), sepstr)) 3091 goto strValueError; 3092 } 3093 break; 3094 case ARRAYCRED: 3095 count = ptr->ns_acnt; 3096 for (i = 0; i < count; i++) { 3097 sepstr = NULL; 3098 if (i != count-1) { 3099 sepstr = SPACESEP; 3100 } 3101 if (__print2buf(buffer, __s_get_credlvl_name(cfg, 3102 (CredLevel_t)ptr->ns_pi[i]), sepstr)) 3103 goto strValueError; 3104 } 3105 break; 3106 case SAMLIST: 3107 case SCLLIST: 3108 case SSDLIST: 3109 count = ptr->ns_acnt; 3110 for (i = 0; i < count; i++) { 3111 if (__print2buf(buffer, ptr->ns_ppc[i], NULL)) 3112 goto strValueError; 3113 3114 if (i == count-1) 3115 continue; 3116 3117 /* Separate items */ 3118 switch (fmt) { 3119 case NS_DOOR_FMT: 3120 if (__print2buf(buffer, DOORLINESEP, NULL) || 3121 __print2buf(buffer, def->name, EQUALSEP)) 3122 goto strValueError; 3123 break; 3124 case NS_FILE_FMT: 3125 if (__print2buf(buffer, "\n", NULL) || 3126 __print2buf(buffer, def->name, EQUSPSEP)) 3127 goto strValueError; 3128 break; 3129 case NS_LDIF_FMT: 3130 if (__print2buf(buffer, "\n", NULL) || 3131 __print2buf(buffer, def->profile_name, 3132 COLSPSEP)) 3133 goto strValueError; 3134 break; 3135 } 3136 } 3137 break; 3138 case ARRAYCP: 3139 count = ptr->ns_acnt; 3140 for (i = 0; i < count; i++) { 3141 sepstr = NULL; 3142 if (i != count-1) { 3143 sepstr = COMMASEP; 3144 } 3145 if (__print2buf(buffer, ptr->ns_ppc[i], sepstr)) 3146 goto strValueError; 3147 } 3148 break; 3149 case SERVLIST: 3150 count = ptr->ns_acnt; 3151 for (i = 0; i < count; i++) { 3152 sepstr = NULL; 3153 if (i != count-1) { 3154 if (fmt == NS_LDIF_FMT) { 3155 sepstr = SPACESEP; 3156 } else { 3157 sepstr = COMMASEP; 3158 } 3159 } 3160 if (__print2buf(buffer, ptr->ns_ppc[i], sepstr)) 3161 goto strValueError; 3162 } 3163 break; 3164 case CHARPTR: 3165 if (ptr->ns_pc == NULL) 3166 break; 3167 if (__print2buf(buffer, ptr->ns_pc, NULL)) 3168 goto strValueError; 3169 break; 3170 case INT: 3171 switch (def->index) { 3172 case NS_LDAP_PREF_ONLY_P: 3173 if (__print2buf(buffer, 3174 __s_get_pref_name((PrefOnly_t)ptr->ns_i), NULL)) 3175 goto strValueError; 3176 break; 3177 case NS_LDAP_SEARCH_REF_P: 3178 if (__print2buf(buffer, __s_get_searchref_name(cfg, 3179 (SearchRef_t)ptr->ns_i), NULL)) 3180 goto strValueError; 3181 break; 3182 case NS_LDAP_SEARCH_SCOPE_P: 3183 if (__print2buf(buffer, __s_get_scope_name(cfg, 3184 (ScopeType_t)ptr->ns_i), NULL)) 3185 goto strValueError; 3186 break; 3187 case NS_LDAP_ENABLE_SHADOW_UPDATE_P: 3188 if (__print2buf(buffer, __s_get_shadowupdate_name( 3189 (enableShadowUpdate_t)ptr->ns_i), NULL)) 3190 goto strValueError; 3191 break; 3192 default: 3193 (void) snprintf(ibuf, sizeof (ibuf), 3194 "%d", ptr->ns_i); 3195 if (__print2buf(buffer, ibuf, NULL)) 3196 goto strValueError; 3197 break; 3198 } 3199 break; 3200 case ATTRMAP: 3201 for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) { 3202 if (hptr->h_type != NS_HASH_AMAP) { 3203 continue; 3204 } 3205 if (!first) { 3206 /* print abuf as "separator" */ 3207 if (fmt == NS_DOOR_FMT) { 3208 if (__print2buf(buffer, DOORLINESEP, 3209 abuf)) 3210 goto strValueError; 3211 } else { 3212 if (__print2buf(buffer, "\n", abuf)) 3213 goto strValueError; 3214 } 3215 } 3216 mptr = hptr->h_map; 3217 if (__print2buf(buffer, mptr->service, COLONSEP) || 3218 __print2buf(buffer, mptr->orig, EQUALSEP)) 3219 goto strValueError; 3220 for (cpp = mptr->map; cpp && *cpp; cpp++) { 3221 /* print *cpp as "separator" */ 3222 sepstr = ""; 3223 if (cpp != mptr->map) 3224 sepstr = SPACESEP; 3225 if (__print2buf(buffer, sepstr, *cpp)) 3226 goto strValueError; 3227 } 3228 first = B_FALSE; 3229 } 3230 break; 3231 case OBJMAP: 3232 for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) { 3233 if (hptr->h_type != NS_HASH_OMAP) { 3234 continue; 3235 } 3236 if (!first) { 3237 /* print abuf as "separator" */ 3238 if (fmt == NS_DOOR_FMT) { 3239 if (__print2buf(buffer, DOORLINESEP, 3240 abuf)) 3241 goto strValueError; 3242 } else { 3243 if (__print2buf(buffer, "\n", abuf)) 3244 goto strValueError; 3245 } 3246 } 3247 mptr = hptr->h_map; 3248 if (__print2buf(buffer, mptr->service, COLONSEP) || 3249 __print2buf(buffer, mptr->orig, EQUALSEP)) 3250 goto strValueError; 3251 for (cpp = mptr->map; cpp && *cpp; cpp++) { 3252 /* print *cpp as "separator" */ 3253 sepstr = ""; 3254 if (cpp != mptr->map) 3255 sepstr = SPACESEP; 3256 if (__print2buf(buffer, sepstr, *cpp)) 3257 goto strValueError; 3258 } 3259 first = B_FALSE; 3260 } 3261 break; 3262 } 3263 3264 retstring = buffer->str; 3265 return (retstring); 3266 3267 strValueError: 3268 if (buffer->len > 0) 3269 free(buffer->str); 3270 return (NULL); 3271 } 3272 3273 /* shared by __door_getldapconfig() and __door_getadmincred() */ 3274 int 3275 __door_getconf(char **buffer, int *buflen, ns_ldap_error_t **error, 3276 int callnumber) 3277 { 3278 typedef union { 3279 ldap_data_t s_d; 3280 char s_b[DOORBUFFERSIZE]; 3281 } space_t; 3282 space_t *space; 3283 3284 ldap_data_t *sptr; 3285 int ndata; 3286 int adata; 3287 char errstr[MAXERROR]; 3288 char *domainname; 3289 ns_ldap_return_code retCode; 3290 ldap_config_out_t *cfghdr; 3291 3292 *error = NULL; 3293 3294 domainname = __getdomainname(); 3295 if (domainname == NULL || buffer == NULL || buflen == NULL || 3296 (strlen(domainname) >= (sizeof (space_t) 3297 - sizeof (space->s_d.ldap_call.ldap_callnumber)))) { 3298 return (NS_LDAP_OP_FAILED); 3299 } 3300 3301 space = (space_t *)calloc(1, sizeof (space_t)); 3302 if (space == NULL) 3303 return (NS_LDAP_MEMORY); 3304 3305 adata = (sizeof (ldap_call_t) + strlen(domainname) +1); 3306 ndata = sizeof (space_t); 3307 space->s_d.ldap_call.ldap_callnumber = callnumber; 3308 (void) strcpy(space->s_d.ldap_call.ldap_u.domainname, domainname); 3309 free(domainname); 3310 domainname = NULL; 3311 sptr = &space->s_d; 3312 3313 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) { 3314 case NS_CACHE_SUCCESS: 3315 break; 3316 case NS_CACHE_NOTFOUND: 3317 (void) snprintf(errstr, sizeof (errstr), 3318 gettext("Door call to " 3319 "ldap_cachemgr failed - error: %d."), 3320 space->s_d.ldap_ret.ldap_errno); 3321 MKERROR(LOG_WARNING, *error, NS_CONFIG_CACHEMGR, 3322 strdup(errstr), NULL); 3323 free(space); 3324 return (NS_LDAP_OP_FAILED); 3325 default: 3326 free(space); 3327 return (NS_LDAP_OP_FAILED); 3328 } 3329 3330 retCode = NS_LDAP_SUCCESS; 3331 3332 /* copy info from door call to buffer here */ 3333 cfghdr = &sptr->ldap_ret.ldap_u.config_str; 3334 *buflen = offsetof(ldap_config_out_t, config_str) + 3335 cfghdr->data_size + 1; 3336 *buffer = calloc(*buflen, sizeof (char)); 3337 if (*buffer == NULL) { 3338 retCode = NS_LDAP_MEMORY; 3339 } else 3340 (void) memcpy(*buffer, cfghdr, *buflen - 1); 3341 3342 if (sptr != &space->s_d) { 3343 (void) munmap((char *)sptr, ndata); 3344 } 3345 free(space); 3346 3347 return (retCode); 3348 } 3349 3350 static int 3351 __door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error) 3352 { 3353 return (__door_getconf(buffer, buflen, error, GETLDAPCONFIGV1)); 3354 } 3355 3356 /* 3357 * SetDoorInfoToUnixCred parses ldapcachemgr configuration information 3358 * for Admin credentials. 3359 */ 3360 int 3361 SetDoorInfoToUnixCred(char *buffer, ns_ldap_error_t **errorp, 3362 UnixCred_t **cred) 3363 { 3364 UnixCred_t *ptr; 3365 char errstr[MAXERROR]; 3366 char *name, *value, valbuf[BUFSIZE]; 3367 char *bufptr = buffer; 3368 char *strptr; 3369 char *rest; 3370 ParamIndexType index = 0; 3371 ldap_config_out_t *cfghdr; 3372 3373 if (errorp == NULL || cred == NULL || *cred == NULL) 3374 return (NS_LDAP_INVALID_PARAM); 3375 *errorp = NULL; 3376 3377 ptr = *cred; 3378 3379 cfghdr = (ldap_config_out_t *)bufptr; 3380 bufptr = (char *)cfghdr->config_str; 3381 3382 strptr = (char *)strtok_r(bufptr, DOORLINESEP, &rest); 3383 for (; ; ) { 3384 if (strptr == NULL) 3385 break; 3386 (void) strlcpy(valbuf, strptr, sizeof (valbuf)); 3387 __s_api_split_key_value(valbuf, &name, &value); 3388 if (__ns_ldap_getParamType(name, &index) != 0) { 3389 (void) snprintf(errstr, MAXERROR, 3390 gettext("SetDoorInfoToUnixCred: " 3391 "Unknown keyword encountered '%s'."), name); 3392 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX, 3393 strdup(errstr), NULL); 3394 return (NS_LDAP_CONFIG); 3395 } 3396 switch (index) { 3397 case NS_LDAP_ADMIN_BINDDN_P: 3398 ptr->userID = (char *)strdup(value); 3399 break; 3400 case NS_LDAP_ADMIN_BINDPASSWD_P: 3401 ptr->passwd = (char *)strdup(value); 3402 break; 3403 default: 3404 (void) snprintf(errstr, MAXERROR, 3405 gettext("SetDoorInfoToUnixCred: " 3406 "Unknown index encountered '%d'."), index); 3407 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX, 3408 strdup(errstr), NULL); 3409 return (NS_LDAP_CONFIG); 3410 } 3411 strptr = (char *)strtok_r(NULL, DOORLINESEP, &rest); 3412 } 3413 3414 return (NS_LDAP_SUCCESS); 3415 } 3416 3417 /* 3418 * SetDoorInfo parses ldapcachemgr configuration information 3419 * and verifies that the profile is version 1 or version 2 based. 3420 * version 2 profiles must have a version number as the first profile 3421 * attribute in the configuration. 3422 */ 3423 static ns_config_t * 3424 SetDoorInfo(char *buffer, ns_ldap_error_t **errorp) 3425 { 3426 ns_config_t *ptr; 3427 char errstr[MAXERROR], errbuf[MAXERROR]; 3428 char *name, *value, valbuf[BUFSIZE]; 3429 char *strptr; 3430 char *rest; 3431 char *bufptr = buffer; 3432 ParamIndexType i; 3433 int ret; 3434 int first = 1; 3435 int errfnd = 0; 3436 ldap_config_out_t *cfghdr; 3437 3438 if (errorp == NULL) 3439 return (NULL); 3440 *errorp = NULL; 3441 3442 ptr = __s_api_create_config(); 3443 if (ptr == NULL) { 3444 return (NULL); 3445 } 3446 3447 /* get config cookie from the header */ 3448 cfghdr = (ldap_config_out_t *)bufptr; 3449 ptr->config_cookie = cfghdr->cookie; 3450 bufptr = (char *)cfghdr->config_str; 3451 3452 strptr = (char *)strtok_r(bufptr, DOORLINESEP, &rest); 3453 for (; ; ) { 3454 if (strptr == NULL) 3455 break; 3456 (void) strlcpy(valbuf, strptr, sizeof (valbuf)); 3457 __s_api_split_key_value(valbuf, &name, &value); 3458 /* Use get_versiontype and check for V1 vs V2 prototypes */ 3459 if (__s_api_get_versiontype(ptr, name, &i) < 0) { 3460 (void) snprintf(errstr, sizeof (errstr), 3461 "%s (%s)\n", 3462 gettext("Illegal profile entry " 3463 "line in configuration."), 3464 name); 3465 errfnd++; 3466 /* Write verify routines and get rid of verify_value here */ 3467 } else if (verify_value(ptr, name, 3468 value, errbuf) != NS_SUCCESS) { 3469 (void) snprintf(errstr, sizeof (errstr), 3470 gettext("%s\n"), errbuf); 3471 errfnd++; 3472 } else if (!first && i == NS_LDAP_FILE_VERSION_P) { 3473 (void) snprintf(errstr, sizeof (errstr), 3474 gettext("Illegal NS_LDAP_FILE_VERSION " 3475 "line in configuration.\n")); 3476 errfnd++; 3477 } 3478 if (errfnd) { 3479 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX, 3480 strdup(errstr), NULL); 3481 } else { 3482 ret = set_default_value(ptr, name, value, errorp); 3483 } 3484 if (errfnd || ret != NS_SUCCESS) { 3485 __s_api_destroy_config(ptr); 3486 return (NULL); 3487 } 3488 first = 0; 3489 3490 strptr = (char *)strtok_r(NULL, DOORLINESEP, &rest); 3491 } 3492 3493 if (__s_api_crosscheck(ptr, errstr, B_TRUE) != NS_SUCCESS) { 3494 __s_api_destroy_config(ptr); 3495 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX, strdup(errstr), 3496 NULL); 3497 return (NULL); 3498 } 3499 3500 return (ptr); 3501 } 3502 3503 static ns_config_t * 3504 LoadCacheConfiguration(ns_config_t *oldcfg, ns_ldap_error_t **error) 3505 { 3506 char *buffer = NULL; 3507 int buflen = 0; 3508 int ret; 3509 ns_config_t *cfg; 3510 ldap_config_out_t *cfghdr; 3511 ldap_get_chg_cookie_t old_cookie; 3512 ldap_get_chg_cookie_t new_cookie; 3513 3514 *error = NULL; 3515 ret = __door_getldapconfig(&buffer, &buflen, error); 3516 3517 if (ret != NS_LDAP_SUCCESS) { 3518 if (*error != NULL && (*error)->message != NULL) 3519 syslog(LOG_WARNING, "libsldap: %s", (*error)->message); 3520 return (NULL); 3521 } 3522 3523 /* No need to reload configuration if config cookie is the same */ 3524 cfghdr = (ldap_config_out_t *)buffer; 3525 new_cookie = cfghdr->cookie; 3526 if (oldcfg != NULL) 3527 old_cookie = oldcfg->config_cookie; 3528 3529 if (oldcfg != NULL && old_cookie.mgr_pid == new_cookie.mgr_pid && 3530 old_cookie.seq_num == new_cookie.seq_num) { 3531 free(buffer); 3532 return (oldcfg); 3533 } 3534 3535 /* now convert from door format */ 3536 cfg = SetDoorInfo(buffer, error); 3537 free(buffer); 3538 3539 if (cfg == NULL && *error != NULL && (*error)->message != NULL) 3540 syslog(LOG_WARNING, "libsldap: %s", (*error)->message); 3541 return (cfg); 3542 } 3543 3544 /* 3545 * converts the time string into seconds. The time string can be specified 3546 * using one of the following time units: 3547 * #s (# of seconds) 3548 * #m (# of minutes) 3549 * #h (# of hours) 3550 * #d (# of days) 3551 * #w (# of weeks) 3552 * NOTE: you can only specify one the above. No combination of the above 3553 * units is allowed. If no unit specified, it will default to "seconds". 3554 */ 3555 static time_t 3556 conv_time(char *s) 3557 { 3558 time_t t; 3559 char c; 3560 int l, m; 3561 long tot; 3562 3563 l = strlen(s); 3564 if (l == 0) 3565 return (0); 3566 c = s[--l]; 3567 m = 0; 3568 switch (c) { 3569 case 'w': /* weeks */ 3570 m = 604800; 3571 break; 3572 case 'd': /* days */ 3573 m = 86400; 3574 break; 3575 case 'h': /* hours */ 3576 m = 3600; 3577 break; 3578 case 'm': /* minutes */ 3579 m = 60; 3580 break; 3581 case 's': /* seconds */ 3582 m = 1; 3583 break; 3584 /* the default case is set to "second" */ 3585 } 3586 if (m != 0) 3587 s[l] = '\0'; 3588 else 3589 m = 1; 3590 errno = 0; 3591 tot = atol(s); 3592 if ((0 == tot) && (EINVAL == errno)) 3593 return (0); 3594 if (((LONG_MAX == tot) || (LONG_MIN == tot)) && (EINVAL == errno)) 3595 return (0); 3596 3597 tot = tot * m; 3598 t = (time_t)tot; 3599 return (t); 3600 } 3601 3602 3603 ns_auth_t * 3604 __s_api_AuthEnumtoStruct(const EnumAuthType_t i) 3605 { 3606 ns_auth_t *ap; 3607 3608 ap = (ns_auth_t *)calloc(1, sizeof (ns_auth_t)); 3609 if (ap == NULL) 3610 return (NULL); 3611 switch (i) { 3612 case NS_LDAP_EA_NONE: 3613 break; 3614 case NS_LDAP_EA_SIMPLE: 3615 ap->type = NS_LDAP_AUTH_SIMPLE; 3616 break; 3617 case NS_LDAP_EA_SASL_CRAM_MD5: 3618 ap->type = NS_LDAP_AUTH_SASL; 3619 ap->saslmech = NS_LDAP_SASL_CRAM_MD5; 3620 break; 3621 case NS_LDAP_EA_SASL_DIGEST_MD5: 3622 ap->type = NS_LDAP_AUTH_SASL; 3623 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3624 break; 3625 case NS_LDAP_EA_SASL_DIGEST_MD5_INT: 3626 ap->type = NS_LDAP_AUTH_SASL; 3627 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3628 ap->saslopt = NS_LDAP_SASLOPT_INT; 3629 break; 3630 case NS_LDAP_EA_SASL_DIGEST_MD5_CONF: 3631 ap->type = NS_LDAP_AUTH_SASL; 3632 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3633 ap->saslopt = NS_LDAP_SASLOPT_PRIV; 3634 break; 3635 case NS_LDAP_EA_SASL_EXTERNAL: 3636 ap->type = NS_LDAP_AUTH_SASL; 3637 ap->saslmech = NS_LDAP_SASL_EXTERNAL; 3638 break; 3639 case NS_LDAP_EA_SASL_GSSAPI: 3640 ap->type = NS_LDAP_AUTH_SASL; 3641 ap->saslmech = NS_LDAP_SASL_GSSAPI; 3642 ap->saslopt = NS_LDAP_SASLOPT_INT | 3643 NS_LDAP_SASLOPT_PRIV; 3644 break; 3645 case NS_LDAP_EA_TLS_NONE: 3646 ap->type = NS_LDAP_AUTH_TLS; 3647 ap->tlstype = NS_LDAP_TLS_NONE; 3648 break; 3649 case NS_LDAP_EA_TLS_SIMPLE: 3650 ap->type = NS_LDAP_AUTH_TLS; 3651 ap->tlstype = NS_LDAP_TLS_SIMPLE; 3652 break; 3653 case NS_LDAP_EA_TLS_SASL_CRAM_MD5: 3654 ap->type = NS_LDAP_AUTH_TLS; 3655 ap->tlstype = NS_LDAP_TLS_SASL; 3656 ap->saslmech = NS_LDAP_SASL_CRAM_MD5; 3657 break; 3658 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5: 3659 ap->type = NS_LDAP_AUTH_TLS; 3660 ap->tlstype = NS_LDAP_TLS_SASL; 3661 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3662 break; 3663 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT: 3664 ap->type = NS_LDAP_AUTH_TLS; 3665 ap->tlstype = NS_LDAP_TLS_SASL; 3666 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3667 ap->saslopt = NS_LDAP_SASLOPT_INT; 3668 break; 3669 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF: 3670 ap->type = NS_LDAP_AUTH_TLS; 3671 ap->tlstype = NS_LDAP_TLS_SASL; 3672 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3673 ap->saslopt = NS_LDAP_SASLOPT_PRIV; 3674 break; 3675 case NS_LDAP_EA_TLS_SASL_EXTERNAL: 3676 ap->type = NS_LDAP_AUTH_TLS; 3677 ap->tlstype = NS_LDAP_TLS_SASL; 3678 ap->saslmech = NS_LDAP_SASL_EXTERNAL; 3679 break; 3680 default: 3681 /* should never get here */ 3682 free(ap); 3683 return (NULL); 3684 } 3685 return (ap); 3686 } 3687 3688 3689 /* 3690 * Parameter Index Type validation routines 3691 */ 3692 3693 /* Validate a positive integer */ 3694 /* Size of errbuf needs to be MAXERROR */ 3695 /* ARGSUSED */ 3696 static int 3697 __s_val_postime(ParamIndexType i, ns_default_config *def, 3698 ns_param_t *param, char *errbuf) 3699 { 3700 char *cp; 3701 long tot; 3702 3703 if (param && param->ns_ptype == CHARPTR && param->ns_pc) { 3704 for (cp = param->ns_pc; cp && *cp; cp++) { 3705 if (*cp >= '0' && *cp <= '9') 3706 continue; 3707 switch (*cp) { 3708 case 'w': /* weeks */ 3709 case 'd': /* days */ 3710 case 'h': /* hours */ 3711 case 'm': /* minutes */ 3712 case 's': /* seconds */ 3713 if (*(cp+1) == '\0') { 3714 break; 3715 } 3716 default: 3717 (void) strcpy(errbuf, "Illegal time value"); 3718 return (NS_PARSE_ERR); 3719 } 3720 } 3721 /* Valid form: [0-9][0-9]*[wdhms]* */ 3722 tot = atol(param->ns_pc); /* check overflow */ 3723 if (tot >= 0) 3724 return (NS_SUCCESS); 3725 } 3726 (void) snprintf(errbuf, MAXERROR, 3727 gettext("Illegal time value in %s"), def->name); 3728 return (NS_PARSE_ERR); 3729 } 3730 3731 3732 /* Validate the Base DN */ 3733 /* It can be empty (RootDSE request) or needs to have an '=' */ 3734 /* Size of errbuf needs to be MAXERROR */ 3735 /* ARGSUSED */ 3736 static int 3737 __s_val_basedn(ParamIndexType i, ns_default_config *def, 3738 ns_param_t *param, char *errbuf) 3739 { 3740 if (param && param->ns_ptype == CHARPTR && 3741 i == NS_LDAP_SEARCH_BASEDN_P && 3742 ((param->ns_pc == NULL) || /* empty */ 3743 (*(param->ns_pc) == '\0') || /* empty */ 3744 (strchr(param->ns_pc, '=') != NULL))) /* '=' */ 3745 { 3746 return (NS_SUCCESS); 3747 } 3748 (void) snprintf(errbuf, MAXERROR, 3749 gettext("Non-existent or invalid DN in %s"), 3750 def->name); 3751 return (NS_PARSE_ERR); 3752 } 3753 3754 3755 /* Validate the serverList */ 3756 /* For each server in list, check if valid IP or hostname */ 3757 /* Size of errbuf needs to be MAXERROR */ 3758 /* ARGSUSED */ 3759 static int 3760 __s_val_serverList(ParamIndexType i, ns_default_config *def, 3761 ns_param_t *param, char *errbuf) 3762 { 3763 for (i = 0; i < param->ns_acnt; i++) { 3764 if ((__s_api_isipv4(param->ns_ppc[i])) || 3765 (__s_api_isipv6(param->ns_ppc[i])) || 3766 (__s_api_ishost(param->ns_ppc[i]))) { 3767 continue; 3768 } 3769 /* err */ 3770 (void) snprintf(errbuf, MAXERROR, 3771 gettext("Invalid server (%s) in %s"), 3772 param->ns_ppc[i], def->name); 3773 return (NS_PARSE_ERR); 3774 } 3775 3776 return (NS_SUCCESS); 3777 } 3778 3779 3780 /* Check for a BINDDN */ 3781 /* It can not be empty and needs to have an '=' */ 3782 /* Size of errbuf needs to be MAXERROR */ 3783 /* ARGSUSED */ 3784 static int 3785 __s_val_binddn(ParamIndexType i, ns_default_config *def, 3786 ns_param_t *param, char *errbuf) 3787 { 3788 char *dntype; 3789 3790 if (param && param->ns_ptype == CHARPTR && 3791 (i == NS_LDAP_BINDDN_P || i == NS_LDAP_ADMIN_BINDDN_P) && 3792 ((param->ns_pc == NULL) || 3793 ((*(param->ns_pc) != '\0') && 3794 (strchr(param->ns_pc, '=') != NULL)))) { 3795 return (NS_SUCCESS); 3796 } 3797 if (i == NS_LDAP_BINDDN_P) 3798 dntype = "proxy"; 3799 else 3800 dntype = "update"; 3801 (void) snprintf(errbuf, MAXERROR, 3802 gettext("NULL or invalid %s bind DN"), dntype); 3803 return (NS_PARSE_ERR); 3804 } 3805 3806 3807 /* Check for a BINDPASSWD */ 3808 /* The string can not be NULL or empty */ 3809 /* Size of errbuf needs to be MAXERROR */ 3810 /* ARGSUSED */ 3811 static int 3812 __s_val_bindpw(ParamIndexType i, ns_default_config *def, 3813 ns_param_t *param, char *errbuf) 3814 { 3815 char *pwtype; 3816 3817 if (param && param->ns_ptype == CHARPTR && 3818 (i == NS_LDAP_BINDPASSWD_P || i == NS_LDAP_ADMIN_BINDPASSWD_P) && 3819 ((param->ns_pc == NULL) || 3820 (*(param->ns_pc) != '\0'))) { 3821 return (NS_SUCCESS); 3822 } 3823 if (i == NS_LDAP_BINDPASSWD_P) 3824 pwtype = "proxy"; 3825 else 3826 pwtype = "admin"; 3827 (void) snprintf(errbuf, MAXERROR, 3828 gettext("NULL %s bind password"), pwtype); 3829 return (NS_PARSE_ERR); 3830 } 3831 3832 /* 3833 * __s_get_hostcertpath returns either the configured host certificate path 3834 * or, if none, the default host certificate path (/var/ldap). Note that this 3835 * does not use __ns_ldap_getParam because it may be called during connection 3836 * setup. This can fail due to insufficient memory. 3837 */ 3838 3839 char * 3840 __s_get_hostcertpath(void) 3841 { 3842 ns_config_t *cfg; 3843 ns_param_t *param; 3844 char *ret = NULL; 3845 3846 cfg = __s_api_get_default_config(); 3847 if (cfg != NULL) { 3848 param = &cfg->paramList[NS_LDAP_HOST_CERTPATH_P]; 3849 if (param->ns_ptype == CHARPTR) 3850 ret = strdup(param->ns_pc); 3851 __s_api_release_config(cfg); 3852 } 3853 if (ret == NULL) 3854 ret = strdup(NSLDAPDIRECTORY); 3855 return (ret); 3856 } 3857 3858 static void 3859 _free_config() 3860 { 3861 if (current_config != NULL) 3862 destroy_config(current_config); 3863 3864 current_config = NULL; 3865 } 3866