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