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