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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * libsldap - library side configuration components 30 * Routines to manage the config structure 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <stddef.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <libintl.h> 39 #include <locale.h> 40 #include <thread.h> 41 #include <synch.h> 42 #include <errno.h> 43 #include <unistd.h> 44 #include <fcntl.h> 45 #include <ctype.h> 46 #include <crypt.h> 47 #include <arpa/inet.h> 48 #include <sys/types.h> 49 #include <sys/stat.h> 50 #include <syslog.h> 51 #include <netdb.h> 52 #include <sys/systeminfo.h> 53 #include <sys/mman.h> 54 #include <sys/time.h> 55 #include <limits.h> 56 #include "ns_sldap.h" 57 #include "ns_internal.h" 58 #include "ns_cache_door.h" 59 #include "ns_connmgmt.h" 60 61 #pragma fini(__s_api_free_sessionPool, __s_api_shutdown_conn_mgmt, \ 62 _free_config, __ns_ldap_doorfd_close) 63 64 static mutex_t ns_parse_lock = DEFAULTMUTEX; 65 static mutex_t ns_loadrefresh_lock = DEFAULTMUTEX; 66 static ns_config_t *current_config = NULL; 67 68 static int cache_server = FALSE; 69 extern thread_key_t ns_cmgkey; 70 71 /* 72 * Parameter Index Type validation routines 73 */ 74 static int 75 __s_val_postime(ParamIndexType i, ns_default_config *def, 76 ns_param_t *param, char *errbuf); 77 static int 78 __s_val_basedn(ParamIndexType i, ns_default_config *def, 79 ns_param_t *param, char *errbuf); 80 81 static int 82 __s_val_binddn(ParamIndexType i, ns_default_config *def, 83 ns_param_t *param, char *errbuf); 84 85 static int 86 __s_val_bindpw(ParamIndexType i, ns_default_config *def, 87 ns_param_t *param, char *errbuf); 88 89 static int 90 __s_val_serverList(ParamIndexType i, ns_default_config *def, 91 ns_param_t *param, char *errbuf); 92 93 /* 94 * Forward declarations 95 */ 96 97 static ns_parse_status 98 verify_value(ns_config_t *cfg, char *name, char *value, char *errstr); 99 100 static int 101 set_default_value(ns_config_t *configptr, char *name, char *value, 102 ns_ldap_error_t **error); 103 104 static void 105 set_curr_config(ns_config_t *ptr); 106 107 static int 108 __door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error); 109 110 static ns_config_t * 111 SetDoorInfo(char *buffer, ns_ldap_error_t **errorp); 112 113 static boolean_t 114 timetorefresh(ns_config_t *cfg); 115 116 static ns_config_t * 117 LoadCacheConfiguration(ns_config_t *, ns_ldap_error_t **error); 118 119 static void ** 120 dupParam(ns_param_t *ptr); 121 122 static time_t 123 conv_time(char *s); 124 125 /* 126 * Structures used in enum <-> string mapping routines 127 */ 128 129 static ns_enum_map ns_auth_enum_v1[] = { 130 { ENUM2INT(NS_LDAP_EA_NONE), "NS_LDAP_AUTH_NONE" }, 131 { ENUM2INT(NS_LDAP_EA_SIMPLE), "NS_LDAP_AUTH_SIMPLE" }, 132 { ENUM2INT(NS_LDAP_EA_SASL_CRAM_MD5), "NS_LDAP_AUTH_SASL_CRAM_MD5" }, 133 { -1, NULL }, 134 }; 135 136 static ns_enum_map ns_auth_enum_v2[] = { 137 { ENUM2INT(NS_LDAP_EA_NONE), "none" }, 138 { ENUM2INT(NS_LDAP_EA_SIMPLE), "simple" }, 139 { ENUM2INT(NS_LDAP_EA_SASL_CRAM_MD5), "sasl/CRAM-MD5" }, 140 { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5), "sasl/DIGEST-MD5" }, 141 { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5_INT), 142 "sasl/DIGEST-MD5:auth-int" }, 143 { ENUM2INT(NS_LDAP_EA_SASL_DIGEST_MD5_CONF), 144 "sasl/DIGEST-MD5:auth-conf" }, 145 { ENUM2INT(NS_LDAP_EA_SASL_EXTERNAL), "sasl/EXTERNAL" }, 146 { ENUM2INT(NS_LDAP_EA_SASL_GSSAPI), "sasl/GSSAPI" }, 147 { ENUM2INT(NS_LDAP_EA_TLS_NONE), "tls:none" }, 148 { ENUM2INT(NS_LDAP_EA_TLS_SIMPLE), "tls:simple" }, 149 { ENUM2INT(NS_LDAP_EA_TLS_SASL_CRAM_MD5), "tls:sasl/CRAM-MD5" }, 150 { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5), "tls:sasl/DIGEST-MD5" }, 151 { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT), 152 "tls:sasl/DIGEST-MD5:auth-int" }, 153 { ENUM2INT(NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF), 154 "tls:sasl/DIGEST-MD5:auth-conf" }, 155 { ENUM2INT(NS_LDAP_EA_TLS_SASL_EXTERNAL), "tls:sasl/EXTERNAL" }, 156 { -1, NULL }, 157 }; 158 159 /* V1 ONLY */ 160 static ns_enum_map ns_sec_enum_v1[] = { 161 { ENUM2INT(NS_LDAP_TLS_NONE), "NS_LDAP_SEC_NONE" }, 162 { -1, NULL }, 163 }; 164 165 /* V2 ONLY */ 166 static ns_enum_map ns_cred_enum_v2[] = { 167 { ENUM2INT(NS_LDAP_CRED_ANON), "anonymous" }, 168 { ENUM2INT(NS_LDAP_CRED_PROXY), "proxy" }, 169 { ENUM2INT(NS_LDAP_CRED_SELF), "self" }, 170 { -1, NULL }, 171 }; 172 173 static ns_enum_map ns_ref_enum_v1[] = { 174 { ENUM2INT(NS_LDAP_FOLLOWREF), "NS_LDAP_FOLLOWREF" }, 175 { ENUM2INT(NS_LDAP_NOREF), "NS_LDAP_NOREF" }, 176 { -1, NULL }, 177 }; 178 179 static ns_enum_map ns_ref_enum_v2[] = { 180 { ENUM2INT(NS_LDAP_FOLLOWREF), "TRUE" }, 181 { ENUM2INT(NS_LDAP_NOREF), "FALSE" }, 182 { -1, NULL }, 183 }; 184 185 static ns_enum_map ns_scope_enum_v1[] = { 186 { ENUM2INT(NS_LDAP_SCOPE_BASE), "NS_LDAP_SCOPE_BASE" }, 187 { ENUM2INT(NS_LDAP_SCOPE_ONELEVEL), "NS_LDAP_SCOPE_ONELEVEL" }, 188 { ENUM2INT(NS_LDAP_SCOPE_SUBTREE), "NS_LDAP_SCOPE_SUBTREE" }, 189 { -1, NULL }, 190 }; 191 192 static ns_enum_map ns_scope_enum_v2[] = { 193 { ENUM2INT(NS_LDAP_SCOPE_BASE), "base" }, 194 { ENUM2INT(NS_LDAP_SCOPE_ONELEVEL), "one" }, 195 { ENUM2INT(NS_LDAP_SCOPE_SUBTREE), "sub" }, 196 { -1, NULL }, 197 }; 198 199 static ns_enum_map ns_pref_enum[] = { 200 { ENUM2INT(NS_LDAP_PREF_FALSE), "NS_LDAP_FALSE" }, 201 { ENUM2INT(NS_LDAP_PREF_TRUE), "NS_LDAP_TRUE" }, 202 { -1, NULL }, 203 }; 204 205 static int ns_def_auth_v1[] = { 206 ENUM2INT(NS_LDAP_EA_NONE), 207 0 208 }; 209 210 static int ns_def_auth_v2[] = { 211 ENUM2INT(NS_LDAP_EA_NONE), 212 0 213 }; 214 215 static int ns_def_cred_v1[] = { 216 ENUM2INT(NS_LDAP_CRED_PROXY), 217 0 218 }; 219 220 static int ns_def_cred_v2[] = { 221 ENUM2INT(NS_LDAP_CRED_ANON), 222 0 223 }; 224 225 /* 226 * The next macro places an integer in the first sizeof(int) bytes of a 227 * void pointer location. For 32-bit, it is the same as "(void *) i". It 228 * is used to solve a problem found during 64-bit testing. The problem 229 * was that for a configuration parameter such as NS_LDAP_SEARCH_REF_P, 230 * which is of type INT and has defined default value, an int 231 * variable(ns_param.ns_pu.i) defined inside an union(ns_pu) structure, is 232 * used to access the defined default value. This requires the default 233 * value to be in the first sizeof(int) bytes of the union element. If 234 * just using "(void *) intval" to declare the default value in the 235 * following defconfig[] structure, the intval data will be placed is the 236 * last sizeof(int) bytes. In which case, when accessing via ns_pu_i in 237 * a 64-bit system, ZERO will be returned as the default value, not the 238 * defined one. 239 * 240 * Note since amd64 is little-endian, the problem is not an issue. 241 * INT2VOIDPTR will just leave the data (i) unchanged. 242 */ 243 #if defined(__amd64) 244 #define INT2VOIDPTR(i) (void *)i 245 #else 246 #define INT2VOIDPTR(i) \ 247 (void *)(((long)(i))<<(8*(sizeof (void *) - sizeof (int)))) 248 #endif 249 /* 250 * The default configuration table 251 * Version 1 entries are first, V2 entries follow. 252 */ 253 static ns_default_config defconfig[] = { 254 /* optional V1 profile */ 255 {"NS_LDAP_FILE_VERSION", NS_LDAP_FILE_VERSION_P, 256 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 257 NULL, /* No version number defined in V1 */ 258 { CHARPTR, 0, (void *)NS_LDAP_VERSION_1 }, 259 NULL, NULL }, 260 261 /* ---------- V1 profile ---------- */ 262 {"NS_LDAP_BINDDN", NS_LDAP_BINDDN_P, 263 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 264 _P1_BINDDN, 265 { CHARPTR, 0, NULL }, 266 __s_val_binddn, NULL }, 267 268 {"NS_LDAP_BINDPASSWD", NS_LDAP_BINDPASSWD_P, 269 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 270 _P1_BINDPASSWORD, 271 { CHARPTR, 0, NULL }, 272 __s_val_bindpw, NULL }, 273 274 {"NS_LDAP_SERVERS", NS_LDAP_SERVERS_P, 275 SERVERCONFIG, ARRAYCP, FALSE, NS_LDAP_V1, 276 _P1_SERVERS, 277 { ARRAYCP, 0, NULL }, 278 __s_val_serverList, NULL }, 279 280 {"NS_LDAP_SEARCH_BASEDN", NS_LDAP_SEARCH_BASEDN_P, 281 SERVERCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 282 _P1_SEARCHBASEDN, 283 { CHARPTR, 0, NULL }, 284 __s_val_basedn, NULL }, 285 286 {"NS_LDAP_AUTH", NS_LDAP_AUTH_P, 287 CLIENTCONFIG, ARRAYAUTH, FALSE, NS_LDAP_V1, 288 _P1_AUTHMETHOD, 289 { ARRAYAUTH, 1, (void *)&ns_def_auth_v1[0] }, 290 NULL, ns_auth_enum_v1 }, 291 292 {"NS_LDAP_TRANSPORT_SEC", NS_LDAP_TRANSPORT_SEC_P, 293 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1, 294 _P1_TRANSPORTSECURITY, 295 { INT, 0, INT2VOIDPTR(NS_LDAP_TLS_NONE) }, 296 NULL, ns_sec_enum_v1 }, 297 298 {"NS_LDAP_SEARCH_REF", NS_LDAP_SEARCH_REF_P, 299 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1, 300 _P1_SEARCHREFERRAL, 301 { INT, 0, INT2VOIDPTR(NS_LDAP_FOLLOWREF) }, 302 NULL, ns_ref_enum_v1 }, 303 304 {"NS_LDAP_DOMAIN", NS_LDAP_DOMAIN_P, 305 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 306 NULL, /* not defined in the Profile */ 307 { CHARPTR, 0, NULL }, 308 NULL, NULL }, 309 310 {"NS_LDAP_EXP", NS_LDAP_EXP_P, 311 SERVERCONFIG, TIMET, TRUE, NS_LDAP_V1, 312 NULL, /* initialized by code to time+NS_LDAP_CACHETTL */ 313 { INT, 0, 0 }, 314 NULL, NULL }, 315 316 {"NS_LDAP_CERT_PATH", NS_LDAP_CERT_PATH_P, 317 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 318 _P1_CERTIFICATEPATH, 319 { CHARPTR, 0, NULL }, 320 NULL, NULL }, 321 322 {"NS_LDAP_CERT_PASS", NS_LDAP_CERT_PASS_P, 323 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 324 _P1_CERTIFICATEPASSWORD, 325 { CHARPTR, 0, NULL }, 326 NULL, NULL }, 327 328 {"NS_LDAP_SEARCH_DN", NS_LDAP_SEARCH_DN_P, 329 CLIENTCONFIG, SSDLIST, FALSE, NS_LDAP_V1, 330 _P1_DATASEARCHDN, 331 { SSDLIST, 0, NULL }, 332 NULL, NULL }, 333 334 {"NS_LDAP_SEARCH_SCOPE", NS_LDAP_SEARCH_SCOPE_P, 335 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1, 336 _P1_SEARCHSCOPE, 337 { INT, 0, INT2VOIDPTR(NS_LDAP_SCOPE_ONELEVEL) }, 338 NULL, ns_scope_enum_v1 }, 339 340 {"NS_LDAP_SEARCH_TIME", NS_LDAP_SEARCH_TIME_P, 341 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1, 342 _P1_SEARCHTIMELIMIT, 343 { INT, 0, INT2VOIDPTR(NS_DEFAULT_SEARCH_TIMEOUT) }, 344 NULL, NULL }, 345 346 {"NS_LDAP_SERVER_PREF", NS_LDAP_SERVER_PREF_P, 347 CLIENTCONFIG, ARRAYCP, FALSE, NS_LDAP_V1, 348 _P1_PREFERREDSERVER, 349 { ARRAYCP, 0, NULL }, 350 __s_val_serverList, NULL }, 351 352 {"NS_LDAP_PREF_ONLY", NS_LDAP_PREF_ONLY_P, 353 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1, 354 _P1_PREFERREDSERVERONLY, 355 { INT, 0, INT2VOIDPTR(NS_LDAP_PREF_FALSE) }, 356 NULL, ns_pref_enum }, 357 358 {"NS_LDAP_CACHETTL", NS_LDAP_CACHETTL_P, 359 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 360 _P1_CACHETTL, 361 { CHARPTR, 0, (void *)EXP_DEFAULT_TTL }, 362 __s_val_postime, NULL }, 363 364 {"NS_LDAP_PROFILE", NS_LDAP_PROFILE_P, 365 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V1, 366 _P_CN, 367 { CHARPTR, 0, (void *)DEFAULTCONFIGNAME }, 368 NULL, NULL }, 369 370 {"NS_LDAP_BIND_TIME", NS_LDAP_BIND_TIME_P, 371 CLIENTCONFIG, INT, TRUE, NS_LDAP_V1, 372 _P1_BINDTIMELIMIT, 373 { INT, 0, INT2VOIDPTR(NS_DEFAULT_BIND_TIMEOUT) }, 374 NULL, NULL }, 375 376 /* This configuration option is not visible in V1 */ 377 {"NS_LDAP_CREDENTIAL_LEVEL", NS_LDAP_CREDENTIAL_LEVEL_P, 378 CLIENTCONFIG, ARRAYCRED, TRUE, NS_LDAP_V1, 379 NULL, /* No version defined in V1 */ 380 { ARRAYCRED, 0, (void *)&ns_def_cred_v1[0] }, 381 NULL, NULL }, 382 383 /* ---------- V2 profile ---------- */ 384 {"NS_LDAP_FILE_VERSION", NS_LDAP_FILE_VERSION_P, 385 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2, 386 NULL, /* No version number defined in V1 */ 387 { CHARPTR, 0, (void *)NS_LDAP_VERSION_2 }, 388 NULL, NULL }, 389 390 {"NS_LDAP_BINDDN", NS_LDAP_BINDDN_P, 391 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2, 392 NULL, /* not defined in the Profile */ 393 { CHARPTR, 0, NULL }, 394 __s_val_binddn, NULL }, 395 {"NS_LDAP_BINDPASSWD", NS_LDAP_BINDPASSWD_P, 396 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2, 397 NULL, /* not defined in the Profile */ 398 { CHARPTR, 0, NULL }, 399 __s_val_bindpw, NULL }, 400 {"NS_LDAP_EXP", NS_LDAP_EXP_P, 401 SERVERCONFIG, TIMET, TRUE, NS_LDAP_V2, 402 NULL, /* initialized by code to time+NS_LDAP_CACHETTL */ 403 { INT, 0, 0 }, 404 NULL, NULL }, 405 406 {"NS_LDAP_SERVER_PREF", NS_LDAP_SERVER_PREF_P, 407 CLIENTCONFIG, SERVLIST, FALSE, NS_LDAP_V2, 408 _P2_PREFERREDSERVER, 409 { SERVLIST, 0, NULL }, 410 __s_val_serverList, NULL }, 411 412 {"NS_LDAP_SERVERS", NS_LDAP_SERVERS_P, 413 SERVERCONFIG, SERVLIST, FALSE, NS_LDAP_V2, 414 _P2_DEFAULTSERVER, 415 { SERVLIST, 0, NULL }, 416 __s_val_serverList, NULL }, 417 418 {"NS_LDAP_SEARCH_BASEDN", NS_LDAP_SEARCH_BASEDN_P, 419 SERVERCONFIG, CHARPTR, TRUE, NS_LDAP_V2, 420 _P2_SEARCHBASEDN, 421 { CHARPTR, 0, NULL }, 422 __s_val_basedn, NULL }, 423 424 {"NS_LDAP_SEARCH_SCOPE", NS_LDAP_SEARCH_SCOPE_P, 425 CLIENTCONFIG, INT, TRUE, NS_LDAP_V2, 426 _P2_SEARCHSCOPE, 427 { INT, 0, INT2VOIDPTR(NS_LDAP_SCOPE_ONELEVEL) }, 428 NULL, ns_scope_enum_v2 }, 429 430 {"NS_LDAP_AUTH", NS_LDAP_AUTH_P, 431 CLIENTCONFIG, ARRAYAUTH, FALSE, NS_LDAP_V2, 432 _P2_AUTHMETHOD, 433 { ARRAYAUTH, 2, (void *)&ns_def_auth_v2[0] }, 434 NULL, ns_auth_enum_v2 }, 435 436 {"NS_LDAP_CREDENTIAL_LEVEL", NS_LDAP_CREDENTIAL_LEVEL_P, 437 CLIENTCONFIG, ARRAYCRED, FALSE, NS_LDAP_V2, 438 _P2_CREDENTIALLEVEL, 439 { ARRAYCRED, 0, (void *)&ns_def_cred_v2[0] }, 440 NULL, ns_cred_enum_v2 }, 441 442 {"NS_LDAP_SERVICE_SEARCH_DESC", NS_LDAP_SERVICE_SEARCH_DESC_P, 443 CLIENTCONFIG, SSDLIST, FALSE, NS_LDAP_V2, 444 _P2_SERVICESEARCHDESC, 445 { SSDLIST, 0, NULL }, 446 NULL, NULL }, 447 448 {"NS_LDAP_SEARCH_TIME", NS_LDAP_SEARCH_TIME_P, 449 CLIENTCONFIG, INT, TRUE, NS_LDAP_V2, 450 _P2_SEARCHTIMELIMIT, 451 { INT, 0, INT2VOIDPTR(NS_DEFAULT_SEARCH_TIMEOUT) }, 452 NULL, NULL }, 453 454 {"NS_LDAP_BIND_TIME", NS_LDAP_BIND_TIME_P, 455 CLIENTCONFIG, INT, TRUE, NS_LDAP_V2, 456 _P2_BINDTIMELIMIT, 457 { INT, 0, INT2VOIDPTR(NS_DEFAULT_BIND_TIMEOUT) }, 458 NULL, NULL }, 459 460 {"NS_LDAP_SEARCH_REF", NS_LDAP_SEARCH_REF_P, 461 CLIENTCONFIG, INT, TRUE, NS_LDAP_V2, 462 _P2_FOLLOWREFERRALS, 463 { INT, 0, INT2VOIDPTR(NS_LDAP_FOLLOWREF) }, 464 NULL, ns_ref_enum_v2 }, 465 466 {"NS_LDAP_CACHETTL", NS_LDAP_CACHETTL_P, 467 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2, 468 _P2_PROFILETTL, 469 { CHARPTR, 0, (void *)EXP_DEFAULT_TTL }, 470 __s_val_postime, NULL }, 471 472 {"NS_LDAP_ATTRIBUTEMAP", NS_LDAP_ATTRIBUTEMAP_P, 473 CLIENTCONFIG, ATTRMAP, FALSE, NS_LDAP_V2, 474 _P2_ATTRIBUTEMAP, 475 { ATTRMAP, 0, NULL }, 476 NULL, NULL }, 477 478 {"NS_LDAP_OBJECTCLASSMAP", NS_LDAP_OBJECTCLASSMAP_P, 479 CLIENTCONFIG, OBJMAP, FALSE, NS_LDAP_V2, 480 _P2_OBJECTCLASSMAP, 481 { OBJMAP, 0, NULL }, 482 NULL, NULL }, 483 484 {"NS_LDAP_PROFILE", NS_LDAP_PROFILE_P, 485 CLIENTCONFIG, CHARPTR, TRUE, NS_LDAP_V2, 486 _P_CN, 487 { CHARPTR, 0, (void *)DEFAULTCONFIGNAME }, 488 NULL, NULL }, 489 490 {"NS_LDAP_SERVICE_AUTH_METHOD", NS_LDAP_SERVICE_AUTH_METHOD_P, 491 CLIENTCONFIG, SAMLIST, FALSE, NS_LDAP_V2, 492 _P2_SERVICEAUTHMETHOD, 493 { SAMLIST, 0, NULL }, 494 NULL, NULL }, 495 496 {"NS_LDAP_SERVICE_CRED_LEVEL", NS_LDAP_SERVICE_CRED_LEVEL_P, 497 CLIENTCONFIG, SCLLIST, FALSE, NS_LDAP_V2, 498 _P2_SERVICECREDLEVEL, 499 { SCLLIST, 0, NULL }, 500 NULL, NULL }, 501 502 {"NS_LDAP_HOST_CERTPATH", NS_LDAP_HOST_CERTPATH_P, 503 CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2, 504 NULL, /* not defined in the Profile */ 505 { CHARPTR, 0, (void *)NSLDAPDIRECTORY }, 506 NULL, NULL }, 507 508 /* array terminator [not an entry] */ 509 {NULL, NS_LDAP_FILE_VERSION_P, 510 CLIENTCONFIG, NS_UNKNOWN, TRUE, NULL, 511 NULL, 512 { NS_UNKNOWN, 0, NULL }, 513 NULL, NULL }, 514 }; 515 516 static char * 517 __getdomainname() 518 { 519 /* 520 * The sysinfo man page recommends using a buffer size 521 * of 257 bytes. MAXHOSTNAMELEN is 256. So add 1 here. 522 */ 523 char buf[MAXHOSTNAMELEN + 1]; 524 int status; 525 526 status = sysinfo(SI_SRPC_DOMAIN, buf, MAXHOSTNAMELEN); 527 if (status < 0) 528 return (NULL); 529 /* error: not enough space to hold returned value */ 530 if (status > sizeof (buf)) 531 return (NULL); 532 return (strdup(buf)); 533 } 534 535 void 536 __ns_ldap_setServer(int set) 537 { 538 cache_server = set; 539 } 540 541 static boolean_t 542 timetorefresh(ns_config_t *cfg) 543 { 544 struct timeval tp; 545 static time_t expire = 0; 546 547 if (cfg == NULL || gettimeofday(&tp, NULL) == -1) 548 return (B_TRUE); 549 550 if (cfg->paramList[NS_LDAP_EXP_P].ns_ptype == TIMET) 551 expire = cfg->paramList[NS_LDAP_EXP_P].ns_tm; 552 else 553 return (B_TRUE); 554 555 return (expire != 0 && tp.tv_sec > expire); 556 } 557 558 int 559 __s_get_enum_value(ns_config_t *ptr, char *value, ParamIndexType i) 560 { 561 register ns_enum_map *mapp; 562 char *pstart = value; 563 char *pend; 564 int len; 565 566 if (pstart == NULL) 567 return (-1); 568 569 /* skip leading spaces */ 570 while (*pstart == SPACETOK) 571 pstart++; 572 /* skip trailing spaces */ 573 pend = pstart + strlen(pstart) - 1; 574 for (; pend >= pstart && *pend == SPACETOK; pend--) 575 ; 576 len = pend - pstart + 1; 577 if (len == 0) 578 return (-1); 579 580 switch (i) { 581 case NS_LDAP_AUTH_P: 582 if (ptr->version == NS_LDAP_V1) 583 mapp = &ns_auth_enum_v1[0]; 584 else 585 mapp = &ns_auth_enum_v2[0]; 586 break; 587 case NS_LDAP_TRANSPORT_SEC_P: 588 return (-1); 589 case NS_LDAP_SEARCH_SCOPE_P: 590 if (ptr->version == NS_LDAP_V1) 591 mapp = &ns_scope_enum_v1[0]; 592 else 593 mapp = &ns_scope_enum_v2[0]; 594 break; 595 case NS_LDAP_SEARCH_REF_P: 596 if (ptr->version == NS_LDAP_V1) 597 mapp = &ns_ref_enum_v1[0]; 598 else 599 mapp = &ns_ref_enum_v2[0]; 600 break; 601 case NS_LDAP_PREF_ONLY_P: 602 mapp = &ns_pref_enum[0]; 603 break; 604 case NS_LDAP_CREDENTIAL_LEVEL_P: 605 if (ptr->version == NS_LDAP_V1) 606 return (-1); 607 else 608 mapp = &ns_cred_enum_v2[0]; 609 break; 610 case NS_LDAP_SERVICE_AUTH_METHOD_P: 611 mapp = &ns_auth_enum_v2[0]; 612 break; 613 case NS_LDAP_SERVICE_CRED_LEVEL_P: 614 mapp = &ns_cred_enum_v2[0]; 615 break; 616 default: 617 return (-1); 618 } 619 620 for (; mapp->name != NULL; mapp++) { 621 if (strncasecmp(pstart, mapp->name, len) == 0 && 622 (strlen(mapp->name) == len)) { 623 return (mapp->value); 624 } 625 } 626 return (-1); 627 } 628 629 char * 630 __s_get_auth_name(ns_config_t *ptr, AuthType_t type) 631 { 632 register ns_enum_map *mapp; 633 634 if (ptr->version == NS_LDAP_V1) 635 mapp = &ns_auth_enum_v1[0]; 636 else 637 mapp = &ns_auth_enum_v2[0]; 638 639 for (; mapp->name != NULL; mapp++) { 640 if (type == INT2AUTHENUM(mapp->value)) { 641 return (mapp->name); 642 } 643 } 644 return ("Unknown AuthType_t type specified"); 645 } 646 647 648 char * 649 __s_get_security_name(ns_config_t *ptr, TlsType_t type) 650 { 651 register ns_enum_map *mapp; 652 653 if (ptr->version == NS_LDAP_V1) { 654 mapp = &ns_sec_enum_v1[0]; 655 656 for (; mapp->name != NULL; mapp++) { 657 if (type == INT2SECENUM(mapp->value)) { 658 return (mapp->name); 659 } 660 } 661 } 662 return ("Unknown TlsType_t type specified"); 663 } 664 665 666 char * 667 __s_get_scope_name(ns_config_t *ptr, ScopeType_t type) 668 { 669 register ns_enum_map *mapp; 670 671 if (ptr->version == NS_LDAP_V1) 672 mapp = &ns_scope_enum_v1[0]; 673 else 674 mapp = &ns_scope_enum_v2[0]; 675 676 for (; mapp->name != NULL; mapp++) { 677 if (type == INT2SCOPEENUM(mapp->value)) { 678 return (mapp->name); 679 } 680 } 681 return ("Unknown ScopeType_t type specified"); 682 } 683 684 685 char * 686 __s_get_pref_name(PrefOnly_t type) 687 { 688 register ns_enum_map *mapp = &ns_pref_enum[0]; 689 690 for (; mapp->name != NULL; mapp++) { 691 if (type == INT2PREFONLYENUM(mapp->value)) { 692 return (mapp->name); 693 } 694 } 695 return ("Unknown PrefOnly_t type specified"); 696 } 697 698 char * 699 __s_get_searchref_name(ns_config_t *ptr, SearchRef_t type) 700 { 701 register ns_enum_map *mapp; 702 703 if (ptr->version == NS_LDAP_V1) 704 mapp = &ns_ref_enum_v1[0]; 705 else 706 mapp = &ns_ref_enum_v2[0]; 707 708 for (; mapp->name != NULL; mapp++) { 709 if (type == INT2SEARCHREFENUM(mapp->value)) { 710 return (mapp->name); 711 } 712 } 713 return ("Unknown SearchRef_t type specified"); 714 } 715 716 static char * 717 __s_get_credlvl_name(ns_config_t *ptr, CredLevel_t type) 718 { 719 register ns_enum_map *mapp; 720 721 if (ptr->version == NS_LDAP_V2) { 722 mapp = &ns_cred_enum_v2[0]; 723 for (; mapp->name != NULL; mapp++) { 724 if (type == INT2CREDLEVELENUM(mapp->value)) { 725 return (mapp->name); 726 } 727 } 728 } 729 return ("Unknown CredLevel_t type specified"); 730 } 731 732 static void 733 destroy_param(ns_config_t *ptr, ParamIndexType type) 734 { 735 int i, j; 736 char **ppc; 737 738 if (ptr == NULL) 739 return; 740 741 /* 742 * This routine is not lock protected because 743 * the config param it may be destroying is not 744 * necessarily THE config. Mutex protect elsewhere. 745 */ 746 switch (ptr->paramList[type].ns_ptype) { 747 case CHARPTR: 748 if (ptr->paramList[type].ns_pc) { 749 free(ptr->paramList[type].ns_pc); 750 ptr->paramList[type].ns_pc = NULL; 751 } 752 break; 753 case SAMLIST: 754 case SCLLIST: 755 case SSDLIST: 756 case ARRAYCP: 757 case SERVLIST: 758 if (ptr->paramList[type].ns_ppc) { 759 ppc = ptr->paramList[type].ns_ppc; 760 j = ptr->paramList[type].ns_acnt; 761 for (i = 0; i < j && ppc[i] != NULL; i++) { 762 free((void *)ppc[i]); 763 } 764 free((void *)ppc); 765 ptr->paramList[type].ns_ppc = NULL; 766 } 767 break; 768 case ARRAYAUTH: 769 case ARRAYCRED: 770 if (ptr->paramList[type].ns_pi) { 771 free(ptr->paramList[type].ns_pi); 772 ptr->paramList[type].ns_pi = NULL; 773 } 774 break; 775 case INT: 776 ptr->paramList[type].ns_i = 0; 777 break; 778 case ATTRMAP: 779 break; 780 case OBJMAP: 781 break; 782 default: 783 break; 784 } 785 ptr->paramList[type].ns_ptype = NS_UNKNOWN; 786 } 787 788 static void 789 destroy_config(ns_config_t *ptr) 790 { 791 ParamIndexType i; 792 793 if (ptr != NULL) { 794 if (ptr == current_config) 795 current_config = NULL; 796 if (ptr->domainName != NULL) 797 free(ptr->domainName); 798 ptr->domainName = NULL; 799 for (i = 0; i <= LAST_VALUE; i++) { 800 destroy_param(ptr, i); 801 } 802 __s_api_destroy_hash(ptr); 803 free(ptr); 804 } 805 } 806 807 /* 808 * Marks the ns_config_t to be deleted and then releases it. (If no other 809 * caller is using, then __s_api_release_config will destroy it.) 810 * 811 * Note that __s_api_destroy_config should only be called if the caller has 812 * created the ns_config_t with __s_api_create_config (with the exception 813 * of set_curr_config). The ns_config_t should be private to the caller. 814 * 815 * This function should not be called with the current_config except by 816 * set_curr_config which locks ns_parse_lock to ensure that no thread 817 * will be waiting on current_config->config_mutex. This ensures that 818 * no caller with be waiting on cfg->config_mutex while it is being 819 * destroyed by __s_api_release_config. 820 */ 821 822 void 823 __s_api_destroy_config(ns_config_t *cfg) 824 { 825 if (cfg != NULL) { 826 (void) mutex_lock(&cfg->config_mutex); 827 cfg->delete = TRUE; 828 (void) mutex_unlock(&cfg->config_mutex); 829 __s_api_release_config(cfg); 830 } 831 } 832 833 834 /* 835 * Increment the configuration use count by one - assumes ns_parse_lock has 836 * been obtained. 837 */ 838 839 static ns_config_t * 840 get_curr_config_unlocked(ns_config_t *cfg) 841 { 842 ns_config_t *ret; 843 844 ret = cfg; 845 if (cfg != NULL) { 846 (void) mutex_lock(&cfg->config_mutex); 847 if (cfg->delete) 848 ret = NULL; 849 else 850 cfg->nUse++; 851 (void) mutex_unlock(&cfg->config_mutex); 852 } 853 return (ret); 854 } 855 856 /* 857 * set_curr_config_global sets the current global config to the 858 * specified ns_config_t. Note that this function is similar 859 * to the project private function __s_api_init_config_global 860 * except that it does not release the new ns_config_t. 861 */ 862 static void 863 set_curr_config_global(ns_config_t *ptr) 864 { 865 ns_config_t *cfg; 866 ns_config_t *cur_cfg; 867 868 (void) mutex_lock(&ns_parse_lock); 869 cur_cfg = current_config; 870 cfg = get_curr_config_unlocked(cur_cfg); 871 if (cfg != ptr) { 872 __s_api_destroy_config(cfg); 873 current_config = ptr; 874 } 875 (void) mutex_unlock(&ns_parse_lock); 876 } 877 878 879 /* 880 * set_curr_config sets the current config or the per connection 881 * management one to the specified ns_config_t. Note that this function 882 * is similar to the project private function __s_api_init_config 883 * except that it does not release the new ns_config_t. Also note 884 * that if there's no per connection management one to set, the 885 * global current config will be set. 886 */ 887 888 static void 889 set_curr_config(ns_config_t *ptr) 890 { 891 ns_config_t *cfg; 892 ns_config_t *cur_cfg; 893 ns_conn_mgmt_t *cmg; 894 int rc; 895 896 rc = thr_getspecific(ns_cmgkey, (void **)&cmg); 897 898 /* set the per connection management config if possible */ 899 if (rc == 0 && cmg != NULL && cmg->config != NULL) { 900 (void) mutex_lock(&cmg->cfg_lock); 901 cur_cfg = cmg->config; 902 cfg = get_curr_config_unlocked(cur_cfg); 903 if (cfg != ptr) { 904 __s_api_destroy_config(cfg); 905 cmg->config = ptr; 906 } 907 (void) mutex_unlock(&cmg->cfg_lock); 908 return; 909 } 910 911 /* else set the global current config */ 912 set_curr_config_global(ptr); 913 } 914 915 /* 916 * Decrements the ns_config_t usage count by one. Delete if delete flag 917 * is set and no other callers are using. 918 */ 919 920 void 921 __s_api_release_config(ns_config_t *cfg) 922 { 923 if (cfg != NULL) { 924 (void) mutex_lock(&cfg->config_mutex); 925 cfg->nUse--; 926 if (cfg->nUse == 0 && cfg->delete) { 927 destroy_config(cfg); 928 } else 929 (void) mutex_unlock(&cfg->config_mutex); 930 } 931 } 932 933 /* 934 * __s_api_init_config function destroys the previous global configuration 935 * sets the new global configuration and then releases it 936 */ 937 void 938 __s_api_init_config_global(ns_config_t *ptr) 939 { 940 set_curr_config_global(ptr); 941 __s_api_release_config(ptr); 942 } 943 944 /* 945 * __s_api_init_config function destroys the previous configuration 946 * sets the new configuration and then releases it. The configuration 947 * may be the global one or the per connection management one. 948 */ 949 void 950 __s_api_init_config(ns_config_t *ptr) 951 { 952 set_curr_config(ptr); 953 __s_api_release_config(ptr); 954 } 955 956 957 /* 958 * Create an ns_config_t, set the usage count to one 959 */ 960 961 ns_config_t * 962 __s_api_create_config(void) 963 { 964 ns_config_t *ret; 965 ret = (ns_config_t *)calloc(1, sizeof (ns_config_t)); 966 if (ret == NULL) 967 return (NULL); 968 969 ret->domainName = __getdomainname(); 970 if (ret->domainName == NULL) { 971 free(ret); 972 return (NULL); 973 } 974 ret->version = NS_LDAP_V1; 975 (void) mutex_init(&ret->config_mutex, USYNC_THREAD, NULL); 976 ret->nUse = 1; 977 ret->delete = B_FALSE; 978 return (ret); 979 } 980 981 /* 982 * __s_api_get_default_config_global returns the current global config 983 */ 984 ns_config_t * 985 __s_api_get_default_config_global(void) 986 { 987 ns_config_t *cfg; 988 ns_config_t *cur_cfg; 989 990 (void) mutex_lock(&ns_parse_lock); 991 cur_cfg = current_config; 992 cfg = get_curr_config_unlocked(cur_cfg); 993 (void) mutex_unlock(&ns_parse_lock); 994 995 return (cfg); 996 } 997 998 /* 999 * __s_api_get_default_config returns the current global config or the 1000 * per connection management one. 1001 */ 1002 ns_config_t * 1003 __s_api_get_default_config(void) 1004 { 1005 ns_config_t *cfg; 1006 ns_config_t *cur_cfg; 1007 ns_conn_mgmt_t *cmg; 1008 int rc; 1009 1010 rc = thr_getspecific(ns_cmgkey, (void **)&cmg); 1011 1012 /* get the per connection management config if available */ 1013 if (rc == 0 && cmg != NULL && cmg->config != NULL) { 1014 (void) mutex_lock(&cmg->cfg_lock); 1015 cur_cfg = cmg->config; 1016 cfg = get_curr_config_unlocked(cur_cfg); 1017 (void) mutex_unlock(&cmg->cfg_lock); 1018 return (cfg); 1019 } 1020 1021 /* else get the global current config */ 1022 return (__s_api_get_default_config_global()); 1023 } 1024 1025 static char * 1026 stripdup(const char *instr) 1027 { 1028 char *pstart = (char *)instr; 1029 char *pend, *ret; 1030 int len; 1031 1032 if (pstart == NULL) 1033 return (NULL); 1034 /* remove leading spaces */ 1035 while (*pstart == SPACETOK) 1036 pstart++; 1037 /* remove trailing spaces */ 1038 pend = pstart + strlen(pstart) - 1; 1039 for (; pend >= pstart && *pend == SPACETOK; pend--) 1040 ; 1041 len = pend - pstart + 1; 1042 if ((ret = malloc(len + 1)) == NULL) 1043 return (NULL); 1044 if (len != 0) { 1045 (void) strncpy(ret, pstart, len); 1046 } 1047 ret[len] = '\0'; 1048 return (ret); 1049 } 1050 1051 /* 1052 * Note that __s_api_crosscheck is assumed to be called with an ns_config_t 1053 * that is properly protected - so that it will not change during the 1054 * duration of the call 1055 */ 1056 1057 /* Size of errstr needs to be MAXERROR */ 1058 ns_parse_status 1059 __s_api_crosscheck(ns_config_t *ptr, char *errstr, int check_dn) 1060 { 1061 int value, j; 1062 time_t tm; 1063 const char *str, *str1; 1064 int i, cnt; 1065 int self, gssapi; 1066 1067 if (ptr == NULL) 1068 return (NS_SUCCESS); 1069 1070 /* check for no server specified */ 1071 if (ptr->paramList[NS_LDAP_SERVERS_P].ns_ppc == NULL) { 1072 if (ptr->version == NS_LDAP_V1) { 1073 str = NULL_OR_STR(__s_api_get_configname( 1074 NS_LDAP_SERVERS_P)); 1075 (void) snprintf(errstr, MAXERROR, 1076 gettext("Configuration Error: No entry for " 1077 "'%s' found"), str); 1078 return (NS_PARSE_ERR); 1079 } else if (ptr->paramList[NS_LDAP_SERVER_PREF_P].ns_ppc == 1080 NULL) { 1081 str = NULL_OR_STR(__s_api_get_configname( 1082 NS_LDAP_SERVERS_P)); 1083 str1 = NULL_OR_STR(__s_api_get_configname( 1084 NS_LDAP_SERVER_PREF_P)); 1085 (void) snprintf(errstr, MAXERROR, 1086 gettext("Configuration Error: " 1087 "Neither '%s' nor '%s' is defined"), str, str1); 1088 return (NS_PARSE_ERR); 1089 } 1090 } 1091 if (ptr->paramList[NS_LDAP_CERT_PASS_P].ns_pc != NULL && 1092 ptr->paramList[NS_LDAP_CERT_PATH_P].ns_pc == NULL) { 1093 str = NULL_OR_STR(__s_api_get_configname( 1094 NS_LDAP_CERT_PASS_P)); 1095 str1 = NULL_OR_STR(__s_api_get_configname( 1096 NS_LDAP_CERT_PATH_P)); 1097 (void) snprintf(errstr, MAXERROR, 1098 gettext("Configuration Error: %s specified " 1099 "but no value for '%s' found"), str, str1); 1100 return (NS_PARSE_ERR); 1101 } 1102 if (ptr->paramList[NS_LDAP_CERT_PASS_P].ns_pc == NULL && 1103 ptr->paramList[NS_LDAP_CERT_PATH_P].ns_pc != NULL) { 1104 str = NULL_OR_STR(__s_api_get_configname( 1105 NS_LDAP_CERT_PATH_P)); 1106 str1 = NULL_OR_STR(__s_api_get_configname( 1107 NS_LDAP_CERT_PASS_P)); 1108 (void) snprintf(errstr, MAXERROR, 1109 gettext("Configuration Error: %s specified " 1110 "but no value for '%s' found"), str, str1); 1111 return (NS_PARSE_ERR); 1112 } 1113 /* check if search basedn has been specified */ 1114 if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ppc == NULL) { 1115 str = NULL_OR_STR(__s_api_get_configname( 1116 NS_LDAP_SEARCH_BASEDN_P)); 1117 (void) snprintf(errstr, MAXERROR, 1118 gettext("Configuration Error: No entry for " 1119 "'%s' found"), str); 1120 return (NS_PARSE_ERR); 1121 } 1122 1123 if (check_dn) { 1124 /* check for auth value....passwd/bindn if necessary */ 1125 1126 for (j = 0; ptr->paramList[NS_LDAP_AUTH_P].ns_pi != NULL && 1127 ptr->paramList[NS_LDAP_AUTH_P].ns_pi[j] != NULL; j++) { 1128 value = ptr->paramList[NS_LDAP_AUTH_P].ns_pi[j]; 1129 switch (value) { 1130 case NS_LDAP_EA_SIMPLE: 1131 case NS_LDAP_EA_SASL_CRAM_MD5: 1132 case NS_LDAP_EA_SASL_DIGEST_MD5: 1133 case NS_LDAP_EA_SASL_DIGEST_MD5_INT: 1134 case NS_LDAP_EA_SASL_DIGEST_MD5_CONF: 1135 case NS_LDAP_EA_TLS_SIMPLE: 1136 case NS_LDAP_EA_TLS_SASL_CRAM_MD5: 1137 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5: 1138 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT: 1139 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF: 1140 if (ptr->paramList[NS_LDAP_BINDDN_P].ns_ppc == NULL) { 1141 str = NULL_OR_STR(__s_api_get_configname( 1142 NS_LDAP_BINDDN_P)); 1143 (void) snprintf(errstr, MAXERROR, 1144 gettext("Configuration Error: No entry for " 1145 "'%s' found"), str); 1146 return (NS_PARSE_ERR); 1147 } 1148 if (ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ppc 1149 == NULL) { 1150 str = NULL_OR_STR(__s_api_get_configname( 1151 NS_LDAP_BINDPASSWD_P)); 1152 (void) snprintf(errstr, MAXERROR, 1153 gettext("Configuration Error: No entry for " 1154 "'%s' found"), str); 1155 return (NS_PARSE_ERR); 1156 } 1157 break; 1158 } 1159 } 1160 } 1161 1162 /* 1163 * If NS_LDAP_CACHETTL is not specified, 1164 * init NS_LDAP_EXP_P here. Otherwise, 1165 * ldap_cachemgr will never refresh the profile. 1166 * Set it to current time + default 1167 * NS_LDAP_CACHETTL 1168 */ 1169 if (ptr->paramList[NS_LDAP_CACHETTL_P].ns_pc == NULL) { 1170 tm = conv_time( 1171 defconfig[NS_LDAP_CACHETTL_P].defval.ns_pc); 1172 ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET; 1173 if (tm != 0) { 1174 tm += time(NULL); 1175 } 1176 ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm; 1177 } 1178 /* 1179 * If credential level self is defined, there should be 1180 * at least an auth method sasl/GSSAPI and vice versa. 1181 */ 1182 self = 0; 1183 cnt = ptr->paramList[NS_LDAP_CREDENTIAL_LEVEL_P].ns_acnt; 1184 for (i = 0; i < cnt; i++) { 1185 if (ptr->paramList[NS_LDAP_CREDENTIAL_LEVEL_P].ns_pi[i] == 1186 NS_LDAP_CRED_SELF) 1187 self++; 1188 } 1189 gssapi = 0; 1190 cnt = ptr->paramList[NS_LDAP_AUTH_P].ns_acnt; 1191 for (i = 0; i < cnt; i++) { 1192 if (ptr->paramList[NS_LDAP_AUTH_P].ns_pi[i] == 1193 NS_LDAP_EA_SASL_GSSAPI) 1194 gssapi++; 1195 } 1196 if (gssapi == 0 && self > 0) { 1197 (void) snprintf(errstr, MAXERROR, 1198 gettext("Configuration Error: " 1199 "Credential level self requires " 1200 "authentication method sasl/GSSAPI")); 1201 return (NS_PARSE_ERR); 1202 } 1203 if (gssapi > 0 && self == 0) { 1204 (void) snprintf(errstr, MAXERROR, 1205 gettext("Configuration Error: " 1206 "Authentication method sasl/GSSAPI " 1207 "requires credential level self")); 1208 return (NS_PARSE_ERR); 1209 } 1210 return (NS_SUCCESS); 1211 } 1212 1213 1214 int 1215 __s_api_get_type(const char *value, ParamIndexType *type) 1216 { 1217 int i; 1218 1219 for (i = 0; defconfig[i].name != NULL; i++) { 1220 if (strcasecmp(defconfig[i].name, value) == 0) { 1221 *type = defconfig[i].index; 1222 return (0); 1223 } 1224 } 1225 return (-1); 1226 } 1227 1228 /* 1229 * Externally defined version of get_type. 1230 * Includes extra error checking 1231 */ 1232 1233 int 1234 __ns_ldap_getParamType(const char *value, ParamIndexType *type) 1235 { 1236 if (value == NULL || type == NULL) 1237 return (-1); 1238 return (__s_api_get_type(value, type)); 1239 } 1240 1241 int 1242 __s_api_get_versiontype(ns_config_t *ptr, char *value, ParamIndexType *type) 1243 { 1244 ns_version_t ver; 1245 int i; 1246 1247 if (ptr == NULL) 1248 return (-1); 1249 1250 ver = ptr->version; 1251 1252 for (i = 0; defconfig[i].name != NULL; i++) { 1253 if (strcasecmp(defconfig[i].name, value) == 0) { 1254 if (defconfig[i].version == ver) { 1255 *type = defconfig[i].index; 1256 return (0); 1257 } 1258 } 1259 } 1260 return (-1); 1261 } 1262 1263 int 1264 __s_api_get_profiletype(char *value, ParamIndexType *type) 1265 { 1266 int i; 1267 1268 for (i = 0; defconfig[i].name != NULL; i++) { 1269 if (defconfig[i].profile_name == NULL) 1270 continue; 1271 if (strcasecmp(defconfig[i].profile_name, value) == 0) { 1272 *type = defconfig[i].index; 1273 return (0); 1274 } 1275 } 1276 return (-1); 1277 } 1278 1279 int 1280 __s_api_get_configtype(ParamIndexType type) 1281 { 1282 int i; 1283 1284 for (i = 0; defconfig[i].name != NULL; i++) { 1285 if (defconfig[i].index == type) { 1286 return (defconfig[i].config_type); 1287 } 1288 } 1289 return (-1); 1290 } 1291 1292 const char * 1293 __s_api_get_configname(ParamIndexType type) 1294 { 1295 int i; 1296 1297 for (i = 0; defconfig[i].name != NULL; i++) { 1298 if (defconfig[i].index == type) { 1299 if (defconfig[i].name[0] == '\0') 1300 return (NULL); 1301 else 1302 return (defconfig[i].name); 1303 } 1304 } 1305 return (NULL); 1306 } 1307 1308 static ns_default_config * 1309 get_defconfig(ns_config_t *ptr, ParamIndexType type) 1310 { 1311 ns_version_t ver; 1312 int i; 1313 1314 ver = ptr->version; 1315 1316 for (i = 0; defconfig[i].name != NULL; i++) { 1317 if (defconfig[i].index == type && 1318 defconfig[i].version == ver) { 1319 return (&defconfig[i]); 1320 } 1321 } 1322 return (NULL); 1323 } 1324 1325 static int 1326 set_default_value(ns_config_t *configptr, char *name, 1327 char *value, ns_ldap_error_t **error) 1328 { 1329 ParamIndexType i; 1330 int ret; 1331 char errstr[MAXERROR]; 1332 1333 if (__s_api_get_type(name, &i) < 0) { 1334 (void) snprintf(errstr, sizeof (errstr), gettext( 1335 "Illegal type name (%s).\n"), name); 1336 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 1337 NULL); 1338 return (NS_LDAP_CONFIG); 1339 } 1340 1341 if (i != NS_LDAP_SERVERS_P && 1342 i != NS_LDAP_SERVICE_AUTH_METHOD_P && 1343 i != NS_LDAP_SERVICE_CRED_LEVEL_P && 1344 i != NS_LDAP_SERVICE_SEARCH_DESC_P && 1345 i != NS_LDAP_SERVER_PREF_P && 1346 i != NS_LDAP_SEARCH_DN_P) { 1347 if (configptr->paramList[i].ns_ptype != NS_UNKNOWN) { 1348 destroy_param(configptr, i); 1349 } 1350 } 1351 1352 ret = __ns_ldap_setParamValue(configptr, i, value, error); 1353 return (ret); 1354 } 1355 1356 1357 /* 1358 * Initialize config to a default state 1359 * By default leave configuration empty 1360 * getParam will automatically get the 1361 * appropriate default value if none exists 1362 */ 1363 1364 void 1365 __ns_ldap_default_config() 1366 { 1367 ns_config_t *ptr; 1368 1369 ptr = __s_api_create_config(); 1370 if (ptr == NULL) 1371 return; 1372 1373 set_curr_config(ptr); 1374 __s_api_release_config(ptr); 1375 } 1376 1377 /* 1378 * Get the current configuration pointer and return it. 1379 * If necessary initialize or refresh the current 1380 * configuration as applicable. If global is set, returns 1381 * the global one. 1382 */ 1383 1384 static ns_config_t * 1385 loadrefresh_config(boolean_t global) 1386 { 1387 ns_config_t *cfg; 1388 ns_config_t *new_cfg; 1389 ns_ldap_error_t *errorp; 1390 1391 /* We want to refresh only one configuration at a time */ 1392 (void) mutex_lock(&ns_loadrefresh_lock); 1393 if (global == B_TRUE) 1394 cfg = __s_api_get_default_config_global(); 1395 else 1396 cfg = __s_api_get_default_config(); 1397 1398 /* (re)initialize configuration if necessary */ 1399 if (!__s_api_isStandalone() && timetorefresh(cfg)) { 1400 new_cfg = LoadCacheConfiguration(cfg, &errorp); 1401 if (new_cfg != NULL && new_cfg != cfg) { 1402 __s_api_release_config(cfg); 1403 if (global == B_TRUE) 1404 set_curr_config_global(new_cfg); 1405 else 1406 set_curr_config(new_cfg); 1407 cfg = new_cfg; 1408 } 1409 if (errorp != NULL) 1410 (void) __ns_ldap_freeError(&errorp); 1411 } 1412 (void) mutex_unlock(&ns_loadrefresh_lock); 1413 return (cfg); 1414 } 1415 1416 /* 1417 * Get the current global configuration pointer and return it. 1418 * If necessary initialize or refresh the current 1419 * configuration as applicable. 1420 */ 1421 1422 ns_config_t * 1423 __s_api_loadrefresh_config_global() 1424 { 1425 return (loadrefresh_config(B_TRUE)); 1426 } 1427 1428 /* 1429 * Get the current configuration pointer and return it. 1430 * If necessary initialize or refresh the current 1431 * configuration as applicable. The configuration may 1432 * be the global one or the per connection management one. 1433 */ 1434 1435 ns_config_t * 1436 __s_api_loadrefresh_config() 1437 { 1438 return (loadrefresh_config(B_FALSE)); 1439 } 1440 1441 /* 1442 * In general this routine is not very usefull. Individual routines can be 1443 * created to do this job. Once that is done, this function can be removed. 1444 * Size of errstr buffer needs to be MAXERROR. 1445 */ 1446 static ns_parse_status 1447 verify_value(ns_config_t *cfg, char *name, char *value, char *errstr) 1448 { 1449 ParamIndexType index = 0; 1450 int found = 0, j; 1451 char *ptr = NULL, *strptr = NULL, buffer[BUFSIZE]; 1452 char *rest; 1453 ns_default_config *def = NULL; 1454 1455 if (__s_api_get_type(name, &index) != 0) { 1456 (void) snprintf(errstr, MAXERROR, 1457 gettext("Unknown keyword encountered '%s'."), name); 1458 return (NS_PARSE_ERR); 1459 } 1460 1461 def = get_defconfig(cfg, index); 1462 1463 /* eat up beginning quote, if any */ 1464 while (value != NULL && (*value == QUOTETOK || *value == SPACETOK)) 1465 value++; 1466 1467 /* eat up space/quote at end of value */ 1468 if (strlen(value) > 0) 1469 ptr = value + strlen(value) - 1; 1470 else 1471 ptr = value; 1472 for (; ptr != value && (*ptr == SPACETOK || *ptr == QUOTETOK); ptr--) { 1473 *ptr = '\0'; 1474 } 1475 1476 switch (index) { 1477 case NS_LDAP_EXP_P: 1478 case NS_LDAP_CACHETTL_P: 1479 case NS_LDAP_CERT_PATH_P: 1480 case NS_LDAP_CERT_PASS_P: 1481 case NS_LDAP_CERT_NICKNAME_P: 1482 case NS_LDAP_BINDDN_P: 1483 case NS_LDAP_BINDPASSWD_P: 1484 case NS_LDAP_DOMAIN_P: 1485 case NS_LDAP_SEARCH_BASEDN_P: 1486 case NS_LDAP_SEARCH_TIME_P: 1487 case NS_LDAP_PROFILE_P: 1488 case NS_LDAP_AUTH_P: 1489 case NS_LDAP_SEARCH_SCOPE_P: 1490 case NS_LDAP_CREDENTIAL_LEVEL_P: 1491 case NS_LDAP_SERVICE_SEARCH_DESC_P: 1492 case NS_LDAP_BIND_TIME_P: 1493 case NS_LDAP_ATTRIBUTEMAP_P: 1494 case NS_LDAP_OBJECTCLASSMAP_P: 1495 case NS_LDAP_SERVICE_AUTH_METHOD_P: 1496 case NS_LDAP_SERVICE_CRED_LEVEL_P: 1497 case NS_LDAP_HOST_CERTPATH_P: 1498 break; 1499 case NS_LDAP_SEARCH_DN_P: 1500 /* depreciated because of service descriptors */ 1501 /* Parse as appropriate at descriptor create time */ 1502 break; 1503 case NS_LDAP_FILE_VERSION_P: 1504 if (value != NULL && 1505 strcasecmp(value, NS_LDAP_VERSION_1) != 0 && 1506 strcasecmp(value, NS_LDAP_VERSION_2) != 0) { 1507 (void) snprintf(errstr, MAXERROR, 1508 gettext("Version mismatch, expected " 1509 "cache version '%s' or '%s' but " 1510 "encountered version '%s'."), 1511 NS_LDAP_VERSION_1, 1512 NS_LDAP_VERSION_2, value); 1513 return (NS_PARSE_ERR); 1514 } 1515 break; 1516 case NS_LDAP_SERVERS_P: 1517 case NS_LDAP_SERVER_PREF_P: 1518 (void) strcpy(buffer, value); 1519 strptr = strtok_r(buffer, ",", &rest); 1520 while (strptr != NULL) { 1521 char *tmp = NULL; 1522 tmp = stripdup(strptr); 1523 if (tmp == NULL || (strchr(tmp, ' ') != NULL)) { 1524 (void) snprintf(errstr, MAXERROR, 1525 gettext("Invalid parameter values " 1526 "'%s' specified for keyword '%s'."), 1527 tmp, name); 1528 free(tmp); 1529 return (NS_PARSE_ERR); 1530 } 1531 free(tmp); 1532 strptr = strtok_r(NULL, ",", &rest); 1533 } 1534 break; 1535 default: 1536 found = 0; j = 0; 1537 while (def->allowed != NULL && 1538 def->allowed[j].name != NULL && j < DEFMAX) { 1539 if (strcmp(def->allowed[j].name, 1540 value) == 0) { 1541 found = 1; 1542 break; 1543 } 1544 j++; 1545 } 1546 if (!found) { 1547 (void) snprintf(errstr, MAXERROR, 1548 gettext("Invalid option specified for " 1549 "'%s' keyword. '%s' is not a recognized " 1550 "keyword value."), name, value); 1551 return (NS_PARSE_ERR); 1552 } 1553 } 1554 1555 return (NS_SUCCESS); 1556 } 1557 1558 void 1559 __s_api_split_key_value(char *buffer, char **name, char **value) 1560 { 1561 char *ptr; 1562 1563 *name = buffer; 1564 /* split into name value pair */ 1565 if ((ptr = strchr(buffer, TOKENSEPARATOR)) != NULL) { 1566 *ptr = '\0'; 1567 ptr++; 1568 /* trim whitespace */ 1569 while (*ptr == SPACETOK) 1570 ptr++; 1571 *value = ptr; 1572 } 1573 } 1574 1575 /* 1576 * Set a parameter value in a generic configuration structure 1577 * Assume any necessary locks are in place. This routine would 1578 * be better named: __ns_ldap_translateString2Param 1579 * 1580 * This routine translates external string format into internal 1581 * param format and saves the result in the param table. 1582 */ 1583 int 1584 __ns_ldap_setParamValue(ns_config_t *ptr, const ParamIndexType type, 1585 const void *data, ns_ldap_error_t **error) 1586 { 1587 ns_default_config *def = NULL; 1588 ns_param_t conf; 1589 ns_mapping_t *map, *rmap; 1590 int i, j, len; 1591 char *cp, *cp2, *end; 1592 char *tcp = NULL; 1593 char errstr[2 * MAXERROR]; 1594 char tbuf[100], *ptbuf; 1595 char *sid, *origA, **mapA; 1596 char **attr; 1597 time_t tm; 1598 int free_memory, exitrc; 1599 char **p; 1600 1601 /* Find ParamIndexType default configuration data */ 1602 def = get_defconfig(ptr, type); 1603 if (def == NULL) { 1604 (void) snprintf(errstr, sizeof (errstr), 1605 gettext("Unable to set value: " 1606 "invalid ParamIndexType (%d)"), type); 1607 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 1608 NULL); 1609 return (NS_LDAP_CONFIG); 1610 } 1611 1612 (void) memset(&conf, 0, sizeof (conf)); 1613 1614 /* data is actually const char */ 1615 cp = (char *)data; 1616 1617 /* eat up beginning quote, if any */ 1618 while (cp && (*cp == QUOTETOK || *cp == SPACETOK)) 1619 cp++; 1620 1621 /* eat up space/quote at end of value */ 1622 end = cp2 = cp + strlen(cp) - 1; 1623 for (; cp2 > cp && (*cp2 == SPACETOK || *cp2 == QUOTETOK); cp2--) 1624 ; 1625 /* data is const, must duplicate */ 1626 if (cp2 != end) { 1627 tcp = (char *)calloc((int)(cp2 - cp + 2), sizeof (char)); 1628 if (tcp == NULL) 1629 return (NS_LDAP_MEMORY); 1630 end = cp2; 1631 cp2 = tcp; 1632 while (cp <= end) { 1633 *cp2++ = *cp++; 1634 } 1635 *cp2 = '\0'; 1636 cp = tcp; 1637 } 1638 1639 /* Parse data according to type */ 1640 switch (def->data_type) { 1641 case INT: 1642 switch (def->index) { 1643 case NS_LDAP_PREF_ONLY_P: 1644 case NS_LDAP_SEARCH_REF_P: 1645 case NS_LDAP_SEARCH_SCOPE_P: 1646 i = __s_get_enum_value(ptr, cp, def->index); 1647 if (i < 0) { 1648 (void) snprintf(errstr, sizeof (errstr), 1649 gettext("Unable to set value: " 1650 "invalid %s (%d)"), def->name, 1651 def->index); 1652 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1653 strdup(errstr), NULL); 1654 if (tcp != NULL) 1655 free(tcp); 1656 return (NS_LDAP_CONFIG); 1657 } 1658 conf.ns_i = i; 1659 break; 1660 case NS_LDAP_TRANSPORT_SEC_P: /* ignore TRANSPORT_SEC */ 1661 break; 1662 default: 1663 cp2 = cp; 1664 if ((*cp2 == '+') || (*cp2 == '-')) 1665 cp2++; 1666 for (/* empty */; *cp2; cp2++) { 1667 if (isdigit(*cp2)) 1668 continue; 1669 1670 (void) snprintf(errstr, sizeof (errstr), 1671 gettext("Unable to set value: " 1672 "invalid %s (%d)"), def->name, 1673 def->index); 1674 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1675 strdup(errstr), NULL); 1676 if (tcp != NULL) 1677 free(tcp); 1678 return (NS_LDAP_CONFIG); 1679 } 1680 i = atoi(cp); 1681 conf.ns_i = i; 1682 break; 1683 } 1684 break; 1685 case TIMET: 1686 /* Do nothing with a TIMET. Initialize it below */ 1687 break; 1688 case CHARPTR: 1689 conf.ns_pc = (char *)strdup(cp); 1690 if (conf.ns_pc == NULL) { 1691 if (tcp != NULL) 1692 free(tcp); 1693 return (NS_LDAP_MEMORY); 1694 } 1695 break; 1696 case SAMLIST: 1697 /* first check to see if colon (:) is there */ 1698 if ((strchr(cp, COLONTOK)) == NULL) { 1699 (void) snprintf(errstr, sizeof (errstr), 1700 gettext("Unable to set value: " 1701 "invalid serviceAuthenticationMethod (%s)"), 1702 cp); 1703 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1704 strdup(errstr), NULL); 1705 if (tcp != NULL) 1706 free(tcp); 1707 return (NS_LDAP_CONFIG); 1708 } 1709 /* Appends an entry to the existing list */ 1710 if (ptr->paramList[type].ns_ptype != SAMLIST) { 1711 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1712 if (conf.ns_ppc == NULL) { 1713 if (tcp != NULL) 1714 free(tcp); 1715 return (NS_LDAP_MEMORY); 1716 } 1717 conf.ns_acnt = 1; 1718 conf.ns_ppc[0] = (char *)strdup(cp); 1719 if (conf.ns_ppc[0] == NULL) { 1720 free(conf.ns_ppc); 1721 if (tcp != NULL) 1722 free(tcp); 1723 return (NS_LDAP_MEMORY); 1724 } 1725 } else { 1726 char *dp, *dpend; 1727 int fnd = 0; 1728 1729 /* Attempt to replace if possible */ 1730 dpend = strchr(cp, COLONTOK); 1731 len = dpend - cp; 1732 dp = (char *)malloc(len+1); 1733 if (dp == NULL) { 1734 if (tcp != NULL) 1735 free(tcp); 1736 return (NS_LDAP_MEMORY); 1737 } 1738 (void) strlcpy(dp, cp, len+1); 1739 fnd = 0; 1740 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 1741 dpend = strchr(ptr->paramList[type].ns_ppc[j], 1742 COLONTOK); 1743 if (dpend == NULL) 1744 continue; 1745 i = dpend - ptr->paramList[type].ns_ppc[j]; 1746 if (i != len) 1747 continue; 1748 if (strncmp(ptr->paramList[type].ns_ppc[j], 1749 dp, len) == 0) { 1750 conf.ns_acnt = 1751 ptr->paramList[type].ns_acnt; 1752 conf.ns_ppc = 1753 ptr->paramList[type].ns_ppc; 1754 ptr->paramList[type].ns_ppc = NULL; 1755 free(conf.ns_ppc[j]); 1756 conf.ns_ppc[j] = (char *)strdup(cp); 1757 if (conf.ns_ppc[j] == NULL) { 1758 free(dp); 1759 __s_api_free2dArray 1760 (conf.ns_ppc); 1761 if (tcp != NULL) 1762 free(tcp); 1763 return (NS_LDAP_MEMORY); 1764 } 1765 fnd = 1; 1766 break; 1767 } 1768 } 1769 free(dp); 1770 1771 if (fnd) 1772 break; /* Replaced completed */ 1773 1774 /* Append */ 1775 len = ptr->paramList[type].ns_acnt + 1; 1776 if (len > 1) { 1777 p = (char **)dupParam(&ptr->paramList[type]); 1778 if (p == NULL) { 1779 if (tcp != NULL) 1780 free(tcp); 1781 return (NS_LDAP_MEMORY); 1782 } 1783 } else 1784 p = NULL; 1785 conf.ns_ppc = 1786 (char **)realloc(p, (len+1) * sizeof (char *)); 1787 if (conf.ns_ppc == NULL) { 1788 __s_api_free2dArray(p); 1789 if (tcp != NULL) 1790 free(tcp); 1791 return (NS_LDAP_MEMORY); 1792 } 1793 conf.ns_acnt = len; 1794 conf.ns_ppc[len-1] = (char *)strdup(cp); 1795 if (conf.ns_ppc[len-1] == NULL) { 1796 __s_api_free2dArray(conf.ns_ppc); 1797 if (tcp != NULL) 1798 free(tcp); 1799 return (NS_LDAP_MEMORY); 1800 } 1801 conf.ns_ppc[len] = NULL; 1802 } 1803 break; 1804 case SCLLIST: 1805 /* first check to see if colon (:) is there */ 1806 if ((strchr(cp, COLONTOK)) == NULL) { 1807 (void) snprintf(errstr, sizeof (errstr), 1808 gettext("Unable to set value: " 1809 "invalid serviceCredentialLevel (%s)"), 1810 cp); 1811 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1812 strdup(errstr), NULL); 1813 if (tcp != NULL) 1814 free(tcp); 1815 return (NS_LDAP_CONFIG); 1816 } 1817 /* Appends an entry to the existing list */ 1818 if (ptr->paramList[type].ns_ptype != SCLLIST) { 1819 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1820 if (conf.ns_ppc == NULL) { 1821 if (tcp != NULL) 1822 free(tcp); 1823 return (NS_LDAP_MEMORY); 1824 } 1825 conf.ns_acnt = 1; 1826 conf.ns_ppc[0] = (char *)strdup(cp); 1827 if (conf.ns_ppc[0] == NULL) { 1828 free(conf.ns_ppc); 1829 if (tcp != NULL) 1830 free(tcp); 1831 return (NS_LDAP_MEMORY); 1832 } 1833 } else { 1834 char *dp, *dpend; 1835 int fnd = 0; 1836 1837 /* Attempt to replace if possible */ 1838 dpend = strchr(cp, COLONTOK); 1839 len = dpend - cp; 1840 dp = (char *)malloc(len+1); 1841 if (dp == NULL) { 1842 if (tcp != NULL) 1843 free(tcp); 1844 return (NS_LDAP_MEMORY); 1845 } 1846 (void) strlcpy(dp, cp, len+1); 1847 fnd = 0; 1848 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 1849 dpend = strchr(ptr->paramList[type].ns_ppc[j], 1850 COLONTOK); 1851 if (dpend == NULL) 1852 continue; 1853 i = dpend - ptr->paramList[type].ns_ppc[j]; 1854 if (i != len) 1855 continue; 1856 if (strncmp(ptr->paramList[type].ns_ppc[j], 1857 dp, len) == 0) { 1858 conf.ns_acnt = 1859 ptr->paramList[type].ns_acnt; 1860 conf.ns_ppc = 1861 ptr->paramList[type].ns_ppc; 1862 ptr->paramList[type].ns_ppc = NULL; 1863 free(conf.ns_ppc[j]); 1864 conf.ns_ppc[j] = (char *)strdup(cp); 1865 if (conf.ns_ppc[j] == NULL) { 1866 free(dp); 1867 __s_api_free2dArray 1868 (conf.ns_ppc); 1869 if (tcp != NULL) 1870 free(tcp); 1871 return (NS_LDAP_MEMORY); 1872 } 1873 fnd = 1; 1874 break; 1875 } 1876 } 1877 free(dp); 1878 1879 if (fnd) 1880 break; /* Replaced completed */ 1881 1882 /* Append */ 1883 len = ptr->paramList[type].ns_acnt + 1; 1884 if (len > 1) { 1885 p = (char **)dupParam(&ptr->paramList[type]); 1886 if (p == NULL) { 1887 if (tcp != NULL) 1888 free(tcp); 1889 return (NS_LDAP_MEMORY); 1890 } 1891 } else 1892 p = NULL; 1893 conf.ns_ppc = 1894 (char **)realloc(p, (len+1) * sizeof (char *)); 1895 if (conf.ns_ppc == NULL) { 1896 __s_api_free2dArray(p); 1897 if (tcp != NULL) 1898 free(tcp); 1899 return (NS_LDAP_MEMORY); 1900 } 1901 conf.ns_acnt = len; 1902 conf.ns_ppc[len-1] = (char *)strdup(cp); 1903 if (conf.ns_ppc[len-1] == NULL) { 1904 __s_api_free2dArray(conf.ns_ppc); 1905 if (tcp != NULL) 1906 free(tcp); 1907 return (NS_LDAP_MEMORY); 1908 } 1909 conf.ns_ppc[len] = NULL; 1910 } 1911 break; 1912 case SSDLIST: 1913 /* 1914 * first check to see if colon (:) is there, 1915 * if so, make sure the serviceId is specified, 1916 * i.e., colon is not the first character 1917 */ 1918 if ((strchr(cp, COLONTOK)) == NULL || *cp == COLONTOK) { 1919 (void) snprintf(errstr, sizeof (errstr), 1920 gettext("Unable to set value: " 1921 "invalid serviceSearchDescriptor (%s)"), 1922 cp); 1923 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 1924 strdup(errstr), NULL); 1925 if (tcp != NULL) 1926 free(tcp); 1927 return (NS_LDAP_CONFIG); 1928 } 1929 /* Appends an entry to the existing list */ 1930 if (ptr->paramList[type].ns_ptype != SSDLIST) { 1931 conf.ns_ppc = (char **)calloc(2, sizeof (char *)); 1932 if (conf.ns_ppc == NULL) { 1933 if (tcp != NULL) 1934 free(tcp); 1935 return (NS_LDAP_MEMORY); 1936 } 1937 conf.ns_acnt = 1; 1938 conf.ns_ppc[0] = (char *)strdup(cp); 1939 if (conf.ns_ppc[0] == NULL) { 1940 free(conf.ns_ppc); 1941 if (tcp != NULL) 1942 free(tcp); 1943 return (NS_LDAP_MEMORY); 1944 } 1945 } else { 1946 char *dp, *dpend; 1947 int fnd = 0; 1948 1949 /* Attempt to replace if possible */ 1950 dpend = strchr(cp, COLONTOK); 1951 len = dpend - cp; 1952 dp = (char *)malloc(len+1); 1953 if (dp == NULL) { 1954 if (tcp != NULL) 1955 free(tcp); 1956 return (NS_LDAP_MEMORY); 1957 } 1958 (void) strlcpy(dp, cp, len+1); 1959 fnd = 0; 1960 for (j = 0; j < ptr->paramList[type].ns_acnt; j++) { 1961 dpend = strchr(ptr->paramList[type].ns_ppc[j], 1962 COLONTOK); 1963 if (dpend == NULL) 1964 continue; 1965 i = dpend - ptr->paramList[type].ns_ppc[j]; 1966 if (i != len) 1967 continue; 1968 if (strncmp(ptr->paramList[type].ns_ppc[j], 1969 dp, len) == 0) { 1970 conf.ns_acnt = 1971 ptr->paramList[type].ns_acnt; 1972 conf.ns_ppc = 1973 ptr->paramList[type].ns_ppc; 1974 ptr->paramList[type].ns_ppc = NULL; 1975 free(conf.ns_ppc[j]); 1976 conf.ns_ppc[j] = (char *)strdup(cp); 1977 if (conf.ns_ppc[j] == NULL) { 1978 free(dp); 1979 __s_api_free2dArray 1980 (conf.ns_ppc); 1981 if (tcp != NULL) 1982 free(tcp); 1983 return (NS_LDAP_MEMORY); 1984 } 1985 fnd = 1; 1986 break; 1987 } 1988 } 1989 free(dp); 1990 1991 if (fnd) 1992 break; /* Replaced completed */ 1993 1994 /* Append */ 1995 len = ptr->paramList[type].ns_acnt + 1; 1996 if (len > 1) { 1997 p = (char **)dupParam(&ptr->paramList[type]); 1998 if (p == NULL) { 1999 if (tcp != NULL) 2000 free(tcp); 2001 return (NS_LDAP_MEMORY); 2002 } 2003 } else 2004 p = NULL; 2005 conf.ns_ppc = 2006 (char **)realloc(p, (len+1) * sizeof (char *)); 2007 if (conf.ns_ppc == NULL) { 2008 __s_api_free2dArray(p); 2009 if (tcp != NULL) 2010 free(tcp); 2011 return (NS_LDAP_MEMORY); 2012 } 2013 conf.ns_acnt = len; 2014 conf.ns_ppc[len-1] = (char *)strdup(cp); 2015 if (conf.ns_ppc[len-1] == NULL) { 2016 __s_api_free2dArray(conf.ns_ppc); 2017 if (tcp != NULL) 2018 free(tcp); 2019 return (NS_LDAP_MEMORY); 2020 } 2021 conf.ns_ppc[len] = NULL; 2022 } 2023 break; 2024 case ARRAYCP: 2025 len = 0; 2026 for (cp2 = cp; *cp2; cp2++) { 2027 if (*cp2 == COMMATOK) 2028 len++; 2029 } 2030 if (cp != cp2) 2031 len++; 2032 if (len == 0) { 2033 conf.ns_ppc = (char **)NULL; 2034 conf.ns_acnt = 0; 2035 break; 2036 } 2037 conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *)); 2038 if (conf.ns_ppc == NULL) { 2039 if (tcp != NULL) 2040 free(tcp); 2041 return (NS_LDAP_MEMORY); 2042 } 2043 conf.ns_acnt = len; 2044 i = 0; 2045 for (cp2 = cp; *cp2; cp2++) { 2046 if (*cp2 == COMMATOK) { 2047 j = cp2 - cp + 1; 2048 conf.ns_ppc[i] = (char *)malloc(j + 1); 2049 if (conf.ns_ppc[i] == NULL) { 2050 __s_api_free2dArray(conf.ns_ppc); 2051 if (tcp != NULL) 2052 free(tcp); 2053 return (NS_LDAP_MEMORY); 2054 } 2055 (void) strlcpy(conf.ns_ppc[i], cp, j); 2056 cp = cp2+1; 2057 while (*cp == SPACETOK || *cp == COMMATOK) 2058 cp++; 2059 cp2 = cp - 1; 2060 i++; 2061 } 2062 } 2063 j = cp2 - cp + 1; 2064 conf.ns_ppc[i] = (char *)malloc(j + 1); 2065 if (conf.ns_ppc[i] == NULL) { 2066 __s_api_free2dArray(conf.ns_ppc); 2067 if (tcp != NULL) 2068 free(tcp); 2069 return (NS_LDAP_MEMORY); 2070 } 2071 (void) strlcpy(conf.ns_ppc[i], cp, j); 2072 break; 2073 case SERVLIST: 2074 len = 0; 2075 for (cp2 = cp; *cp2; cp2++) { 2076 if (*cp2 == SPACETOK || *cp2 == COMMATOK) { 2077 len++; 2078 for (; *(cp2 + 1) == SPACETOK || 2079 *(cp2 +1) == COMMATOK; cp2++) 2080 ; 2081 } 2082 } 2083 if (cp != cp2) 2084 len++; 2085 if (len == 0) { 2086 conf.ns_ppc = (char **)NULL; 2087 conf.ns_acnt = 0; 2088 break; 2089 } 2090 conf.ns_ppc = (char **)calloc(len + 1, sizeof (char *)); 2091 if (conf.ns_ppc == NULL) { 2092 if (tcp != NULL) 2093 free(tcp); 2094 return (NS_LDAP_MEMORY); 2095 } 2096 conf.ns_acnt = len; 2097 i = 0; 2098 for (cp2 = cp; *cp2; cp2++) { 2099 if (*cp2 == SPACETOK || *cp2 == COMMATOK) { 2100 j = cp2 - cp + 1; 2101 conf.ns_ppc[i] = (char *)malloc(j + 1); 2102 if (conf.ns_ppc[i] == NULL) { 2103 __s_api_free2dArray(conf.ns_ppc); 2104 if (tcp != NULL) 2105 free(tcp); 2106 return (NS_LDAP_MEMORY); 2107 } 2108 (void) strlcpy(conf.ns_ppc[i], cp, j); 2109 cp = cp2+1; 2110 while (*cp == SPACETOK || *cp == COMMATOK) 2111 cp++; 2112 cp2 = cp - 1; 2113 i++; 2114 } 2115 } 2116 j = cp2 - cp + 1; 2117 conf.ns_ppc[i] = (char *)malloc(j + 1); 2118 if (conf.ns_ppc[i] == NULL) { 2119 __s_api_free2dArray(conf.ns_ppc); 2120 if (tcp != NULL) 2121 free(tcp); 2122 return (NS_LDAP_MEMORY); 2123 } 2124 (void) strlcpy(conf.ns_ppc[i], cp, j); 2125 break; 2126 case ARRAYAUTH: 2127 len = 0; 2128 for (cp2 = cp; *cp2; cp2++) { 2129 if (*cp2 == SEMITOK || *cp2 == COMMATOK) 2130 len++; 2131 } 2132 if (cp != cp2) 2133 len++; 2134 if (len == 0) { 2135 conf.ns_pi = (int *)NULL; 2136 conf.ns_acnt = 0; 2137 break; 2138 } 2139 conf.ns_pi = (int *)calloc(len + 1, sizeof (int)); 2140 if (conf.ns_pi == 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 == SEMITOK || *cp2 == COMMATOK) { 2149 j = cp2 - cp + 1; 2150 if (j > sizeof (tbuf)) { 2151 j = -1; 2152 ptbuf = cp; 2153 } else { 2154 (void) strlcpy(tbuf, cp, j); 2155 j = __s_get_enum_value(ptr, tbuf, 2156 def->index); 2157 ptbuf = tbuf; 2158 } 2159 if (j < 0) { 2160 (void) snprintf(errstr, sizeof (errstr), 2161 gettext("Unable to set value: " 2162 "invalid " 2163 "authenticationMethod (%s)"), 2164 ptbuf); 2165 MKERROR(LOG_ERR, *error, 2166 NS_CONFIG_SYNTAX, 2167 strdup(errstr), NULL); 2168 free(conf.ns_pi); 2169 if (tcp != NULL) 2170 free(tcp); 2171 return (NS_LDAP_CONFIG); 2172 } 2173 conf.ns_pi[i] = j; 2174 cp = cp2+1; 2175 i++; 2176 } 2177 } 2178 j = cp2 - cp + 1; 2179 if (j > sizeof (tbuf)) { 2180 j = -1; 2181 ptbuf = cp; 2182 } else { 2183 (void) strlcpy(tbuf, cp, j); 2184 j = __s_get_enum_value(ptr, tbuf, def->index); 2185 ptbuf = tbuf; 2186 } 2187 if (j < 0) { 2188 (void) snprintf(errstr, sizeof (errstr), 2189 gettext("Unable to set value: " 2190 "invalid authenticationMethod (%s)"), ptbuf); 2191 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2192 strdup(errstr), NULL); 2193 if (tcp != NULL) 2194 free(tcp); 2195 return (NS_LDAP_CONFIG); 2196 } 2197 conf.ns_pi[i] = j; 2198 break; 2199 case ARRAYCRED: 2200 len = 0; 2201 for (cp2 = cp; *cp2; cp2++) { 2202 if (*cp2 == SPACETOK) 2203 len++; 2204 } 2205 if (cp != cp2) 2206 len++; 2207 if (len == 0) { 2208 conf.ns_pi = (int *)NULL; 2209 conf.ns_acnt = 0; 2210 break; 2211 } 2212 conf.ns_pi = (int *)calloc(len + 1, sizeof (int)); 2213 if (conf.ns_pi == NULL) { 2214 if (tcp != NULL) 2215 free(tcp); 2216 return (NS_LDAP_MEMORY); 2217 } 2218 conf.ns_acnt = len; 2219 i = 0; 2220 for (cp2 = cp; *cp2; cp2++) { 2221 if (*cp2 == SPACETOK) { 2222 j = cp2 - cp + 1; 2223 if (j > sizeof (tbuf)) { 2224 j = -1; 2225 ptbuf = cp; 2226 } else { 2227 (void) strlcpy(tbuf, cp, j); 2228 j = __s_get_enum_value(ptr, tbuf, 2229 def->index); 2230 ptbuf = tbuf; 2231 } 2232 if (j < 0) { 2233 (void) snprintf(errstr, sizeof (errstr), 2234 gettext("Unable to set value: " 2235 "invalid credentialLevel (%s)"), 2236 ptbuf); 2237 MKERROR(LOG_ERR, *error, 2238 NS_CONFIG_SYNTAX, 2239 strdup(errstr), NULL); 2240 free(conf.ns_pi); 2241 if (tcp != NULL) 2242 free(tcp); 2243 return (NS_LDAP_CONFIG); 2244 } 2245 conf.ns_pi[i] = j; 2246 cp = cp2+1; 2247 i++; 2248 } 2249 } 2250 j = cp2 - cp + 1; 2251 if (j > sizeof (tbuf)) { 2252 j = -1; 2253 ptbuf = cp; 2254 } else { 2255 (void) strlcpy(tbuf, cp, j); 2256 j = __s_get_enum_value(ptr, tbuf, def->index); 2257 ptbuf = tbuf; 2258 } 2259 if (j < 0) { 2260 (void) snprintf(errstr, sizeof (errstr), 2261 gettext("Unable to set value: " 2262 "invalid credentialLevel (%s)"), ptbuf); 2263 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2264 strdup(errstr), NULL); 2265 if (tcp != NULL) 2266 free(tcp); 2267 return (NS_LDAP_CONFIG); 2268 } 2269 conf.ns_pi[i] = j; 2270 break; 2271 case ATTRMAP: 2272 case OBJMAP: 2273 i = __s_api_parse_map(cp, &sid, &origA, &mapA); 2274 if (i != NS_HASH_RC_SUCCESS) { 2275 if (i == NS_HASH_RC_NO_MEMORY) { 2276 exitrc = NS_LDAP_MEMORY; 2277 } else { 2278 (void) snprintf(errstr, sizeof (errstr), 2279 gettext("Unable to set value: " 2280 "invalid schema mapping (%s)"), cp); 2281 exitrc = NS_LDAP_CONFIG; 2282 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 2283 strdup(errstr), NULL); 2284 } 2285 if (tcp) 2286 free(tcp); 2287 return (exitrc); 2288 } 2289 2290 /* 2291 * Add reverse map first. 2292 * There could be more than one. 2293 */ 2294 for (attr = mapA; *attr; attr++) { 2295 2296 free_memory = 1; 2297 exitrc = NS_LDAP_MEMORY; 2298 2299 rmap = (ns_mapping_t *)calloc(1, 2300 sizeof (ns_mapping_t)); 2301 if (rmap) { 2302 rmap->service = strdup(sid); 2303 if (rmap->service) { 2304 rmap->orig = strdup(*attr); 2305 if (rmap->orig) { 2306 rmap->map = (char **)calloc(2, 2307 sizeof (char *)); 2308 if (rmap->map) { 2309 (rmap->map)[0] = 2310 strdup(origA); 2311 if ((rmap->map)[0]) 2312 free_memory = 0; 2313 } 2314 } 2315 } 2316 } 2317 2318 if (free_memory == 0) { 2319 if (def->data_type == ATTRMAP) { 2320 rmap->type = NS_ATTR_MAP; 2321 i = __s_api_add_map2hash(ptr, 2322 NS_HASH_RAMAP, rmap); 2323 } else { 2324 rmap->type = NS_OBJ_MAP; 2325 i = __s_api_add_map2hash(ptr, 2326 NS_HASH_ROMAP, rmap); 2327 } 2328 2329 if (i != NS_HASH_RC_SUCCESS) { 2330 switch (i) { 2331 case NS_HASH_RC_CONFIG_ERROR: 2332 exitrc = NS_LDAP_INTERNAL; 2333 (void) snprintf(errstr, 2334 sizeof (errstr), 2335 gettext( 2336 "Unable to set value: " 2337 "no configuration info " 2338 "for schema map " 2339 "update (%s)"), cp); 2340 MKERROR(LOG_ERR, *error, 2341 NS_LDAP_INTERNAL, 2342 strdup(errstr), 2343 NULL); 2344 break; 2345 case NS_HASH_RC_EXISTED: 2346 exitrc = NS_LDAP_CONFIG; 2347 (void) snprintf(errstr, 2348 sizeof (errstr), 2349 gettext( 2350 "Unable to set value: " 2351 "schema map " 2352 "already existed for " 2353 "(%s, %s)."), 2354 *attr, origA); 2355 MKERROR(LOG_ERR, *error, 2356 NS_CONFIG_SYNTAX, 2357 strdup(errstr), 2358 NULL); 2359 break; 2360 case NS_HASH_RC_NO_MEMORY: 2361 exitrc = NS_LDAP_MEMORY; 2362 break; 2363 } 2364 free_memory = 1; 2365 } 2366 } 2367 2368 if (free_memory) { 2369 if (tcp) 2370 free(tcp); 2371 free(sid); 2372 free(origA); 2373 __s_api_free2dArray(mapA); 2374 if (rmap) { 2375 if (rmap->service) 2376 free(rmap->service); 2377 if (rmap->orig) 2378 free(rmap->orig); 2379 if (rmap->map) { 2380 if ((rmap->map)[0]) 2381 free((rmap->map)[0]); 2382 free(rmap->map); 2383 } 2384 free(rmap); 2385 } 2386 return (exitrc); 2387 } 2388 } 2389 2390 /* 2391 * For performance gain, 2392 * add a "schema mapping existed" indicator 2393 * for the given service if not already added. 2394 * This dummy map needs not be removed, if 2395 * the next real map add operation fails. 2396 * since the caller, e.g. ldap_cachemgr. 2397 * should exit anyway. 2398 */ 2399 free_memory = 1; 2400 exitrc = NS_LDAP_MEMORY; 2401 2402 map = (ns_mapping_t *)calloc(1, 2403 sizeof (ns_mapping_t)); 2404 if (map) { 2405 map->service = strdup(sid); 2406 if (map->service) { 2407 map->orig = strdup( 2408 NS_HASH_SCHEMA_MAPPING_EXISTED); 2409 if (map->orig) { 2410 map->map = (char **)calloc(2, 2411 sizeof (char *)); 2412 if (map->map) { 2413 (map->map)[0] = 2414 strdup(sid); 2415 if ((map->map)[0]) 2416 free_memory = 0; 2417 } 2418 } 2419 } 2420 } 2421 2422 if (free_memory == 0) { 2423 map->type = NS_ATTR_MAP; 2424 /* 2425 * add to reverse map, 2426 * so that "ldapclient list" 2427 * would not show it 2428 */ 2429 i = __s_api_add_map2hash(ptr, 2430 NS_HASH_RAMAP, map); 2431 2432 /* 2433 * ignore "map already existed" error, 2434 * just need one per service. 2435 * Need however to free memory allocated 2436 * for map. 2437 */ 2438 if (i != NS_HASH_RC_SUCCESS && 2439 i != NS_HASH_RC_EXISTED) { 2440 switch (i) { 2441 case NS_HASH_RC_CONFIG_ERROR: 2442 exitrc = NS_LDAP_INTERNAL; 2443 (void) snprintf(errstr, 2444 sizeof (errstr), 2445 gettext( 2446 "Unable to set value: " 2447 "no configuration info " 2448 "for schema map " 2449 "update (%s)"), cp); 2450 MKERROR(LOG_ERR, *error, 2451 NS_LDAP_INTERNAL, 2452 strdup(errstr), 2453 NULL); 2454 break; 2455 case NS_HASH_RC_NO_MEMORY: 2456 exitrc = NS_LDAP_MEMORY; 2457 break; 2458 } 2459 free_memory = 1; 2460 } else if (i == NS_HASH_RC_EXISTED) { 2461 if (map->service) 2462 free(map->service); 2463 if (map->orig) 2464 free(map->orig); 2465 if (map->map) { 2466 if ((map->map)[0]) 2467 free((map->map)[0]); 2468 free(map->map); 2469 } 2470 free(map); 2471 map = NULL; 2472 } 2473 } 2474 2475 if (free_memory) { 2476 if (tcp) 2477 free(tcp); 2478 free(sid); 2479 free(origA); 2480 __s_api_free2dArray(mapA); 2481 if (map) { 2482 if (map->service) 2483 free(map->service); 2484 if (map->orig) 2485 free(map->orig); 2486 if (map->map) { 2487 if ((map->map)[0]) 2488 free((map->map)[0]); 2489 free(map->map); 2490 } 2491 free(map); 2492 } 2493 return (exitrc); 2494 } 2495 2496 /* 2497 * add the real schema map 2498 */ 2499 free_memory = 1; 2500 exitrc = NS_LDAP_MEMORY; 2501 map = (ns_mapping_t *)calloc(1, sizeof (ns_mapping_t)); 2502 if (map) { 2503 map->service = sid; 2504 map->orig = origA; 2505 map->map = mapA; 2506 2507 if (def->data_type == ATTRMAP) { 2508 map->type = NS_ATTR_MAP; 2509 i = __s_api_add_map2hash(ptr, 2510 NS_HASH_AMAP, map); 2511 } else { 2512 map->type = NS_OBJ_MAP; 2513 i = __s_api_add_map2hash(ptr, 2514 NS_HASH_OMAP, map); 2515 } 2516 2517 if (i != NS_HASH_RC_SUCCESS) { 2518 switch (i) { 2519 case NS_HASH_RC_CONFIG_ERROR: 2520 exitrc = NS_LDAP_INTERNAL; 2521 (void) snprintf(errstr, 2522 sizeof (errstr), 2523 gettext( 2524 "Unable to set value: " 2525 "no configuration info " 2526 "for schema map " 2527 "update (%s)"), cp); 2528 MKERROR(LOG_ERR, *error, 2529 NS_LDAP_INTERNAL, 2530 strdup(errstr), 2531 NULL); 2532 break; 2533 case NS_HASH_RC_EXISTED: 2534 exitrc = NS_LDAP_CONFIG; 2535 (void) snprintf(errstr, 2536 sizeof (errstr), 2537 gettext( 2538 "Unable to set value: " 2539 "schema map " 2540 "already existed for " 2541 "'%s'."), origA); 2542 MKERROR(LOG_ERR, *error, 2543 NS_CONFIG_SYNTAX, 2544 strdup(errstr), 2545 NULL); 2546 break; 2547 case NS_HASH_RC_NO_MEMORY: 2548 exitrc = NS_LDAP_MEMORY; 2549 break; 2550 } 2551 free_memory = 1; 2552 } else 2553 free_memory = 0; 2554 } 2555 2556 if (free_memory) { 2557 if (tcp) 2558 free(tcp); 2559 free(sid); 2560 free(origA); 2561 __s_api_free2dArray(mapA); 2562 if (map) 2563 free(map); 2564 return (exitrc); 2565 } 2566 2567 break; 2568 default: 2569 /* This should never happen. */ 2570 (void) snprintf(errstr, sizeof (errstr), 2571 gettext("Unable to set value: invalid configuration " 2572 "type (%d)"), def->data_type); 2573 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 2574 NULL); 2575 if (tcp != NULL) 2576 free(tcp); 2577 return (NS_LDAP_CONFIG); 2578 } 2579 conf.ns_ptype = def->data_type; 2580 if (tcp != NULL) 2581 free(tcp); 2582 2583 /* Individually written verify routines here can replace */ 2584 /* verify_value. Verify conf (data) as appropriate here */ 2585 if (def->ns_verify != NULL) { 2586 if ((*def->ns_verify)(type, def, &conf, errstr) != NS_SUCCESS) { 2587 ns_param_t sav_conf; 2588 2589 (void) snprintf(errstr, sizeof (errstr), 2590 gettext("%s"), errstr); 2591 MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX, 2592 strdup(errstr), NULL); 2593 2594 sav_conf = ptr->paramList[type]; 2595 ptr->paramList[type] = conf; 2596 destroy_param(ptr, type); 2597 ptr->paramList[type] = sav_conf; 2598 2599 return (NS_LDAP_CONFIG); 2600 } 2601 } 2602 2603 /* post evaluate the data */ 2604 2605 /* 2606 * if this is for setting a password, 2607 * encrypt the password first. 2608 * NOTE evalue() is smart and will just return 2609 * the value passed if it is already encrypted. 2610 * 2611 * Init NS_LDAP_EXP_P here when CACHETTL is updated 2612 */ 2613 if (type == NS_LDAP_BINDPASSWD_P) { 2614 cp = conf.ns_pc; 2615 cp2 = evalue((char *)cp); 2616 conf.ns_pc = cp2; 2617 free(cp); 2618 cp = NULL; 2619 } else if (type == NS_LDAP_FILE_VERSION_P) { 2620 ptr->version = NS_LDAP_V1; 2621 if (strcasecmp(conf.ns_pc, NS_LDAP_VERSION_2) == 0) { 2622 ptr->version = NS_LDAP_V2; 2623 } 2624 } else if (type == NS_LDAP_CACHETTL_P) { 2625 cp = conf.ns_pc; 2626 tm = conv_time(cp); 2627 ptr->paramList[NS_LDAP_EXP_P].ns_ptype = TIMET; 2628 if (tm != 0) { 2629 tm += time(NULL); 2630 } 2631 ptr->paramList[NS_LDAP_EXP_P].ns_tm = tm; 2632 } 2633 2634 /* Everything checks out move new values into param */ 2635 destroy_param(ptr, type); 2636 /* Assign new/updated value into paramList */ 2637 ptr->paramList[type] = conf; 2638 2639 return (NS_LDAP_SUCCESS); 2640 } 2641 2642 2643 /* 2644 * Set a parameter value in the 'config' configuration structure 2645 * Lock as appropriate 2646 */ 2647 2648 int 2649 __ns_ldap_setParam(const ParamIndexType type, 2650 const void *data, ns_ldap_error_t **error) 2651 { 2652 ns_ldap_error_t *errorp; 2653 int ret; 2654 char errstr[2 * MAXERROR]; 2655 ns_config_t *cfg; 2656 ns_config_t *cfg_g = (ns_config_t *)-1; 2657 ns_config_t *new_cfg; 2658 boolean_t reinit_connmgmt = B_FALSE; 2659 2660 /* We want to refresh only one configuration at a time */ 2661 (void) mutex_lock(&ns_loadrefresh_lock); 2662 cfg = __s_api_get_default_config(); 2663 2664 if (cache_server == TRUE) { 2665 if (cfg == NULL) { 2666 __ns_ldap_default_config(); 2667 cfg = __s_api_get_default_config(); 2668 if (cfg == NULL) { 2669 (void) mutex_unlock(&ns_loadrefresh_lock); 2670 return (NS_LDAP_MEMORY); 2671 } 2672 } 2673 } else { 2674 /* 2675 * This code always return error here on client side, 2676 * this needs to change once libsldap is used by more 2677 * applications that need to set parameters. 2678 */ 2679 (void) snprintf(errstr, sizeof (errstr), 2680 gettext("Unable to set parameter from a client in " 2681 "__ns_ldap_setParam()")); 2682 MKERROR(LOG_WARNING, *error, NS_CONFIG_SYNTAX, strdup(errstr), 2683 NULL); 2684 if (cfg != NULL) 2685 __s_api_release_config(cfg); 2686 (void) mutex_unlock(&ns_loadrefresh_lock); 2687 return (NS_LDAP_CONFIG); 2688 } 2689 2690 /* (re)initialize configuration if necessary */ 2691 if (!__s_api_isStandalone() && 2692 cache_server == FALSE && timetorefresh(cfg)) 2693 cfg_g = __s_api_get_default_config_global(); 2694 /* only (re)initialize the global configuration */ 2695 if (cfg == cfg_g) { 2696 if (cfg_g != NULL) 2697 __s_api_release_config(cfg_g); 2698 new_cfg = LoadCacheConfiguration(cfg, &errorp); 2699 if (new_cfg != cfg) 2700 __s_api_release_config(cfg); 2701 if (new_cfg == NULL) { 2702 (void) snprintf(errstr, sizeof (errstr), 2703 gettext("Unable to load configuration '%s' " 2704 "('%s')."), NSCONFIGFILE, 2705 errorp != NULL && errorp->message != NULL ? 2706 errorp->message : ""); 2707 MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED, 2708 strdup(errstr), NULL); 2709 if (errorp != NULL) 2710 (void) __ns_ldap_freeError(&errorp); 2711 (void) mutex_unlock(&ns_loadrefresh_lock); 2712 return (NS_LDAP_CONFIG); 2713 } 2714 if (new_cfg != cfg) { 2715 set_curr_config_global(new_cfg); 2716 cfg = new_cfg; 2717 reinit_connmgmt = B_TRUE; 2718 } 2719 } 2720 (void) mutex_unlock(&ns_loadrefresh_lock); 2721 2722 if (reinit_connmgmt == B_TRUE) 2723 __s_api_reinit_conn_mgmt_new_config(cfg); 2724 2725 /* translate input and save in the parameter list */ 2726 ret = __ns_ldap_setParamValue(cfg, type, data, error); 2727 2728 __s_api_release_config(cfg); 2729 2730 return (ret); 2731 } 2732 2733 2734 /* 2735 * Make a copy of a parameter entry 2736 */ 2737 2738 static void ** 2739 dupParam(ns_param_t *ptr) 2740 { 2741 int count, i; 2742 void **dupdata, *ret; 2743 int *intptr; 2744 char *cp, tmbuf[32]; 2745 static time_t expire = 0; 2746 ns_auth_t *ap; 2747 2748 switch (ptr->ns_ptype) { 2749 case ARRAYAUTH: 2750 case ARRAYCRED: 2751 case SAMLIST: 2752 case SCLLIST: 2753 case SSDLIST: 2754 case SERVLIST: 2755 case ARRAYCP: 2756 count = ptr->ns_acnt; 2757 if (count == 0) 2758 return (NULL); 2759 break; 2760 case CHARPTR: 2761 case INT: 2762 case TIMET: 2763 count = 1; 2764 } 2765 2766 dupdata = (void **)calloc((count + 1), sizeof (void *)); 2767 if (dupdata == NULL) 2768 return (NULL); 2769 2770 switch (ptr->ns_ptype) { 2771 case ARRAYAUTH: 2772 for (i = 0; i < count; i++) { 2773 ap = __s_api_AuthEnumtoStruct( 2774 (EnumAuthType_t)ptr->ns_pi[i]); 2775 if (ap == NULL) { 2776 free(dupdata); 2777 return (NULL); 2778 } 2779 dupdata[i] = ap; 2780 } 2781 break; 2782 case ARRAYCRED: 2783 for (i = 0; i < count; i++) { 2784 intptr = (int *)malloc(sizeof (int)); 2785 if (intptr == NULL) { 2786 free(dupdata); 2787 return (NULL); 2788 } 2789 dupdata[i] = (void *)intptr; 2790 *intptr = ptr->ns_pi[i]; 2791 } 2792 break; 2793 case SAMLIST: 2794 case SCLLIST: 2795 case SSDLIST: 2796 case SERVLIST: 2797 case ARRAYCP: 2798 for (i = 0; i < count; i++) { 2799 ret = (void *)strdup(ptr->ns_ppc[i]); 2800 if (ret == NULL) { 2801 free(dupdata); 2802 return (NULL); 2803 } 2804 dupdata[i] = ret; 2805 } 2806 break; 2807 case CHARPTR: 2808 if (ptr->ns_pc == NULL) { 2809 free(dupdata); 2810 return (NULL); 2811 } 2812 ret = (void *)strdup(ptr->ns_pc); 2813 if (ret == NULL) { 2814 free(dupdata); 2815 return (NULL); 2816 } 2817 dupdata[0] = ret; 2818 break; 2819 case INT: 2820 intptr = (int *)malloc(sizeof (int)); 2821 if (intptr == NULL) { 2822 free(dupdata); 2823 return (NULL); 2824 } 2825 *intptr = ptr->ns_i; 2826 dupdata[0] = (void *)intptr; 2827 break; 2828 case TIMET: 2829 expire = ptr->ns_tm; 2830 tmbuf[31] = '\0'; 2831 cp = lltostr((long)expire, &tmbuf[31]); 2832 ret = (void *)strdup(cp); 2833 if (ret == NULL) { 2834 free(dupdata); 2835 return (NULL); 2836 } 2837 dupdata[0] = ret; 2838 break; 2839 } 2840 return (dupdata); 2841 } 2842 2843 int 2844 __ns_ldap_freeParam(void ***data) 2845 { 2846 void **tmp; 2847 int i = 0; 2848 2849 if (*data == NULL) 2850 return (NS_LDAP_SUCCESS); 2851 2852 for (i = 0, tmp = *data; tmp[i] != NULL; i++) 2853 free(tmp[i]); 2854 2855 free(*data); 2856 2857 *data = NULL; 2858 2859 return (NS_LDAP_SUCCESS); 2860 } 2861 2862 /* 2863 * Get the internal format for a parameter value. This 2864 * routine makes a copy of an internal param value from 2865 * the currently active parameter list and returns it. 2866 */ 2867 2868 int 2869 __ns_ldap_getParam(const ParamIndexType Param, 2870 void ***data, ns_ldap_error_t **error) 2871 { 2872 char errstr[2 * MAXERROR]; 2873 ns_ldap_error_t *errorp; 2874 ns_default_config *def; 2875 ns_config_t *cfg; 2876 ns_config_t *cfg_g = (ns_config_t *)-1; 2877 ns_config_t *new_cfg; 2878 boolean_t reinit_connmgmt = B_FALSE; 2879 2880 if (data == NULL) 2881 return (NS_LDAP_INVALID_PARAM); 2882 2883 *data = NULL; 2884 2885 /* We want to refresh only one configuration at a time */ 2886 (void) mutex_lock(&ns_loadrefresh_lock); 2887 cfg = __s_api_get_default_config(); 2888 2889 /* (re)initialize configuration if necessary */ 2890 if (!__s_api_isStandalone() && 2891 cache_server == FALSE && timetorefresh(cfg)) 2892 cfg_g = __s_api_get_default_config_global(); 2893 /* only (re)initialize the global configuration */ 2894 if (cfg == cfg_g) { 2895 if (cfg_g != NULL) 2896 __s_api_release_config(cfg_g); 2897 new_cfg = LoadCacheConfiguration(cfg, &errorp); 2898 if (new_cfg != cfg) 2899 __s_api_release_config(cfg); 2900 if (new_cfg == NULL) { 2901 (void) snprintf(errstr, sizeof (errstr), 2902 gettext("Unable to load configuration " 2903 "'%s' ('%s')."), 2904 NSCONFIGFILE, 2905 errorp != NULL && errorp->message != NULL ? 2906 errorp->message : ""); 2907 MKERROR(LOG_WARNING, *error, NS_CONFIG_NOTLOADED, 2908 strdup(errstr), NULL); 2909 if (errorp != NULL) 2910 (void) __ns_ldap_freeError(&errorp); 2911 (void) mutex_unlock(&ns_loadrefresh_lock); 2912 return (NS_LDAP_CONFIG); 2913 } 2914 if (new_cfg != cfg) { 2915 set_curr_config_global(new_cfg); 2916 cfg = new_cfg; 2917 reinit_connmgmt = B_TRUE; 2918 } 2919 } 2920 (void) mutex_unlock(&ns_loadrefresh_lock); 2921 2922 if (reinit_connmgmt == B_TRUE) 2923 __s_api_reinit_conn_mgmt_new_config(cfg); 2924 2925 if (cfg == NULL) { 2926 (void) snprintf(errstr, sizeof (errstr), 2927 gettext("No configuration information available.")); 2928 MKERROR(LOG_ERR, *error, NS_CONFIG_NOTLOADED, 2929 strdup(errstr), NULL); 2930 return (NS_LDAP_CONFIG); 2931 } 2932 2933 if (Param == NS_LDAP_DOMAIN_P) { 2934 *data = (void **)calloc(2, sizeof (void *)); 2935 if (*data == NULL) { 2936 __s_api_release_config(cfg); 2937 return (NS_LDAP_MEMORY); 2938 } 2939 (*data)[0] = (void *)strdup(cfg->domainName); 2940 if ((*data)[0] == NULL) { 2941 free(*data); 2942 __s_api_release_config(cfg); 2943 return (NS_LDAP_MEMORY); 2944 } 2945 } else if (cfg->paramList[Param].ns_ptype == NS_UNKNOWN) { 2946 /* get default */ 2947 def = get_defconfig(cfg, Param); 2948 if (def != NULL) 2949 *data = dupParam(&def->defval); 2950 } else { 2951 *data = dupParam(&(cfg->paramList[Param])); 2952 } 2953 __s_api_release_config(cfg); 2954 2955 return (NS_LDAP_SUCCESS); 2956 } 2957 2958 /* 2959 * This routine takes a parameter in internal format and 2960 * translates it into a variety of string formats for various 2961 * outputs (doors/file/ldif). This routine would be better 2962 * named: __ns_ldap_translateParam2String 2963 */ 2964 2965 char * 2966 __s_api_strValue(ns_config_t *cfg, char *str, 2967 int bufsz, ParamIndexType index, 2968 ns_strfmt_t fmt) 2969 { 2970 ns_default_config *def = NULL; 2971 ns_param_t *ptr; 2972 ns_hash_t *hptr; 2973 ns_mapping_t *mptr; 2974 char ibuf[14], *buf; 2975 char abuf[64], **cpp; 2976 int alen, count, i, sz; 2977 int seplen = strlen(COMMASEP) + strlen(DOORLINESEP); 2978 int first; 2979 2980 if (cfg == NULL || str == NULL) 2981 return (NULL); 2982 2983 /* NS_LDAP_EXP and TRANSPORT_SEC are not exported externally */ 2984 if (index == NS_LDAP_EXP_P || index == NS_LDAP_TRANSPORT_SEC_P) 2985 return (NULL); 2986 2987 /* Return nothing if the value is the default */ 2988 if (cfg->paramList[index].ns_ptype == NS_UNKNOWN) 2989 return (NULL); 2990 2991 ptr = &(cfg->paramList[index]); 2992 2993 abuf[0] = '\0'; 2994 alen = 0; 2995 2996 /* get default */ 2997 def = get_defconfig(cfg, index); 2998 if (def == NULL) 2999 return (NULL); 3000 3001 switch (fmt) { 3002 case NS_DOOR_FMT: 3003 (void) strlcpy(abuf, def->name, sizeof (abuf)); 3004 (void) strlcat(abuf, EQUALSEP, sizeof (abuf)); 3005 break; 3006 case NS_FILE_FMT: 3007 (void) strlcpy(abuf, def->name, sizeof (abuf)); 3008 (void) strlcat(abuf, EQUSPSEP, sizeof (abuf)); 3009 break; 3010 case NS_LDIF_FMT: 3011 /* If no LDIF attr exists ignore the entry */ 3012 if (def->profile_name == NULL) 3013 return (NULL); 3014 (void) strlcpy(abuf, def->profile_name, sizeof (abuf)); 3015 (void) strlcat(abuf, COLSPSEP, sizeof (abuf)); 3016 break; 3017 default: 3018 break; 3019 } 3020 alen = strlen(abuf); 3021 if (alen > bufsz) 3022 return (NULL); 3023 3024 buf = str; 3025 (void) strlcpy(buf, abuf, bufsz); 3026 3027 switch (ptr->ns_ptype) { 3028 case ARRAYAUTH: 3029 count = ptr->ns_acnt; 3030 sz = 0; 3031 for (i = 0; i < count; i++) { 3032 sz += strlen(__s_get_auth_name(cfg, 3033 (AuthType_t)(ptr->ns_pi[i]))) + seplen; 3034 } 3035 sz = sz + alen + 1; 3036 if (sz <= bufsz) { 3037 buf = str; 3038 } else { 3039 buf = (char *)calloc(sz, sizeof (char)); 3040 if (buf == NULL) 3041 return (NULL); 3042 (void) strcpy(buf, abuf); 3043 } 3044 for (i = 0; i < count; i++) { 3045 (void) strcat(buf, 3046 __s_get_auth_name(cfg, 3047 (AuthType_t)(ptr->ns_pi[i]))); 3048 if (i != count-1) { 3049 if (cfg->version == NS_LDAP_V1) 3050 (void) strcat(buf, COMMASEP); 3051 else 3052 (void) strcat(buf, SEMISEP); 3053 } 3054 } 3055 break; 3056 case ARRAYCRED: 3057 count = ptr->ns_acnt; 3058 sz = 0; 3059 for (i = 0; i < count; i++) { 3060 sz += strlen(__s_get_credlvl_name(cfg, 3061 (CredLevel_t)ptr->ns_pi[i])) + seplen; 3062 } 3063 sz = sz + alen + 1; 3064 if (sz <= bufsz) { 3065 buf = str; 3066 } else { 3067 buf = (char *)calloc(sz, sizeof (char)); 3068 if (buf == NULL) 3069 return (NULL); 3070 (void) strcpy(buf, abuf); 3071 } 3072 for (i = 0; i < count; i++) { 3073 (void) strcat(buf, 3074 __s_get_credlvl_name(cfg, 3075 (CredLevel_t)ptr->ns_pi[i])); 3076 if (i != count-1) { 3077 (void) strcat(buf, SPACESEP); 3078 } 3079 } 3080 break; 3081 case SAMLIST: 3082 case SCLLIST: 3083 case SSDLIST: 3084 count = ptr->ns_acnt; 3085 sz = 0; 3086 for (i = 0; i < count; i++) { 3087 sz += strlen(ptr->ns_ppc[i]) + seplen; 3088 } 3089 sz = sz + alen + 1; 3090 /* 3091 * We need to allocate buffer depending on the 'fmt' and 3092 * on the number of ns_ptype's present(count) as we add 3093 * name' or 'profile_name' and DOORLINESEP or new line 3094 * char to the buffer - see below. 3095 */ 3096 switch (fmt) { 3097 case NS_LDIF_FMT: 3098 sz += count * (strlen(def->profile_name) 3099 + strlen(COLSPSEP) + strlen("\n")); 3100 break; 3101 case NS_FILE_FMT: 3102 sz += count * (strlen(def->name) 3103 + strlen(EQUALSEP) + strlen("\n")); 3104 break; 3105 case NS_DOOR_FMT: 3106 sz += count * (strlen(def->name) 3107 + strlen(EQUALSEP) + strlen(DOORLINESEP)); 3108 break; 3109 } 3110 if (sz <= bufsz) { 3111 buf = str; 3112 } else { 3113 buf = (char *)calloc(sz, sizeof (char)); 3114 if (buf == NULL) 3115 return (NULL); 3116 (void) strcpy(buf, abuf); 3117 } 3118 for (i = 0; i < count; i++) { 3119 (void) strcat(buf, ptr->ns_ppc[i]); 3120 if (i != count-1) { 3121 /* Separate items */ 3122 switch (fmt) { 3123 case NS_DOOR_FMT: 3124 (void) strcat(buf, DOORLINESEP); 3125 (void) strcat(buf, def->name); 3126 (void) strcat(buf, EQUALSEP); 3127 break; 3128 case NS_FILE_FMT: 3129 (void) strcat(buf, "\n"); 3130 (void) strcat(buf, def->name); 3131 (void) strcat(buf, EQUSPSEP); 3132 break; 3133 case NS_LDIF_FMT: 3134 (void) strcat(buf, "\n"); 3135 (void) strcat(buf, def->profile_name); 3136 (void) strcat(buf, COLSPSEP); 3137 break; 3138 } 3139 } 3140 } 3141 break; 3142 case ARRAYCP: 3143 count = ptr->ns_acnt; 3144 sz = 0; 3145 for (i = 0; i < count; i++) { 3146 sz += strlen(ptr->ns_ppc[i]) + seplen; 3147 } 3148 sz = sz + alen + 1; 3149 if (sz <= bufsz) { 3150 buf = str; 3151 } else { 3152 buf = (char *)calloc(sz, sizeof (char)); 3153 if (buf == NULL) 3154 return (NULL); 3155 (void) strcpy(buf, abuf); 3156 } 3157 for (i = 0; i < count; i++) { 3158 (void) strcat(buf, ptr->ns_ppc[i]); 3159 if (i != count-1) { 3160 (void) strcat(buf, COMMASEP); 3161 } 3162 } 3163 break; 3164 case SERVLIST: 3165 count = ptr->ns_acnt; 3166 sz = 0; 3167 for (i = 0; i < count; i++) { 3168 sz += strlen(ptr->ns_ppc[i]) + seplen; 3169 } 3170 sz = sz + alen + 1; 3171 if (sz <= bufsz) { 3172 buf = str; 3173 } else { 3174 buf = (char *)calloc(sz, sizeof (char)); 3175 if (buf == NULL) 3176 return (NULL); 3177 (void) strcpy(buf, abuf); 3178 } 3179 for (i = 0; i < count; i++) { 3180 (void) strcat(buf, ptr->ns_ppc[i]); 3181 if (i != count-1) { 3182 if (fmt == NS_LDIF_FMT) 3183 (void) strcat(buf, SPACESEP); 3184 else 3185 (void) strcat(buf, COMMASEP); 3186 } 3187 } 3188 break; 3189 case CHARPTR: 3190 if (ptr->ns_pc == NULL) 3191 break; 3192 sz = strlen(ptr->ns_pc) + alen + 1; 3193 if (sz > bufsz) { 3194 buf = (char *)calloc(sz, sizeof (char)); 3195 if (buf == NULL) 3196 return (NULL); 3197 (void) strcpy(buf, abuf); 3198 } 3199 (void) strcat(buf, ptr->ns_pc); 3200 break; 3201 case INT: 3202 switch (def->index) { 3203 case NS_LDAP_PREF_ONLY_P: 3204 (void) strcat(buf, 3205 __s_get_pref_name((PrefOnly_t)ptr->ns_i)); 3206 break; 3207 case NS_LDAP_SEARCH_REF_P: 3208 (void) strcat(buf, 3209 __s_get_searchref_name(cfg, 3210 (SearchRef_t)ptr->ns_i)); 3211 break; 3212 case NS_LDAP_SEARCH_SCOPE_P: 3213 (void) strcat(buf, 3214 __s_get_scope_name(cfg, 3215 (ScopeType_t)ptr->ns_i)); 3216 break; 3217 default: 3218 (void) snprintf(ibuf, sizeof (ibuf), 3219 "%d", ptr->ns_i); 3220 (void) strcat(buf, ibuf); 3221 break; 3222 } 3223 break; 3224 case ATTRMAP: 3225 buf[0] = '\0'; 3226 first = 1; 3227 for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) { 3228 if (hptr->h_type != NS_HASH_AMAP) { 3229 continue; 3230 } 3231 if (!first) { 3232 if (fmt == NS_DOOR_FMT) 3233 (void) strcat(buf, DOORLINESEP); 3234 else 3235 (void) strcat(buf, "\n"); 3236 } 3237 mptr = hptr->h_map; 3238 (void) strcat(buf, abuf); 3239 (void) strcat(buf, mptr->service); 3240 (void) strcat(buf, COLONSEP); 3241 (void) strcat(buf, mptr->orig); 3242 (void) strcat(buf, EQUALSEP); 3243 for (cpp = mptr->map; cpp && *cpp; cpp++) { 3244 if (cpp != mptr->map) 3245 (void) strcat(buf, SPACESEP); 3246 (void) strcat(buf, *cpp); 3247 } 3248 first = 0; 3249 } 3250 break; 3251 case OBJMAP: 3252 buf[0] = '\0'; 3253 first = 1; 3254 for (hptr = cfg->llHead; hptr; hptr = hptr->h_llnext) { 3255 if (hptr->h_type != NS_HASH_OMAP) { 3256 continue; 3257 } 3258 if (!first) { 3259 if (fmt == NS_DOOR_FMT) 3260 (void) strcat(buf, DOORLINESEP); 3261 else 3262 (void) strcat(buf, "\n"); 3263 } 3264 mptr = hptr->h_map; 3265 (void) strcat(buf, abuf); 3266 (void) strcat(buf, mptr->service); 3267 (void) strcat(buf, COLONSEP); 3268 (void) strcat(buf, mptr->orig); 3269 (void) strcat(buf, EQUALSEP); 3270 for (cpp = mptr->map; cpp && *cpp; cpp++) { 3271 if (cpp != mptr->map) 3272 (void) strcat(buf, SPACESEP); 3273 (void) strcat(buf, *cpp); 3274 } 3275 first = 0; 3276 } 3277 break; 3278 } 3279 return (buf); 3280 } 3281 3282 static int 3283 __door_getldapconfig(char **buffer, int *buflen, ns_ldap_error_t **error) 3284 { 3285 typedef union { 3286 ldap_data_t s_d; 3287 char s_b[DOORBUFFERSIZE]; 3288 } space_t; 3289 space_t *space; 3290 3291 ldap_data_t *sptr; 3292 int ndata; 3293 int adata; 3294 char errstr[MAXERROR]; 3295 char *domainname; 3296 ns_ldap_return_code retCode; 3297 ldap_config_out_t *cfghdr; 3298 3299 *error = NULL; 3300 3301 domainname = __getdomainname(); 3302 if (domainname == NULL || buffer == NULL || buflen == NULL || 3303 (strlen(domainname) >= (sizeof (space_t) 3304 - sizeof (space->s_d.ldap_call.ldap_callnumber)))) { 3305 return (NS_LDAP_OP_FAILED); 3306 } 3307 3308 space = (space_t *)calloc(1, sizeof (space_t)); 3309 if (space == NULL) 3310 return (NS_LDAP_MEMORY); 3311 3312 adata = (sizeof (ldap_call_t) + strlen(domainname) +1); 3313 ndata = sizeof (space_t); 3314 space->s_d.ldap_call.ldap_callnumber = GETLDAPCONFIGV1; 3315 (void) strcpy(space->s_d.ldap_call.ldap_u.domainname, domainname); 3316 free(domainname); 3317 domainname = NULL; 3318 sptr = &space->s_d; 3319 3320 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) { 3321 case NS_CACHE_SUCCESS: 3322 break; 3323 case NS_CACHE_NOTFOUND: 3324 (void) snprintf(errstr, sizeof (errstr), 3325 gettext("Door call to " 3326 "ldap_cachemgr failed - error: %d."), 3327 space->s_d.ldap_ret.ldap_errno); 3328 MKERROR(LOG_WARNING, *error, NS_CONFIG_CACHEMGR, 3329 strdup(errstr), NULL); 3330 free(space); 3331 return (NS_LDAP_OP_FAILED); 3332 default: 3333 free(space); 3334 return (NS_LDAP_OP_FAILED); 3335 } 3336 3337 retCode = NS_LDAP_SUCCESS; 3338 3339 /* copy info from door call to buffer here */ 3340 cfghdr = &sptr->ldap_ret.ldap_u.config_str; 3341 *buflen = offsetof(ldap_config_out_t, config_str) + 3342 cfghdr->data_size + 1; 3343 *buffer = calloc(*buflen, sizeof (char)); 3344 if (*buffer == NULL) { 3345 retCode = NS_LDAP_MEMORY; 3346 } else 3347 (void) memcpy(*buffer, cfghdr, *buflen - 1); 3348 3349 if (sptr != &space->s_d) { 3350 (void) munmap((char *)sptr, ndata); 3351 } 3352 free(space); 3353 3354 return (retCode); 3355 } 3356 3357 /* 3358 * SetDoorInfo parses ldapcachemgr configuration information 3359 * and verifies that the profile is version 1 or version 2 based. 3360 * version 2 profiles must have a version number as the first profile 3361 * attribute in the configuration. 3362 */ 3363 static ns_config_t * 3364 SetDoorInfo(char *buffer, ns_ldap_error_t **errorp) 3365 { 3366 ns_config_t *ptr; 3367 char errstr[MAXERROR], errbuf[MAXERROR]; 3368 char *name, *value, valbuf[BUFSIZE]; 3369 char *strptr; 3370 char *rest; 3371 char *bufptr = buffer; 3372 ParamIndexType i; 3373 int ret; 3374 int first = 1; 3375 int errfnd = 0; 3376 ldap_config_out_t *cfghdr; 3377 3378 if (errorp == NULL) 3379 return (NULL); 3380 *errorp = NULL; 3381 3382 ptr = __s_api_create_config(); 3383 if (ptr == NULL) { 3384 return (NULL); 3385 } 3386 3387 /* get config cookie from the header */ 3388 cfghdr = (ldap_config_out_t *)bufptr; 3389 ptr->config_cookie = cfghdr->cookie; 3390 bufptr = (char *)cfghdr->config_str; 3391 3392 strptr = (char *)strtok_r(bufptr, DOORLINESEP, &rest); 3393 for (; ; ) { 3394 if (strptr == NULL) 3395 break; 3396 (void) strlcpy(valbuf, strptr, sizeof (valbuf)); 3397 __s_api_split_key_value(valbuf, &name, &value); 3398 /* Use get_versiontype and check for V1 vs V2 prototypes */ 3399 if (__s_api_get_versiontype(ptr, name, &i) < 0) { 3400 (void) snprintf(errstr, sizeof (errstr), 3401 "%s (%s)\n", 3402 gettext("Illegal profile entry " 3403 "line in configuration."), 3404 name); 3405 errfnd++; 3406 /* Write verify routines and get rid of verify_value here */ 3407 } else if (verify_value(ptr, name, 3408 value, errbuf) != NS_SUCCESS) { 3409 (void) snprintf(errstr, sizeof (errstr), 3410 gettext("%s\n"), errbuf); 3411 errfnd++; 3412 } else if (!first && i == NS_LDAP_FILE_VERSION_P) { 3413 (void) snprintf(errstr, sizeof (errstr), 3414 gettext("Illegal NS_LDAP_FILE_VERSION " 3415 "line in configuration.\n")); 3416 errfnd++; 3417 } 3418 if (errfnd) { 3419 MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX, 3420 strdup(errstr), NULL); 3421 } else { 3422 ret = set_default_value(ptr, name, value, errorp); 3423 } 3424 if (errfnd || ret != NS_SUCCESS) { 3425 __s_api_destroy_config(ptr); 3426 return (NULL); 3427 } 3428 first = 0; 3429 3430 strptr = (char *)strtok_r(NULL, DOORLINESEP, &rest); 3431 } 3432 3433 if (__s_api_crosscheck(ptr, errstr, B_TRUE) != NS_SUCCESS) { 3434 __s_api_destroy_config(ptr); 3435 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX, strdup(errstr), 3436 NULL); 3437 return (NULL); 3438 } 3439 3440 return (ptr); 3441 } 3442 3443 static ns_config_t * 3444 LoadCacheConfiguration(ns_config_t *oldcfg, ns_ldap_error_t **error) 3445 { 3446 char *buffer = NULL; 3447 int buflen = 0; 3448 int ret; 3449 ns_config_t *cfg; 3450 ldap_config_out_t *cfghdr; 3451 ldap_get_chg_cookie_t old_cookie; 3452 ldap_get_chg_cookie_t new_cookie; 3453 3454 *error = NULL; 3455 ret = __door_getldapconfig(&buffer, &buflen, error); 3456 3457 if (ret != NS_LDAP_SUCCESS) { 3458 if (*error != NULL && (*error)->message != NULL) 3459 syslog(LOG_WARNING, "libsldap: %s", (*error)->message); 3460 return (NULL); 3461 } 3462 3463 /* No need to reload configuration if config cookie is the same */ 3464 cfghdr = (ldap_config_out_t *)buffer; 3465 new_cookie = cfghdr->cookie; 3466 if (oldcfg != NULL) 3467 old_cookie = oldcfg->config_cookie; 3468 3469 if (oldcfg != NULL && old_cookie.mgr_pid == new_cookie.mgr_pid && 3470 old_cookie.seq_num == new_cookie.seq_num) { 3471 free(buffer); 3472 return (oldcfg); 3473 } 3474 3475 /* now convert from door format */ 3476 cfg = SetDoorInfo(buffer, error); 3477 free(buffer); 3478 3479 if (cfg == NULL && *error != NULL && (*error)->message != NULL) 3480 syslog(LOG_WARNING, "libsldap: %s", (*error)->message); 3481 return (cfg); 3482 } 3483 3484 /* 3485 * converts the time string into seconds. The time string can be specified 3486 * using one of the following time units: 3487 * #s (# of seconds) 3488 * #m (# of minutes) 3489 * #h (# of hours) 3490 * #d (# of days) 3491 * #w (# of weeks) 3492 * NOTE: you can only specify one the above. No combination of the above 3493 * units is allowed. If no unit specified, it will default to "seconds". 3494 */ 3495 static time_t 3496 conv_time(char *s) 3497 { 3498 time_t t; 3499 char c; 3500 int l, m; 3501 long tot; 3502 3503 l = strlen(s); 3504 if (l == 0) 3505 return (0); 3506 c = s[--l]; 3507 m = 0; 3508 switch (c) { 3509 case 'w': /* weeks */ 3510 m = 604800; 3511 break; 3512 case 'd': /* days */ 3513 m = 86400; 3514 break; 3515 case 'h': /* hours */ 3516 m = 3600; 3517 break; 3518 case 'm': /* minutes */ 3519 m = 60; 3520 break; 3521 case 's': /* seconds */ 3522 m = 1; 3523 break; 3524 /* the default case is set to "second" */ 3525 } 3526 if (m != 0) 3527 s[l] = '\0'; 3528 else 3529 m = 1; 3530 errno = 0; 3531 tot = atol(s); 3532 if ((0 == tot) && (EINVAL == errno)) 3533 return (0); 3534 if (((LONG_MAX == tot) || (LONG_MIN == tot)) && (EINVAL == errno)) 3535 return (0); 3536 3537 tot = tot * m; 3538 t = (time_t)tot; 3539 return (t); 3540 } 3541 3542 3543 ns_auth_t * 3544 __s_api_AuthEnumtoStruct(const EnumAuthType_t i) 3545 { 3546 ns_auth_t *ap; 3547 3548 ap = (ns_auth_t *)calloc(1, sizeof (ns_auth_t)); 3549 if (ap == NULL) 3550 return (NULL); 3551 switch (i) { 3552 case NS_LDAP_EA_NONE: 3553 break; 3554 case NS_LDAP_EA_SIMPLE: 3555 ap->type = NS_LDAP_AUTH_SIMPLE; 3556 break; 3557 case NS_LDAP_EA_SASL_CRAM_MD5: 3558 ap->type = NS_LDAP_AUTH_SASL; 3559 ap->saslmech = NS_LDAP_SASL_CRAM_MD5; 3560 break; 3561 case NS_LDAP_EA_SASL_DIGEST_MD5: 3562 ap->type = NS_LDAP_AUTH_SASL; 3563 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3564 break; 3565 case NS_LDAP_EA_SASL_DIGEST_MD5_INT: 3566 ap->type = NS_LDAP_AUTH_SASL; 3567 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3568 ap->saslopt = NS_LDAP_SASLOPT_INT; 3569 break; 3570 case NS_LDAP_EA_SASL_DIGEST_MD5_CONF: 3571 ap->type = NS_LDAP_AUTH_SASL; 3572 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3573 ap->saslopt = NS_LDAP_SASLOPT_PRIV; 3574 break; 3575 case NS_LDAP_EA_SASL_EXTERNAL: 3576 ap->type = NS_LDAP_AUTH_SASL; 3577 ap->saslmech = NS_LDAP_SASL_EXTERNAL; 3578 break; 3579 case NS_LDAP_EA_SASL_GSSAPI: 3580 ap->type = NS_LDAP_AUTH_SASL; 3581 ap->saslmech = NS_LDAP_SASL_GSSAPI; 3582 ap->saslopt = NS_LDAP_SASLOPT_INT | 3583 NS_LDAP_SASLOPT_PRIV; 3584 break; 3585 case NS_LDAP_EA_TLS_NONE: 3586 ap->type = NS_LDAP_AUTH_TLS; 3587 ap->tlstype = NS_LDAP_TLS_NONE; 3588 break; 3589 case NS_LDAP_EA_TLS_SIMPLE: 3590 ap->type = NS_LDAP_AUTH_TLS; 3591 ap->tlstype = NS_LDAP_TLS_SIMPLE; 3592 break; 3593 case NS_LDAP_EA_TLS_SASL_CRAM_MD5: 3594 ap->type = NS_LDAP_AUTH_TLS; 3595 ap->tlstype = NS_LDAP_TLS_SASL; 3596 ap->saslmech = NS_LDAP_SASL_CRAM_MD5; 3597 break; 3598 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5: 3599 ap->type = NS_LDAP_AUTH_TLS; 3600 ap->tlstype = NS_LDAP_TLS_SASL; 3601 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3602 break; 3603 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_INT: 3604 ap->type = NS_LDAP_AUTH_TLS; 3605 ap->tlstype = NS_LDAP_TLS_SASL; 3606 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3607 ap->saslopt = NS_LDAP_SASLOPT_INT; 3608 break; 3609 case NS_LDAP_EA_TLS_SASL_DIGEST_MD5_CONF: 3610 ap->type = NS_LDAP_AUTH_TLS; 3611 ap->tlstype = NS_LDAP_TLS_SASL; 3612 ap->saslmech = NS_LDAP_SASL_DIGEST_MD5; 3613 ap->saslopt = NS_LDAP_SASLOPT_PRIV; 3614 break; 3615 case NS_LDAP_EA_TLS_SASL_EXTERNAL: 3616 ap->type = NS_LDAP_AUTH_TLS; 3617 ap->tlstype = NS_LDAP_TLS_SASL; 3618 ap->saslmech = NS_LDAP_SASL_EXTERNAL; 3619 break; 3620 default: 3621 /* should never get here */ 3622 free(ap); 3623 return (NULL); 3624 } 3625 return (ap); 3626 } 3627 3628 3629 /* 3630 * Parameter Index Type validation routines 3631 */ 3632 3633 /* Validate a positive integer */ 3634 /* Size of errbuf needs to be MAXERROR */ 3635 /* ARGSUSED */ 3636 static int 3637 __s_val_postime(ParamIndexType i, ns_default_config *def, 3638 ns_param_t *param, char *errbuf) 3639 { 3640 char *cp; 3641 long tot; 3642 3643 if (param && param->ns_ptype == CHARPTR && param->ns_pc) { 3644 for (cp = param->ns_pc; cp && *cp; cp++) { 3645 if (*cp >= '0' && *cp <= '9') 3646 continue; 3647 switch (*cp) { 3648 case 'w': /* weeks */ 3649 case 'd': /* days */ 3650 case 'h': /* hours */ 3651 case 'm': /* minutes */ 3652 case 's': /* seconds */ 3653 if (*(cp+1) == '\0') { 3654 break; 3655 } 3656 default: 3657 (void) strcpy(errbuf, "Illegal time value"); 3658 return (NS_PARSE_ERR); 3659 } 3660 } 3661 /* Valid form: [0-9][0-9]*[wdhms]* */ 3662 tot = atol(param->ns_pc); /* check overflow */ 3663 if (tot >= 0) 3664 return (NS_SUCCESS); 3665 } 3666 (void) snprintf(errbuf, MAXERROR, 3667 gettext("Illegal time value in %s"), def->name); 3668 return (NS_PARSE_ERR); 3669 } 3670 3671 3672 /* Validate the Base DN */ 3673 /* It can be empty (RootDSE request) or needs to have an '=' */ 3674 /* Size of errbuf needs to be MAXERROR */ 3675 /* ARGSUSED */ 3676 static int 3677 __s_val_basedn(ParamIndexType i, ns_default_config *def, 3678 ns_param_t *param, char *errbuf) 3679 { 3680 if (param && param->ns_ptype == CHARPTR && 3681 i == NS_LDAP_SEARCH_BASEDN_P && 3682 ((param->ns_pc == NULL) || /* empty */ 3683 (*(param->ns_pc) == '\0') || /* empty */ 3684 (strchr(param->ns_pc, '=') != NULL))) /* '=' */ 3685 { 3686 return (NS_SUCCESS); 3687 } 3688 (void) snprintf(errbuf, MAXERROR, 3689 gettext("Non-existent or invalid DN in %s"), 3690 def->name); 3691 return (NS_PARSE_ERR); 3692 } 3693 3694 3695 /* Validate the serverList */ 3696 /* For each server in list, check if valid IP or hostname */ 3697 /* Size of errbuf needs to be MAXERROR */ 3698 /* ARGSUSED */ 3699 static int 3700 __s_val_serverList(ParamIndexType i, ns_default_config *def, 3701 ns_param_t *param, char *errbuf) 3702 { 3703 for (i = 0; i < param->ns_acnt; i++) { 3704 if ((__s_api_isipv4(param->ns_ppc[i])) || 3705 (__s_api_isipv6(param->ns_ppc[i])) || 3706 (__s_api_ishost(param->ns_ppc[i]))) { 3707 continue; 3708 } 3709 /* err */ 3710 (void) snprintf(errbuf, MAXERROR, 3711 gettext("Invalid server (%s) in %s"), 3712 param->ns_ppc[i], def->name); 3713 return (NS_PARSE_ERR); 3714 } 3715 3716 return (NS_SUCCESS); 3717 } 3718 3719 3720 /* Check for a BINDDN */ 3721 /* It can not be empty and needs to have an '=' */ 3722 /* Size of errbuf needs to be MAXERROR */ 3723 /* ARGSUSED */ 3724 static int 3725 __s_val_binddn(ParamIndexType i, ns_default_config *def, 3726 ns_param_t *param, char *errbuf) 3727 { 3728 if (param && param->ns_ptype == CHARPTR && 3729 i == NS_LDAP_BINDDN_P && 3730 ((param->ns_pc == NULL) || 3731 ((*(param->ns_pc) != '\0') && 3732 (strchr(param->ns_pc, '=') != NULL)))) { 3733 return (NS_SUCCESS); 3734 } 3735 (void) snprintf(errbuf, MAXERROR, 3736 gettext("NULL or invalid proxy bind DN")); 3737 return (NS_PARSE_ERR); 3738 } 3739 3740 3741 /* Check for a BINDPASSWD */ 3742 /* The string can not be NULL or empty */ 3743 /* Size of errbuf needs to be MAXERROR */ 3744 /* ARGSUSED */ 3745 static int 3746 __s_val_bindpw(ParamIndexType i, ns_default_config *def, 3747 ns_param_t *param, char *errbuf) 3748 { 3749 if (param && param->ns_ptype == CHARPTR && 3750 i == NS_LDAP_BINDPASSWD_P && 3751 ((param->ns_pc == NULL) || 3752 (*(param->ns_pc) != '\0'))) { 3753 return (NS_SUCCESS); 3754 } 3755 (void) snprintf(errbuf, MAXERROR, 3756 gettext("NULL proxy bind password")); 3757 return (NS_PARSE_ERR); 3758 } 3759 3760 /* 3761 * __s_get_hostcertpath returns either the configured host certificate path 3762 * or, if none, the default host certificate path (/var/ldap). Note that this 3763 * does not use __ns_ldap_getParam because it may be called during connection 3764 * setup. This can fail due to insufficient memory. 3765 */ 3766 3767 char * 3768 __s_get_hostcertpath(void) 3769 { 3770 ns_config_t *cfg; 3771 ns_param_t *param; 3772 char *ret = NULL; 3773 3774 cfg = __s_api_get_default_config(); 3775 if (cfg != NULL) { 3776 param = &cfg->paramList[NS_LDAP_HOST_CERTPATH_P]; 3777 if (param->ns_ptype == CHARPTR) 3778 ret = strdup(param->ns_pc); 3779 __s_api_release_config(cfg); 3780 } 3781 if (ret == NULL) 3782 ret = strdup(NSLDAPDIRECTORY); 3783 return (ret); 3784 } 3785 3786 static void 3787 _free_config() 3788 { 3789 if (current_config != NULL) 3790 destroy_config(current_config); 3791 3792 current_config = NULL; 3793 } 3794