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