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