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