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