1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * kadmin/ldap_util/kdb5_ldap_services.c 10 */ 11 12 /* Copyright (c) 2004-2005, Novell, Inc. 13 * All rights reserved. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions are met: 17 * 18 * * Redistributions of source code must retain the above copyright notice, 19 * this list of conditions and the following disclaimer. 20 * * Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * * The copyright holder's name is not used to endorse or promote products 24 * derived from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Create / Delete / Modify / View / List service objects. 41 */ 42 43 /* 44 * Service objects have rights over realm objects and principals. The following 45 * functions manage the service objects. 46 */ 47 48 #include <stdio.h> 49 #include <k5-int.h> 50 #include <libintl.h> /* Solaris Kerberos */ 51 #include <locale.h> /* Solaris Kerberos */ 52 #include "kdb5_ldap_util.h" 53 #include "kdb5_ldap_list.h" 54 55 #ifdef HAVE_EDIRECTORY 56 57 krb5_error_code 58 rem_service_entry_from_file(int argc, 59 char *argv[], 60 char *file_name, 61 char *service_object); 62 63 extern char *yes; 64 extern krb5_boolean db_inited; 65 66 static int process_host_list(char **host_list, int servicetype) 67 { 68 krb5_error_code retval = 0; 69 char *pchr = NULL; 70 char host_str[MAX_LEN_LIST_ENTRY] = "", proto_str[PROTOCOL_STR_LEN + 1] = "", port_str[PORT_STR_LEN + 1] = ""; 71 int j = 0; 72 73 /* Protocol and port number processing */ 74 for (j = 0; host_list[j]; j++) { 75 /* Look for one hash */ 76 if ((pchr = strchr(host_list[j], HOST_INFO_DELIMITER))) { 77 unsigned int hostname_len = pchr - host_list[j]; 78 79 /* Check input for buffer overflow */ 80 if (hostname_len >= MAX_LEN_LIST_ENTRY) { 81 retval = EINVAL; 82 goto cleanup; 83 } 84 85 /* First copy off the host name portion */ 86 strncpy (host_str, host_list[j], hostname_len); 87 88 /* Parse for the protocol string and translate to number */ 89 strncpy (proto_str, pchr + 1, PROTOCOL_STR_LEN); 90 if (!strcmp(proto_str, "udp")) 91 sprintf (proto_str, "%d", PROTOCOL_NUM_UDP); 92 else if (!strcmp(proto_str, "tcp")) 93 sprintf (proto_str, "%d", PROTOCOL_NUM_TCP); 94 else 95 proto_str[0] = '\0'; /* Make the string null if invalid */ 96 97 /* Look for one more hash */ 98 if ((pchr = strchr(pchr + 1, HOST_INFO_DELIMITER))) { 99 /* Parse for the port string and check if it is numeric */ 100 strncpy (port_str, pchr + 1, PORT_STR_LEN); 101 if (!strtol(port_str, NULL, 10)) /* Not a valid number */ 102 port_str[0] = '\0'; 103 } else 104 port_str[0] = '\0'; 105 } else { /* We have only host name */ 106 strncpy (host_str, host_list[j], MAX_LEN_LIST_ENTRY - 1); 107 proto_str[0] = '\0'; 108 port_str[0] = '\0'; 109 } 110 111 /* Now, based on service type, fill in suitable protocol 112 and port values if they are absent or not matching */ 113 if (servicetype == LDAP_KDC_SERVICE) { 114 if (proto_str[0] == '\0') 115 sprintf (proto_str, "%d", PROTOCOL_DEFAULT_KDC); 116 117 if (port_str[0] == '\0') 118 sprintf (port_str, "%d", PORT_DEFAULT_KDC); 119 } else if (servicetype == LDAP_ADMIN_SERVICE) { 120 if (proto_str[0] == '\0') 121 sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM); 122 else if (strcmp(proto_str, "1")) { 123 sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM); 124 125 /* Print warning message */ 126 printf (gettext("Admin Server supports only TCP protocol, hence setting that\n")); 127 } 128 129 if (port_str[0] == '\0') 130 sprintf (port_str, "%d", PORT_DEFAULT_ADM); 131 } else if (servicetype == LDAP_PASSWD_SERVICE) { 132 if (proto_str[0] == '\0') 133 sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD); 134 else if (strcmp(proto_str, "0")) { 135 sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD); 136 137 /* Print warning message */ 138 printf (gettext("Password Server supports only UDP protocol, hence setting that\n")); 139 } 140 141 if (port_str[0] == '\0') 142 sprintf (port_str, "%d", PORT_DEFAULT_PWD); 143 } 144 145 /* Finally form back the string */ 146 free (host_list[j]); 147 host_list[j] = (char*) malloc(sizeof(char) * 148 (strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1)); 149 if (host_list[j] == NULL) { 150 retval = ENOMEM; 151 goto cleanup; 152 } 153 snprintf (host_list[j], strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1, 154 "%s#%s#%s", host_str, proto_str, port_str); 155 } 156 157 cleanup: 158 return retval; 159 } 160 161 162 /* 163 * Given a realm name, this function will convert it to a DN by appending the 164 * Kerberos container location. 165 */ 166 static krb5_error_code 167 convert_realm_name2dn_list(list, krbcontainer_loc) 168 char **list; 169 const char *krbcontainer_loc; 170 { 171 krb5_error_code retval = 0; 172 char temp_str[MAX_DN_CHARS] = "\0"; 173 char *temp_node = NULL; 174 int i = 0; 175 176 if (list == NULL) { 177 return EINVAL; 178 } 179 180 for (i = 0; (list[i] != NULL) && (i < MAX_LIST_ENTRIES); i++) { 181 /* Restrict copying to max. length to avoid buffer overflow */ 182 snprintf (temp_str, MAX_DN_CHARS, "cn=%s,%s", list[i], krbcontainer_loc); 183 184 /* Make copy of string to temporary node */ 185 temp_node = strdup(temp_str); 186 if (list[i] == NULL) { 187 retval = ENOMEM; 188 goto cleanup; 189 } 190 191 /* On success, free list node and attach new one */ 192 free (list[i]); 193 list[i] = temp_node; 194 temp_node = NULL; 195 } 196 197 cleanup: 198 return retval; 199 } 200 201 202 /* 203 * This function will create a service object on the LDAP Server, with the 204 * specified attributes. 205 */ 206 void kdb5_ldap_create_service(argc, argv) 207 int argc; 208 char *argv[]; 209 { 210 char *me = argv[0]; 211 krb5_error_code retval = 0; 212 krb5_ldap_service_params *srvparams = NULL; 213 krb5_boolean print_usage = FALSE; 214 krb5_boolean no_msg = FALSE; 215 int mask = 0; 216 char **extra_argv = NULL; 217 int extra_argc = 0; 218 int i = 0; 219 krb5_ldap_realm_params *rparams = NULL; 220 int rmask = 0; 221 int rightsmask =0; 222 char **temprdns = NULL; 223 char *realmName = NULL; 224 kdb5_dal_handle *dal_handle = NULL; 225 krb5_ldap_context *ldap_context=NULL; 226 krb5_boolean service_obj_created = FALSE; 227 228 /* Check for number of arguments */ 229 if ((argc < 3) || (argc > 10)) { 230 exit_status++; 231 goto err_usage; 232 } 233 234 /* Allocate memory for service parameters structure */ 235 srvparams = (krb5_ldap_service_params*) calloc(1, sizeof(krb5_ldap_service_params)); 236 if (srvparams == NULL) { 237 retval = ENOMEM; 238 goto cleanup; 239 } 240 241 dal_handle = (kdb5_dal_handle *) util_context->db_context; 242 ldap_context = (krb5_ldap_context *) dal_handle->db_context; 243 244 /* Allocate memory for extra arguments to be used for setting 245 password -- it's OK to allocate as much as the total number 246 of arguments */ 247 extra_argv = (char **) calloc((unsigned int)argc, sizeof(char*)); 248 if (extra_argv == NULL) { 249 retval = ENOMEM; 250 goto cleanup; 251 } 252 253 /* Set first of the extra arguments as the program name */ 254 extra_argv[0] = me; 255 extra_argc++; 256 257 /* Read Kerberos container info, to construct realm DN from name 258 * and for assigning rights 259 */ 260 if ((retval = krb5_ldap_read_krbcontainer_params(util_context, 261 &(ldap_context->krbcontainer)))) { 262 com_err(me, retval, gettext("while reading Kerberos container information")); 263 goto cleanup; 264 } 265 266 /* Parse all arguments */ 267 for (i = 1; i < argc; i++) { 268 if (!strcmp(argv[i], "-kdc")) { 269 srvparams->servicetype = LDAP_KDC_SERVICE; 270 } else if (!strcmp(argv[i], "-admin")) { 271 srvparams->servicetype = LDAP_ADMIN_SERVICE; 272 } else if (!strcmp(argv[i], "-pwd")) { 273 srvparams->servicetype = LDAP_PASSWD_SERVICE; 274 } else if (!strcmp(argv[i], "-servicehost")) { 275 if (++i > argc - 1) 276 goto err_usage; 277 278 srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES, 279 sizeof(char *)); 280 if (srvparams->krbhostservers == NULL) { 281 retval = ENOMEM; 282 goto cleanup; 283 } 284 285 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, 286 srvparams->krbhostservers))) { 287 goto cleanup; 288 } 289 290 if ((retval = process_host_list (srvparams->krbhostservers, 291 srvparams->servicetype))) { 292 goto cleanup; 293 } 294 295 mask |= LDAP_SERVICE_HOSTSERVER; 296 } else if (!strcmp(argv[i], "-realm")) { 297 if (++i > argc - 1) 298 goto err_usage; 299 300 srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES, 301 sizeof(char *)); 302 if (srvparams->krbrealmreferences == NULL) { 303 retval = ENOMEM; 304 goto cleanup; 305 } 306 307 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, 308 srvparams->krbrealmreferences))) { 309 goto cleanup; 310 } 311 312 /* Convert realm names to realm DNs */ 313 if ((retval = convert_realm_name2dn_list( 314 srvparams->krbrealmreferences, 315 ldap_context->krbcontainer->DN))) { 316 goto cleanup; 317 } 318 319 mask |= LDAP_SERVICE_REALMREFERENCE; 320 } 321 /* If argument is none of the above and beginning with '-', 322 * it must be related to password -- collect it 323 * to pass onto kdb5_ldap_set_service_password() 324 */ 325 else if (*(argv[i]) == '-') { 326 /* Checking for options of setting the password for the 327 * service (by using 'setsrvpw') is not modular. --need to 328 * have a common function that can be shared with 'setsrvpw' 329 */ 330 if (!strcmp(argv[i], "-randpw")) { 331 extra_argv[extra_argc] = argv[i]; 332 extra_argc++; 333 } else if (!strcmp(argv[i], "-fileonly")) { 334 extra_argv[extra_argc] = argv[i]; 335 extra_argc++; 336 } 337 /* For '-f' option alone, pick up the following argument too */ 338 else if (!strcmp(argv[i], "-f")) { 339 extra_argv[extra_argc] = argv[i]; 340 extra_argc++; 341 342 if (++i > argc - 1) 343 goto err_usage; 344 345 extra_argv[extra_argc] = argv[i]; 346 extra_argc++; 347 } else { /* Any other option is invalid */ 348 exit_status++; 349 goto err_usage; 350 } 351 } else { /* Any other argument must be service DN */ 352 /* First check if service DN is already provided -- 353 * if so, there's a usage error 354 */ 355 if (srvparams->servicedn != NULL) { 356 com_err(me, EINVAL, gettext("while creating service object")); 357 goto err_usage; 358 } 359 360 /* If not present already, fill up service DN */ 361 srvparams->servicedn = strdup(argv[i]); 362 if (srvparams->servicedn == NULL) { 363 com_err(me, ENOMEM, gettext("while creating service object")); 364 goto err_nomsg; 365 } 366 } 367 } 368 369 /* No point in proceeding further if service DN value is not available */ 370 if (srvparams->servicedn == NULL) { 371 com_err(me, EINVAL, gettext("while creating service object")); 372 goto err_usage; 373 } 374 375 if (srvparams->servicetype == 0) { /* Not provided and hence not set */ 376 com_err(me, EINVAL, gettext("while creating service object")); 377 goto err_usage; 378 } 379 380 /* Create object with all attributes provided */ 381 if ((retval = krb5_ldap_create_service(util_context, srvparams, mask))) 382 goto cleanup; 383 384 service_obj_created = TRUE; 385 386 /* ** NOTE ** srvparams structure should not be modified, as it is 387 * used for deletion of the service object in case of any failures 388 * from now on. 389 */ 390 391 /* Set password too */ 392 if (extra_argc >= 1) { 393 /* Set service DN as the last argument */ 394 extra_argv[extra_argc] = strdup(srvparams->servicedn); 395 if (extra_argv[extra_argc] == NULL) { 396 retval = ENOMEM; 397 goto cleanup; 398 } 399 extra_argc++; 400 401 if ((retval = kdb5_ldap_set_service_password(extra_argc, extra_argv)) != 0) { 402 goto err_nomsg; 403 } 404 } 405 /* Rights assignment */ 406 if (mask & LDAP_SERVICE_REALMREFERENCE) { 407 408 printf("%s", gettext("Changing rights for the service object. Please wait ... ")); 409 fflush(stdout); 410 411 rightsmask =0; 412 rightsmask |= LDAP_REALM_RIGHTS; 413 rightsmask |= LDAP_SUBTREE_RIGHTS; 414 415 if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) { 416 for (i=0; (srvparams->krbrealmreferences[i] != NULL); i++) { 417 418 /* Get the realm name, not the dn */ 419 temprdns = ldap_explode_dn(srvparams->krbrealmreferences[i], 1); 420 421 if (temprdns[0] == NULL) { 422 retval = EINVAL; 423 goto cleanup; 424 } 425 426 realmName = strdup(temprdns[0]); 427 if (realmName == NULL) { 428 retval = ENOMEM; 429 goto cleanup; 430 } 431 432 if ((retval = krb5_ldap_read_realm_params(util_context, 433 realmName, &rparams, &rmask))) { 434 com_err(me, retval, gettext("while reading information of realm '%s'"), 435 realmName); 436 goto cleanup; 437 } 438 439 if ((retval = krb5_ldap_add_service_rights(util_context, 440 srvparams->servicetype, srvparams->servicedn, 441 realmName, rparams->subtree, rightsmask))) { 442 printf(gettext("failed\n")); 443 com_err(me, retval, gettext("while assigning rights '%s'"), 444 srvparams->servicedn); 445 goto cleanup; 446 } 447 448 if (rparams) 449 krb5_ldap_free_realm_params(rparams); 450 } 451 } 452 printf(gettext("done\n")); 453 } 454 goto cleanup; 455 456 err_usage: 457 print_usage = TRUE; 458 459 err_nomsg: 460 no_msg = TRUE; 461 462 cleanup: 463 464 if ((retval != 0) && (service_obj_created == TRUE)) { 465 /* This is for deleting the service object if something goes 466 * wrong in creating the service object 467 */ 468 469 /* srvparams is populated from the user input and should be correct as 470 * we were successful in creating a service object. Reusing the same 471 */ 472 krb5_ldap_delete_service(util_context, srvparams, srvparams->servicedn); 473 } 474 475 /* Clean-up structure */ 476 krb5_ldap_free_service (util_context, srvparams); 477 478 if (extra_argv) { 479 free (extra_argv); 480 extra_argv = NULL; 481 } 482 if (realmName) { 483 free(realmName); 484 realmName = NULL; 485 } 486 if (print_usage) 487 db_usage (CREATE_SERVICE); 488 489 if (retval) { 490 if (!no_msg) 491 com_err(me, retval, gettext("while creating service object")); 492 493 exit_status++; 494 } 495 496 return; 497 } 498 499 500 /* 501 * This function will modify the attributes of a given service 502 * object on the LDAP Server 503 */ 504 void kdb5_ldap_modify_service(argc, argv) 505 int argc; 506 char *argv[]; 507 { 508 char *me = argv[0]; 509 krb5_error_code retval = 0; 510 krb5_ldap_service_params *srvparams = NULL; 511 krb5_boolean print_usage = FALSE; 512 krb5_boolean no_msg = FALSE; 513 char *servicedn = NULL; 514 int i = 0; 515 int in_mask = 0, out_mask = 0; 516 int srvhost_flag = 0, realmdn_flag = 0; 517 char **list = NULL; 518 int existing_entries = 0, new_entries = 0; 519 char **temp_ptr = NULL; 520 krb5_ldap_realm_params *rparams = NULL; 521 int j = 0; 522 int rmask = 0; 523 int rightsmask =0; 524 char **oldrealmrefs = NULL; 525 char **newrealmrefs = NULL; 526 char **temprdns = NULL; 527 char *realmName = NULL; 528 kdb5_dal_handle *dal_handle = NULL; 529 krb5_ldap_context *ldap_context=NULL; 530 531 /* Check for number of arguments */ 532 if ((argc < 3) || (argc > 10)) { 533 exit_status++; 534 goto err_usage; 535 } 536 537 dal_handle = (kdb5_dal_handle *) util_context->db_context; 538 ldap_context = (krb5_ldap_context *) dal_handle->db_context; 539 540 /* Parse all arguments, only to pick up service DN (Pass 1) */ 541 for (i = 1; i < argc; i++) { 542 /* Skip arguments next to 'servicehost' 543 and 'realmdn' arguments */ 544 if (!strcmp(argv[i], "-servicehost")) { 545 ++i; 546 } else if (!strcmp(argv[i], "-clearservicehost")) { 547 ++i; 548 } else if (!strcmp(argv[i], "-addservicehost")) { 549 ++i; 550 } else if (!strcmp(argv[i], "-realm")) { 551 ++i; 552 } else if (!strcmp(argv[i], "-clearrealm")) { 553 ++i; 554 } else if (!strcmp(argv[i], "-addrealm")) { 555 ++i; 556 } else { /* Any other argument must be service DN */ 557 /* First check if service DN is already provided -- 558 if so, there's a usage error */ 559 if (servicedn != NULL) { 560 com_err(me, EINVAL, gettext("while modifying service object")); 561 goto err_usage; 562 } 563 564 /* If not present already, fill up service DN */ 565 servicedn = strdup(argv[i]); 566 if (servicedn == NULL) { 567 com_err(me, ENOMEM, gettext("while modifying service object")); 568 goto err_nomsg; 569 } 570 } 571 } 572 573 /* No point in proceeding further if service DN value is not available */ 574 if (servicedn == NULL) { 575 com_err(me, EINVAL, gettext("while modifying service object")); 576 goto err_usage; 577 } 578 579 retval = krb5_ldap_read_service(util_context, servicedn, &srvparams, &in_mask); 580 if (retval) { 581 com_err(argv[0], retval, gettext("while reading information of service '%s'"), 582 servicedn); 583 goto err_nomsg; 584 } 585 586 /* Read Kerberos container info, to construct realm DN from name 587 * and for assigning rights 588 */ 589 if ((retval = krb5_ldap_read_krbcontainer_params(util_context, 590 &(ldap_context->krbcontainer)))) { 591 com_err(me, retval, gettext("while reading Kerberos container information")); 592 goto cleanup; 593 } 594 595 /* Parse all arguments, but skip the service DN (Pass 2) */ 596 for (i = 1; i < argc; i++) { 597 if (!strcmp(argv[i], "-servicehost")) { 598 if (++i > argc - 1) 599 goto err_usage; 600 601 /* Free the old list if available */ 602 if (srvparams->krbhostservers) { 603 krb5_free_list_entries (srvparams->krbhostservers); 604 free (srvparams->krbhostservers); 605 } 606 607 srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES, 608 sizeof(char *)); 609 if (srvparams->krbhostservers == NULL) { 610 retval = ENOMEM; 611 goto cleanup; 612 } 613 614 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, 615 srvparams->krbhostservers))) { 616 goto cleanup; 617 } 618 619 if ((retval = process_host_list (srvparams->krbhostservers, 620 srvparams->servicetype))) { 621 goto cleanup; 622 } 623 624 out_mask |= LDAP_SERVICE_HOSTSERVER; 625 626 /* Set flag to ignore 'add' and 'clear' */ 627 srvhost_flag = 1; 628 } else if (!strcmp(argv[i], "-clearservicehost")) { 629 if (++i > argc - 1) 630 goto err_usage; 631 632 if (!srvhost_flag) { 633 /* If attribute doesn't exist, don't permit 'clear' option */ 634 if ((in_mask & LDAP_SERVICE_HOSTSERVER) == 0) { 635 /* Send out some proper error message here */ 636 com_err(me, EINVAL, gettext("service host list is empty\n")); 637 goto err_nomsg; 638 } 639 640 /* Allocate list for processing */ 641 list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 642 if (list == NULL) { 643 retval = ENOMEM; 644 goto cleanup; 645 } 646 647 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) 648 goto cleanup; 649 650 if ((retval = process_host_list (list, srvparams->servicetype))) { 651 goto cleanup; 652 } 653 654 list_modify_str_array(&(srvparams->krbhostservers), 655 (const char**)list, LIST_MODE_DELETE); 656 657 out_mask |= LDAP_SERVICE_HOSTSERVER; 658 659 /* Clean up */ 660 free (list); 661 list = NULL; 662 } 663 } else if (!strcmp(argv[i], "-addservicehost")) { 664 if (++i > argc - 1) 665 goto err_usage; 666 667 if (!srvhost_flag) { 668 /* Allocate list for processing */ 669 list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 670 if (list == NULL) { 671 retval = ENOMEM; 672 goto cleanup; 673 } 674 675 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) 676 goto cleanup; 677 678 if ((retval = process_host_list (list, srvparams->servicetype))) { 679 goto cleanup; 680 } 681 682 /* Call list_modify_str_array() only if host server attribute 683 * exists already --Actually, it's better to handle this 684 * within list_modify_str_array() 685 */ 686 if (in_mask & LDAP_SERVICE_HOSTSERVER) { 687 /* Re-size existing list */ 688 existing_entries = list_count_str_array(srvparams->krbhostservers); 689 new_entries = list_count_str_array(list); 690 temp_ptr = (char **) realloc(srvparams->krbhostservers, 691 sizeof(char *) * (existing_entries + new_entries + 1)); 692 if (temp_ptr == NULL) { 693 retval = ENOMEM; 694 goto cleanup; 695 } 696 srvparams->krbhostservers = temp_ptr; 697 698 list_modify_str_array(&(srvparams->krbhostservers), 699 (const char**)list, LIST_MODE_ADD); 700 701 /* Clean up */ 702 free (list); 703 list = NULL; 704 } else 705 srvparams->krbhostservers = list; 706 707 out_mask |= LDAP_SERVICE_HOSTSERVER; 708 } 709 } else if (!strcmp(argv[i], "-realm")) { 710 if (++i > argc - 1) 711 goto err_usage; 712 713 if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences)) { 714 if (!oldrealmrefs) { 715 /* Store the old realm list for removing rights */ 716 oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 717 if (oldrealmrefs == NULL) { 718 retval = ENOMEM; 719 goto cleanup; 720 } 721 722 for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) { 723 oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]); 724 if (oldrealmrefs[j] == NULL) { 725 retval = ENOMEM; 726 goto cleanup; 727 } 728 } 729 oldrealmrefs[j] = NULL; 730 } 731 732 /* Free the old list if available */ 733 krb5_free_list_entries (srvparams->krbrealmreferences); 734 free (srvparams->krbrealmreferences); 735 } 736 737 srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES, 738 sizeof(char *)); 739 if (srvparams->krbrealmreferences == NULL) { 740 retval = ENOMEM; 741 goto cleanup; 742 } 743 744 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, 745 srvparams->krbrealmreferences))) { 746 goto cleanup; 747 } 748 749 /* Convert realm names to realm DNs */ 750 if ((retval = convert_realm_name2dn_list( 751 srvparams->krbrealmreferences, 752 ldap_context->krbcontainer->DN))) { 753 goto cleanup; 754 } 755 756 out_mask |= LDAP_SERVICE_REALMREFERENCE; 757 758 /* Set flag to ignore 'add' and 'clear' */ 759 realmdn_flag = 1; 760 } else if (!strcmp(argv[i], "-clearrealm")) { 761 if (++i > argc - 1) 762 goto err_usage; 763 764 if (!realmdn_flag) { 765 /* If attribute doesn't exist, don't permit 'clear' option */ 766 if (((in_mask & LDAP_SERVICE_REALMREFERENCE) == 0) || (srvparams->krbrealmreferences == NULL)) { 767 /* Send out some proper error message here */ 768 goto err_nomsg; 769 } 770 771 if (!oldrealmrefs) { 772 /* Store the old realm list for removing rights */ 773 oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 774 if (oldrealmrefs == NULL) { 775 retval = ENOMEM; 776 goto cleanup; 777 } 778 779 for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) { 780 oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]); 781 if (oldrealmrefs[j] == NULL) { 782 retval = ENOMEM; 783 goto cleanup; 784 } 785 } 786 oldrealmrefs[j] = NULL; 787 } 788 789 /* Allocate list for processing */ 790 list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 791 if (list == NULL) { 792 retval = ENOMEM; 793 goto cleanup; 794 } 795 796 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) 797 goto cleanup; 798 799 /* Convert realm names to realm DNs */ 800 if ((retval = convert_realm_name2dn_list(list, 801 ldap_context->krbcontainer->DN))) { 802 goto cleanup; 803 } 804 805 list_modify_str_array(&(srvparams->krbrealmreferences), 806 (const char**)list, LIST_MODE_DELETE); 807 808 out_mask |= LDAP_SERVICE_REALMREFERENCE; 809 810 /* Clean up */ 811 free (list); 812 list = NULL; 813 } 814 } else if (!strcmp(argv[i], "-addrealm")) { 815 if (++i > argc - 1) 816 goto err_usage; 817 818 if (!realmdn_flag) { 819 /* Allocate list for processing */ 820 list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 821 if (list == NULL) { 822 retval = ENOMEM; 823 goto cleanup; 824 } 825 826 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) 827 goto cleanup; 828 829 /* Convert realm names to realm DNs */ 830 if ((retval = convert_realm_name2dn_list(list, 831 ldap_context->krbcontainer->DN))) { 832 goto cleanup; 833 } 834 835 if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences) && (!oldrealmrefs)) { 836 /* Store the old realm list for removing rights */ 837 oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 838 if (oldrealmrefs == NULL) { 839 retval = ENOMEM; 840 goto cleanup; 841 } 842 843 for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) { 844 oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]); 845 if (oldrealmrefs[j] == NULL) { 846 retval = ENOMEM; 847 goto cleanup; 848 } 849 } 850 oldrealmrefs[j] = NULL; 851 } 852 853 /* Call list_modify_str_array() only if realm DN attribute 854 * exists already -- Actually, it's better to handle this 855 * within list_modify_str_array() */ 856 if (in_mask & LDAP_SERVICE_REALMREFERENCE) { 857 /* Re-size existing list */ 858 existing_entries = list_count_str_array( 859 srvparams->krbrealmreferences); 860 new_entries = list_count_str_array(list); 861 temp_ptr = (char **) realloc(srvparams->krbrealmreferences, 862 sizeof(char *) * (existing_entries + new_entries + 1)); 863 if (temp_ptr == NULL) { 864 retval = ENOMEM; 865 goto cleanup; 866 } 867 srvparams->krbrealmreferences = temp_ptr; 868 869 list_modify_str_array(&(srvparams->krbrealmreferences), 870 (const char**)list, LIST_MODE_ADD); 871 872 /* Clean up */ 873 free (list); 874 list = NULL; 875 } else 876 srvparams->krbrealmreferences = list; 877 878 out_mask |= LDAP_SERVICE_REALMREFERENCE; 879 } 880 } else { 881 /* Any other argument must be service DN 882 -- skip it */ 883 } 884 } 885 886 /* Modify attributes of object */ 887 if ((retval = krb5_ldap_modify_service(util_context, srvparams, out_mask))) 888 goto cleanup; 889 890 /* Service rights modification code */ 891 if (out_mask & LDAP_SERVICE_REALMREFERENCE) { 892 893 printf("%s", gettext("Changing rights for the service object. Please wait ... ")); 894 fflush(stdout); 895 896 newrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 897 if (newrealmrefs == NULL) { 898 retval = ENOMEM; 899 goto cleanup; 900 } 901 902 if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) { 903 for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) { 904 newrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]); 905 if (newrealmrefs[j] == NULL) { 906 retval = ENOMEM; 907 goto cleanup; 908 } 909 } 910 newrealmrefs[j] = NULL; 911 } 912 disjoint_members(oldrealmrefs, newrealmrefs); 913 914 /* Delete the rights for the given service, on each of the realm 915 * container & subtree in the old realm reference list. 916 */ 917 if (oldrealmrefs) { 918 rightsmask = 0; 919 rightsmask |= LDAP_REALM_RIGHTS; 920 rightsmask |= LDAP_SUBTREE_RIGHTS; 921 922 for (i = 0; (oldrealmrefs[i] != NULL); i++) { 923 /* Get the realm name, not the dn */ 924 temprdns = ldap_explode_dn(oldrealmrefs[i], 1); 925 926 if (temprdns[0] == NULL) { 927 retval = EINVAL; 928 goto cleanup; 929 } 930 931 realmName = strdup(temprdns[0]); 932 if (realmName == NULL) { 933 retval = ENOMEM; 934 goto cleanup; 935 } 936 937 if ((retval = krb5_ldap_read_realm_params(util_context, 938 realmName, &rparams, &rmask))) { 939 com_err(me, retval, gettext("while reading information of realm '%s'"), 940 realmName); 941 goto err_nomsg; 942 } 943 944 if ((retval = krb5_ldap_delete_service_rights(util_context, 945 srvparams->servicetype, srvparams->servicedn, 946 realmName, rparams->subtree, rightsmask))) { 947 printf(gettext("failed\n")); 948 com_err(me, retval, gettext("while assigning rights '%s'"), 949 srvparams->servicedn); 950 goto err_nomsg; 951 } 952 953 if (rparams) 954 krb5_ldap_free_realm_params(rparams); 955 } 956 } 957 958 /* Add the rights for the given service, on each of the realm 959 * container & subtree in the new realm reference list. 960 */ 961 if (newrealmrefs) { 962 rightsmask = 0; 963 rightsmask |= LDAP_REALM_RIGHTS; 964 rightsmask |= LDAP_SUBTREE_RIGHTS; 965 966 for (i = 0; (newrealmrefs[i] != NULL); i++) { 967 /* Get the realm name, not the dn */ 968 temprdns = ldap_explode_dn(newrealmrefs[i], 1); 969 970 if (temprdns[0] == NULL) { 971 retval = EINVAL; 972 goto cleanup; 973 } 974 975 realmName = strdup(temprdns[0]); 976 if (realmName == NULL) { 977 retval = ENOMEM; 978 goto cleanup; 979 } 980 981 if ((retval = krb5_ldap_read_krbcontainer_params(util_context, 982 &(ldap_context->krbcontainer)))) { 983 com_err(me, retval, 984 gettext("while reading Kerberos container information")); 985 goto cleanup; 986 } 987 988 if ((retval = krb5_ldap_read_realm_params(util_context, 989 realmName, &rparams, &rmask))) { 990 com_err(me, retval, gettext("while reading information of realm '%s'"), 991 realmName); 992 goto err_nomsg; 993 } 994 995 if ((retval = krb5_ldap_add_service_rights(util_context, 996 srvparams->servicetype, srvparams->servicedn, 997 realmName, rparams->subtree, rightsmask))) { 998 printf(gettext("failed\n")); 999 com_err(me, retval, gettext("while assigning rights '%s'"), 1000 srvparams->servicedn); 1001 goto err_nomsg; 1002 } 1003 1004 if (rparams) { 1005 krb5_ldap_free_realm_params(rparams); 1006 rparams = NULL; 1007 } 1008 } 1009 printf(gettext("done\n")); 1010 } 1011 } 1012 goto cleanup; 1013 1014 err_usage: 1015 print_usage = TRUE; 1016 1017 err_nomsg: 1018 no_msg = TRUE; 1019 1020 cleanup: 1021 /* Clean-up structure */ 1022 krb5_ldap_free_service(util_context, srvparams); 1023 1024 if (servicedn) 1025 free(servicedn); 1026 1027 if (list) { 1028 free(list); 1029 list = NULL; 1030 } 1031 1032 if (oldrealmrefs) { 1033 for (i = 0; oldrealmrefs[i] != NULL; i++) 1034 free(oldrealmrefs[i]); 1035 free(oldrealmrefs); 1036 } 1037 1038 if (newrealmrefs) { 1039 for (i = 0; newrealmrefs[i] != NULL; i++) 1040 free(newrealmrefs[i]); 1041 free(newrealmrefs); 1042 } 1043 if (realmName) { 1044 free(realmName); 1045 realmName = NULL; 1046 } 1047 1048 if (print_usage) 1049 db_usage(MODIFY_SERVICE); 1050 1051 if (retval) { 1052 if (!no_msg) 1053 com_err(me, retval, gettext("while modifying service object")); 1054 exit_status++; 1055 } 1056 1057 return; 1058 } 1059 1060 1061 /* 1062 * This function will delete the entry corresponding to the service object 1063 * from the service password file. 1064 */ 1065 static krb5_error_code 1066 rem_service_entry_from_file(argc, argv, file_name, service_object) 1067 int argc; 1068 char *argv[]; 1069 char *file_name; 1070 char *service_object; 1071 { 1072 int st = EINVAL; 1073 char *me = argv[0]; 1074 char *tmp_file = NULL; 1075 int tmpfd = -1; 1076 FILE *pfile = NULL; 1077 unsigned int len = 0; 1078 char line[MAX_LEN]={0}; 1079 mode_t omask = umask(077); 1080 1081 /* Check for permissions on the password file */ 1082 if (access(file_name, W_OK) == -1) { 1083 /* If the specified file itself is not there, no need to show error */ 1084 if (errno == ENOENT) { 1085 st=0; 1086 goto cleanup; 1087 } else { 1088 com_err(me, errno, gettext("while deleting entry from file %s", file_name)); 1089 goto cleanup; 1090 } 1091 } 1092 1093 /* Create a temporary file which contains all the entries except the 1094 entry for the given service dn */ 1095 pfile = fopen(file_name, "r+F"); 1096 if (pfile == NULL) { 1097 com_err(me, errno, gettext("while deleting entry from file %s"), file_name); 1098 goto cleanup; 1099 } 1100 1101 /* Create a new file with the extension .tmp */ 1102 tmp_file = (char *)malloc(strlen(file_name) + 4 + 1); 1103 if (tmp_file == NULL) { 1104 com_err(me, ENOMEM, gettext("while deleting entry from file")); 1105 fclose(pfile); 1106 goto cleanup; 1107 } 1108 snprintf (tmp_file, strlen(file_name) + 4 + 1, "%s%s", file_name, ".tmp"); 1109 1110 1111 tmpfd = creat(tmp_file, S_IRUSR|S_IWUSR); 1112 umask(omask); 1113 if (tmpfd == -1) { 1114 com_err(me, errno, gettext("while deleting entry from file\n")); 1115 fclose(pfile); 1116 goto cleanup; 1117 } 1118 1119 /* Copy only those lines which donot have the specified service dn */ 1120 while (fgets(line, MAX_LEN, pfile) != NULL) { 1121 if ((strstr(line, service_object) != NULL) && 1122 (line[strlen(service_object)] == '#')) { 1123 continue; 1124 } else { 1125 len = strlen(line); 1126 if (write(tmpfd, line, len) != len) { 1127 com_err(me, errno, gettext("while deleting entry from file\n")); 1128 close(tmpfd); 1129 unlink(tmp_file); 1130 fclose(pfile); 1131 goto cleanup; 1132 } 1133 } 1134 } 1135 1136 fclose(pfile); 1137 if (unlink(file_name) == 0) { 1138 link(tmp_file, file_name); 1139 } else { 1140 com_err(me, errno, gettext("while deleting entry from file\n")); 1141 } 1142 unlink(tmp_file); 1143 1144 st=0; 1145 1146 cleanup: 1147 1148 if (tmp_file) 1149 free(tmp_file); 1150 1151 return st; 1152 } 1153 1154 1155 /* 1156 * This function will delete the service object from the LDAP Server 1157 * and unlink the references to the Realm objects (if any) 1158 */ 1159 void 1160 kdb5_ldap_destroy_service(argc, argv) 1161 int argc; 1162 char *argv[]; 1163 { 1164 int i = 0; 1165 char buf[5] = {0}; 1166 krb5_error_code retval = EINVAL; 1167 int force = 0; 1168 char *servicedn = NULL; 1169 char *stashfilename = NULL; 1170 int mask = 0; 1171 krb5_ldap_service_params *lserparams = NULL; 1172 krb5_boolean print_usage = FALSE; 1173 1174 if ((argc < 2) || (argc > 5)) { 1175 exit_status++; 1176 goto err_usage; 1177 } 1178 1179 for (i=1; i < argc; i++) { 1180 1181 if (strcmp(argv[i],"-force")==0) { 1182 force++; 1183 } else if (strcmp(argv[i],"-f")==0) { 1184 if (argv[i+1]) { 1185 stashfilename=strdup(argv[i+1]); 1186 if (stashfilename == NULL) { 1187 com_err(argv[0], ENOMEM, gettext("while destroying service")); 1188 exit_status++; 1189 goto cleanup; 1190 } 1191 i++; 1192 } else { 1193 exit_status++; 1194 goto err_usage; 1195 } 1196 } else { 1197 if ((argv[i]) && (servicedn == NULL)) { 1198 servicedn=strdup(argv[i]); 1199 if (servicedn == NULL) { 1200 com_err(argv[0], ENOMEM, gettext("while destroying service")); 1201 exit_status++; 1202 goto cleanup; 1203 } 1204 } else { 1205 exit_status++; 1206 goto err_usage; 1207 } 1208 } 1209 } 1210 1211 if (!servicedn) { 1212 exit_status++; 1213 goto err_usage; 1214 } 1215 1216 if (!force) { 1217 printf(gettext("This will delete the service object '%s', are you sure?\n"), servicedn); 1218 printf(gettext("(type 'yes' to confirm)? ")); 1219 if (fgets(buf, sizeof(buf), stdin) == NULL) { 1220 exit_status++; 1221 goto cleanup;; 1222 } 1223 if (strcmp(buf, yes)) { 1224 exit_status++; 1225 goto cleanup; 1226 } 1227 } 1228 1229 if ((retval = krb5_ldap_read_service(util_context, servicedn, 1230 &lserparams, &mask))) { 1231 com_err(argv[0], retval, gettext("while destroying service '%s'"), servicedn); 1232 exit_status++; 1233 goto cleanup; 1234 } 1235 1236 retval = krb5_ldap_delete_service(util_context, lserparams, servicedn); 1237 1238 if (retval) { 1239 com_err(argv[0], retval, gettext("while destroying service '%s'"), servicedn); 1240 exit_status++; 1241 goto cleanup; 1242 } 1243 1244 if (stashfilename == NULL) { 1245 stashfilename = strdup(DEF_SERVICE_PASSWD_FILE); 1246 if (stashfilename == NULL) { 1247 com_err(argv[0], ENOMEM, gettext("while destroying service")); 1248 exit_status++; 1249 goto cleanup; 1250 } 1251 } 1252 printf(gettext("** service object '%s' deleted.\n"), servicedn); 1253 retval = rem_service_entry_from_file(argc, argv, stashfilename, servicedn); 1254 1255 if (retval) 1256 printf(gettext("** error removing service object entry '%s' from password file.\n"), 1257 servicedn); 1258 1259 goto cleanup; 1260 1261 1262 err_usage: 1263 print_usage = TRUE; 1264 1265 cleanup: 1266 1267 if (lserparams) { 1268 krb5_ldap_free_service(util_context, lserparams); 1269 } 1270 1271 if (servicedn) { 1272 free(servicedn); 1273 } 1274 1275 if (stashfilename) { 1276 free(stashfilename); 1277 } 1278 1279 if (print_usage) { 1280 db_usage(DESTROY_SERVICE); 1281 } 1282 1283 return; 1284 } 1285 1286 1287 /* 1288 * This function will display information about the given service object 1289 */ 1290 void kdb5_ldap_view_service(argc, argv) 1291 int argc; 1292 char *argv[]; 1293 { 1294 krb5_ldap_service_params *lserparams = NULL; 1295 krb5_error_code retval = 0; 1296 char *servicedn = NULL; 1297 int mask = 0; 1298 krb5_boolean print_usage = FALSE; 1299 1300 if (!(argc == 2)) { 1301 exit_status++; 1302 goto err_usage; 1303 } 1304 1305 servicedn=strdup(argv[1]); 1306 if (servicedn == NULL) { 1307 com_err(argv[0], ENOMEM, gettext("while viewing service")); 1308 exit_status++; 1309 goto cleanup; 1310 } 1311 1312 if ((retval = krb5_ldap_read_service(util_context, servicedn, &lserparams, &mask))) { 1313 com_err(argv[0], retval, gettext("while viewing service '%s'"), servicedn); 1314 exit_status++; 1315 goto cleanup; 1316 } 1317 1318 print_service_params(lserparams, mask); 1319 1320 goto cleanup; 1321 1322 err_usage: 1323 print_usage = TRUE; 1324 1325 cleanup: 1326 1327 if (lserparams) { 1328 krb5_ldap_free_service(util_context, lserparams); 1329 } 1330 1331 if (servicedn) 1332 free(servicedn); 1333 1334 if (print_usage) { 1335 db_usage(VIEW_SERVICE); 1336 } 1337 1338 return; 1339 } 1340 1341 1342 /* 1343 * This function will list the DNs of kerberos services present on 1344 * the LDAP Server under a specific sub-tree (entire tree by default) 1345 */ 1346 void kdb5_ldap_list_services(argc, argv) 1347 int argc; 1348 char *argv[]; 1349 { 1350 char *me = argv[0]; 1351 krb5_error_code retval = 0; 1352 char *basedn = NULL; 1353 char **list = NULL; 1354 char **plist = NULL; 1355 krb5_boolean print_usage = FALSE; 1356 1357 /* Check for number of arguments */ 1358 if ((argc != 1) && (argc != 3)) { 1359 exit_status++; 1360 goto err_usage; 1361 } 1362 1363 /* Parse base DN argument if present */ 1364 if (argc == 3) { 1365 if (strcmp(argv[1], "-basedn")) { 1366 retval = EINVAL; 1367 goto err_usage; 1368 } 1369 1370 basedn = strdup(argv[2]); 1371 if (basedn == NULL) { 1372 com_err(me, ENOMEM, gettext("while listing services")); 1373 exit_status++; 1374 goto cleanup; 1375 } 1376 } 1377 1378 retval = krb5_ldap_list_services(util_context, basedn, &list); 1379 if ((retval != 0) || (list == NULL)) { 1380 exit_status++; 1381 goto cleanup; 1382 } 1383 1384 for (plist = list; *plist != NULL; plist++) { 1385 printf("%s\n", *plist); 1386 } 1387 1388 goto cleanup; 1389 1390 err_usage: 1391 print_usage = TRUE; 1392 1393 cleanup: 1394 if (list != NULL) { 1395 krb5_free_list_entries (list); 1396 free (list); 1397 } 1398 1399 if (basedn) 1400 free (basedn); 1401 1402 if (print_usage) { 1403 db_usage(LIST_SERVICE); 1404 } 1405 1406 if (retval) { 1407 com_err(me, retval, gettext("while listing policy objects")); 1408 exit_status++; 1409 } 1410 1411 return; 1412 } 1413 1414 1415 /* 1416 * This function will print the service object information 1417 * to the standard output 1418 */ 1419 static void 1420 print_service_params(lserparams, mask) 1421 krb5_ldap_service_params *lserparams; 1422 int mask; 1423 { 1424 int i=0; 1425 1426 /* Print the service dn */ 1427 printf("%20s%-20s\n", gettext("Service dn: "), lserparams->servicedn); 1428 1429 /* Print the service type of the object to be read */ 1430 if (lserparams->servicetype == LDAP_KDC_SERVICE) { 1431 printf("%20s%-20s\n", gettext("Service type: "), "kdc"); 1432 } else if (lserparams->servicetype == LDAP_ADMIN_SERVICE) { 1433 printf("%20s%-20s\n", gettext("Service type: "), "admin"); 1434 } else if (lserparams->servicetype == LDAP_PASSWD_SERVICE) { 1435 printf("%20s%-20s\n", gettext("Service type: "), "pwd"); 1436 } 1437 1438 /* Print the host server values */ 1439 printf("%20s\n", gettext("Service host list: ")); 1440 if (mask & LDAP_SERVICE_HOSTSERVER) { 1441 for (i=0; lserparams->krbhostservers[i] != NULL; ++i) { 1442 printf("%20s%-50s\n","",lserparams->krbhostservers[i]); 1443 } 1444 } 1445 1446 /* Print the realm reference dn values */ 1447 printf("%20s\n", gettext("Realm DN list: ")); 1448 if (mask & LDAP_SERVICE_REALMREFERENCE) { 1449 for (i=0; lserparams && lserparams->krbrealmreferences && lserparams->krbrealmreferences[i] != NULL; ++i) { 1450 printf("%20s%-50s\n","",lserparams->krbrealmreferences[i]); 1451 } 1452 } 1453 1454 return; 1455 } 1456 1457 1458 /* 1459 * This function will generate random password of length(RANDOM_PASSWD_LEN) 1460 * 1461 * 1462 * INPUT: 1463 * ctxt - context 1464 * 1465 * OUTPUT: 1466 * RANDOM_PASSWD_LEN length random password 1467 */ 1468 static int generate_random_password(krb5_context ctxt, char **randpwd, unsigned int *passlen) 1469 { 1470 char *random_pwd = NULL; 1471 int ret = 0; 1472 krb5_data data; 1473 int i=0; 1474 /*int len = 0;*/ 1475 1476 /* setting random password length in the range 16-32 */ 1477 srand((unsigned int)(time(0) ^ getpid())); 1478 1479 data.length = RANDOM_PASSWD_LEN; 1480 random_pwd = (char *)malloc(data.length + 1); 1481 if (random_pwd == NULL) { 1482 com_err("setsrvpw", ENOMEM, gettext("while generating random password")); 1483 return ENOMEM; 1484 } 1485 memset(random_pwd, 0, data.length + 1); 1486 data.data = random_pwd; 1487 1488 ret = krb5_c_random_make_octets(ctxt, &data); 1489 if (ret) { 1490 com_err("setsrvpw", ret, gettext("Error generating random password")); 1491 free(random_pwd); 1492 return ret; 1493 } 1494 1495 for (i=0; i<data.length; i++) { 1496 /* restricting to ascii chars. Need to change this when 8.8 supports */ 1497 if ((unsigned char)random_pwd[i] > 127) { 1498 random_pwd[i] = (unsigned char)random_pwd[i] % 128; 1499 } else if (random_pwd[i] == 0) { 1500 random_pwd[i] = (rand()/(RAND_MAX/127 + 1))+1; 1501 } 1502 } 1503 1504 *randpwd = random_pwd; 1505 *passlen = data.length; 1506 1507 return 0; 1508 } 1509 1510 1511 /* 1512 * This function will set the password of the service object in the directory 1513 * and/or the specified service password file. 1514 * 1515 * 1516 * INPUT: 1517 * argc - contains the number of arguments for this sub-command 1518 * argv - array of arguments for this sub-command 1519 * 1520 * OUTPUT: 1521 * void 1522 */ 1523 int 1524 kdb5_ldap_set_service_password(argc, argv) 1525 int argc; 1526 char **argv; 1527 { 1528 krb5_ldap_context *lparams = NULL; 1529 char *file_name = NULL; 1530 char *tmp_file = NULL; 1531 char *me = argv[0]; 1532 int filelen = 0; 1533 int random_passwd = 0; 1534 int set_dir_pwd = 1; 1535 krb5_boolean db_init_local = FALSE; 1536 char *service_object = NULL; 1537 char *passwd = NULL; 1538 char *prompt1 = NULL; 1539 char *prompt2 = NULL; 1540 unsigned int passwd_len = 0; 1541 krb5_error_code errcode = -1; 1542 int retval = 0, i = 0; 1543 unsigned int len = 0; 1544 krb5_boolean print_usage = FALSE; 1545 FILE *pfile = NULL; 1546 char *str = NULL; 1547 char line[MAX_LEN]; 1548 kdb5_dal_handle *dal_handle = NULL; 1549 struct data encrypted_passwd = {0, NULL}; 1550 1551 /* The arguments for setsrv password should contain the service object DN 1552 * and options to specify whether the password should be updated in file only 1553 * or both file and directory. So the possible combination of arguments are: 1554 * setsrvpw servicedn wherein argc is 2 1555 * setsrvpw -fileonly servicedn wherein argc is 3 1556 * setsrvpw -randpw servicedn wherein argc is 3 1557 * setsrvpw -f filename servicedn wherein argc is 4 1558 * setsrvpw -fileonly -f filename servicedn wherein argc is 5 1559 * setsrvpw -randpw -f filename servicedn wherein argc is 5 1560 */ 1561 if ((argc < 2) || (argc > 5)) { 1562 print_usage = TRUE; 1563 goto cleanup; 1564 } 1565 1566 dal_handle = (kdb5_dal_handle *)util_context->db_context; 1567 lparams = (krb5_ldap_context *) dal_handle->db_context; 1568 1569 if (lparams == NULL) { 1570 printf(gettext("%s: Invalid LDAP handle\n"), me); 1571 goto cleanup; 1572 } 1573 1574 /* Parse the arguments */ 1575 for (i = 1; i < argc -1 ; i++) { 1576 if (strcmp(argv[i], "-randpw") == 0) { 1577 random_passwd = 1; 1578 } else if (strcmp(argv[i], "-fileonly") == 0) { 1579 set_dir_pwd = 0; 1580 } else if (strcmp(argv[i], "-f") == 0) { 1581 if (argv[++i] == NULL) { 1582 print_usage = TRUE; 1583 goto cleanup; 1584 } 1585 1586 file_name = strdup(argv[i]); 1587 if (file_name == NULL) { 1588 com_err(me, ENOMEM, gettext("while setting service object password")); 1589 goto cleanup; 1590 } 1591 /* Verify if the file location has the proper file name 1592 * for eg, if the file location is a directory like /home/temp/, 1593 * we reject it. 1594 */ 1595 filelen = strlen(file_name); 1596 if ((filelen == 0) || (file_name[filelen-1] == '/')) { 1597 printf(gettext("%s: Filename not specified for setting service object password\n"), me); 1598 print_usage = TRUE; 1599 goto cleanup; 1600 } 1601 } else { 1602 printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me); 1603 print_usage = TRUE; 1604 goto cleanup; 1605 } 1606 } 1607 1608 if (i != argc-1) { 1609 print_usage = TRUE; 1610 goto cleanup; 1611 } 1612 1613 service_object = strdup(argv[i]); 1614 if (service_object == NULL) { 1615 com_err(me, ENOMEM, gettext("while setting service object password")); 1616 goto cleanup; 1617 } 1618 1619 if (strlen(service_object) == 0) { 1620 printf(gettext("%s: Service object not specified for \"setsrvpw\" command\n"), me); 1621 print_usage = TRUE; 1622 goto cleanup; 1623 } 1624 1625 if (service_object[0] == '-') { 1626 print_usage = TRUE; 1627 goto cleanup; 1628 } 1629 1630 if (file_name == NULL) { 1631 file_name = strdup(DEF_SERVICE_PASSWD_FILE); 1632 if (file_name == NULL) { 1633 com_err(me, ENOMEM, gettext("while setting service object password")); 1634 goto cleanup; 1635 } 1636 } 1637 1638 if (set_dir_pwd) { 1639 if (db_inited == FALSE) { 1640 if ((errcode = krb5_ldap_db_init(util_context, lparams))) { 1641 com_err(me, errcode, gettext("while initializing database")); 1642 goto cleanup; 1643 } 1644 db_init_local = TRUE; 1645 } 1646 } 1647 1648 if (random_passwd) { 1649 if (!set_dir_pwd) { 1650 printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me); 1651 print_usage = TRUE; 1652 goto cleanup; 1653 } else { 1654 /* Generate random password */ 1655 1656 if ((errcode = generate_random_password(util_context, &passwd, &passwd_len))) { 1657 printf(gettext("%s: Failed to set service object password\n"), me); 1658 goto cleanup; 1659 } 1660 passwd_len = strlen(passwd); 1661 } 1662 } else { 1663 /* Get the service object password from the terminal */ 1664 passwd = (char *)malloc(MAX_SERVICE_PASSWD_LEN + 1); 1665 if (passwd == NULL) { 1666 com_err(me, ENOMEM, gettext("while setting service object password")); 1667 goto cleanup; 1668 } 1669 memset(passwd, 0, MAX_SERVICE_PASSWD_LEN + 1); 1670 passwd_len = MAX_SERVICE_PASSWD_LEN; 1671 1672 len = strlen(service_object); 1673 /* size of allocation=strlen of servicedn + strlen("Password for \" \"")=20 */ 1674 prompt1 = (char *)malloc(len + 20); 1675 if (prompt1 == NULL) { 1676 com_err(me, ENOMEM, gettext("while setting service object password")); 1677 goto cleanup; 1678 } 1679 sprintf(prompt1, gettext("Password for \"%s\""), service_object); 1680 1681 /* size of allocation=strlen of servicedn + strlen("Re-enter Password for \" \"")=30 */ 1682 prompt2 = (char *)malloc(len + 30); 1683 if (prompt2 == NULL) { 1684 com_err(me, ENOMEM, gettext("while setting service object password")); 1685 free(prompt1); 1686 goto cleanup; 1687 } 1688 sprintf(prompt2, gettext("Re-enter password for \"%s\""), service_object); 1689 1690 retval = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len); 1691 free(prompt1); 1692 free(prompt2); 1693 if (retval) { 1694 com_err(me, retval, gettext("while setting service object password")); 1695 memset(passwd, 0, MAX_SERVICE_PASSWD_LEN); 1696 goto cleanup; 1697 } 1698 if (passwd_len == 0) { 1699 printf(gettext("%s: Invalid password\n"), me); 1700 memset(passwd, 0, MAX_SERVICE_PASSWD_LEN); 1701 goto cleanup; 1702 } 1703 passwd_len = strlen(passwd); 1704 } 1705 1706 /* Hex the password */ 1707 { 1708 krb5_data pwd, hex; 1709 pwd.length = passwd_len; 1710 pwd.data = passwd; 1711 1712 errcode = tohex(pwd, &hex); 1713 if (errcode != 0) { 1714 if (hex.length != 0) { 1715 memset(hex.data, 0, hex.length); 1716 free(hex.data); 1717 } 1718 com_err(me, errcode, gettext("Failed to convert the password to hex")); 1719 memset(passwd, 0, passwd_len); 1720 goto cleanup; 1721 } 1722 /* Password = {CRYPT}<encrypted password>:<encrypted key> */ 1723 encrypted_passwd.value = (unsigned char *)malloc(strlen(service_object) + 1724 1 + 5 + hex.length + 2); 1725 if (encrypted_passwd.value == NULL) { 1726 com_err(me, ENOMEM, gettext("while setting service object password")); 1727 memset(passwd, 0, passwd_len); 1728 memset(hex.data, 0, hex.length); 1729 free(hex.data); 1730 goto cleanup; 1731 } 1732 encrypted_passwd.value[strlen(service_object) + 1733 1 + 5 + hex.length + 1] = '\0'; 1734 sprintf((char *)encrypted_passwd.value, "%s#{HEX}%s\n", service_object, hex.data); 1735 encrypted_passwd.len = strlen((char *)encrypted_passwd.value); 1736 memset(hex.data, 0, hex.length); 1737 free(hex.data); 1738 } 1739 1740 /* We should check if the file exists and we have permission to write into that file */ 1741 if (access(file_name, W_OK) == -1) { 1742 if (errno == ENOENT) { 1743 mode_t omask; 1744 int fd = -1; 1745 1746 printf(gettext("File does not exist. Creating the file %s...\n"), file_name); 1747 omask = umask(077); 1748 fd = creat(file_name, S_IRUSR|S_IWUSR); 1749 umask(omask); 1750 if (fd == -1) { 1751 com_err(me, errno, gettext("Error creating file %s"), file_name); 1752 memset(passwd, 0, passwd_len); 1753 goto cleanup; 1754 } 1755 close(fd); 1756 } else { 1757 com_err(me, errno, gettext("Unable to access the file %s"), file_name); 1758 memset(passwd, 0, passwd_len); 1759 goto cleanup; 1760 } 1761 } 1762 1763 if (set_dir_pwd) { 1764 if ((errcode = krb5_ldap_set_service_passwd(util_context, service_object, passwd)) != 0) { 1765 com_err(me, errcode, gettext("Failed to set password for service object %s"), service_object); 1766 memset(passwd, 0, passwd_len); 1767 goto cleanup; 1768 } 1769 } 1770 1771 memset(passwd, 0, passwd_len); 1772 1773 1774 /* TODO: file lock for the service password file */ 1775 /* set password in the file */ 1776 pfile = fopen(file_name, "r+F"); 1777 if (pfile == NULL) { 1778 com_err(me, errno, gettext("Failed to open file %s"), file_name); 1779 goto cleanup; 1780 } 1781 1782 while (fgets(line, MAX_LEN, pfile) != NULL) { 1783 if ((str = strstr(line, service_object)) != NULL) { 1784 if (line[strlen(service_object)] == '#') { 1785 break; 1786 } 1787 str = NULL; 1788 } 1789 } 1790 if (str == NULL) { 1791 if (feof(pfile)) { 1792 /* If the service object dn is not present in the service password file */ 1793 if (fwrite(encrypted_passwd.value, (unsigned int)encrypted_passwd.len, 1, pfile) != 1) { 1794 com_err(me, errno, gettext("Failed to write service object password to file")); 1795 goto cleanup; 1796 } 1797 } else { 1798 com_err(me, errno, gettext("Error reading service object password file")); 1799 goto cleanup; 1800 } 1801 fclose(pfile); 1802 pfile = NULL; 1803 } else { 1804 /* Password entry for the service object is already present in the file */ 1805 /* Delete the existing entry and add the new entry */ 1806 FILE *newfile = NULL; 1807 mode_t omask; 1808 1809 /* Create a new file with the extension .tmp */ 1810 tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1)); 1811 if (tmp_file == NULL) { 1812 com_err(me, ENOMEM, gettext("while setting service object password")); 1813 goto cleanup; 1814 } 1815 sprintf(tmp_file,"%s.%s",file_name,"tmp"); 1816 1817 omask = umask(077); 1818 newfile = fopen(tmp_file, "w+F"); 1819 umask(omask); 1820 if (newfile == NULL) { 1821 com_err(me, errno, gettext("Error creating file %s"), tmp_file); 1822 goto cleanup; 1823 } 1824 1825 1826 fseek(pfile, 0, SEEK_SET); 1827 while (fgets(line, MAX_LEN, pfile) != NULL) { 1828 if (((str = strstr(line, service_object)) != NULL) && (line[strlen(service_object)] == '#')) { 1829 if (fprintf(newfile, "%s", encrypted_passwd.value) < 0) { 1830 com_err(me, errno, gettext("Failed to write service object password to file")); 1831 fclose(newfile); 1832 unlink(tmp_file); 1833 goto cleanup; 1834 } 1835 } else { 1836 len = strlen(line); 1837 if (fprintf(newfile, "%s", line) < 0) { 1838 com_err(me, errno, gettext("Failed to write service object password to file")); 1839 fclose(newfile); 1840 unlink(tmp_file); 1841 goto cleanup; 1842 } 1843 } 1844 } 1845 1846 if (!feof(pfile)) { 1847 com_err(me, errno, gettext("Error reading service object password file")); 1848 fclose(newfile); 1849 unlink(tmp_file); 1850 goto cleanup; 1851 } 1852 1853 /* TODO: file lock for the service password file */ 1854 fclose(pfile); 1855 pfile = NULL; 1856 1857 fclose(newfile); 1858 newfile = NULL; 1859 1860 if (unlink(file_name) == 0) { 1861 link(tmp_file, file_name); 1862 } else { 1863 com_err(me, errno, gettext("Failed to write service object password to file")); 1864 unlink(tmp_file); 1865 goto cleanup; 1866 } 1867 unlink(tmp_file); 1868 } 1869 errcode = 0; 1870 1871 cleanup: 1872 if (db_init_local) 1873 krb5_ldap_close(util_context); 1874 1875 if (service_object) 1876 free(service_object); 1877 1878 if (file_name) 1879 free(file_name); 1880 1881 if (passwd) 1882 free(passwd); 1883 1884 if (encrypted_passwd.value) { 1885 memset(encrypted_passwd.value, 0, encrypted_passwd.len); 1886 free(encrypted_passwd.value); 1887 } 1888 1889 if (pfile) 1890 fclose(pfile); 1891 1892 if (tmp_file) 1893 free(tmp_file); 1894 1895 if (print_usage) 1896 db_usage(SET_SRV_PW); 1897 1898 return errcode; 1899 } 1900 1901 #else /* #ifdef HAVE_EDIRECTORY */ 1902 1903 /* 1904 * Convert the user supplied password into hexadecimal and stash it. Only a 1905 * little more secure than storing plain password in the file ... 1906 */ 1907 void 1908 kdb5_ldap_stash_service_password(argc, argv) 1909 int argc; 1910 char **argv; 1911 { 1912 int ret = 0; 1913 unsigned int passwd_len = 0; 1914 char *me = argv[0]; 1915 char *service_object = NULL; 1916 char *file_name = NULL, *tmp_file = NULL; 1917 char passwd[MAX_SERVICE_PASSWD_LEN]; 1918 char *str = NULL; 1919 char line[MAX_LEN]; 1920 int fd; 1921 FILE *pfile = NULL; 1922 krb5_boolean print_usage = FALSE; 1923 krb5_data hexpasswd = {0, 0, NULL}; 1924 mode_t old_mode = 0; 1925 1926 /* 1927 * Format: 1928 * stashsrvpw [-f filename] service_dn 1929 * where 1930 * 'service_dn' is the DN of the service object 1931 * 'filename' is the path of the stash file 1932 */ 1933 if (argc != 2 && argc != 4) { 1934 print_usage = TRUE; 1935 goto cleanup; 1936 } 1937 1938 if (argc == 4) { 1939 /* Find the stash file name */ 1940 if (strcmp (argv[1], "-f") == 0) { 1941 if (((file_name = strdup (argv[2])) == NULL) || 1942 ((service_object = strdup (argv[3])) == NULL)) { 1943 com_err(me, ENOMEM, gettext("while setting service object password")); 1944 goto cleanup; 1945 } 1946 } else if (strcmp (argv[2], "-f") == 0) { 1947 if (((file_name = strdup (argv[3])) == NULL) || 1948 ((service_object = strdup (argv[1])) == NULL)) { 1949 com_err(me, ENOMEM, gettext("while setting service object password")); 1950 goto cleanup; 1951 } 1952 } else { 1953 print_usage = TRUE; 1954 goto cleanup; 1955 } 1956 if (file_name == NULL) { 1957 com_err(me, ENOMEM, gettext("while setting service object password")); 1958 goto cleanup; 1959 } 1960 } else { /* argc == 2 */ 1961 char *section; 1962 1963 service_object = strdup (argv[1]); 1964 if (service_object == NULL) { 1965 com_err(me, ENOMEM, gettext("while setting service object password")); 1966 goto cleanup; 1967 } 1968 1969 /* Pick up the stash-file name from krb5.conf */ 1970 profile_get_string(util_context->profile, KDB_REALM_SECTION, 1971 util_context->default_realm, KDB_MODULE_POINTER, NULL, §ion); 1972 1973 if (section == NULL) { 1974 profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION, 1975 KDB_MODULE_POINTER, NULL, NULL, §ion); 1976 if (section == NULL) { 1977 /* Stash file path neither in krb5.conf nor on command line */ 1978 file_name = strdup(DEF_SERVICE_PASSWD_FILE); 1979 if (file_name == NULL) { 1980 com_err(me, ENOMEM, gettext("while setting service object password")); 1981 goto cleanup; 1982 } 1983 goto done; 1984 } 1985 } 1986 1987 profile_get_string (util_context->profile, KDB_MODULE_SECTION, section, 1988 "ldap_service_password_file", NULL, &file_name); 1989 1990 /* 1991 * Solaris Kerberos: use default if ldap_service_password_file not set 1992 */ 1993 if (file_name == NULL) { 1994 file_name = strdup(DEF_SERVICE_PASSWD_FILE); 1995 if (file_name == NULL) { 1996 com_err(me, ENOMEM, gettext("while setting service object password")); 1997 goto cleanup; 1998 } 1999 } 2000 } 2001 done: 2002 2003 /* Get password from user */ 2004 { 2005 char prompt1[256], prompt2[256]; 2006 2007 /* Get the service object password from the terminal */ 2008 memset(passwd, 0, sizeof (passwd)); 2009 passwd_len = sizeof (passwd); 2010 2011 /* size of prompt = strlen of servicedn + strlen("Password for \" \"") */ 2012 assert (sizeof (prompt1) > (strlen (service_object) 2013 + sizeof ("Password for \" \""))); 2014 sprintf(prompt1, gettext("Password for \"%s\""), service_object); 2015 2016 /* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */ 2017 assert (sizeof (prompt2) > (strlen (service_object) 2018 + sizeof ("Re-enter Password for \" \""))); 2019 sprintf(prompt2, gettext("Re-enter password for \"%s\""), service_object); 2020 2021 ret = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len); 2022 if (ret != 0) { 2023 com_err(me, ret, gettext("while setting service object password")); 2024 memset(passwd, 0, sizeof (passwd)); 2025 goto cleanup; 2026 } 2027 2028 if (passwd_len == 0) { 2029 printf(gettext("%s: Invalid password\n"), me); 2030 memset(passwd, 0, MAX_SERVICE_PASSWD_LEN); 2031 goto cleanup; 2032 } 2033 } 2034 2035 /* Convert the password to hexadecimal */ 2036 { 2037 krb5_data pwd; 2038 2039 pwd.length = passwd_len; 2040 pwd.data = passwd; 2041 2042 ret = tohex(pwd, &hexpasswd); 2043 if (ret != 0) { 2044 com_err(me, ret, gettext("Failed to convert the password to hexadecimal")); 2045 memset(passwd, 0, passwd_len); 2046 goto cleanup; 2047 } 2048 } 2049 memset(passwd, 0, passwd_len); 2050 2051 /* TODO: file lock for the service passowrd file */ 2052 2053 /* set password in the file */ 2054 #if 0 /* ************ Begin IFDEF'ed OUT ***************************** */ 2055 old_mode = umask(0177); 2056 pfile = fopen(file_name, "a+"); 2057 if (pfile == NULL) { 2058 com_err(me, errno, gettext("Failed to open file %s: %s"), file_name, 2059 strerror (errno)); 2060 goto cleanup; 2061 } 2062 rewind (pfile); 2063 umask(old_mode); 2064 #else 2065 /* Solaris Kerberos: safer than the above */ 2066 fd = open(file_name, O_CREAT|O_RDWR|O_APPEND, 0600); 2067 if (fd < 0) { 2068 com_err(me, errno, gettext("Failed to open file %s: %s"), file_name, 2069 strerror (errno)); 2070 goto cleanup; 2071 } 2072 pfile = fdopen(fd, "a+F"); 2073 if (pfile == NULL) { 2074 com_err(me, errno, gettext("Failed to open file %s: %s"), file_name, 2075 strerror (errno)); 2076 goto cleanup; 2077 } 2078 rewind (pfile); 2079 #endif 2080 2081 while (fgets (line, MAX_LEN, pfile) != NULL) { 2082 if ((str = strstr (line, service_object)) != NULL) { 2083 /* 2084 * White spaces not allowed, # delimits the service dn from the 2085 * password 2086 */ 2087 if (line [strlen (service_object)] == '#') 2088 break; 2089 str = NULL; 2090 } 2091 } 2092 2093 if (str == NULL) { 2094 if (feof(pfile)) { 2095 /* If the service object dn is not present in the service password file */ 2096 if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) { 2097 com_err(me, errno, gettext("Failed to write service object password to file")); 2098 fclose(pfile); 2099 goto cleanup; 2100 } 2101 } else { 2102 com_err(me, errno, gettext("Error reading service object password file")); 2103 fclose(pfile); 2104 goto cleanup; 2105 } 2106 fclose(pfile); 2107 } else { 2108 /* 2109 * Password entry for the service object is already present in the file 2110 * Delete the existing entry and add the new entry 2111 */ 2112 FILE *newfile; 2113 2114 mode_t omask; 2115 2116 /* Create a new file with the extension .tmp */ 2117 tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1)); 2118 if (tmp_file == NULL) { 2119 com_err(me, ENOMEM, gettext("while setting service object password")); 2120 fclose(pfile); 2121 goto cleanup; 2122 } 2123 sprintf(tmp_file,"%s.%s",file_name,"tmp"); 2124 2125 omask = umask(077); 2126 newfile = fopen(tmp_file, "wF"); 2127 umask (omask); 2128 if (newfile == NULL) { 2129 com_err(me, errno, gettext("Error creating file %s"), tmp_file); 2130 fclose(pfile); 2131 goto cleanup; 2132 } 2133 2134 fseek(pfile, 0, SEEK_SET); 2135 while (fgets(line, MAX_LEN, pfile) != NULL) { 2136 if (((str = strstr(line, service_object)) != NULL) && 2137 (line[strlen(service_object)] == '#')) { 2138 if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) { 2139 com_err(me, errno, gettext("Failed to write service object password to file")); 2140 fclose(newfile); 2141 unlink(tmp_file); 2142 fclose(pfile); 2143 goto cleanup; 2144 } 2145 } else { 2146 if (fprintf (newfile, "%s", line) < 0) { 2147 com_err(me, errno, gettext("Failed to write service object password to file")); 2148 fclose(newfile); 2149 unlink(tmp_file); 2150 fclose(pfile); 2151 goto cleanup; 2152 } 2153 } 2154 } 2155 2156 if (!feof(pfile)) { 2157 com_err(me, errno, gettext("Error reading service object password file")); 2158 fclose(newfile); 2159 unlink(tmp_file); 2160 fclose(pfile); 2161 goto cleanup; 2162 } 2163 2164 /* TODO: file lock for the service passowrd file */ 2165 2166 fclose(pfile); 2167 fclose(newfile); 2168 2169 ret = rename(tmp_file, file_name); 2170 if (ret != 0) { 2171 com_err(me, errno, gettext("Failed to write service object password to " 2172 "file")); 2173 goto cleanup; 2174 } 2175 } 2176 ret = 0; 2177 2178 cleanup: 2179 2180 if (hexpasswd.length != 0) { 2181 memset(hexpasswd.data, 0, hexpasswd.length); 2182 free(hexpasswd.data); 2183 } 2184 2185 if (service_object) 2186 free(service_object); 2187 2188 if (file_name) 2189 free(file_name); 2190 2191 if (tmp_file) 2192 free(tmp_file); 2193 2194 if (print_usage) 2195 usage(); 2196 /* db_usage(STASH_SRV_PW); */ 2197 2198 if (ret) 2199 exit_status++; 2200 } 2201 2202 #endif /* #ifdef HAVE_EDIRECTORY */ 2203