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