1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* libsldap - cachemgr side configuration components */ 27 28 #include <stdio.h> 29 #include <sys/types.h> 30 #include <stdlib.h> 31 #include <libintl.h> 32 #include <string.h> 33 #include <ctype.h> 34 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <unistd.h> 38 #include <syslog.h> 39 #include <locale.h> 40 #include <errno.h> 41 #include <sys/time.h> 42 43 #include "ns_sldap.h" 44 #include "ns_internal.h" 45 #include "ns_cache_door.h" 46 47 #define ALWAYS 1 48 49 50 /* 51 * ************************************************************** 52 * Configuration File Routines 53 * ************************************************************** 54 */ 55 56 57 /* Size of the errstr buffer needs to be MAXERROR */ 58 static int 59 read_line(FILE *fp, char *buffer, int buflen, char *errstr) 60 { 61 int linelen; 62 char c; 63 64 *errstr = '\0'; 65 66 for (linelen = 0; linelen < buflen; ) { 67 c = getc(fp); 68 if (c == EOF) 69 break; 70 switch (c) { 71 case '\n': 72 if (linelen > 0 && buffer[linelen - 1] == '\\') { 73 /* Continuation line found */ 74 --linelen; 75 } else { 76 /* end of line found */ 77 buffer[linelen] = '\0'; 78 return (linelen); 79 } 80 break; 81 default: 82 buffer[linelen++] = c; 83 } 84 } 85 86 if (linelen >= buflen) { 87 (void) snprintf(errstr, MAXERROR, 88 gettext("Buffer overflow, line too long.")); 89 return (-2); 90 } else if (linelen > 0 && buffer[linelen - 1] == '\\') { 91 (void) snprintf(errstr, MAXERROR, 92 gettext("Unterminated continuation line.")); 93 return (-2); 94 } else { 95 /* end of file */ 96 buffer[linelen] = '\0'; 97 } 98 return (linelen > 0 ? linelen : -1); 99 } 100 101 102 static ns_parse_status 103 read_file(ns_config_t *ptr, int cred_file, ns_ldap_error_t **error) 104 { 105 ParamIndexType i = 0; 106 char errstr[MAXERROR]; 107 char buffer[BUFSIZE], *name, *value; 108 int emptyfile, lineno; 109 FILE *fp; 110 int ret; 111 int linelen; 112 char *file; 113 int first = 1; 114 115 116 if (cred_file) { 117 file = NSCREDFILE; 118 } else { 119 file = NSCONFIGFILE; 120 } 121 fp = fopen(file, "rF"); 122 if (fp == NULL) { 123 (void) snprintf(errstr, sizeof (errstr), 124 gettext("Unable to open filename '%s' " 125 "for reading (errno=%d)."), file, errno); 126 MKERROR(LOG_ERR, *error, NS_CONFIG_FILE, strdup(errstr), 127 NS_PARSE_ERR); 128 return (NS_NOTFOUND); 129 } 130 131 emptyfile = 1; 132 lineno = 0; 133 for (; ; ) { 134 if ((linelen = read_line(fp, buffer, sizeof (buffer), 135 errstr)) < 0) 136 /* End of file */ 137 break; 138 lineno++; 139 if (linelen == 0) 140 continue; 141 /* get rid of comment lines */ 142 if (buffer[0] == '#') 143 continue; 144 emptyfile = 0; 145 name = NULL; 146 value = NULL; 147 __s_api_split_key_value(buffer, &name, &value); 148 if (name == NULL || value == NULL) { 149 (void) snprintf(errstr, sizeof (errstr), 150 gettext("Missing Name or Value on line %d."), 151 lineno); 152 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 153 strdup(errstr), NS_PARSE_ERR); 154 (void) fclose(fp); 155 return (NS_PARSE_ERR); 156 } 157 if (__s_api_get_versiontype(ptr, name, &i) != 0) { 158 (void) snprintf(errstr, sizeof (errstr), 159 gettext("Illegal profile type on line %d."), 160 lineno); 161 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 162 strdup(errstr), NS_PARSE_ERR); 163 (void) fclose(fp); 164 return (NS_PARSE_ERR); 165 } 166 if (!first && i == NS_LDAP_FILE_VERSION_P) { 167 (void) snprintf(errstr, sizeof (errstr), 168 gettext("Illegal NS_LDAP_FILE_VERSION " 169 "on line %d."), lineno); 170 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 171 strdup(errstr), NS_PARSE_ERR); 172 (void) fclose(fp); 173 return (NS_PARSE_ERR); 174 } 175 first = 0; 176 switch (__s_api_get_configtype(i)) { 177 case SERVERCONFIG: 178 case CLIENTCONFIG: 179 if (cred_file == 0) { 180 ret = __ns_ldap_setParamValue(ptr, i, value, 181 error); 182 if (ret != NS_SUCCESS) { 183 (void) fclose(fp); 184 return (ret); 185 } 186 } else if (i != NS_LDAP_FILE_VERSION_P) { 187 (void) snprintf(errstr, sizeof (errstr), 188 gettext("Illegal entry in '%s' on " 189 "line %d"), file, lineno); 190 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 191 strdup(errstr), NS_PARSE_ERR); 192 (void) fclose(fp); 193 return (NS_PARSE_ERR); 194 } 195 break; 196 case CREDCONFIG: 197 if (i == NS_LDAP_FILE_VERSION_P) 198 break; 199 if (cred_file) { 200 ret = __ns_ldap_setParamValue(ptr, i, value, 201 error); 202 if (ret != NS_SUCCESS) { 203 (void) fclose(fp); 204 return (ret); 205 } 206 } else { 207 (void) snprintf(errstr, sizeof (errstr), 208 gettext("Illegal entry in '%s' on " 209 "line %d"), file, lineno); 210 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 211 strdup(errstr), NS_PARSE_ERR); 212 (void) fclose(fp); 213 return (NS_PARSE_ERR); 214 } 215 } 216 } 217 (void) fclose(fp); 218 if (!cred_file && emptyfile) { 219 /* Error in read_line */ 220 (void) snprintf(errstr, sizeof (errstr), 221 gettext("Empty config file: '%s'"), file); 222 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 223 NS_PARSE_ERR); 224 return (NS_PARSE_ERR); 225 } 226 if (linelen == -2) { 227 /* Error in read_line */ 228 (void) snprintf(errstr, sizeof (errstr), 229 gettext("Line too long in '%s'"), file); 230 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 231 NS_PARSE_ERR); 232 return (NS_PARSE_ERR); 233 } 234 return (NS_SUCCESS); 235 } 236 237 238 static 239 ns_ldap_return_code 240 set_attr(ns_config_t *config_struct, char *attr_name, char *attr_val, 241 ns_ldap_error_t **errorp) 242 { 243 ParamIndexType idx; 244 char errmsg[MAXERROR]; 245 246 if (errorp == NULL) { 247 return (NS_LDAP_INVALID_PARAM); 248 } 249 250 *errorp = NULL; 251 252 /* 253 * This double call is made due to the presence of 254 * two sets of LDAP config. attribute names. 255 * An LDAP configuration can be obtained either from a server 256 * or from SMF. The former sends a DUA with attributes' names 257 * styled like "preferredServerList". But local configurations 258 * will have names inherited from the /var/ldap/ldap* files such as 259 * "NS_LDAP_SERVER_PREF". 260 * So, the standalone bits are able to process both sets of 261 * attributes' names. 262 */ 263 if (__s_api_get_profiletype(attr_name, &idx) < 0 && 264 __s_api_get_versiontype(config_struct, attr_name, &idx) < 0) { 265 (void) snprintf(errmsg, sizeof (errmsg), 266 gettext("Illegal DUAProfile property: <%s>."), attr_name); 267 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), 268 NS_LDAP_MEMORY); 269 return (NS_LDAP_CONFIG); 270 } 271 272 return (__ns_ldap_setParamValue(config_struct, idx, attr_val, errorp)); 273 } 274 275 276 /* 277 * This function creates a configuration which will be used 278 * for all LDAP requests in the Standalone mode. 279 * 280 * INPUT: 281 * config - a buffer returned by __ns_ldap_getConnectionInfo()'s 282 * dua_profile parameter. 283 * 284 */ 285 ns_config_t * 286 __s_api_create_config_door_str(char *config, ns_ldap_error_t **errorp) 287 { 288 char *attr, *attrName, *attrVal, *rest; 289 ns_config_t *configStruct = NULL; 290 char errmsg[MAXERROR]; 291 292 if (config == NULL || errorp == NULL) 293 return (NULL); 294 295 if ((configStruct = __s_api_create_config()) == NULL) { 296 return (NULL); 297 } 298 299 *errorp = NULL; 300 301 attr = strtok_r(config, DOORLINESEP, &rest); 302 if (!attr) { 303 __s_api_destroy_config(configStruct); 304 (void) snprintf(errmsg, sizeof (errmsg), 305 gettext("DUAProfile received from the server" 306 " has bad format")); 307 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL); 308 return (NULL); 309 } 310 311 do { 312 __s_api_split_key_value(attr, &attrName, &attrVal); 313 314 if (attrName == NULL || attrVal == NULL) { 315 __s_api_destroy_config(configStruct); 316 (void) snprintf(errmsg, sizeof (errmsg), 317 gettext("Attribute %s is not valid"), attr); 318 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, 319 strdup(errmsg), NULL); 320 return (NULL); 321 } 322 323 /* Get the version of the profile. */ 324 if (strcasecmp(attrName, "objectclass") == 0) { 325 if (strcasecmp(attrVal, _PROFILE2_OBJECTCLASS) == 0) { 326 if (__ns_ldap_setParamValue(configStruct, 327 NS_LDAP_FILE_VERSION_P, 328 NS_LDAP_VERSION_2, 329 errorp) != NS_LDAP_SUCCESS) { 330 __s_api_destroy_config(configStruct); 331 return (NULL); 332 } 333 } else if (strcasecmp(attrVal, 334 _PROFILE1_OBJECTCLASS) == 0) { 335 if (__ns_ldap_setParamValue(configStruct, 336 NS_LDAP_FILE_VERSION_P, 337 NS_LDAP_VERSION_1, 338 errorp) != NS_LDAP_SUCCESS) { 339 __s_api_destroy_config(configStruct); 340 return (NULL); 341 } 342 } 343 continue; 344 } 345 346 if (set_attr(configStruct, attrName, attrVal, errorp) != 347 NS_LDAP_SUCCESS) { 348 __s_api_destroy_config(configStruct); 349 return (NULL); 350 } 351 } while (attr = strtok_r(NULL, DOORLINESEP, &rest)); 352 353 if (__s_api_crosscheck(configStruct, errmsg, B_FALSE) != NS_SUCCESS) { 354 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL); 355 __s_api_destroy_config(configStruct); 356 return (NULL); 357 } 358 359 return (configStruct); 360 } 361 362 363 /* 364 * Cache Manager side of configuration file loading 365 */ 366 367 ns_ldap_error_t * 368 __ns_ldap_LoadConfiguration() 369 { 370 ns_ldap_error_t *error = NULL; 371 ns_config_t *ptr = NULL; 372 char errstr[MAXERROR]; 373 ns_parse_status ret; 374 375 376 ptr = __s_api_create_config(); 377 if (ptr == NULL) { 378 (void) snprintf(errstr, sizeof (errstr), 379 gettext("__ns_ldap_LoadConfiguration: Out of memory.")); 380 MKERROR(LOG_ERR, error, NS_CONFIG_NOTLOADED, 381 strdup(errstr), NULL); 382 return (error); 383 } 384 385 /* Load in Configuration file */ 386 ret = read_file(ptr, 0, &error); 387 if (ret != NS_SUCCESS) { 388 __s_api_destroy_config(ptr); 389 return (error); 390 } 391 392 /* Load in Credential file */ 393 ret = read_file(ptr, 1, &error); 394 if (ret != NS_SUCCESS) { 395 __s_api_destroy_config(ptr); 396 return (error); 397 } 398 399 if (__s_api_crosscheck(ptr, errstr, B_TRUE) != NS_SUCCESS) { 400 __s_api_destroy_config(ptr); 401 MKERROR(LOG_ERR, error, NS_CONFIG_SYNTAX, strdup(errstr), NULL); 402 return (error); 403 } 404 405 __s_api_init_config(ptr); 406 return (NULL); 407 } 408 409 410 int 411 __print2buf(LineBuf *line, const char *toprint, char *sep) 412 { 413 int newsz = 0; 414 int newmax = 0; 415 char *str; 416 417 if (line == NULL) 418 return (-1); 419 420 newsz = strlen(toprint) + line->len + 1; 421 if (sep != NULL) { 422 newsz += strlen(sep); 423 } 424 if (line->alloc == 0 || newsz > line->alloc) { 425 /* Round up to next buffer and add 1 */ 426 newmax = (((newsz+(BUFSIZ-1))/BUFSIZ)+1) * BUFSIZ; 427 if (line->alloc == 0) 428 line->str = (char *)calloc(newmax, 1); 429 else { 430 /* 431 * if realloc() returns NULL, 432 * the original buffer is untouched. 433 * It needs to be freed. 434 */ 435 str = (char *)realloc(line->str, newmax); 436 if (str == NULL) { 437 free(line->str); 438 line->str = NULL; 439 } 440 else 441 line->str = str; 442 } 443 line->alloc = newmax; 444 if (line->str == NULL) { 445 line->alloc = 0; 446 line->len = 0; 447 return (-1); 448 } 449 } 450 /* now add new 'toprint' data to buffer */ 451 (void) strlcat(line->str, toprint, line->alloc); 452 if (sep != NULL) { 453 (void) strlcat(line->str, sep, line->alloc); 454 } 455 line->len = newsz; 456 return (0); 457 } 458 459 460 /* 461 * __ns_ldap_LoadDoorInfo is a routine used by the ldapcachemgr 462 * to create a configuration buffer to transmit back to a client 463 * domainname is transmitted to ldapcachemgr and ldapcachemgr uses 464 * it to select a configuration to transmit back. Otherwise it 465 * is essentially unused in sldap. 466 * If cred_only is not 0, then only the credentials for shadow 467 * update are taken care of. 468 */ 469 470 ns_ldap_error_t * 471 __ns_ldap_LoadDoorInfo(LineBuf *configinfo, char *domainname, 472 ns_config_t *new, int cred_only) 473 { 474 ns_config_t *ptr; 475 char errstr[MAXERROR]; 476 ns_ldap_error_t *errorp; 477 char *str; 478 ParamIndexType i = 0; 479 int len; 480 ldap_config_out_t *cout; 481 482 /* 483 * If new is NULL, it outputs the flatten data of current default 484 * config, if it's non-NULL, it outputs the flatten data of a temporary 485 * config. It's used to compare the new config data with the current 486 * default config data. 487 */ 488 if (new == NULL) 489 ptr = __s_api_get_default_config(); 490 else 491 ptr = new; 492 if (ptr == NULL) { 493 (void) snprintf(errstr, sizeof (errstr), 494 gettext("No configuration information available for %s."), 495 domainname == NULL ? "<no domain specified>" : domainname); 496 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED, 497 strdup(errstr), NULL); 498 return (errorp); 499 } 500 (void) memset((char *)configinfo, 0, sizeof (LineBuf)); 501 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) { 502 if (cred_only) { 503 /* only exposed credential for shadow update */ 504 if (i != NS_LDAP_ADMIN_BINDDN_P && 505 i != NS_LDAP_ADMIN_BINDPASSWD_P) 506 continue; 507 } else { 508 /* credential for shadow update is not to be exposed */ 509 if (i == NS_LDAP_ADMIN_BINDDN_P || 510 i == NS_LDAP_ADMIN_BINDPASSWD_P) 511 continue; 512 } 513 str = __s_api_strValue(ptr, i, NS_DOOR_FMT); 514 if (str == NULL) 515 continue; 516 if (__print2buf(configinfo, str, DOORLINESEP)) { 517 (void) snprintf(errstr, sizeof (errstr), 518 gettext("__print2buf: Out of memory.")); 519 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED, 520 strdup(errstr), NULL); 521 __s_api_release_config(ptr); 522 free(str); 523 return (errorp); 524 } 525 free(str); 526 } 527 if (new == NULL) 528 __s_api_release_config(ptr); 529 530 /* 531 * The new interface of the configuration between ldap_cachemgr 532 * & libsldap contains a header structure ldap_config_out_t. 533 * The flatten configuration data configinfo->str is cloned 534 * to cout->config_str, configinfo->len is saved in 535 * cout->data_size and cout->cookie is set later after this function 536 * is returned in ldap_cachemgr. 537 * configinfo->str & configinfo->len are reused to save info of 538 * header + data. 539 * The format: 540 * [cookie|data_size|config_str .............] 541 */ 542 543 if (configinfo->str) { 544 len = sizeof (ldap_config_out_t) - sizeof (int) + 545 configinfo->len; 546 if ((cout = calloc(1, len)) == NULL) { 547 free(configinfo->str); 548 configinfo->str = NULL; 549 configinfo->len = 0; 550 (void) snprintf(errstr, sizeof (errstr), 551 gettext("calloc: Out of memory.")); 552 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED, 553 strdup(errstr), NULL); 554 return (errorp); 555 } 556 /* 557 * cout->cookie is set by the caller, 558 * which is in ldap_cachemgr. 559 */ 560 cout->data_size = configinfo->len; 561 (void) memcpy(cout->config_str, configinfo->str, 562 configinfo->len); 563 free(configinfo->str); 564 configinfo->str = (char *)cout; 565 configinfo->len = len; 566 } 567 return (NULL); 568 } 569 570 571 ns_ldap_error_t * 572 __ns_ldap_DumpLdif(char *filename) 573 { 574 ns_config_t *ptr; 575 char errstr[MAXERROR]; 576 ns_ldap_error_t *errorp; 577 char *str; 578 FILE *fp; 579 ParamIndexType i = 0; 580 char *profile, *container, *base; 581 582 ptr = __s_api_get_default_config(); 583 if (ptr == NULL) { 584 (void) snprintf(errstr, sizeof (errstr), 585 gettext("No configuration information available.")); 586 MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr), 587 NULL); 588 return (errorp); 589 } 590 591 if (filename == NULL) { 592 fp = stdout; 593 } else { 594 fp = fopen(filename, "wF"); 595 if (fp == NULL) { 596 (void) snprintf(errstr, sizeof (errstr), 597 gettext("Unable to open filename %s for ldif " 598 "dump (errno=%d)."), filename, errno); 599 MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE, 600 strdup(errstr), NULL); 601 __s_api_release_config(ptr); 602 return (errorp); 603 } 604 (void) fchmod(fileno(fp), 0444); 605 } 606 607 if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ptype != CHARPTR || 608 ptr->paramList[NS_LDAP_PROFILE_P].ns_ptype != CHARPTR) { 609 (void) snprintf(errstr, sizeof (errstr), 610 gettext("Required BaseDN and/or Profile name " 611 "ldif fields not present")); 612 MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE, strdup(errstr), 613 NULL); 614 __s_api_release_config(ptr); 615 return (errorp); 616 } 617 618 profile = ptr->paramList[NS_LDAP_PROFILE_P].ns_pc; 619 base = ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_pc; 620 container = _PROFILE_CONTAINER; 621 622 /* 623 * Construct DN, but since this is the profile, there is no need 624 * to worry about mapping. The profile itself can not be mapped 625 */ 626 (void) fprintf(fp, "dn: cn=%s,ou=%s,%s\n", profile, container, base); 627 628 /* dump objectclass names */ 629 if (ptr->version == NS_LDAP_V1) { 630 (void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n", 631 _PROFILE1_OBJECTCLASS); 632 } else { 633 (void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n", 634 _PROFILE2_OBJECTCLASS); 635 } 636 637 /* For each parameter - construct value */ 638 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) { 639 str = __s_api_strValue(ptr, i, NS_LDIF_FMT); 640 if (str == NULL) 641 continue; 642 /* 643 * don't dump binddn, bind password, admin binddn, admin 644 * bind password, enableShadowUpdate flag, or cert path 645 * as they are not part of version 2 profiles 646 */ 647 if ((i != NS_LDAP_BINDDN_P) && 648 (i != NS_LDAP_BINDPASSWD_P) && 649 (i != NS_LDAP_ADMIN_BINDDN_P) && 650 (i != NS_LDAP_ADMIN_BINDPASSWD_P) && 651 (i != NS_LDAP_ENABLE_SHADOW_UPDATE_P) && 652 (i != NS_LDAP_HOST_CERTPATH_P)) 653 (void) fprintf(fp, "%s\n", str); 654 free(str); 655 } 656 657 if (filename != NULL) 658 (void) fclose(fp); 659 660 __s_api_release_config(ptr); 661 return (NULL); 662 } 663 664 /* 665 * This routine can process the configuration and/or 666 * the credential files at the same time. 667 * files is char *[3] = { "config", "cred", NULL }; 668 */ 669 670 static 671 ns_ldap_error_t * 672 __ns_ldap_DumpConfigFiles(char **files) 673 { 674 char *filename; 675 int fi; 676 int docred; 677 ns_config_t *ptr; 678 char *str; 679 char errstr[MAXERROR]; 680 ParamIndexType i = 0; 681 FILE *fp; 682 int rc; 683 ns_ldap_error_t *errorp = NULL; 684 struct stat buf; 685 int cfgtype; 686 boolean_t file_export_error = B_FALSE; 687 688 ptr = __s_api_get_default_config(); 689 if (ptr == NULL) { 690 (void) snprintf(errstr, sizeof (errstr), 691 gettext("No configuration information available.")); 692 MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr), 693 NULL); 694 return (errorp); 695 } 696 697 for (fi = 0; fi < 2; fi++) { 698 docred = 0; 699 filename = files[fi]; 700 if (filename == NULL) 701 continue; 702 if (fi == 1) 703 docred++; 704 rc = stat(filename, &buf); 705 fp = fopen(filename, "wF"); 706 if (fp == NULL) { 707 (void) snprintf(errstr, sizeof (errstr), 708 gettext("Unable to open filename %s" 709 " for configuration dump (%s)."), 710 filename, strerror(errno)); 711 MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE, 712 strdup(errstr), NULL); 713 __s_api_release_config(ptr); 714 return (errorp); 715 } 716 if (rc == 0) { 717 if (fchmod(fileno(fp), buf.st_mode) != 0) { 718 (void) snprintf(errstr, sizeof (errstr), 719 gettext("Unable to set permissions for file" 720 " %s for configuration dump (%s)."), 721 filename, strerror(errno)); 722 (void) fclose(fp); 723 file_export_error = B_TRUE; 724 break; 725 } 726 } else { 727 if (fchmod(fileno(fp), 0400) != 0) { 728 (void) snprintf(errstr, sizeof (errstr), 729 gettext("Unable to set permissions for file" 730 " %s for configuration dump (%s)."), 731 filename, strerror(errno)); 732 (void) fclose(fp); 733 file_export_error = B_TRUE; 734 break; 735 } 736 } 737 if (fprintf(fp, "#\n# %s\n#\n", DONOTEDIT) < 0) { 738 (void) snprintf(errstr, sizeof (errstr), gettext( 739 "Writing to file %s for configuration dump failed " 740 "(%s)."), filename, strerror(errno)); 741 file_export_error = B_TRUE; 742 } 743 744 /* assume VERSION is set and it outputs first */ 745 746 /* For each parameter - construct value */ 747 for (i = 0; !file_export_error && (i <= NS_LDAP_MAX_PIT_P); 748 i++) { 749 cfgtype = __s_api_get_configtype(i); 750 if ((docred == 0 && cfgtype == CREDCONFIG) || 751 (docred == 1 && cfgtype != CREDCONFIG)) 752 continue; 753 754 str = __s_api_strValue(ptr, i, NS_FILE_FMT); 755 if (str == NULL) 756 continue; 757 if (fprintf(fp, "%s\n", str) < 0) { 758 (void) snprintf(errstr, sizeof (errstr), 759 gettext("Writing to file %s for" 760 "configuration dump failed (%s)."), 761 filename, strerror(errno)); 762 file_export_error = B_TRUE; 763 } 764 765 free(str); 766 } 767 if (fclose(fp) != 0) { 768 /* Break if error already hit */ 769 if (file_export_error) 770 break; 771 772 (void) snprintf(errstr, sizeof (errstr), gettext( 773 "Writing to file %s for configuration dump failed " 774 "during file close (%s)."), filename, 775 strerror(errno)); 776 file_export_error = B_TRUE; 777 break; 778 } 779 780 } 781 782 if (file_export_error) { 783 MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE, 784 strdup(errstr), NULL); 785 (void) unlink(filename); 786 } 787 788 __s_api_release_config(ptr); 789 return (errorp); 790 } 791 792 ns_ldap_error_t * 793 __ns_ldap_DumpConfiguration(char *file) 794 { 795 ns_ldap_error_t *ret; 796 char *files[3]; 797 798 files[0] = NULL; 799 files[1] = NULL; 800 files[2] = NULL; 801 if (strcmp(file, NSCONFIGFILE) == 0) { 802 files[0] = file; 803 } else if (strcmp(file, NSCONFIGREFRESH) == 0) { 804 files[0] = file; 805 } else if (strcmp(file, NSCREDFILE) == 0) { 806 files[1] = file; 807 } else if (strcmp(file, NSCREDREFRESH) == 0) { 808 files[1] = file; 809 } 810 ret = __ns_ldap_DumpConfigFiles(files); 811 return (ret); 812 } 813 814 /* 815 * ************************************************************** 816 * Misc Routines 817 * ************************************************************** 818 */ 819 820 ns_config_t * 821 __ns_ldap_make_config(ns_ldap_result_t *result) 822 { 823 int l, m; 824 char val[BUFSIZE]; 825 char *attrname; 826 ns_ldap_entry_t *entry; 827 ns_ldap_attr_t *attr; 828 char **attrval; 829 ParamIndexType index; 830 ns_config_t *ptr; 831 ns_ldap_error_t *error = NULL; 832 int prof_ver; 833 ns_config_t *curr_ptr = NULL; 834 char errstr[MAXERROR]; 835 ns_ldap_error_t *errorp; 836 LineBuf buffer; 837 char *sepstr; 838 839 if (result == NULL) 840 return (NULL); 841 842 if (result->entries_count > 1) { 843 (void) snprintf(errstr, MAXERROR, 844 gettext("Configuration Error: More than one profile " 845 "found")); 846 MKERROR(LOG_ERR, errorp, NS_PARSE_ERR, strdup(errstr), NULL); 847 (void) __ns_ldap_freeError(&errorp); 848 return (NULL); 849 } 850 851 ptr = __s_api_create_config(); 852 if (ptr == NULL) 853 return (NULL); 854 855 curr_ptr = __s_api_get_default_config(); 856 if (curr_ptr == NULL) { 857 __s_api_destroy_config(ptr); 858 return (NULL); 859 } 860 861 /* Check to see if the profile is version 1 or version 2 */ 862 prof_ver = 1; 863 entry = result->entry; 864 for (l = 0; l < entry->attr_count; l++) { 865 attr = entry->attr_pair[l]; 866 867 attrname = attr->attrname; 868 if (attrname == NULL) 869 continue; 870 if (strcasecmp(attrname, "objectclass") == 0) { 871 for (m = 0; m < attr->value_count; m++) { 872 if (strcasecmp(_PROFILE2_OBJECTCLASS, 873 attr->attrvalue[m]) == 0) { 874 prof_ver = 2; 875 break; 876 } 877 } 878 } 879 } 880 /* update the configuration to accept v1 or v2 attributes */ 881 if (prof_ver == 1) { 882 (void) strcpy(val, NS_LDAP_VERSION_1); 883 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P, 884 val, &error); 885 } else { 886 (void) strcpy(val, NS_LDAP_VERSION_2); 887 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P, 888 val, &error); 889 } 890 891 for (l = 0; l < entry->attr_count; l++) { 892 attr = entry->attr_pair[l]; 893 894 attrname = attr->attrname; 895 if (attrname == NULL) 896 continue; 897 if (__s_api_get_profiletype(attrname, &index) != 0) 898 continue; 899 900 attrval = attr->attrvalue; 901 switch (index) { 902 case NS_LDAP_SEARCH_DN_P: 903 case NS_LDAP_SERVICE_SEARCH_DESC_P: 904 case NS_LDAP_ATTRIBUTEMAP_P: 905 case NS_LDAP_OBJECTCLASSMAP_P: 906 case NS_LDAP_SERVICE_CRED_LEVEL_P: 907 case NS_LDAP_SERVICE_AUTH_METHOD_P: 908 /* Multiple Value - insert 1 at a time */ 909 for (m = 0; m < attr->value_count; m++) { 910 (void) __ns_ldap_setParamValue(ptr, index, 911 attrval[m], &error); 912 } 913 break; 914 default: 915 (void) memset((void *)&buffer, 0, sizeof (LineBuf)); 916 917 /* Single or Multiple Value */ 918 for (m = 0; m < attr->value_count; m++) { 919 sepstr = NULL; 920 if (m != attr->value_count - 1) { 921 sepstr = SPACESEP; 922 } 923 if (__print2buf(&buffer, attrval[m], sepstr)) 924 goto makeconfigerror; 925 } 926 (void) __ns_ldap_setParamValue(ptr, index, buffer.str, 927 &error); 928 if (buffer.len > 0) { 929 free(buffer.str); 930 buffer.len = 0; 931 } 932 break; 933 } 934 } 935 if (ptr->version != NS_LDAP_V1) { 936 ParamIndexType i; 937 if (curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_ptype == CHARPTR) { 938 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_BINDDN_P, 939 curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_pc, 940 &error); 941 } 942 if (curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ptype == 943 CHARPTR) { 944 (void) __ns_ldap_setParamValue(ptr, 945 NS_LDAP_BINDPASSWD_P, 946 curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_pc, 947 &error); 948 } 949 i = NS_LDAP_ENABLE_SHADOW_UPDATE_P; 950 if (curr_ptr->paramList[i].ns_ptype == INT) { 951 char *valt; 952 valt = __s_get_shadowupdate_name( 953 curr_ptr->paramList[i].ns_i); 954 (void) __ns_ldap_setParamValue(ptr, i, valt, &error); 955 } 956 if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_ptype == 957 CHARPTR) { 958 (void) __ns_ldap_setParamValue(ptr, 959 NS_LDAP_ADMIN_BINDDN_P, 960 curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_pc, 961 &error); 962 } 963 if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_ptype == 964 CHARPTR) { 965 (void) __ns_ldap_setParamValue(ptr, 966 NS_LDAP_ADMIN_BINDPASSWD_P, 967 curr_ptr-> 968 paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_pc, 969 &error); 970 } 971 if (curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_ptype == 972 CHARPTR) { 973 (void) __ns_ldap_setParamValue(ptr, 974 NS_LDAP_HOST_CERTPATH_P, 975 curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_pc, 976 &error); 977 } 978 } 979 __s_api_release_config(curr_ptr); 980 return (ptr); 981 982 makeconfigerror: 983 if (buffer.len > 0) 984 free(buffer.str); 985 986 __s_api_debug_pause(LOG_ERR, NS_PARSE_ERR, 987 "__ns_ldap_make_config: Not enough memory"); 988 return (NULL); 989 } 990 991 /* 992 * Download a profile into our internal structure. The calling application 993 * needs to DumpConfig() to save the information to NSCONFIGFILE and NSCREDFILE 994 * if desired. 995 */ 996 int 997 __ns_ldap_download(const char *profile, char *addr, char *baseDN, 998 ns_ldap_error_t **errorp) 999 { 1000 char filter[BUFSIZE]; 1001 int rc; 1002 ns_ldap_result_t *result = NULL; 1003 ns_config_t *ptr = NULL; 1004 ns_config_t *new_ptr = NULL; 1005 char errstr[MAXERROR]; 1006 1007 *errorp = NULL; 1008 if (baseDN == NULL) 1009 return (NS_LDAP_INVALID_PARAM); 1010 1011 ptr = __s_api_get_default_config(); 1012 if (ptr == NULL) { 1013 (void) snprintf(errstr, sizeof (errstr), 1014 gettext("No configuration information available.")); 1015 MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr), 1016 NS_LDAP_MEMORY); 1017 return (NS_LDAP_CONFIG); 1018 } 1019 1020 rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SEARCH_BASEDN_P, baseDN, 1021 errorp); 1022 if (rc != NS_LDAP_SUCCESS) { 1023 __s_api_release_config(ptr); 1024 return (rc); 1025 } 1026 1027 rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SERVERS_P, addr, errorp); 1028 __s_api_release_config(ptr); 1029 if (rc != NS_LDAP_SUCCESS) 1030 return (rc); 1031 1032 (void) snprintf(filter, sizeof (filter), _PROFILE_FILTER, 1033 _PROFILE1_OBJECTCLASS, _PROFILE2_OBJECTCLASS, profile); 1034 rc = __ns_ldap_list(_PROFILE_CONTAINER, (const char *)filter, 1035 NULL, NULL, NULL, 0, &result, errorp, NULL, NULL); 1036 1037 if (rc != NS_LDAP_SUCCESS) 1038 return (rc); 1039 1040 new_ptr = __ns_ldap_make_config(result); 1041 (void) __ns_ldap_freeResult(&result); 1042 1043 if (new_ptr == NULL) 1044 return (NS_LDAP_OP_FAILED); 1045 1046 rc = __s_api_crosscheck(new_ptr, errstr, B_FALSE); 1047 if (rc != NS_LDAP_SUCCESS) { 1048 __s_api_destroy_config(new_ptr); 1049 MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr), 1050 NS_LDAP_MEMORY); 1051 return (NS_LDAP_CONFIG); 1052 } 1053 1054 __s_api_init_config(new_ptr); 1055 return (rc); 1056 } 1057 1058 /* 1059 * ************************************************************** 1060 * Configuration Printing Routines 1061 * ************************************************************** 1062 */ 1063 1064 /* 1065 * Yes the use of stdio is okay here because all we are doing is sending 1066 * output to stdout. This would not be necessary if we could get to the 1067 * configuration pointer outside this file. 1068 */ 1069 ns_ldap_error_t * 1070 __ns_ldap_print_config(int verbose) 1071 { 1072 ns_config_t *ptr; 1073 char errstr[MAXERROR]; 1074 ns_ldap_error_t *errorp; 1075 char *str; 1076 int i; 1077 1078 ptr = __s_api_get_default_config(); 1079 if (ptr == NULL) { 1080 errorp = __ns_ldap_LoadConfiguration(); 1081 if (errorp != NULL) 1082 return (errorp); 1083 ptr = __s_api_get_default_config(); 1084 if (ptr == NULL) { 1085 (void) snprintf(errstr, sizeof (errstr), 1086 gettext("No configuration information.")); 1087 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED, 1088 strdup(errstr), NULL); 1089 return (errorp); 1090 } 1091 } 1092 1093 if (verbose && (ptr->domainName != NULL)) { 1094 (void) fputs("ptr->domainName ", stdout); 1095 (void) fputs(ptr->domainName, stdout); 1096 (void) putchar('\n'); 1097 } 1098 /* For each parameter - construct value */ 1099 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) { 1100 /* 1101 * Version 1 skipped this entry because: 1102 * 1103 * don't print default cache TTL for now since 1104 * we don't store it in the ldap_client_file. 1105 */ 1106 if ((i == NS_LDAP_CACHETTL_P) && (ptr->version == NS_LDAP_V1)) 1107 continue; 1108 1109 /* the credential for shadow update is not to be exposed */ 1110 if (i == NS_LDAP_ADMIN_BINDDN_P || 1111 i == NS_LDAP_ADMIN_BINDPASSWD_P) 1112 continue; 1113 1114 str = __s_api_strValue(ptr, i, NS_FILE_FMT); 1115 if (str == NULL) 1116 continue; 1117 if (verbose) 1118 (void) putchar('\t'); 1119 (void) fprintf(stdout, "%s\n", str); 1120 free(str); 1121 } 1122 1123 __s_api_release_config(ptr); 1124 return (NULL); 1125 } 1126