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), NULL); 127 return (NS_NOTFOUND); 128 } 129 130 emptyfile = 1; 131 lineno = 0; 132 for (; ; ) { 133 if ((linelen = read_line(fp, buffer, sizeof (buffer), 134 errstr)) < 0) 135 /* End of file */ 136 break; 137 lineno++; 138 if (linelen == 0) 139 continue; 140 /* get rid of comment lines */ 141 if (buffer[0] == '#') 142 continue; 143 emptyfile = 0; 144 name = NULL; 145 value = NULL; 146 __s_api_split_key_value(buffer, &name, &value); 147 if (name == NULL || value == NULL) { 148 (void) snprintf(errstr, sizeof (errstr), 149 gettext("Missing Name or Value on line %d."), 150 lineno); 151 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 152 strdup(errstr), NULL); 153 (void) fclose(fp); 154 return (NS_PARSE_ERR); 155 } 156 if (__s_api_get_versiontype(ptr, name, &i) != 0) { 157 (void) snprintf(errstr, sizeof (errstr), 158 gettext("Illegal profile type on line %d."), 159 lineno); 160 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 161 strdup(errstr), NULL); 162 (void) fclose(fp); 163 return (NS_PARSE_ERR); 164 } 165 if (!first && i == NS_LDAP_FILE_VERSION_P) { 166 (void) snprintf(errstr, sizeof (errstr), 167 gettext("Illegal NS_LDAP_FILE_VERSION " 168 "on line %d."), lineno); 169 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 170 strdup(errstr), NULL); 171 (void) fclose(fp); 172 return (NS_PARSE_ERR); 173 } 174 first = 0; 175 switch (__s_api_get_configtype(i)) { 176 case SERVERCONFIG: 177 case CLIENTCONFIG: 178 if (cred_file == 0) { 179 ret = __ns_ldap_setParamValue(ptr, i, value, 180 error); 181 if (ret != NS_SUCCESS) { 182 (void) fclose(fp); 183 return (ret); 184 } 185 } else if (i != NS_LDAP_FILE_VERSION_P) { 186 (void) snprintf(errstr, sizeof (errstr), 187 gettext("Illegal entry in '%s' on " 188 "line %d"), file, lineno); 189 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 190 strdup(errstr), NULL); 191 (void) fclose(fp); 192 return (NS_PARSE_ERR); 193 } 194 break; 195 case CREDCONFIG: 196 if (i == NS_LDAP_FILE_VERSION_P) 197 break; 198 if (cred_file) { 199 ret = __ns_ldap_setParamValue(ptr, i, value, 200 error); 201 if (ret != NS_SUCCESS) { 202 (void) fclose(fp); 203 return (ret); 204 } 205 } else { 206 (void) snprintf(errstr, sizeof (errstr), 207 gettext("Illegal entry in '%s' on " 208 "line %d"), file, lineno); 209 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, 210 strdup(errstr), NULL); 211 (void) fclose(fp); 212 return (NS_PARSE_ERR); 213 } 214 } 215 } 216 (void) fclose(fp); 217 if (!cred_file && emptyfile) { 218 /* Error in read_line */ 219 (void) snprintf(errstr, sizeof (errstr), 220 gettext("Empty config file: '%s'"), file); 221 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 222 NULL); 223 return (NS_PARSE_ERR); 224 } 225 if (linelen == -2) { 226 /* Error in read_line */ 227 (void) snprintf(errstr, sizeof (errstr), 228 gettext("Line too long in '%s'"), file); 229 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr), 230 NULL); 231 return (NS_PARSE_ERR); 232 } 233 return (NS_SUCCESS); 234 } 235 236 237 static 238 ns_ldap_return_code 239 set_attr(ns_config_t *config_struct, 240 char *attr_name, 241 char *attr_val, 242 ns_ldap_error_t **errorp) 243 { 244 ParamIndexType idx; 245 char errmsg[MAXERROR]; 246 247 if (errorp == NULL) { 248 return (NS_LDAP_INVALID_PARAM); 249 } 250 251 *errorp = NULL; 252 253 /* 254 * This double call is made due to the presence of 255 * two sets of LDAP config. attribute names. 256 * An LDAP configuration can be obtained either from a server 257 * or from SMF. The former sends a DUA with attributes' names 258 * styled like "preferredServerList". But local configurations 259 * will have names inherited from the /var/ldap/ldap* files such as 260 * "NS_LDAP_SERVER_PREF". 261 * So, the standalone bits are able to process both sets of 262 * attributes' names. 263 */ 264 if (__s_api_get_profiletype(attr_name, &idx) < 0 && 265 __s_api_get_versiontype(config_struct, attr_name, &idx) < 0) { 266 (void) snprintf(errmsg, sizeof (errmsg), 267 gettext("Illegal DUAProfile property: <%s>."), attr_name); 268 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL); 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 static int 411 _print2buf(LineBuf *line, char *toprint, int addsep) 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 (addsep) { 422 newsz += strlen(DOORLINESEP); 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 (addsep) { 453 (void) strlcat(line->str, DOORLINESEP, 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 */ 467 468 ns_ldap_error_t * 469 __ns_ldap_LoadDoorInfo(LineBuf *configinfo, char *domainname, ns_config_t *new) 470 { 471 ns_config_t *ptr; 472 char errstr[MAXERROR]; 473 ns_ldap_error_t *errorp; 474 char string[BUFSIZE]; 475 char *str; 476 ParamIndexType i = 0; 477 int len; 478 ldap_config_out_t *cout; 479 480 /* 481 * If new is NULL, it outputs the flatten data of current default 482 * config, if it's non-NULL, it outputs the flatten data of a temporary 483 * config. It's used to compare the new config data with the current 484 * default config data. 485 */ 486 if (new == NULL) 487 ptr = __s_api_get_default_config(); 488 else 489 ptr = new; 490 if (ptr == NULL) { 491 (void) snprintf(errstr, sizeof (errstr), 492 gettext("No configuration information available for %s."), 493 domainname == NULL ? "<no domain specified>" : domainname); 494 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED, 495 strdup(errstr), NULL); 496 return (errorp); 497 } 498 (void) memset((char *)configinfo, 0, sizeof (LineBuf)); 499 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) { 500 /* the credential for shadow update is not to be exposed */ 501 if (i == NS_LDAP_ADMIN_BINDDN_P || 502 i == NS_LDAP_ADMIN_BINDPASSWD_P) 503 continue; 504 str = __s_api_strValue(ptr, string, sizeof (string), i, 505 NS_DOOR_FMT); 506 if (str == NULL) 507 continue; 508 if (_print2buf(configinfo, str, 1) != 0) { 509 (void) snprintf(errstr, sizeof (errstr), 510 gettext("_print2buf: Out of memory.")); 511 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED, 512 strdup(errstr), NULL); 513 __s_api_release_config(ptr); 514 if (str != (char *)&string[0]) { 515 free(str); 516 str = NULL; 517 } 518 return (errorp); 519 } 520 if (str != (char *)&string[0]) { 521 free(str); 522 str = NULL; 523 } 524 } 525 if (new == NULL) 526 __s_api_release_config(ptr); 527 528 /* 529 * The new interface of the configuration between ldap_cachemgr 530 * & libsldap contains a header structure ldap_config_out_t. 531 * The flatten configuration data configinfo->str is cloned 532 * to cout->config_str, configinfo->len is saved in 533 * cout->data_size and cout->cookie is set later after this function 534 * is returned in ldap_cachemgr. 535 * configinfo->str & configinfo->len are reused to save info of 536 * header + data. 537 * The format: 538 * [cookie|data_size|config_str .............] 539 */ 540 541 if (configinfo->str) { 542 len = sizeof (ldap_config_out_t) - sizeof (int) + 543 configinfo->len; 544 if ((cout = calloc(1, len)) == NULL) { 545 free(configinfo->str); 546 configinfo->str = NULL; 547 configinfo->len = 0; 548 (void) snprintf(errstr, sizeof (errstr), 549 gettext("calloc: Out of memory.")); 550 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED, 551 strdup(errstr), NULL); 552 return (errorp); 553 } 554 /* 555 * cout->cookie is set by the caller, 556 * which is in ldap_cachemgr. 557 */ 558 cout->data_size = configinfo->len; 559 (void) memcpy(cout->config_str, configinfo->str, 560 configinfo->len); 561 free(configinfo->str); 562 configinfo->str = (char *)cout; 563 configinfo->len = len; 564 } 565 return (NULL); 566 } 567 568 569 ns_ldap_error_t * 570 __ns_ldap_DumpLdif(char *filename) 571 { 572 ns_config_t *ptr; 573 char errstr[MAXERROR]; 574 ns_ldap_error_t *errorp; 575 char string[BUFSIZE]; 576 char *str; 577 FILE *fp; 578 ParamIndexType i = 0; 579 char *profile, *container, *base; 580 581 ptr = __s_api_get_default_config(); 582 if (ptr == NULL) { 583 (void) snprintf(errstr, sizeof (errstr), 584 gettext("No configuration information available.")); 585 MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr), 586 NULL); 587 return (errorp); 588 } 589 590 if (filename == NULL) { 591 fp = stdout; 592 } else { 593 fp = fopen(filename, "wF"); 594 if (fp == NULL) { 595 (void) snprintf(errstr, sizeof (errstr), 596 gettext("Unable to open filename %s for ldif " 597 "dump (errno=%d)."), filename, errno); 598 MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE, 599 strdup(errstr), NULL); 600 __s_api_release_config(ptr); 601 return (errorp); 602 } 603 (void) fchmod(fileno(fp), 0444); 604 } 605 606 if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ptype != CHARPTR || 607 ptr->paramList[NS_LDAP_PROFILE_P].ns_ptype != CHARPTR) { 608 (void) snprintf(errstr, sizeof (errstr), 609 gettext("Required BaseDN and/or Profile name " 610 "ldif fields not present")); 611 MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE, strdup(errstr), 612 NULL); 613 __s_api_release_config(ptr); 614 return (errorp); 615 } 616 617 profile = ptr->paramList[NS_LDAP_PROFILE_P].ns_pc; 618 base = ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_pc; 619 container = _PROFILE_CONTAINER; 620 621 /* 622 * Construct DN, but since this is the profile, there is no need 623 * to worry about mapping. The profile itself can not be mapped 624 */ 625 (void) fprintf(fp, "dn: cn=%s,ou=%s,%s\n", profile, container, base); 626 627 /* dump objectclass names */ 628 if (ptr->version == NS_LDAP_V1) { 629 (void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n", 630 _PROFILE1_OBJECTCLASS); 631 } else { 632 (void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n", 633 _PROFILE2_OBJECTCLASS); 634 } 635 636 /* For each parameter - construct value */ 637 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) { 638 str = __s_api_strValue(ptr, string, BUFSIZ, i, NS_LDIF_FMT); 639 if (str == NULL) 640 continue; 641 /* 642 * don't dump binddn, bind password, admin binddn, admin 643 * bind password, enableShadowUpdate flag, or cert path 644 * as they are not part of version 2 profiles 645 */ 646 if ((i != NS_LDAP_BINDDN_P) && 647 (i != NS_LDAP_BINDPASSWD_P) && 648 (i != NS_LDAP_ADMIN_BINDDN_P) && 649 (i != NS_LDAP_ADMIN_BINDPASSWD_P) && 650 (i != NS_LDAP_ENABLE_SHADOW_UPDATE_P) && 651 (i != NS_LDAP_HOST_CERTPATH_P)) 652 (void) fprintf(fp, "%s\n", str); 653 if (str != (char *)&string[0]) { 654 free(str); 655 str = NULL; 656 } 657 } 658 659 if (filename != NULL) 660 (void) fclose(fp); 661 662 __s_api_release_config(ptr); 663 return (NULL); 664 } 665 666 /* 667 * This routine can process the configuration and/or 668 * the credential files at the same time. 669 * files is char *[3] = { "config", "cred", NULL }; 670 */ 671 672 static 673 ns_ldap_error_t * 674 __ns_ldap_DumpConfigFiles(char **files) 675 { 676 char *filename; 677 int fi; 678 int docred; 679 ns_config_t *ptr; 680 char string[BUFSIZE]; 681 char *str; 682 char errstr[MAXERROR]; 683 ParamIndexType i = 0; 684 FILE *fp; 685 int rc; 686 ns_ldap_error_t *errorp = NULL; 687 struct stat buf; 688 int cfgtype; 689 boolean_t file_export_error = B_FALSE; 690 691 ptr = __s_api_get_default_config(); 692 if (ptr == NULL) { 693 (void) snprintf(errstr, sizeof (errstr), 694 gettext("No configuration information available.")); 695 MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr), 696 NULL); 697 return (errorp); 698 } 699 700 for (fi = 0; fi < 2; fi++) { 701 docred = 0; 702 filename = files[fi]; 703 if (filename == NULL) 704 continue; 705 if (fi == 1) 706 docred++; 707 rc = stat(filename, &buf); 708 fp = fopen(filename, "wF"); 709 if (fp == NULL) { 710 (void) snprintf(errstr, sizeof (errstr), 711 gettext("Unable to open filename %s" 712 " for configuration dump (%s)."), 713 filename, strerror(errno)); 714 MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE, 715 strdup(errstr), NULL); 716 __s_api_release_config(ptr); 717 return (errorp); 718 } 719 if (rc == 0) { 720 if (fchmod(fileno(fp), buf.st_mode) != 0) { 721 (void) snprintf(errstr, sizeof (errstr), 722 gettext("Unable to set permissions for file" 723 " %s for configuration dump (%s)."), 724 filename, strerror(errno)); 725 (void) fclose(fp); 726 file_export_error = B_TRUE; 727 break; 728 } 729 } else { 730 if (fchmod(fileno(fp), 0400) != 0) { 731 (void) snprintf(errstr, sizeof (errstr), 732 gettext("Unable to set permissions for file" 733 " %s for configuration dump (%s)."), 734 filename, strerror(errno)); 735 (void) fclose(fp); 736 file_export_error = B_TRUE; 737 break; 738 } 739 } 740 if (fprintf(fp, "#\n# %s\n#\n", DONOTEDIT) < 0) { 741 (void) snprintf(errstr, sizeof (errstr), gettext( 742 "Writing to file %s for configuration dump failed " 743 "(%s)."), filename, strerror(errno)); 744 file_export_error = B_TRUE; 745 } 746 747 /* assume VERSION is set and it outputs first */ 748 749 /* For each parameter - construct value */ 750 for (i = 0; !file_export_error && (i <= NS_LDAP_MAX_PIT_P); 751 i++) { 752 cfgtype = __s_api_get_configtype(i); 753 if ((docred == 0 && cfgtype == CREDCONFIG) || 754 (docred == 1 && cfgtype != CREDCONFIG)) 755 continue; 756 757 str = __s_api_strValue(ptr, string, BUFSIZ, i, 758 NS_FILE_FMT); 759 if (str == NULL) 760 continue; 761 if (fprintf(fp, "%s\n", str) < 0) { 762 (void) snprintf(errstr, sizeof (errstr), 763 gettext("Writing to file %s for" 764 "configuration dump failed (%s)."), 765 filename, strerror(errno)); 766 file_export_error = B_TRUE; 767 } 768 769 if (str != (char *)&string[0]) { 770 free(str); 771 str = NULL; 772 } 773 } 774 if (fclose(fp) != 0) { 775 /* Break if error already hit */ 776 if (file_export_error) 777 break; 778 779 (void) snprintf(errstr, sizeof (errstr), gettext( 780 "Writing to file %s for configuration dump failed " 781 "during file close (%s)."), filename, 782 strerror(errno)); 783 file_export_error = B_TRUE; 784 break; 785 } 786 787 } 788 789 if (file_export_error) { 790 MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE, 791 strdup(errstr), NULL); 792 (void) unlink(filename); 793 } 794 795 __s_api_release_config(ptr); 796 return (errorp); 797 } 798 799 ns_ldap_error_t * 800 __ns_ldap_DumpConfiguration(char *file) 801 { 802 ns_ldap_error_t *ret; 803 char *files[3]; 804 805 files[0] = NULL; 806 files[1] = NULL; 807 files[2] = NULL; 808 if (strcmp(file, NSCONFIGFILE) == 0) { 809 files[0] = file; 810 } else if (strcmp(file, NSCONFIGREFRESH) == 0) { 811 files[0] = file; 812 } else if (strcmp(file, NSCREDFILE) == 0) { 813 files[1] = file; 814 } else if (strcmp(file, NSCREDREFRESH) == 0) { 815 files[1] = file; 816 } 817 ret = __ns_ldap_DumpConfigFiles(files); 818 return (ret); 819 } 820 821 /* 822 * ************************************************************** 823 * Misc Routines 824 * ************************************************************** 825 */ 826 827 ns_config_t * 828 __ns_ldap_make_config(ns_ldap_result_t *result) 829 { 830 int l, m; 831 char val[BUFSIZ]; 832 char *attrname; 833 ns_ldap_entry_t *entry; 834 ns_ldap_attr_t *attr; 835 char **attrval; 836 ParamIndexType index; 837 ns_config_t *ptr; 838 ns_ldap_error_t *error = NULL; 839 int firsttime; 840 int prof_ver; 841 ns_config_t *curr_ptr = NULL; 842 char errstr[MAXERROR]; 843 ns_ldap_error_t *errorp; 844 845 if (result == NULL) 846 return (NULL); 847 848 if (result->entries_count > 1) { 849 (void) snprintf(errstr, MAXERROR, 850 gettext("Configuration Error: More than one profile " 851 "found")); 852 MKERROR(LOG_ERR, errorp, NS_PARSE_ERR, strdup(errstr), NULL); 853 (void) __ns_ldap_freeError(&errorp); 854 return (NULL); 855 } 856 857 ptr = __s_api_create_config(); 858 if (ptr == NULL) 859 return (NULL); 860 861 curr_ptr = __s_api_get_default_config(); 862 if (curr_ptr == NULL) { 863 __s_api_destroy_config(ptr); 864 return (NULL); 865 } 866 867 /* Check to see if the profile is version 1 or version 2 */ 868 prof_ver = 1; 869 entry = result->entry; 870 for (l = 0; l < entry->attr_count; l++) { 871 attr = entry->attr_pair[l]; 872 873 attrname = attr->attrname; 874 if (attrname == NULL) 875 continue; 876 if (strcasecmp(attrname, "objectclass") == 0) { 877 for (m = 0; m < attr->value_count; m++) { 878 if (strcasecmp(_PROFILE2_OBJECTCLASS, 879 attr->attrvalue[m]) == 0) { 880 prof_ver = 2; 881 break; 882 } 883 } 884 } 885 } 886 /* update the configuration to accept v1 or v2 attributes */ 887 if (prof_ver == 1) { 888 (void) strcpy(val, NS_LDAP_VERSION_1); 889 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P, 890 val, &error); 891 } else { 892 (void) strcpy(val, NS_LDAP_VERSION_2); 893 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P, 894 val, &error); 895 } 896 897 for (l = 0; l < entry->attr_count; l++) { 898 attr = entry->attr_pair[l]; 899 900 attrname = attr->attrname; 901 if (attrname == NULL) 902 continue; 903 if (__s_api_get_profiletype(attrname, &index) != 0) 904 continue; 905 906 attrval = attr->attrvalue; 907 switch (index) { 908 case NS_LDAP_SEARCH_DN_P: 909 case NS_LDAP_SERVICE_SEARCH_DESC_P: 910 case NS_LDAP_ATTRIBUTEMAP_P: 911 case NS_LDAP_OBJECTCLASSMAP_P: 912 case NS_LDAP_SERVICE_CRED_LEVEL_P: 913 case NS_LDAP_SERVICE_AUTH_METHOD_P: 914 /* Multiple Value - insert 1 at a time */ 915 for (m = 0; m < attr->value_count; m++) { 916 (void) __ns_ldap_setParamValue(ptr, index, 917 attrval[m], &error); 918 } 919 break; 920 default: 921 firsttime = 1; 922 /* Single or Multiple Value */ 923 val[0] = '\0'; 924 for (m = 0; m < attr->value_count; m++) { 925 if (firsttime == 1) { 926 firsttime = 0; 927 (void) strlcpy(val, attrval[m], 928 sizeof (val)); 929 } else { 930 (void) strlcat(val, " ", sizeof (val)); 931 (void) strlcat(val, attrval[m], 932 sizeof (val)); 933 } 934 } 935 (void) __ns_ldap_setParamValue(ptr, index, val, &error); 936 937 break; 938 } 939 } 940 if (ptr->version != NS_LDAP_V1) { 941 ParamIndexType i; 942 if (curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_ptype == CHARPTR) { 943 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_BINDDN_P, 944 curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_pc, 945 &error); 946 } 947 if (curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ptype == 948 CHARPTR) { 949 (void) __ns_ldap_setParamValue(ptr, 950 NS_LDAP_BINDPASSWD_P, 951 curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_pc, 952 &error); 953 } 954 i = NS_LDAP_ENABLE_SHADOW_UPDATE_P; 955 if (curr_ptr->paramList[i].ns_ptype == INT) { 956 char *val; 957 val = __s_get_shadowupdate_name( 958 curr_ptr->paramList[i].ns_i); 959 (void) __ns_ldap_setParamValue(ptr, i, val, &error); 960 } 961 if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_ptype == 962 CHARPTR) { 963 (void) __ns_ldap_setParamValue(ptr, 964 NS_LDAP_ADMIN_BINDDN_P, 965 curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_pc, 966 &error); 967 } 968 if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_ptype == 969 CHARPTR) { 970 (void) __ns_ldap_setParamValue(ptr, 971 NS_LDAP_ADMIN_BINDPASSWD_P, 972 curr_ptr-> 973 paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_pc, 974 &error); 975 } 976 if (curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_ptype == 977 CHARPTR) { 978 (void) __ns_ldap_setParamValue(ptr, 979 NS_LDAP_HOST_CERTPATH_P, 980 curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_pc, 981 &error); 982 } 983 } 984 __s_api_release_config(curr_ptr); 985 return (ptr); 986 } 987 988 /* 989 * Download a profile into our internal structure. The calling application 990 * needs to DumpConfig() to save the information to NSCONFIGFILE and NSCREDFILE 991 * if desired. 992 */ 993 int 994 __ns_ldap_download(const char *profile, char *addr, char *baseDN, 995 ns_ldap_error_t **errorp) 996 { 997 char filter[BUFSIZ]; 998 int rc; 999 ns_ldap_result_t *result = NULL; 1000 ns_config_t *ptr = NULL; 1001 ns_config_t *new_ptr = NULL; 1002 char errstr[MAXERROR]; 1003 1004 *errorp = NULL; 1005 if (baseDN == NULL) 1006 return (NS_LDAP_INVALID_PARAM); 1007 1008 ptr = __s_api_get_default_config(); 1009 if (ptr == NULL) { 1010 (void) snprintf(errstr, sizeof (errstr), 1011 gettext("No configuration information available.")); 1012 MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr), 1013 NULL); 1014 return (NS_LDAP_CONFIG); 1015 } 1016 1017 rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SEARCH_BASEDN_P, baseDN, 1018 errorp); 1019 if (rc != NS_LDAP_SUCCESS) { 1020 __s_api_release_config(ptr); 1021 return (rc); 1022 } 1023 1024 rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SERVERS_P, addr, errorp); 1025 __s_api_release_config(ptr); 1026 if (rc != NS_LDAP_SUCCESS) 1027 return (rc); 1028 1029 (void) snprintf(filter, sizeof (filter), _PROFILE_FILTER, 1030 _PROFILE1_OBJECTCLASS, _PROFILE2_OBJECTCLASS, profile); 1031 rc = __ns_ldap_list(_PROFILE_CONTAINER, (const char *)filter, 1032 NULL, NULL, NULL, 0, &result, errorp, NULL, NULL); 1033 1034 if (rc != NS_LDAP_SUCCESS) 1035 return (rc); 1036 1037 new_ptr = __ns_ldap_make_config(result); 1038 (void) __ns_ldap_freeResult(&result); 1039 1040 if (new_ptr == NULL) 1041 return (NS_LDAP_OP_FAILED); 1042 1043 rc = __s_api_crosscheck(new_ptr, errstr, B_FALSE); 1044 if (rc != NS_LDAP_SUCCESS) { 1045 __s_api_destroy_config(new_ptr); 1046 MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr), 1047 NULL); 1048 return (NS_LDAP_CONFIG); 1049 } 1050 1051 __s_api_init_config(new_ptr); 1052 return (rc); 1053 } 1054 1055 /* 1056 * ************************************************************** 1057 * Configuration Printing Routines 1058 * ************************************************************** 1059 */ 1060 1061 /* 1062 * Yes the use of stdio is okay here because all we are doing is sending 1063 * output to stdout. This would not be necessary if we could get to the 1064 * configuration pointer outside this file. 1065 */ 1066 ns_ldap_error_t * 1067 __ns_ldap_print_config(int verbose) 1068 { 1069 ns_config_t *ptr; 1070 char errstr[MAXERROR]; 1071 ns_ldap_error_t *errorp; 1072 char string[BUFSIZE]; 1073 char *str; 1074 int i; 1075 1076 ptr = __s_api_get_default_config(); 1077 if (ptr == NULL) { 1078 errorp = __ns_ldap_LoadConfiguration(); 1079 if (errorp != NULL) 1080 return (errorp); 1081 ptr = __s_api_get_default_config(); 1082 if (ptr == NULL) { 1083 (void) snprintf(errstr, sizeof (errstr), 1084 gettext("No configuration information.")); 1085 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED, 1086 strdup(errstr), NULL); 1087 return (errorp); 1088 } 1089 } 1090 1091 if (verbose && (ptr->domainName != NULL)) { 1092 (void) fputs("ptr->domainName ", stdout); 1093 (void) fputs(ptr->domainName, stdout); 1094 (void) putchar('\n'); 1095 } 1096 /* For each parameter - construct value */ 1097 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) { 1098 /* 1099 * Version 1 skipped this entry because: 1100 * 1101 * don't print default cache TTL for now since 1102 * we don't store it in the ldap_client_file. 1103 */ 1104 if ((i == NS_LDAP_CACHETTL_P) && (ptr->version == NS_LDAP_V1)) 1105 continue; 1106 1107 /* the credential for shadow update is not to be exposed */ 1108 if (i == NS_LDAP_ADMIN_BINDDN_P || 1109 i == NS_LDAP_ADMIN_BINDPASSWD_P) 1110 continue; 1111 1112 str = __s_api_strValue(ptr, string, BUFSIZ, i, NS_FILE_FMT); 1113 if (str == NULL) 1114 continue; 1115 if (verbose) 1116 (void) putchar('\t'); 1117 (void) fprintf(stdout, "%s\n", str); 1118 if (str != (char *)&string[0]) { 1119 free(str); 1120 str = NULL; 1121 } 1122 } 1123 1124 __s_api_release_config(ptr); 1125 return (NULL); 1126 } 1127