154925bf6Swillf /* 2*dd9ccd46S * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 354925bf6Swillf * Use is subject to license terms. 454925bf6Swillf */ 554925bf6Swillf 654925bf6Swillf /* 754925bf6Swillf * kadmin/ldap_util/kdb5_ldap_services.c 854925bf6Swillf */ 954925bf6Swillf 1054925bf6Swillf /* Copyright (c) 2004-2005, Novell, Inc. 1154925bf6Swillf * All rights reserved. 1254925bf6Swillf * 1354925bf6Swillf * Redistribution and use in source and binary forms, with or without 1454925bf6Swillf * modification, are permitted provided that the following conditions are met: 1554925bf6Swillf * 1654925bf6Swillf * * Redistributions of source code must retain the above copyright notice, 1754925bf6Swillf * this list of conditions and the following disclaimer. 1854925bf6Swillf * * Redistributions in binary form must reproduce the above copyright 1954925bf6Swillf * notice, this list of conditions and the following disclaimer in the 2054925bf6Swillf * documentation and/or other materials provided with the distribution. 2154925bf6Swillf * * The copyright holder's name is not used to endorse or promote products 2254925bf6Swillf * derived from this software without specific prior written permission. 2354925bf6Swillf * 2454925bf6Swillf * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2554925bf6Swillf * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2654925bf6Swillf * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2754925bf6Swillf * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2854925bf6Swillf * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2954925bf6Swillf * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3054925bf6Swillf * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3154925bf6Swillf * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3254925bf6Swillf * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3354925bf6Swillf * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3454925bf6Swillf * POSSIBILITY OF SUCH DAMAGE. 3554925bf6Swillf */ 3654925bf6Swillf 3754925bf6Swillf /* 3854925bf6Swillf * Create / Delete / Modify / View / List service objects. 3954925bf6Swillf */ 4054925bf6Swillf 4154925bf6Swillf /* 4254925bf6Swillf * Service objects have rights over realm objects and principals. The following 4354925bf6Swillf * functions manage the service objects. 4454925bf6Swillf */ 4554925bf6Swillf 4654925bf6Swillf #include <stdio.h> 4754925bf6Swillf #include <k5-int.h> 4854925bf6Swillf #include <libintl.h> /* Solaris Kerberos */ 4954925bf6Swillf #include <locale.h> /* Solaris Kerberos */ 5054925bf6Swillf #include "kdb5_ldap_util.h" 5154925bf6Swillf #include "kdb5_ldap_list.h" 5254925bf6Swillf 5354925bf6Swillf #ifdef HAVE_EDIRECTORY 5454925bf6Swillf 5554925bf6Swillf krb5_error_code 5654925bf6Swillf rem_service_entry_from_file(int argc, 5754925bf6Swillf char *argv[], 5854925bf6Swillf char *file_name, 5954925bf6Swillf char *service_object); 6054925bf6Swillf 6154925bf6Swillf extern char *yes; 6254925bf6Swillf extern krb5_boolean db_inited; 6354925bf6Swillf 6454925bf6Swillf static int process_host_list(char **host_list, int servicetype) 6554925bf6Swillf { 6654925bf6Swillf krb5_error_code retval = 0; 6754925bf6Swillf char *pchr = NULL; 6854925bf6Swillf char host_str[MAX_LEN_LIST_ENTRY] = "", proto_str[PROTOCOL_STR_LEN + 1] = "", port_str[PORT_STR_LEN + 1] = ""; 6954925bf6Swillf int j = 0; 7054925bf6Swillf 7154925bf6Swillf /* Protocol and port number processing */ 7254925bf6Swillf for (j = 0; host_list[j]; j++) { 7354925bf6Swillf /* Look for one hash */ 7454925bf6Swillf if ((pchr = strchr(host_list[j], HOST_INFO_DELIMITER))) { 7554925bf6Swillf unsigned int hostname_len = pchr - host_list[j]; 7654925bf6Swillf 7754925bf6Swillf /* Check input for buffer overflow */ 7854925bf6Swillf if (hostname_len >= MAX_LEN_LIST_ENTRY) { 7954925bf6Swillf retval = EINVAL; 8054925bf6Swillf goto cleanup; 8154925bf6Swillf } 8254925bf6Swillf 8354925bf6Swillf /* First copy off the host name portion */ 8454925bf6Swillf strncpy (host_str, host_list[j], hostname_len); 8554925bf6Swillf 8654925bf6Swillf /* Parse for the protocol string and translate to number */ 8754925bf6Swillf strncpy (proto_str, pchr + 1, PROTOCOL_STR_LEN); 8854925bf6Swillf if (!strcmp(proto_str, "udp")) 8954925bf6Swillf sprintf (proto_str, "%d", PROTOCOL_NUM_UDP); 9054925bf6Swillf else if (!strcmp(proto_str, "tcp")) 9154925bf6Swillf sprintf (proto_str, "%d", PROTOCOL_NUM_TCP); 9254925bf6Swillf else 9354925bf6Swillf proto_str[0] = '\0'; /* Make the string null if invalid */ 9454925bf6Swillf 9554925bf6Swillf /* Look for one more hash */ 9654925bf6Swillf if ((pchr = strchr(pchr + 1, HOST_INFO_DELIMITER))) { 9754925bf6Swillf /* Parse for the port string and check if it is numeric */ 9854925bf6Swillf strncpy (port_str, pchr + 1, PORT_STR_LEN); 9954925bf6Swillf if (!strtol(port_str, NULL, 10)) /* Not a valid number */ 10054925bf6Swillf port_str[0] = '\0'; 10154925bf6Swillf } else 10254925bf6Swillf port_str[0] = '\0'; 10354925bf6Swillf } else { /* We have only host name */ 10454925bf6Swillf strncpy (host_str, host_list[j], MAX_LEN_LIST_ENTRY - 1); 10554925bf6Swillf proto_str[0] = '\0'; 10654925bf6Swillf port_str[0] = '\0'; 10754925bf6Swillf } 10854925bf6Swillf 10954925bf6Swillf /* Now, based on service type, fill in suitable protocol 11054925bf6Swillf and port values if they are absent or not matching */ 11154925bf6Swillf if (servicetype == LDAP_KDC_SERVICE) { 11254925bf6Swillf if (proto_str[0] == '\0') 11354925bf6Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_KDC); 11454925bf6Swillf 11554925bf6Swillf if (port_str[0] == '\0') 11654925bf6Swillf sprintf (port_str, "%d", PORT_DEFAULT_KDC); 11754925bf6Swillf } else if (servicetype == LDAP_ADMIN_SERVICE) { 11854925bf6Swillf if (proto_str[0] == '\0') 11954925bf6Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM); 12054925bf6Swillf else if (strcmp(proto_str, "1")) { 12154925bf6Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM); 12254925bf6Swillf 12354925bf6Swillf /* Print warning message */ 12454925bf6Swillf printf (gettext("Admin Server supports only TCP protocol, hence setting that\n")); 12554925bf6Swillf } 12654925bf6Swillf 12754925bf6Swillf if (port_str[0] == '\0') 12854925bf6Swillf sprintf (port_str, "%d", PORT_DEFAULT_ADM); 12954925bf6Swillf } else if (servicetype == LDAP_PASSWD_SERVICE) { 13054925bf6Swillf if (proto_str[0] == '\0') 13154925bf6Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD); 13254925bf6Swillf else if (strcmp(proto_str, "0")) { 13354925bf6Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD); 13454925bf6Swillf 13554925bf6Swillf /* Print warning message */ 13654925bf6Swillf printf (gettext("Password Server supports only UDP protocol, hence setting that\n")); 13754925bf6Swillf } 13854925bf6Swillf 13954925bf6Swillf if (port_str[0] == '\0') 14054925bf6Swillf sprintf (port_str, "%d", PORT_DEFAULT_PWD); 14154925bf6Swillf } 14254925bf6Swillf 14354925bf6Swillf /* Finally form back the string */ 14454925bf6Swillf free (host_list[j]); 14554925bf6Swillf host_list[j] = (char*) malloc(sizeof(char) * 14654925bf6Swillf (strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1)); 14754925bf6Swillf if (host_list[j] == NULL) { 14854925bf6Swillf retval = ENOMEM; 14954925bf6Swillf goto cleanup; 15054925bf6Swillf } 15154925bf6Swillf snprintf (host_list[j], strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1, 15254925bf6Swillf "%s#%s#%s", host_str, proto_str, port_str); 15354925bf6Swillf } 15454925bf6Swillf 15554925bf6Swillf cleanup: 15654925bf6Swillf return retval; 15754925bf6Swillf } 15854925bf6Swillf 15954925bf6Swillf 16054925bf6Swillf /* 16154925bf6Swillf * Given a realm name, this function will convert it to a DN by appending the 16254925bf6Swillf * Kerberos container location. 16354925bf6Swillf */ 16454925bf6Swillf static krb5_error_code 16554925bf6Swillf convert_realm_name2dn_list(list, krbcontainer_loc) 16654925bf6Swillf char **list; 16754925bf6Swillf const char *krbcontainer_loc; 16854925bf6Swillf { 16954925bf6Swillf krb5_error_code retval = 0; 17054925bf6Swillf char temp_str[MAX_DN_CHARS] = "\0"; 17154925bf6Swillf char *temp_node = NULL; 17254925bf6Swillf int i = 0; 17354925bf6Swillf 17454925bf6Swillf if (list == NULL) { 17554925bf6Swillf return EINVAL; 17654925bf6Swillf } 17754925bf6Swillf 17854925bf6Swillf for (i = 0; (list[i] != NULL) && (i < MAX_LIST_ENTRIES); i++) { 17954925bf6Swillf /* Restrict copying to max. length to avoid buffer overflow */ 18054925bf6Swillf snprintf (temp_str, MAX_DN_CHARS, "cn=%s,%s", list[i], krbcontainer_loc); 18154925bf6Swillf 18254925bf6Swillf /* Make copy of string to temporary node */ 18354925bf6Swillf temp_node = strdup(temp_str); 18454925bf6Swillf if (list[i] == NULL) { 18554925bf6Swillf retval = ENOMEM; 18654925bf6Swillf goto cleanup; 18754925bf6Swillf } 18854925bf6Swillf 18954925bf6Swillf /* On success, free list node and attach new one */ 19054925bf6Swillf free (list[i]); 19154925bf6Swillf list[i] = temp_node; 19254925bf6Swillf temp_node = NULL; 19354925bf6Swillf } 19454925bf6Swillf 19554925bf6Swillf cleanup: 19654925bf6Swillf return retval; 19754925bf6Swillf } 19854925bf6Swillf 19954925bf6Swillf 20054925bf6Swillf /* 20154925bf6Swillf * This function will create a service object on the LDAP Server, with the 20254925bf6Swillf * specified attributes. 20354925bf6Swillf */ 20454925bf6Swillf void kdb5_ldap_create_service(argc, argv) 20554925bf6Swillf int argc; 20654925bf6Swillf char *argv[]; 20754925bf6Swillf { 208*dd9ccd46S /* Solaris Kerberos */ 209*dd9ccd46S char *me = progname; 21054925bf6Swillf krb5_error_code retval = 0; 21154925bf6Swillf krb5_ldap_service_params *srvparams = NULL; 21254925bf6Swillf krb5_boolean print_usage = FALSE; 21354925bf6Swillf krb5_boolean no_msg = FALSE; 21454925bf6Swillf int mask = 0; 21554925bf6Swillf char **extra_argv = NULL; 21654925bf6Swillf int extra_argc = 0; 21754925bf6Swillf int i = 0; 21854925bf6Swillf krb5_ldap_realm_params *rparams = NULL; 21954925bf6Swillf int rmask = 0; 22054925bf6Swillf int rightsmask =0; 22154925bf6Swillf char **temprdns = NULL; 22254925bf6Swillf char *realmName = NULL; 22354925bf6Swillf kdb5_dal_handle *dal_handle = NULL; 22454925bf6Swillf krb5_ldap_context *ldap_context=NULL; 22554925bf6Swillf krb5_boolean service_obj_created = FALSE; 22654925bf6Swillf 22754925bf6Swillf /* Check for number of arguments */ 22854925bf6Swillf if ((argc < 3) || (argc > 10)) { 22954925bf6Swillf exit_status++; 23054925bf6Swillf goto err_usage; 23154925bf6Swillf } 23254925bf6Swillf 23354925bf6Swillf /* Allocate memory for service parameters structure */ 23454925bf6Swillf srvparams = (krb5_ldap_service_params*) calloc(1, sizeof(krb5_ldap_service_params)); 23554925bf6Swillf if (srvparams == NULL) { 23654925bf6Swillf retval = ENOMEM; 23754925bf6Swillf goto cleanup; 23854925bf6Swillf } 23954925bf6Swillf 24054925bf6Swillf dal_handle = (kdb5_dal_handle *) util_context->db_context; 24154925bf6Swillf ldap_context = (krb5_ldap_context *) dal_handle->db_context; 24254925bf6Swillf 24354925bf6Swillf /* Allocate memory for extra arguments to be used for setting 24454925bf6Swillf password -- it's OK to allocate as much as the total number 24554925bf6Swillf of arguments */ 24654925bf6Swillf extra_argv = (char **) calloc((unsigned int)argc, sizeof(char*)); 24754925bf6Swillf if (extra_argv == NULL) { 24854925bf6Swillf retval = ENOMEM; 24954925bf6Swillf goto cleanup; 25054925bf6Swillf } 25154925bf6Swillf 25254925bf6Swillf /* Set first of the extra arguments as the program name */ 25354925bf6Swillf extra_argv[0] = me; 25454925bf6Swillf extra_argc++; 25554925bf6Swillf 25654925bf6Swillf /* Read Kerberos container info, to construct realm DN from name 25754925bf6Swillf * and for assigning rights 25854925bf6Swillf */ 25954925bf6Swillf if ((retval = krb5_ldap_read_krbcontainer_params(util_context, 26054925bf6Swillf &(ldap_context->krbcontainer)))) { 26154925bf6Swillf com_err(me, retval, gettext("while reading Kerberos container information")); 26254925bf6Swillf goto cleanup; 26354925bf6Swillf } 26454925bf6Swillf 26554925bf6Swillf /* Parse all arguments */ 26654925bf6Swillf for (i = 1; i < argc; i++) { 26754925bf6Swillf if (!strcmp(argv[i], "-kdc")) { 26854925bf6Swillf srvparams->servicetype = LDAP_KDC_SERVICE; 26954925bf6Swillf } else if (!strcmp(argv[i], "-admin")) { 27054925bf6Swillf srvparams->servicetype = LDAP_ADMIN_SERVICE; 27154925bf6Swillf } else if (!strcmp(argv[i], "-pwd")) { 27254925bf6Swillf srvparams->servicetype = LDAP_PASSWD_SERVICE; 27354925bf6Swillf } else if (!strcmp(argv[i], "-servicehost")) { 27454925bf6Swillf if (++i > argc - 1) 27554925bf6Swillf goto err_usage; 27654925bf6Swillf 27754925bf6Swillf srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES, 27854925bf6Swillf sizeof(char *)); 27954925bf6Swillf if (srvparams->krbhostservers == NULL) { 28054925bf6Swillf retval = ENOMEM; 28154925bf6Swillf goto cleanup; 28254925bf6Swillf } 28354925bf6Swillf 28454925bf6Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, 28554925bf6Swillf srvparams->krbhostservers))) { 28654925bf6Swillf goto cleanup; 28754925bf6Swillf } 28854925bf6Swillf 28954925bf6Swillf if ((retval = process_host_list (srvparams->krbhostservers, 29054925bf6Swillf srvparams->servicetype))) { 29154925bf6Swillf goto cleanup; 29254925bf6Swillf } 29354925bf6Swillf 29454925bf6Swillf mask |= LDAP_SERVICE_HOSTSERVER; 29554925bf6Swillf } else if (!strcmp(argv[i], "-realm")) { 29654925bf6Swillf if (++i > argc - 1) 29754925bf6Swillf goto err_usage; 29854925bf6Swillf 29954925bf6Swillf srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES, 30054925bf6Swillf sizeof(char *)); 30154925bf6Swillf if (srvparams->krbrealmreferences == NULL) { 30254925bf6Swillf retval = ENOMEM; 30354925bf6Swillf goto cleanup; 30454925bf6Swillf } 30554925bf6Swillf 30654925bf6Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, 30754925bf6Swillf srvparams->krbrealmreferences))) { 30854925bf6Swillf goto cleanup; 30954925bf6Swillf } 31054925bf6Swillf 31154925bf6Swillf /* Convert realm names to realm DNs */ 31254925bf6Swillf if ((retval = convert_realm_name2dn_list( 31354925bf6Swillf srvparams->krbrealmreferences, 31454925bf6Swillf ldap_context->krbcontainer->DN))) { 31554925bf6Swillf goto cleanup; 31654925bf6Swillf } 31754925bf6Swillf 31854925bf6Swillf mask |= LDAP_SERVICE_REALMREFERENCE; 31954925bf6Swillf } 32054925bf6Swillf /* If argument is none of the above and beginning with '-', 32154925bf6Swillf * it must be related to password -- collect it 32254925bf6Swillf * to pass onto kdb5_ldap_set_service_password() 32354925bf6Swillf */ 32454925bf6Swillf else if (*(argv[i]) == '-') { 32554925bf6Swillf /* Checking for options of setting the password for the 32654925bf6Swillf * service (by using 'setsrvpw') is not modular. --need to 32754925bf6Swillf * have a common function that can be shared with 'setsrvpw' 32854925bf6Swillf */ 32954925bf6Swillf if (!strcmp(argv[i], "-randpw")) { 33054925bf6Swillf extra_argv[extra_argc] = argv[i]; 33154925bf6Swillf extra_argc++; 33254925bf6Swillf } else if (!strcmp(argv[i], "-fileonly")) { 33354925bf6Swillf extra_argv[extra_argc] = argv[i]; 33454925bf6Swillf extra_argc++; 33554925bf6Swillf } 33654925bf6Swillf /* For '-f' option alone, pick up the following argument too */ 33754925bf6Swillf else if (!strcmp(argv[i], "-f")) { 33854925bf6Swillf extra_argv[extra_argc] = argv[i]; 33954925bf6Swillf extra_argc++; 34054925bf6Swillf 34154925bf6Swillf if (++i > argc - 1) 34254925bf6Swillf goto err_usage; 34354925bf6Swillf 34454925bf6Swillf extra_argv[extra_argc] = argv[i]; 34554925bf6Swillf extra_argc++; 34654925bf6Swillf } else { /* Any other option is invalid */ 34754925bf6Swillf exit_status++; 34854925bf6Swillf goto err_usage; 34954925bf6Swillf } 35054925bf6Swillf } else { /* Any other argument must be service DN */ 35154925bf6Swillf /* First check if service DN is already provided -- 35254925bf6Swillf * if so, there's a usage error 35354925bf6Swillf */ 35454925bf6Swillf if (srvparams->servicedn != NULL) { 35554925bf6Swillf com_err(me, EINVAL, gettext("while creating service object")); 35654925bf6Swillf goto err_usage; 35754925bf6Swillf } 35854925bf6Swillf 35954925bf6Swillf /* If not present already, fill up service DN */ 36054925bf6Swillf srvparams->servicedn = strdup(argv[i]); 36154925bf6Swillf if (srvparams->servicedn == NULL) { 36254925bf6Swillf com_err(me, ENOMEM, gettext("while creating service object")); 36354925bf6Swillf goto err_nomsg; 36454925bf6Swillf } 36554925bf6Swillf } 36654925bf6Swillf } 36754925bf6Swillf 36854925bf6Swillf /* No point in proceeding further if service DN value is not available */ 36954925bf6Swillf if (srvparams->servicedn == NULL) { 37054925bf6Swillf com_err(me, EINVAL, gettext("while creating service object")); 37154925bf6Swillf goto err_usage; 37254925bf6Swillf } 37354925bf6Swillf 37454925bf6Swillf if (srvparams->servicetype == 0) { /* Not provided and hence not set */ 37554925bf6Swillf com_err(me, EINVAL, gettext("while creating service object")); 37654925bf6Swillf goto err_usage; 37754925bf6Swillf } 37854925bf6Swillf 37954925bf6Swillf /* Create object with all attributes provided */ 38054925bf6Swillf if ((retval = krb5_ldap_create_service(util_context, srvparams, mask))) 38154925bf6Swillf goto cleanup; 38254925bf6Swillf 38354925bf6Swillf service_obj_created = TRUE; 38454925bf6Swillf 38554925bf6Swillf /* ** NOTE ** srvparams structure should not be modified, as it is 38654925bf6Swillf * used for deletion of the service object in case of any failures 38754925bf6Swillf * from now on. 38854925bf6Swillf */ 38954925bf6Swillf 39054925bf6Swillf /* Set password too */ 39154925bf6Swillf if (extra_argc >= 1) { 39254925bf6Swillf /* Set service DN as the last argument */ 39354925bf6Swillf extra_argv[extra_argc] = strdup(srvparams->servicedn); 39454925bf6Swillf if (extra_argv[extra_argc] == NULL) { 39554925bf6Swillf retval = ENOMEM; 39654925bf6Swillf goto cleanup; 39754925bf6Swillf } 39854925bf6Swillf extra_argc++; 39954925bf6Swillf 40054925bf6Swillf if ((retval = kdb5_ldap_set_service_password(extra_argc, extra_argv)) != 0) { 40154925bf6Swillf goto err_nomsg; 40254925bf6Swillf } 40354925bf6Swillf } 40454925bf6Swillf /* Rights assignment */ 40554925bf6Swillf if (mask & LDAP_SERVICE_REALMREFERENCE) { 40654925bf6Swillf 40754925bf6Swillf printf("%s", gettext("Changing rights for the service object. Please wait ... ")); 40854925bf6Swillf fflush(stdout); 40954925bf6Swillf 41054925bf6Swillf rightsmask =0; 41154925bf6Swillf rightsmask |= LDAP_REALM_RIGHTS; 41254925bf6Swillf rightsmask |= LDAP_SUBTREE_RIGHTS; 41354925bf6Swillf 41454925bf6Swillf if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) { 41554925bf6Swillf for (i=0; (srvparams->krbrealmreferences[i] != NULL); i++) { 41654925bf6Swillf 41754925bf6Swillf /* Get the realm name, not the dn */ 41854925bf6Swillf temprdns = ldap_explode_dn(srvparams->krbrealmreferences[i], 1); 41954925bf6Swillf 42054925bf6Swillf if (temprdns[0] == NULL) { 42154925bf6Swillf retval = EINVAL; 42254925bf6Swillf goto cleanup; 42354925bf6Swillf } 42454925bf6Swillf 42554925bf6Swillf realmName = strdup(temprdns[0]); 42654925bf6Swillf if (realmName == NULL) { 42754925bf6Swillf retval = ENOMEM; 42854925bf6Swillf goto cleanup; 42954925bf6Swillf } 43054925bf6Swillf 43154925bf6Swillf if ((retval = krb5_ldap_read_realm_params(util_context, 43254925bf6Swillf realmName, &rparams, &rmask))) { 43354925bf6Swillf com_err(me, retval, gettext("while reading information of realm '%s'"), 43454925bf6Swillf realmName); 43554925bf6Swillf goto cleanup; 43654925bf6Swillf } 43754925bf6Swillf 43854925bf6Swillf if ((retval = krb5_ldap_add_service_rights(util_context, 43954925bf6Swillf srvparams->servicetype, srvparams->servicedn, 44054925bf6Swillf realmName, rparams->subtree, rightsmask))) { 44154925bf6Swillf printf(gettext("failed\n")); 44254925bf6Swillf com_err(me, retval, gettext("while assigning rights '%s'"), 44354925bf6Swillf srvparams->servicedn); 44454925bf6Swillf goto cleanup; 44554925bf6Swillf } 44654925bf6Swillf 44754925bf6Swillf if (rparams) 44854925bf6Swillf krb5_ldap_free_realm_params(rparams); 44954925bf6Swillf } 45054925bf6Swillf } 45154925bf6Swillf printf(gettext("done\n")); 45254925bf6Swillf } 45354925bf6Swillf goto cleanup; 45454925bf6Swillf 45554925bf6Swillf err_usage: 45654925bf6Swillf print_usage = TRUE; 45754925bf6Swillf 45854925bf6Swillf err_nomsg: 45954925bf6Swillf no_msg = TRUE; 46054925bf6Swillf 46154925bf6Swillf cleanup: 46254925bf6Swillf 46354925bf6Swillf if ((retval != 0) && (service_obj_created == TRUE)) { 46454925bf6Swillf /* This is for deleting the service object if something goes 46554925bf6Swillf * wrong in creating the service object 46654925bf6Swillf */ 46754925bf6Swillf 46854925bf6Swillf /* srvparams is populated from the user input and should be correct as 46954925bf6Swillf * we were successful in creating a service object. Reusing the same 47054925bf6Swillf */ 47154925bf6Swillf krb5_ldap_delete_service(util_context, srvparams, srvparams->servicedn); 47254925bf6Swillf } 47354925bf6Swillf 47454925bf6Swillf /* Clean-up structure */ 47554925bf6Swillf krb5_ldap_free_service (util_context, srvparams); 47654925bf6Swillf 47754925bf6Swillf if (extra_argv) { 47854925bf6Swillf free (extra_argv); 47954925bf6Swillf extra_argv = NULL; 48054925bf6Swillf } 48154925bf6Swillf if (realmName) { 48254925bf6Swillf free(realmName); 48354925bf6Swillf realmName = NULL; 48454925bf6Swillf } 48554925bf6Swillf if (print_usage) 48654925bf6Swillf db_usage (CREATE_SERVICE); 48754925bf6Swillf 48854925bf6Swillf if (retval) { 48954925bf6Swillf if (!no_msg) 49054925bf6Swillf com_err(me, retval, gettext("while creating service object")); 49154925bf6Swillf 49254925bf6Swillf exit_status++; 49354925bf6Swillf } 49454925bf6Swillf 49554925bf6Swillf return; 49654925bf6Swillf } 49754925bf6Swillf 49854925bf6Swillf 49954925bf6Swillf /* 50054925bf6Swillf * This function will modify the attributes of a given service 50154925bf6Swillf * object on the LDAP Server 50254925bf6Swillf */ 50354925bf6Swillf void kdb5_ldap_modify_service(argc, argv) 50454925bf6Swillf int argc; 50554925bf6Swillf char *argv[]; 50654925bf6Swillf { 507*dd9ccd46S /* Solaris Kerberos */ 508*dd9ccd46S char *me = progname; 50954925bf6Swillf krb5_error_code retval = 0; 51054925bf6Swillf krb5_ldap_service_params *srvparams = NULL; 51154925bf6Swillf krb5_boolean print_usage = FALSE; 51254925bf6Swillf krb5_boolean no_msg = FALSE; 51354925bf6Swillf char *servicedn = NULL; 51454925bf6Swillf int i = 0; 51554925bf6Swillf int in_mask = 0, out_mask = 0; 51654925bf6Swillf int srvhost_flag = 0, realmdn_flag = 0; 51754925bf6Swillf char **list = NULL; 51854925bf6Swillf int existing_entries = 0, new_entries = 0; 51954925bf6Swillf char **temp_ptr = NULL; 52054925bf6Swillf krb5_ldap_realm_params *rparams = NULL; 52154925bf6Swillf int j = 0; 52254925bf6Swillf int rmask = 0; 52354925bf6Swillf int rightsmask =0; 52454925bf6Swillf char **oldrealmrefs = NULL; 52554925bf6Swillf char **newrealmrefs = NULL; 52654925bf6Swillf char **temprdns = NULL; 52754925bf6Swillf char *realmName = NULL; 52854925bf6Swillf kdb5_dal_handle *dal_handle = NULL; 52954925bf6Swillf krb5_ldap_context *ldap_context=NULL; 53054925bf6Swillf 53154925bf6Swillf /* Check for number of arguments */ 53254925bf6Swillf if ((argc < 3) || (argc > 10)) { 53354925bf6Swillf exit_status++; 53454925bf6Swillf goto err_usage; 53554925bf6Swillf } 53654925bf6Swillf 53754925bf6Swillf dal_handle = (kdb5_dal_handle *) util_context->db_context; 53854925bf6Swillf ldap_context = (krb5_ldap_context *) dal_handle->db_context; 53954925bf6Swillf 54054925bf6Swillf /* Parse all arguments, only to pick up service DN (Pass 1) */ 54154925bf6Swillf for (i = 1; i < argc; i++) { 54254925bf6Swillf /* Skip arguments next to 'servicehost' 54354925bf6Swillf and 'realmdn' arguments */ 54454925bf6Swillf if (!strcmp(argv[i], "-servicehost")) { 54554925bf6Swillf ++i; 54654925bf6Swillf } else if (!strcmp(argv[i], "-clearservicehost")) { 54754925bf6Swillf ++i; 54854925bf6Swillf } else if (!strcmp(argv[i], "-addservicehost")) { 54954925bf6Swillf ++i; 55054925bf6Swillf } else if (!strcmp(argv[i], "-realm")) { 55154925bf6Swillf ++i; 55254925bf6Swillf } else if (!strcmp(argv[i], "-clearrealm")) { 55354925bf6Swillf ++i; 55454925bf6Swillf } else if (!strcmp(argv[i], "-addrealm")) { 55554925bf6Swillf ++i; 55654925bf6Swillf } else { /* Any other argument must be service DN */ 55754925bf6Swillf /* First check if service DN is already provided -- 55854925bf6Swillf if so, there's a usage error */ 55954925bf6Swillf if (servicedn != NULL) { 56054925bf6Swillf com_err(me, EINVAL, gettext("while modifying service object")); 56154925bf6Swillf goto err_usage; 56254925bf6Swillf } 56354925bf6Swillf 56454925bf6Swillf /* If not present already, fill up service DN */ 56554925bf6Swillf servicedn = strdup(argv[i]); 56654925bf6Swillf if (servicedn == NULL) { 56754925bf6Swillf com_err(me, ENOMEM, gettext("while modifying service object")); 56854925bf6Swillf goto err_nomsg; 56954925bf6Swillf } 57054925bf6Swillf } 57154925bf6Swillf } 57254925bf6Swillf 57354925bf6Swillf /* No point in proceeding further if service DN value is not available */ 57454925bf6Swillf if (servicedn == NULL) { 57554925bf6Swillf com_err(me, EINVAL, gettext("while modifying service object")); 57654925bf6Swillf goto err_usage; 57754925bf6Swillf } 57854925bf6Swillf 57954925bf6Swillf retval = krb5_ldap_read_service(util_context, servicedn, &srvparams, &in_mask); 58054925bf6Swillf if (retval) { 581*dd9ccd46S /* Solaris Kerberos */ 582*dd9ccd46S com_err(me, retval, gettext("while reading information of service '%s'"), 58354925bf6Swillf servicedn); 58454925bf6Swillf goto err_nomsg; 58554925bf6Swillf } 58654925bf6Swillf 58754925bf6Swillf /* Read Kerberos container info, to construct realm DN from name 58854925bf6Swillf * and for assigning rights 58954925bf6Swillf */ 59054925bf6Swillf if ((retval = krb5_ldap_read_krbcontainer_params(util_context, 59154925bf6Swillf &(ldap_context->krbcontainer)))) { 59254925bf6Swillf com_err(me, retval, gettext("while reading Kerberos container information")); 59354925bf6Swillf goto cleanup; 59454925bf6Swillf } 59554925bf6Swillf 59654925bf6Swillf /* Parse all arguments, but skip the service DN (Pass 2) */ 59754925bf6Swillf for (i = 1; i < argc; i++) { 59854925bf6Swillf if (!strcmp(argv[i], "-servicehost")) { 59954925bf6Swillf if (++i > argc - 1) 60054925bf6Swillf goto err_usage; 60154925bf6Swillf 60254925bf6Swillf /* Free the old list if available */ 60354925bf6Swillf if (srvparams->krbhostservers) { 60454925bf6Swillf krb5_free_list_entries (srvparams->krbhostservers); 60554925bf6Swillf free (srvparams->krbhostservers); 60654925bf6Swillf } 60754925bf6Swillf 60854925bf6Swillf srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES, 60954925bf6Swillf sizeof(char *)); 61054925bf6Swillf if (srvparams->krbhostservers == NULL) { 61154925bf6Swillf retval = ENOMEM; 61254925bf6Swillf goto cleanup; 61354925bf6Swillf } 61454925bf6Swillf 61554925bf6Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, 61654925bf6Swillf srvparams->krbhostservers))) { 61754925bf6Swillf goto cleanup; 61854925bf6Swillf } 61954925bf6Swillf 62054925bf6Swillf if ((retval = process_host_list (srvparams->krbhostservers, 62154925bf6Swillf srvparams->servicetype))) { 62254925bf6Swillf goto cleanup; 62354925bf6Swillf } 62454925bf6Swillf 62554925bf6Swillf out_mask |= LDAP_SERVICE_HOSTSERVER; 62654925bf6Swillf 62754925bf6Swillf /* Set flag to ignore 'add' and 'clear' */ 62854925bf6Swillf srvhost_flag = 1; 62954925bf6Swillf } else if (!strcmp(argv[i], "-clearservicehost")) { 63054925bf6Swillf if (++i > argc - 1) 63154925bf6Swillf goto err_usage; 63254925bf6Swillf 63354925bf6Swillf if (!srvhost_flag) { 63454925bf6Swillf /* If attribute doesn't exist, don't permit 'clear' option */ 63554925bf6Swillf if ((in_mask & LDAP_SERVICE_HOSTSERVER) == 0) { 63654925bf6Swillf /* Send out some proper error message here */ 63754925bf6Swillf com_err(me, EINVAL, gettext("service host list is empty\n")); 63854925bf6Swillf goto err_nomsg; 63954925bf6Swillf } 64054925bf6Swillf 64154925bf6Swillf /* Allocate list for processing */ 64254925bf6Swillf list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 64354925bf6Swillf if (list == NULL) { 64454925bf6Swillf retval = ENOMEM; 64554925bf6Swillf goto cleanup; 64654925bf6Swillf } 64754925bf6Swillf 64854925bf6Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) 64954925bf6Swillf goto cleanup; 65054925bf6Swillf 65154925bf6Swillf if ((retval = process_host_list (list, srvparams->servicetype))) { 65254925bf6Swillf goto cleanup; 65354925bf6Swillf } 65454925bf6Swillf 65554925bf6Swillf list_modify_str_array(&(srvparams->krbhostservers), 65654925bf6Swillf (const char**)list, LIST_MODE_DELETE); 65754925bf6Swillf 65854925bf6Swillf out_mask |= LDAP_SERVICE_HOSTSERVER; 65954925bf6Swillf 66054925bf6Swillf /* Clean up */ 66154925bf6Swillf free (list); 66254925bf6Swillf list = NULL; 66354925bf6Swillf } 66454925bf6Swillf } else if (!strcmp(argv[i], "-addservicehost")) { 66554925bf6Swillf if (++i > argc - 1) 66654925bf6Swillf goto err_usage; 66754925bf6Swillf 66854925bf6Swillf if (!srvhost_flag) { 66954925bf6Swillf /* Allocate list for processing */ 67054925bf6Swillf list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 67154925bf6Swillf if (list == NULL) { 67254925bf6Swillf retval = ENOMEM; 67354925bf6Swillf goto cleanup; 67454925bf6Swillf } 67554925bf6Swillf 67654925bf6Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) 67754925bf6Swillf goto cleanup; 67854925bf6Swillf 67954925bf6Swillf if ((retval = process_host_list (list, srvparams->servicetype))) { 68054925bf6Swillf goto cleanup; 68154925bf6Swillf } 68254925bf6Swillf 68354925bf6Swillf /* Call list_modify_str_array() only if host server attribute 68454925bf6Swillf * exists already --Actually, it's better to handle this 68554925bf6Swillf * within list_modify_str_array() 68654925bf6Swillf */ 68754925bf6Swillf if (in_mask & LDAP_SERVICE_HOSTSERVER) { 68854925bf6Swillf /* Re-size existing list */ 68954925bf6Swillf existing_entries = list_count_str_array(srvparams->krbhostservers); 69054925bf6Swillf new_entries = list_count_str_array(list); 69154925bf6Swillf temp_ptr = (char **) realloc(srvparams->krbhostservers, 69254925bf6Swillf sizeof(char *) * (existing_entries + new_entries + 1)); 69354925bf6Swillf if (temp_ptr == NULL) { 69454925bf6Swillf retval = ENOMEM; 69554925bf6Swillf goto cleanup; 69654925bf6Swillf } 69754925bf6Swillf srvparams->krbhostservers = temp_ptr; 69854925bf6Swillf 69954925bf6Swillf list_modify_str_array(&(srvparams->krbhostservers), 70054925bf6Swillf (const char**)list, LIST_MODE_ADD); 70154925bf6Swillf 70254925bf6Swillf /* Clean up */ 70354925bf6Swillf free (list); 70454925bf6Swillf list = NULL; 70554925bf6Swillf } else 70654925bf6Swillf srvparams->krbhostservers = list; 70754925bf6Swillf 70854925bf6Swillf out_mask |= LDAP_SERVICE_HOSTSERVER; 70954925bf6Swillf } 71054925bf6Swillf } else if (!strcmp(argv[i], "-realm")) { 71154925bf6Swillf if (++i > argc - 1) 71254925bf6Swillf goto err_usage; 71354925bf6Swillf 71454925bf6Swillf if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences)) { 71554925bf6Swillf if (!oldrealmrefs) { 71654925bf6Swillf /* Store the old realm list for removing rights */ 71754925bf6Swillf oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 71854925bf6Swillf if (oldrealmrefs == NULL) { 71954925bf6Swillf retval = ENOMEM; 72054925bf6Swillf goto cleanup; 72154925bf6Swillf } 72254925bf6Swillf 72354925bf6Swillf for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) { 72454925bf6Swillf oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]); 72554925bf6Swillf if (oldrealmrefs[j] == NULL) { 72654925bf6Swillf retval = ENOMEM; 72754925bf6Swillf goto cleanup; 72854925bf6Swillf } 72954925bf6Swillf } 73054925bf6Swillf oldrealmrefs[j] = NULL; 73154925bf6Swillf } 73254925bf6Swillf 73354925bf6Swillf /* Free the old list if available */ 73454925bf6Swillf krb5_free_list_entries (srvparams->krbrealmreferences); 73554925bf6Swillf free (srvparams->krbrealmreferences); 73654925bf6Swillf } 73754925bf6Swillf 73854925bf6Swillf srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES, 73954925bf6Swillf sizeof(char *)); 74054925bf6Swillf if (srvparams->krbrealmreferences == NULL) { 74154925bf6Swillf retval = ENOMEM; 74254925bf6Swillf goto cleanup; 74354925bf6Swillf } 74454925bf6Swillf 74554925bf6Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, 74654925bf6Swillf srvparams->krbrealmreferences))) { 74754925bf6Swillf goto cleanup; 74854925bf6Swillf } 74954925bf6Swillf 75054925bf6Swillf /* Convert realm names to realm DNs */ 75154925bf6Swillf if ((retval = convert_realm_name2dn_list( 75254925bf6Swillf srvparams->krbrealmreferences, 75354925bf6Swillf ldap_context->krbcontainer->DN))) { 75454925bf6Swillf goto cleanup; 75554925bf6Swillf } 75654925bf6Swillf 75754925bf6Swillf out_mask |= LDAP_SERVICE_REALMREFERENCE; 75854925bf6Swillf 75954925bf6Swillf /* Set flag to ignore 'add' and 'clear' */ 76054925bf6Swillf realmdn_flag = 1; 76154925bf6Swillf } else if (!strcmp(argv[i], "-clearrealm")) { 76254925bf6Swillf if (++i > argc - 1) 76354925bf6Swillf goto err_usage; 76454925bf6Swillf 76554925bf6Swillf if (!realmdn_flag) { 76654925bf6Swillf /* If attribute doesn't exist, don't permit 'clear' option */ 76754925bf6Swillf if (((in_mask & LDAP_SERVICE_REALMREFERENCE) == 0) || (srvparams->krbrealmreferences == NULL)) { 76854925bf6Swillf /* Send out some proper error message here */ 76954925bf6Swillf goto err_nomsg; 77054925bf6Swillf } 77154925bf6Swillf 77254925bf6Swillf if (!oldrealmrefs) { 77354925bf6Swillf /* Store the old realm list for removing rights */ 77454925bf6Swillf oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 77554925bf6Swillf if (oldrealmrefs == NULL) { 77654925bf6Swillf retval = ENOMEM; 77754925bf6Swillf goto cleanup; 77854925bf6Swillf } 77954925bf6Swillf 78054925bf6Swillf for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) { 78154925bf6Swillf oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]); 78254925bf6Swillf if (oldrealmrefs[j] == NULL) { 78354925bf6Swillf retval = ENOMEM; 78454925bf6Swillf goto cleanup; 78554925bf6Swillf } 78654925bf6Swillf } 78754925bf6Swillf oldrealmrefs[j] = NULL; 78854925bf6Swillf } 78954925bf6Swillf 79054925bf6Swillf /* Allocate list for processing */ 79154925bf6Swillf list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 79254925bf6Swillf if (list == NULL) { 79354925bf6Swillf retval = ENOMEM; 79454925bf6Swillf goto cleanup; 79554925bf6Swillf } 79654925bf6Swillf 79754925bf6Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) 79854925bf6Swillf goto cleanup; 79954925bf6Swillf 80054925bf6Swillf /* Convert realm names to realm DNs */ 80154925bf6Swillf if ((retval = convert_realm_name2dn_list(list, 80254925bf6Swillf ldap_context->krbcontainer->DN))) { 80354925bf6Swillf goto cleanup; 80454925bf6Swillf } 80554925bf6Swillf 80654925bf6Swillf list_modify_str_array(&(srvparams->krbrealmreferences), 80754925bf6Swillf (const char**)list, LIST_MODE_DELETE); 80854925bf6Swillf 80954925bf6Swillf out_mask |= LDAP_SERVICE_REALMREFERENCE; 81054925bf6Swillf 81154925bf6Swillf /* Clean up */ 81254925bf6Swillf free (list); 81354925bf6Swillf list = NULL; 81454925bf6Swillf } 81554925bf6Swillf } else if (!strcmp(argv[i], "-addrealm")) { 81654925bf6Swillf if (++i > argc - 1) 81754925bf6Swillf goto err_usage; 81854925bf6Swillf 81954925bf6Swillf if (!realmdn_flag) { 82054925bf6Swillf /* Allocate list for processing */ 82154925bf6Swillf list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 82254925bf6Swillf if (list == NULL) { 82354925bf6Swillf retval = ENOMEM; 82454925bf6Swillf goto cleanup; 82554925bf6Swillf } 82654925bf6Swillf 82754925bf6Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) 82854925bf6Swillf goto cleanup; 82954925bf6Swillf 83054925bf6Swillf /* Convert realm names to realm DNs */ 83154925bf6Swillf if ((retval = convert_realm_name2dn_list(list, 83254925bf6Swillf ldap_context->krbcontainer->DN))) { 83354925bf6Swillf goto cleanup; 83454925bf6Swillf } 83554925bf6Swillf 83654925bf6Swillf if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences) && (!oldrealmrefs)) { 83754925bf6Swillf /* Store the old realm list for removing rights */ 83854925bf6Swillf oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 83954925bf6Swillf if (oldrealmrefs == NULL) { 84054925bf6Swillf retval = ENOMEM; 84154925bf6Swillf goto cleanup; 84254925bf6Swillf } 84354925bf6Swillf 84454925bf6Swillf for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) { 84554925bf6Swillf oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]); 84654925bf6Swillf if (oldrealmrefs[j] == NULL) { 84754925bf6Swillf retval = ENOMEM; 84854925bf6Swillf goto cleanup; 84954925bf6Swillf } 85054925bf6Swillf } 85154925bf6Swillf oldrealmrefs[j] = NULL; 85254925bf6Swillf } 85354925bf6Swillf 85454925bf6Swillf /* Call list_modify_str_array() only if realm DN attribute 85554925bf6Swillf * exists already -- Actually, it's better to handle this 85654925bf6Swillf * within list_modify_str_array() */ 85754925bf6Swillf if (in_mask & LDAP_SERVICE_REALMREFERENCE) { 85854925bf6Swillf /* Re-size existing list */ 85954925bf6Swillf existing_entries = list_count_str_array( 86054925bf6Swillf srvparams->krbrealmreferences); 86154925bf6Swillf new_entries = list_count_str_array(list); 86254925bf6Swillf temp_ptr = (char **) realloc(srvparams->krbrealmreferences, 86354925bf6Swillf sizeof(char *) * (existing_entries + new_entries + 1)); 86454925bf6Swillf if (temp_ptr == NULL) { 86554925bf6Swillf retval = ENOMEM; 86654925bf6Swillf goto cleanup; 86754925bf6Swillf } 86854925bf6Swillf srvparams->krbrealmreferences = temp_ptr; 86954925bf6Swillf 87054925bf6Swillf list_modify_str_array(&(srvparams->krbrealmreferences), 87154925bf6Swillf (const char**)list, LIST_MODE_ADD); 87254925bf6Swillf 87354925bf6Swillf /* Clean up */ 87454925bf6Swillf free (list); 87554925bf6Swillf list = NULL; 87654925bf6Swillf } else 87754925bf6Swillf srvparams->krbrealmreferences = list; 87854925bf6Swillf 87954925bf6Swillf out_mask |= LDAP_SERVICE_REALMREFERENCE; 88054925bf6Swillf } 88154925bf6Swillf } else { 88254925bf6Swillf /* Any other argument must be service DN 88354925bf6Swillf -- skip it */ 88454925bf6Swillf } 88554925bf6Swillf } 88654925bf6Swillf 88754925bf6Swillf /* Modify attributes of object */ 88854925bf6Swillf if ((retval = krb5_ldap_modify_service(util_context, srvparams, out_mask))) 88954925bf6Swillf goto cleanup; 89054925bf6Swillf 89154925bf6Swillf /* Service rights modification code */ 89254925bf6Swillf if (out_mask & LDAP_SERVICE_REALMREFERENCE) { 89354925bf6Swillf 89454925bf6Swillf printf("%s", gettext("Changing rights for the service object. Please wait ... ")); 89554925bf6Swillf fflush(stdout); 89654925bf6Swillf 89754925bf6Swillf newrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*)); 89854925bf6Swillf if (newrealmrefs == NULL) { 89954925bf6Swillf retval = ENOMEM; 90054925bf6Swillf goto cleanup; 90154925bf6Swillf } 90254925bf6Swillf 90354925bf6Swillf if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) { 90454925bf6Swillf for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) { 90554925bf6Swillf newrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]); 90654925bf6Swillf if (newrealmrefs[j] == NULL) { 90754925bf6Swillf retval = ENOMEM; 90854925bf6Swillf goto cleanup; 90954925bf6Swillf } 91054925bf6Swillf } 91154925bf6Swillf newrealmrefs[j] = NULL; 91254925bf6Swillf } 91354925bf6Swillf disjoint_members(oldrealmrefs, newrealmrefs); 91454925bf6Swillf 91554925bf6Swillf /* Delete the rights for the given service, on each of the realm 91654925bf6Swillf * container & subtree in the old realm reference list. 91754925bf6Swillf */ 91854925bf6Swillf if (oldrealmrefs) { 91954925bf6Swillf rightsmask = 0; 92054925bf6Swillf rightsmask |= LDAP_REALM_RIGHTS; 92154925bf6Swillf rightsmask |= LDAP_SUBTREE_RIGHTS; 92254925bf6Swillf 92354925bf6Swillf for (i = 0; (oldrealmrefs[i] != NULL); i++) { 92454925bf6Swillf /* Get the realm name, not the dn */ 92554925bf6Swillf temprdns = ldap_explode_dn(oldrealmrefs[i], 1); 92654925bf6Swillf 92754925bf6Swillf if (temprdns[0] == NULL) { 92854925bf6Swillf retval = EINVAL; 92954925bf6Swillf goto cleanup; 93054925bf6Swillf } 93154925bf6Swillf 93254925bf6Swillf realmName = strdup(temprdns[0]); 93354925bf6Swillf if (realmName == NULL) { 93454925bf6Swillf retval = ENOMEM; 93554925bf6Swillf goto cleanup; 93654925bf6Swillf } 93754925bf6Swillf 93854925bf6Swillf if ((retval = krb5_ldap_read_realm_params(util_context, 93954925bf6Swillf realmName, &rparams, &rmask))) { 94054925bf6Swillf com_err(me, retval, gettext("while reading information of realm '%s'"), 94154925bf6Swillf realmName); 94254925bf6Swillf goto err_nomsg; 94354925bf6Swillf } 94454925bf6Swillf 94554925bf6Swillf if ((retval = krb5_ldap_delete_service_rights(util_context, 94654925bf6Swillf srvparams->servicetype, srvparams->servicedn, 94754925bf6Swillf realmName, rparams->subtree, rightsmask))) { 94854925bf6Swillf printf(gettext("failed\n")); 94954925bf6Swillf com_err(me, retval, gettext("while assigning rights '%s'"), 95054925bf6Swillf srvparams->servicedn); 95154925bf6Swillf goto err_nomsg; 95254925bf6Swillf } 95354925bf6Swillf 95454925bf6Swillf if (rparams) 95554925bf6Swillf krb5_ldap_free_realm_params(rparams); 95654925bf6Swillf } 95754925bf6Swillf } 95854925bf6Swillf 95954925bf6Swillf /* Add the rights for the given service, on each of the realm 96054925bf6Swillf * container & subtree in the new realm reference list. 96154925bf6Swillf */ 96254925bf6Swillf if (newrealmrefs) { 96354925bf6Swillf rightsmask = 0; 96454925bf6Swillf rightsmask |= LDAP_REALM_RIGHTS; 96554925bf6Swillf rightsmask |= LDAP_SUBTREE_RIGHTS; 96654925bf6Swillf 96754925bf6Swillf for (i = 0; (newrealmrefs[i] != NULL); i++) { 96854925bf6Swillf /* Get the realm name, not the dn */ 96954925bf6Swillf temprdns = ldap_explode_dn(newrealmrefs[i], 1); 97054925bf6Swillf 97154925bf6Swillf if (temprdns[0] == NULL) { 97254925bf6Swillf retval = EINVAL; 97354925bf6Swillf goto cleanup; 97454925bf6Swillf } 97554925bf6Swillf 97654925bf6Swillf realmName = strdup(temprdns[0]); 97754925bf6Swillf if (realmName == NULL) { 97854925bf6Swillf retval = ENOMEM; 97954925bf6Swillf goto cleanup; 98054925bf6Swillf } 98154925bf6Swillf 98254925bf6Swillf if ((retval = krb5_ldap_read_krbcontainer_params(util_context, 98354925bf6Swillf &(ldap_context->krbcontainer)))) { 98454925bf6Swillf com_err(me, retval, 98554925bf6Swillf gettext("while reading Kerberos container information")); 98654925bf6Swillf goto cleanup; 98754925bf6Swillf } 98854925bf6Swillf 98954925bf6Swillf if ((retval = krb5_ldap_read_realm_params(util_context, 99054925bf6Swillf realmName, &rparams, &rmask))) { 99154925bf6Swillf com_err(me, retval, gettext("while reading information of realm '%s'"), 99254925bf6Swillf realmName); 99354925bf6Swillf goto err_nomsg; 99454925bf6Swillf } 99554925bf6Swillf 99654925bf6Swillf if ((retval = krb5_ldap_add_service_rights(util_context, 99754925bf6Swillf srvparams->servicetype, srvparams->servicedn, 99854925bf6Swillf realmName, rparams->subtree, rightsmask))) { 99954925bf6Swillf printf(gettext("failed\n")); 100054925bf6Swillf com_err(me, retval, gettext("while assigning rights '%s'"), 100154925bf6Swillf srvparams->servicedn); 100254925bf6Swillf goto err_nomsg; 100354925bf6Swillf } 100454925bf6Swillf 100554925bf6Swillf if (rparams) { 100654925bf6Swillf krb5_ldap_free_realm_params(rparams); 100754925bf6Swillf rparams = NULL; 100854925bf6Swillf } 100954925bf6Swillf } 101054925bf6Swillf printf(gettext("done\n")); 101154925bf6Swillf } 101254925bf6Swillf } 101354925bf6Swillf goto cleanup; 101454925bf6Swillf 101554925bf6Swillf err_usage: 101654925bf6Swillf print_usage = TRUE; 101754925bf6Swillf 101854925bf6Swillf err_nomsg: 101954925bf6Swillf no_msg = TRUE; 102054925bf6Swillf 102154925bf6Swillf cleanup: 102254925bf6Swillf /* Clean-up structure */ 102354925bf6Swillf krb5_ldap_free_service(util_context, srvparams); 102454925bf6Swillf 102554925bf6Swillf if (servicedn) 102654925bf6Swillf free(servicedn); 102754925bf6Swillf 102854925bf6Swillf if (list) { 102954925bf6Swillf free(list); 103054925bf6Swillf list = NULL; 103154925bf6Swillf } 103254925bf6Swillf 103354925bf6Swillf if (oldrealmrefs) { 103454925bf6Swillf for (i = 0; oldrealmrefs[i] != NULL; i++) 103554925bf6Swillf free(oldrealmrefs[i]); 103654925bf6Swillf free(oldrealmrefs); 103754925bf6Swillf } 103854925bf6Swillf 103954925bf6Swillf if (newrealmrefs) { 104054925bf6Swillf for (i = 0; newrealmrefs[i] != NULL; i++) 104154925bf6Swillf free(newrealmrefs[i]); 104254925bf6Swillf free(newrealmrefs); 104354925bf6Swillf } 104454925bf6Swillf if (realmName) { 104554925bf6Swillf free(realmName); 104654925bf6Swillf realmName = NULL; 104754925bf6Swillf } 104854925bf6Swillf 104954925bf6Swillf if (print_usage) 105054925bf6Swillf db_usage(MODIFY_SERVICE); 105154925bf6Swillf 105254925bf6Swillf if (retval) { 105354925bf6Swillf if (!no_msg) 105454925bf6Swillf com_err(me, retval, gettext("while modifying service object")); 105554925bf6Swillf exit_status++; 105654925bf6Swillf } 105754925bf6Swillf 105854925bf6Swillf return; 105954925bf6Swillf } 106054925bf6Swillf 106154925bf6Swillf 106254925bf6Swillf /* 106354925bf6Swillf * This function will delete the entry corresponding to the service object 106454925bf6Swillf * from the service password file. 106554925bf6Swillf */ 106654925bf6Swillf static krb5_error_code 106754925bf6Swillf rem_service_entry_from_file(argc, argv, file_name, service_object) 106854925bf6Swillf int argc; 106954925bf6Swillf char *argv[]; 107054925bf6Swillf char *file_name; 107154925bf6Swillf char *service_object; 107254925bf6Swillf { 107354925bf6Swillf int st = EINVAL; 1074*dd9ccd46S /* Solaris Kerberos */ 1075*dd9ccd46S char *me = progname; 107654925bf6Swillf char *tmp_file = NULL; 107754925bf6Swillf int tmpfd = -1; 107854925bf6Swillf FILE *pfile = NULL; 107954925bf6Swillf unsigned int len = 0; 108054925bf6Swillf char line[MAX_LEN]={0}; 108154925bf6Swillf mode_t omask = umask(077); 108254925bf6Swillf 108354925bf6Swillf /* Check for permissions on the password file */ 108454925bf6Swillf if (access(file_name, W_OK) == -1) { 108554925bf6Swillf /* If the specified file itself is not there, no need to show error */ 108654925bf6Swillf if (errno == ENOENT) { 108754925bf6Swillf st=0; 108854925bf6Swillf goto cleanup; 108954925bf6Swillf } else { 109054925bf6Swillf com_err(me, errno, gettext("while deleting entry from file %s", file_name)); 109154925bf6Swillf goto cleanup; 109254925bf6Swillf } 109354925bf6Swillf } 109454925bf6Swillf 109554925bf6Swillf /* Create a temporary file which contains all the entries except the 109654925bf6Swillf entry for the given service dn */ 109754925bf6Swillf pfile = fopen(file_name, "r+F"); 109854925bf6Swillf if (pfile == NULL) { 109954925bf6Swillf com_err(me, errno, gettext("while deleting entry from file %s"), file_name); 110054925bf6Swillf goto cleanup; 110154925bf6Swillf } 110254925bf6Swillf 110354925bf6Swillf /* Create a new file with the extension .tmp */ 110454925bf6Swillf tmp_file = (char *)malloc(strlen(file_name) + 4 + 1); 110554925bf6Swillf if (tmp_file == NULL) { 110654925bf6Swillf com_err(me, ENOMEM, gettext("while deleting entry from file")); 110754925bf6Swillf fclose(pfile); 110854925bf6Swillf goto cleanup; 110954925bf6Swillf } 111054925bf6Swillf snprintf (tmp_file, strlen(file_name) + 4 + 1, "%s%s", file_name, ".tmp"); 111154925bf6Swillf 111254925bf6Swillf 111354925bf6Swillf tmpfd = creat(tmp_file, S_IRUSR|S_IWUSR); 111454925bf6Swillf umask(omask); 111554925bf6Swillf if (tmpfd == -1) { 111654925bf6Swillf com_err(me, errno, gettext("while deleting entry from file\n")); 111754925bf6Swillf fclose(pfile); 111854925bf6Swillf goto cleanup; 111954925bf6Swillf } 112054925bf6Swillf 112154925bf6Swillf /* Copy only those lines which donot have the specified service dn */ 112254925bf6Swillf while (fgets(line, MAX_LEN, pfile) != NULL) { 112354925bf6Swillf if ((strstr(line, service_object) != NULL) && 112454925bf6Swillf (line[strlen(service_object)] == '#')) { 112554925bf6Swillf continue; 112654925bf6Swillf } else { 112754925bf6Swillf len = strlen(line); 112854925bf6Swillf if (write(tmpfd, line, len) != len) { 112954925bf6Swillf com_err(me, errno, gettext("while deleting entry from file\n")); 113054925bf6Swillf close(tmpfd); 113154925bf6Swillf unlink(tmp_file); 113254925bf6Swillf fclose(pfile); 113354925bf6Swillf goto cleanup; 113454925bf6Swillf } 113554925bf6Swillf } 113654925bf6Swillf } 113754925bf6Swillf 113854925bf6Swillf fclose(pfile); 113954925bf6Swillf if (unlink(file_name) == 0) { 114054925bf6Swillf link(tmp_file, file_name); 114154925bf6Swillf } else { 114254925bf6Swillf com_err(me, errno, gettext("while deleting entry from file\n")); 114354925bf6Swillf } 114454925bf6Swillf unlink(tmp_file); 114554925bf6Swillf 114654925bf6Swillf st=0; 114754925bf6Swillf 114854925bf6Swillf cleanup: 114954925bf6Swillf 115054925bf6Swillf if (tmp_file) 115154925bf6Swillf free(tmp_file); 115254925bf6Swillf 115354925bf6Swillf return st; 115454925bf6Swillf } 115554925bf6Swillf 115654925bf6Swillf 115754925bf6Swillf /* 115854925bf6Swillf * This function will delete the service object from the LDAP Server 115954925bf6Swillf * and unlink the references to the Realm objects (if any) 116054925bf6Swillf */ 116154925bf6Swillf void 116254925bf6Swillf kdb5_ldap_destroy_service(argc, argv) 116354925bf6Swillf int argc; 116454925bf6Swillf char *argv[]; 116554925bf6Swillf { 116654925bf6Swillf int i = 0; 116754925bf6Swillf char buf[5] = {0}; 116854925bf6Swillf krb5_error_code retval = EINVAL; 116954925bf6Swillf int force = 0; 117054925bf6Swillf char *servicedn = NULL; 117154925bf6Swillf char *stashfilename = NULL; 117254925bf6Swillf int mask = 0; 117354925bf6Swillf krb5_ldap_service_params *lserparams = NULL; 117454925bf6Swillf krb5_boolean print_usage = FALSE; 117554925bf6Swillf 117654925bf6Swillf if ((argc < 2) || (argc > 5)) { 117754925bf6Swillf exit_status++; 117854925bf6Swillf goto err_usage; 117954925bf6Swillf } 118054925bf6Swillf 118154925bf6Swillf for (i=1; i < argc; i++) { 118254925bf6Swillf 118354925bf6Swillf if (strcmp(argv[i],"-force")==0) { 118454925bf6Swillf force++; 118554925bf6Swillf } else if (strcmp(argv[i],"-f")==0) { 118654925bf6Swillf if (argv[i+1]) { 118754925bf6Swillf stashfilename=strdup(argv[i+1]); 118854925bf6Swillf if (stashfilename == NULL) { 1189*dd9ccd46S /* Solaris Kerberos */ 1190*dd9ccd46S com_err(progname, ENOMEM, gettext("while destroying service")); 119154925bf6Swillf exit_status++; 119254925bf6Swillf goto cleanup; 119354925bf6Swillf } 119454925bf6Swillf i++; 119554925bf6Swillf } else { 119654925bf6Swillf exit_status++; 119754925bf6Swillf goto err_usage; 119854925bf6Swillf } 119954925bf6Swillf } else { 120054925bf6Swillf if ((argv[i]) && (servicedn == NULL)) { 120154925bf6Swillf servicedn=strdup(argv[i]); 120254925bf6Swillf if (servicedn == NULL) { 1203*dd9ccd46S /* Solaris Kerberos */ 1204*dd9ccd46S com_err(progname, ENOMEM, gettext("while destroying service")); 120554925bf6Swillf exit_status++; 120654925bf6Swillf goto cleanup; 120754925bf6Swillf } 120854925bf6Swillf } else { 120954925bf6Swillf exit_status++; 121054925bf6Swillf goto err_usage; 121154925bf6Swillf } 121254925bf6Swillf } 121354925bf6Swillf } 121454925bf6Swillf 121554925bf6Swillf if (!servicedn) { 121654925bf6Swillf exit_status++; 121754925bf6Swillf goto err_usage; 121854925bf6Swillf } 121954925bf6Swillf 122054925bf6Swillf if (!force) { 122154925bf6Swillf printf(gettext("This will delete the service object '%s', are you sure?\n"), servicedn); 122254925bf6Swillf printf(gettext("(type 'yes' to confirm)? ")); 122354925bf6Swillf if (fgets(buf, sizeof(buf), stdin) == NULL) { 122454925bf6Swillf exit_status++; 122554925bf6Swillf goto cleanup;; 122654925bf6Swillf } 122754925bf6Swillf if (strcmp(buf, yes)) { 122854925bf6Swillf exit_status++; 122954925bf6Swillf goto cleanup; 123054925bf6Swillf } 123154925bf6Swillf } 123254925bf6Swillf 123354925bf6Swillf if ((retval = krb5_ldap_read_service(util_context, servicedn, 123454925bf6Swillf &lserparams, &mask))) { 1235*dd9ccd46S /* Solaris Kerberos */ 1236*dd9ccd46S com_err(progname, retval, gettext("while destroying service '%s'"), servicedn); 123754925bf6Swillf exit_status++; 123854925bf6Swillf goto cleanup; 123954925bf6Swillf } 124054925bf6Swillf 124154925bf6Swillf retval = krb5_ldap_delete_service(util_context, lserparams, servicedn); 124254925bf6Swillf 124354925bf6Swillf if (retval) { 1244*dd9ccd46S /* Solaris Kerberos */ 1245*dd9ccd46S com_err(progname, retval, gettext("while destroying service '%s'"), servicedn); 124654925bf6Swillf exit_status++; 124754925bf6Swillf goto cleanup; 124854925bf6Swillf } 124954925bf6Swillf 125054925bf6Swillf if (stashfilename == NULL) { 125154925bf6Swillf stashfilename = strdup(DEF_SERVICE_PASSWD_FILE); 125254925bf6Swillf if (stashfilename == NULL) { 1253*dd9ccd46S /* Solaris Kerberos */ 1254*dd9ccd46S com_err(progname, ENOMEM, gettext("while destroying service")); 125554925bf6Swillf exit_status++; 125654925bf6Swillf goto cleanup; 125754925bf6Swillf } 125854925bf6Swillf } 125954925bf6Swillf printf(gettext("** service object '%s' deleted.\n"), servicedn); 126054925bf6Swillf retval = rem_service_entry_from_file(argc, argv, stashfilename, servicedn); 126154925bf6Swillf 126254925bf6Swillf if (retval) 126354925bf6Swillf printf(gettext("** error removing service object entry '%s' from password file.\n"), 126454925bf6Swillf servicedn); 126554925bf6Swillf 126654925bf6Swillf goto cleanup; 126754925bf6Swillf 126854925bf6Swillf 126954925bf6Swillf err_usage: 127054925bf6Swillf print_usage = TRUE; 127154925bf6Swillf 127254925bf6Swillf cleanup: 127354925bf6Swillf 127454925bf6Swillf if (lserparams) { 127554925bf6Swillf krb5_ldap_free_service(util_context, lserparams); 127654925bf6Swillf } 127754925bf6Swillf 127854925bf6Swillf if (servicedn) { 127954925bf6Swillf free(servicedn); 128054925bf6Swillf } 128154925bf6Swillf 128254925bf6Swillf if (stashfilename) { 128354925bf6Swillf free(stashfilename); 128454925bf6Swillf } 128554925bf6Swillf 128654925bf6Swillf if (print_usage) { 128754925bf6Swillf db_usage(DESTROY_SERVICE); 128854925bf6Swillf } 128954925bf6Swillf 129054925bf6Swillf return; 129154925bf6Swillf } 129254925bf6Swillf 129354925bf6Swillf 129454925bf6Swillf /* 129554925bf6Swillf * This function will display information about the given service object 129654925bf6Swillf */ 129754925bf6Swillf void kdb5_ldap_view_service(argc, argv) 129854925bf6Swillf int argc; 129954925bf6Swillf char *argv[]; 130054925bf6Swillf { 130154925bf6Swillf krb5_ldap_service_params *lserparams = NULL; 130254925bf6Swillf krb5_error_code retval = 0; 130354925bf6Swillf char *servicedn = NULL; 130454925bf6Swillf int mask = 0; 130554925bf6Swillf krb5_boolean print_usage = FALSE; 130654925bf6Swillf 130754925bf6Swillf if (!(argc == 2)) { 130854925bf6Swillf exit_status++; 130954925bf6Swillf goto err_usage; 131054925bf6Swillf } 131154925bf6Swillf 131254925bf6Swillf servicedn=strdup(argv[1]); 131354925bf6Swillf if (servicedn == NULL) { 1314*dd9ccd46S /* Solaris Kerberos */ 1315*dd9ccd46S com_err(progname, ENOMEM, gettext("while viewing service")); 131654925bf6Swillf exit_status++; 131754925bf6Swillf goto cleanup; 131854925bf6Swillf } 131954925bf6Swillf 132054925bf6Swillf if ((retval = krb5_ldap_read_service(util_context, servicedn, &lserparams, &mask))) { 1321*dd9ccd46S /* Solaris Kerberos */ 1322*dd9ccd46S com_err(progname, retval, gettext("while viewing service '%s'"), servicedn); 132354925bf6Swillf exit_status++; 132454925bf6Swillf goto cleanup; 132554925bf6Swillf } 132654925bf6Swillf 132754925bf6Swillf print_service_params(lserparams, mask); 132854925bf6Swillf 132954925bf6Swillf goto cleanup; 133054925bf6Swillf 133154925bf6Swillf err_usage: 133254925bf6Swillf print_usage = TRUE; 133354925bf6Swillf 133454925bf6Swillf cleanup: 133554925bf6Swillf 133654925bf6Swillf if (lserparams) { 133754925bf6Swillf krb5_ldap_free_service(util_context, lserparams); 133854925bf6Swillf } 133954925bf6Swillf 134054925bf6Swillf if (servicedn) 134154925bf6Swillf free(servicedn); 134254925bf6Swillf 134354925bf6Swillf if (print_usage) { 134454925bf6Swillf db_usage(VIEW_SERVICE); 134554925bf6Swillf } 134654925bf6Swillf 134754925bf6Swillf return; 134854925bf6Swillf } 134954925bf6Swillf 135054925bf6Swillf 135154925bf6Swillf /* 135254925bf6Swillf * This function will list the DNs of kerberos services present on 135354925bf6Swillf * the LDAP Server under a specific sub-tree (entire tree by default) 135454925bf6Swillf */ 135554925bf6Swillf void kdb5_ldap_list_services(argc, argv) 135654925bf6Swillf int argc; 135754925bf6Swillf char *argv[]; 135854925bf6Swillf { 1359*dd9ccd46S /* Solaris Kerberos */ 1360*dd9ccd46S char *me = progname; 136154925bf6Swillf krb5_error_code retval = 0; 136254925bf6Swillf char *basedn = NULL; 136354925bf6Swillf char **list = NULL; 136454925bf6Swillf char **plist = NULL; 136554925bf6Swillf krb5_boolean print_usage = FALSE; 136654925bf6Swillf 136754925bf6Swillf /* Check for number of arguments */ 136854925bf6Swillf if ((argc != 1) && (argc != 3)) { 136954925bf6Swillf exit_status++; 137054925bf6Swillf goto err_usage; 137154925bf6Swillf } 137254925bf6Swillf 137354925bf6Swillf /* Parse base DN argument if present */ 137454925bf6Swillf if (argc == 3) { 137554925bf6Swillf if (strcmp(argv[1], "-basedn")) { 137654925bf6Swillf retval = EINVAL; 137754925bf6Swillf goto err_usage; 137854925bf6Swillf } 137954925bf6Swillf 138054925bf6Swillf basedn = strdup(argv[2]); 138154925bf6Swillf if (basedn == NULL) { 138254925bf6Swillf com_err(me, ENOMEM, gettext("while listing services")); 138354925bf6Swillf exit_status++; 138454925bf6Swillf goto cleanup; 138554925bf6Swillf } 138654925bf6Swillf } 138754925bf6Swillf 138854925bf6Swillf retval = krb5_ldap_list_services(util_context, basedn, &list); 138954925bf6Swillf if ((retval != 0) || (list == NULL)) { 139054925bf6Swillf exit_status++; 139154925bf6Swillf goto cleanup; 139254925bf6Swillf } 139354925bf6Swillf 139454925bf6Swillf for (plist = list; *plist != NULL; plist++) { 139554925bf6Swillf printf("%s\n", *plist); 139654925bf6Swillf } 139754925bf6Swillf 139854925bf6Swillf goto cleanup; 139954925bf6Swillf 140054925bf6Swillf err_usage: 140154925bf6Swillf print_usage = TRUE; 140254925bf6Swillf 140354925bf6Swillf cleanup: 140454925bf6Swillf if (list != NULL) { 140554925bf6Swillf krb5_free_list_entries (list); 140654925bf6Swillf free (list); 140754925bf6Swillf } 140854925bf6Swillf 140954925bf6Swillf if (basedn) 141054925bf6Swillf free (basedn); 141154925bf6Swillf 141254925bf6Swillf if (print_usage) { 141354925bf6Swillf db_usage(LIST_SERVICE); 141454925bf6Swillf } 141554925bf6Swillf 141654925bf6Swillf if (retval) { 141754925bf6Swillf com_err(me, retval, gettext("while listing policy objects")); 141854925bf6Swillf exit_status++; 141954925bf6Swillf } 142054925bf6Swillf 142154925bf6Swillf return; 142254925bf6Swillf } 142354925bf6Swillf 142454925bf6Swillf 142554925bf6Swillf /* 142654925bf6Swillf * This function will print the service object information 142754925bf6Swillf * to the standard output 142854925bf6Swillf */ 142954925bf6Swillf static void 143054925bf6Swillf print_service_params(lserparams, mask) 143154925bf6Swillf krb5_ldap_service_params *lserparams; 143254925bf6Swillf int mask; 143354925bf6Swillf { 143454925bf6Swillf int i=0; 143554925bf6Swillf 143654925bf6Swillf /* Print the service dn */ 143754925bf6Swillf printf("%20s%-20s\n", gettext("Service dn: "), lserparams->servicedn); 143854925bf6Swillf 143954925bf6Swillf /* Print the service type of the object to be read */ 144054925bf6Swillf if (lserparams->servicetype == LDAP_KDC_SERVICE) { 144154925bf6Swillf printf("%20s%-20s\n", gettext("Service type: "), "kdc"); 144254925bf6Swillf } else if (lserparams->servicetype == LDAP_ADMIN_SERVICE) { 144354925bf6Swillf printf("%20s%-20s\n", gettext("Service type: "), "admin"); 144454925bf6Swillf } else if (lserparams->servicetype == LDAP_PASSWD_SERVICE) { 144554925bf6Swillf printf("%20s%-20s\n", gettext("Service type: "), "pwd"); 144654925bf6Swillf } 144754925bf6Swillf 144854925bf6Swillf /* Print the host server values */ 144954925bf6Swillf printf("%20s\n", gettext("Service host list: ")); 145054925bf6Swillf if (mask & LDAP_SERVICE_HOSTSERVER) { 145154925bf6Swillf for (i=0; lserparams->krbhostservers[i] != NULL; ++i) { 145254925bf6Swillf printf("%20s%-50s\n","",lserparams->krbhostservers[i]); 145354925bf6Swillf } 145454925bf6Swillf } 145554925bf6Swillf 145654925bf6Swillf /* Print the realm reference dn values */ 145754925bf6Swillf printf("%20s\n", gettext("Realm DN list: ")); 145854925bf6Swillf if (mask & LDAP_SERVICE_REALMREFERENCE) { 145954925bf6Swillf for (i=0; lserparams && lserparams->krbrealmreferences && lserparams->krbrealmreferences[i] != NULL; ++i) { 146054925bf6Swillf printf("%20s%-50s\n","",lserparams->krbrealmreferences[i]); 146154925bf6Swillf } 146254925bf6Swillf } 146354925bf6Swillf 146454925bf6Swillf return; 146554925bf6Swillf } 146654925bf6Swillf 146754925bf6Swillf 146854925bf6Swillf /* 146954925bf6Swillf * This function will generate random password of length(RANDOM_PASSWD_LEN) 147054925bf6Swillf * 147154925bf6Swillf * 147254925bf6Swillf * INPUT: 147354925bf6Swillf * ctxt - context 147454925bf6Swillf * 147554925bf6Swillf * OUTPUT: 147654925bf6Swillf * RANDOM_PASSWD_LEN length random password 147754925bf6Swillf */ 147854925bf6Swillf static int generate_random_password(krb5_context ctxt, char **randpwd, unsigned int *passlen) 147954925bf6Swillf { 148054925bf6Swillf char *random_pwd = NULL; 148154925bf6Swillf int ret = 0; 148254925bf6Swillf krb5_data data; 148354925bf6Swillf int i=0; 148454925bf6Swillf /*int len = 0;*/ 148554925bf6Swillf 148654925bf6Swillf /* setting random password length in the range 16-32 */ 148754925bf6Swillf srand((unsigned int)(time(0) ^ getpid())); 148854925bf6Swillf 148954925bf6Swillf data.length = RANDOM_PASSWD_LEN; 149054925bf6Swillf random_pwd = (char *)malloc(data.length + 1); 149154925bf6Swillf if (random_pwd == NULL) { 149254925bf6Swillf com_err("setsrvpw", ENOMEM, gettext("while generating random password")); 149354925bf6Swillf return ENOMEM; 149454925bf6Swillf } 149554925bf6Swillf memset(random_pwd, 0, data.length + 1); 149654925bf6Swillf data.data = random_pwd; 149754925bf6Swillf 149854925bf6Swillf ret = krb5_c_random_make_octets(ctxt, &data); 149954925bf6Swillf if (ret) { 150054925bf6Swillf com_err("setsrvpw", ret, gettext("Error generating random password")); 150154925bf6Swillf free(random_pwd); 150254925bf6Swillf return ret; 150354925bf6Swillf } 150454925bf6Swillf 150554925bf6Swillf for (i=0; i<data.length; i++) { 150654925bf6Swillf /* restricting to ascii chars. Need to change this when 8.8 supports */ 150754925bf6Swillf if ((unsigned char)random_pwd[i] > 127) { 150854925bf6Swillf random_pwd[i] = (unsigned char)random_pwd[i] % 128; 150954925bf6Swillf } else if (random_pwd[i] == 0) { 151054925bf6Swillf random_pwd[i] = (rand()/(RAND_MAX/127 + 1))+1; 151154925bf6Swillf } 151254925bf6Swillf } 151354925bf6Swillf 151454925bf6Swillf *randpwd = random_pwd; 151554925bf6Swillf *passlen = data.length; 151654925bf6Swillf 151754925bf6Swillf return 0; 151854925bf6Swillf } 151954925bf6Swillf 152054925bf6Swillf 152154925bf6Swillf /* 152254925bf6Swillf * This function will set the password of the service object in the directory 152354925bf6Swillf * and/or the specified service password file. 152454925bf6Swillf * 152554925bf6Swillf * 152654925bf6Swillf * INPUT: 152754925bf6Swillf * argc - contains the number of arguments for this sub-command 152854925bf6Swillf * argv - array of arguments for this sub-command 152954925bf6Swillf * 153054925bf6Swillf * OUTPUT: 153154925bf6Swillf * void 153254925bf6Swillf */ 153354925bf6Swillf int 153454925bf6Swillf kdb5_ldap_set_service_password(argc, argv) 153554925bf6Swillf int argc; 153654925bf6Swillf char **argv; 153754925bf6Swillf { 153854925bf6Swillf krb5_ldap_context *lparams = NULL; 153954925bf6Swillf char *file_name = NULL; 154054925bf6Swillf char *tmp_file = NULL; 1541*dd9ccd46S /* Solaris Kerberos */ 1542*dd9ccd46S char *me = progname; 154354925bf6Swillf int filelen = 0; 154454925bf6Swillf int random_passwd = 0; 154554925bf6Swillf int set_dir_pwd = 1; 154654925bf6Swillf krb5_boolean db_init_local = FALSE; 154754925bf6Swillf char *service_object = NULL; 154854925bf6Swillf char *passwd = NULL; 154954925bf6Swillf char *prompt1 = NULL; 155054925bf6Swillf char *prompt2 = NULL; 155154925bf6Swillf unsigned int passwd_len = 0; 155254925bf6Swillf krb5_error_code errcode = -1; 155354925bf6Swillf int retval = 0, i = 0; 155454925bf6Swillf unsigned int len = 0; 155554925bf6Swillf krb5_boolean print_usage = FALSE; 155654925bf6Swillf FILE *pfile = NULL; 155754925bf6Swillf char *str = NULL; 155854925bf6Swillf char line[MAX_LEN]; 155954925bf6Swillf kdb5_dal_handle *dal_handle = NULL; 156054925bf6Swillf struct data encrypted_passwd = {0, NULL}; 156154925bf6Swillf 156254925bf6Swillf /* The arguments for setsrv password should contain the service object DN 156354925bf6Swillf * and options to specify whether the password should be updated in file only 156454925bf6Swillf * or both file and directory. So the possible combination of arguments are: 156554925bf6Swillf * setsrvpw servicedn wherein argc is 2 156654925bf6Swillf * setsrvpw -fileonly servicedn wherein argc is 3 156754925bf6Swillf * setsrvpw -randpw servicedn wherein argc is 3 156854925bf6Swillf * setsrvpw -f filename servicedn wherein argc is 4 156954925bf6Swillf * setsrvpw -fileonly -f filename servicedn wherein argc is 5 157054925bf6Swillf * setsrvpw -randpw -f filename servicedn wherein argc is 5 157154925bf6Swillf */ 157254925bf6Swillf if ((argc < 2) || (argc > 5)) { 157354925bf6Swillf print_usage = TRUE; 157454925bf6Swillf goto cleanup; 157554925bf6Swillf } 157654925bf6Swillf 157754925bf6Swillf dal_handle = (kdb5_dal_handle *)util_context->db_context; 157854925bf6Swillf lparams = (krb5_ldap_context *) dal_handle->db_context; 157954925bf6Swillf 158054925bf6Swillf if (lparams == NULL) { 158154925bf6Swillf printf(gettext("%s: Invalid LDAP handle\n"), me); 158254925bf6Swillf goto cleanup; 158354925bf6Swillf } 158454925bf6Swillf 158554925bf6Swillf /* Parse the arguments */ 158654925bf6Swillf for (i = 1; i < argc -1 ; i++) { 158754925bf6Swillf if (strcmp(argv[i], "-randpw") == 0) { 158854925bf6Swillf random_passwd = 1; 158954925bf6Swillf } else if (strcmp(argv[i], "-fileonly") == 0) { 159054925bf6Swillf set_dir_pwd = 0; 159154925bf6Swillf } else if (strcmp(argv[i], "-f") == 0) { 159254925bf6Swillf if (argv[++i] == NULL) { 159354925bf6Swillf print_usage = TRUE; 159454925bf6Swillf goto cleanup; 159554925bf6Swillf } 159654925bf6Swillf 159754925bf6Swillf file_name = strdup(argv[i]); 159854925bf6Swillf if (file_name == NULL) { 159954925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 160054925bf6Swillf goto cleanup; 160154925bf6Swillf } 160254925bf6Swillf /* Verify if the file location has the proper file name 160354925bf6Swillf * for eg, if the file location is a directory like /home/temp/, 160454925bf6Swillf * we reject it. 160554925bf6Swillf */ 160654925bf6Swillf filelen = strlen(file_name); 160754925bf6Swillf if ((filelen == 0) || (file_name[filelen-1] == '/')) { 160854925bf6Swillf printf(gettext("%s: Filename not specified for setting service object password\n"), me); 160954925bf6Swillf print_usage = TRUE; 161054925bf6Swillf goto cleanup; 161154925bf6Swillf } 161254925bf6Swillf } else { 161354925bf6Swillf printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me); 161454925bf6Swillf print_usage = TRUE; 161554925bf6Swillf goto cleanup; 161654925bf6Swillf } 161754925bf6Swillf } 161854925bf6Swillf 161954925bf6Swillf if (i != argc-1) { 162054925bf6Swillf print_usage = TRUE; 162154925bf6Swillf goto cleanup; 162254925bf6Swillf } 162354925bf6Swillf 162454925bf6Swillf service_object = strdup(argv[i]); 162554925bf6Swillf if (service_object == NULL) { 162654925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 162754925bf6Swillf goto cleanup; 162854925bf6Swillf } 162954925bf6Swillf 163054925bf6Swillf if (strlen(service_object) == 0) { 163154925bf6Swillf printf(gettext("%s: Service object not specified for \"setsrvpw\" command\n"), me); 163254925bf6Swillf print_usage = TRUE; 163354925bf6Swillf goto cleanup; 163454925bf6Swillf } 163554925bf6Swillf 163654925bf6Swillf if (service_object[0] == '-') { 163754925bf6Swillf print_usage = TRUE; 163854925bf6Swillf goto cleanup; 163954925bf6Swillf } 164054925bf6Swillf 164154925bf6Swillf if (file_name == NULL) { 164254925bf6Swillf file_name = strdup(DEF_SERVICE_PASSWD_FILE); 164354925bf6Swillf if (file_name == NULL) { 164454925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 164554925bf6Swillf goto cleanup; 164654925bf6Swillf } 164754925bf6Swillf } 164854925bf6Swillf 164954925bf6Swillf if (set_dir_pwd) { 165054925bf6Swillf if (db_inited == FALSE) { 165154925bf6Swillf if ((errcode = krb5_ldap_db_init(util_context, lparams))) { 165254925bf6Swillf com_err(me, errcode, gettext("while initializing database")); 165354925bf6Swillf goto cleanup; 165454925bf6Swillf } 165554925bf6Swillf db_init_local = TRUE; 165654925bf6Swillf } 165754925bf6Swillf } 165854925bf6Swillf 165954925bf6Swillf if (random_passwd) { 166054925bf6Swillf if (!set_dir_pwd) { 166154925bf6Swillf printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me); 166254925bf6Swillf print_usage = TRUE; 166354925bf6Swillf goto cleanup; 166454925bf6Swillf } else { 166554925bf6Swillf /* Generate random password */ 166654925bf6Swillf 166754925bf6Swillf if ((errcode = generate_random_password(util_context, &passwd, &passwd_len))) { 166854925bf6Swillf printf(gettext("%s: Failed to set service object password\n"), me); 166954925bf6Swillf goto cleanup; 167054925bf6Swillf } 167154925bf6Swillf passwd_len = strlen(passwd); 167254925bf6Swillf } 167354925bf6Swillf } else { 167454925bf6Swillf /* Get the service object password from the terminal */ 167554925bf6Swillf passwd = (char *)malloc(MAX_SERVICE_PASSWD_LEN + 1); 167654925bf6Swillf if (passwd == NULL) { 167754925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 167854925bf6Swillf goto cleanup; 167954925bf6Swillf } 168054925bf6Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN + 1); 168154925bf6Swillf passwd_len = MAX_SERVICE_PASSWD_LEN; 168254925bf6Swillf 168354925bf6Swillf len = strlen(service_object); 168454925bf6Swillf /* size of allocation=strlen of servicedn + strlen("Password for \" \"")=20 */ 168554925bf6Swillf prompt1 = (char *)malloc(len + 20); 168654925bf6Swillf if (prompt1 == NULL) { 168754925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 168854925bf6Swillf goto cleanup; 168954925bf6Swillf } 169054925bf6Swillf sprintf(prompt1, gettext("Password for \"%s\""), service_object); 169154925bf6Swillf 169254925bf6Swillf /* size of allocation=strlen of servicedn + strlen("Re-enter Password for \" \"")=30 */ 169354925bf6Swillf prompt2 = (char *)malloc(len + 30); 169454925bf6Swillf if (prompt2 == NULL) { 169554925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 169654925bf6Swillf free(prompt1); 169754925bf6Swillf goto cleanup; 169854925bf6Swillf } 169954925bf6Swillf sprintf(prompt2, gettext("Re-enter password for \"%s\""), service_object); 170054925bf6Swillf 170154925bf6Swillf retval = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len); 170254925bf6Swillf free(prompt1); 170354925bf6Swillf free(prompt2); 170454925bf6Swillf if (retval) { 170554925bf6Swillf com_err(me, retval, gettext("while setting service object password")); 170654925bf6Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN); 170754925bf6Swillf goto cleanup; 170854925bf6Swillf } 170954925bf6Swillf if (passwd_len == 0) { 171054925bf6Swillf printf(gettext("%s: Invalid password\n"), me); 171154925bf6Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN); 171254925bf6Swillf goto cleanup; 171354925bf6Swillf } 171454925bf6Swillf passwd_len = strlen(passwd); 171554925bf6Swillf } 171654925bf6Swillf 171754925bf6Swillf /* Hex the password */ 171854925bf6Swillf { 171954925bf6Swillf krb5_data pwd, hex; 172054925bf6Swillf pwd.length = passwd_len; 172154925bf6Swillf pwd.data = passwd; 172254925bf6Swillf 172354925bf6Swillf errcode = tohex(pwd, &hex); 172454925bf6Swillf if (errcode != 0) { 172554925bf6Swillf if (hex.length != 0) { 172654925bf6Swillf memset(hex.data, 0, hex.length); 172754925bf6Swillf free(hex.data); 172854925bf6Swillf } 172954925bf6Swillf com_err(me, errcode, gettext("Failed to convert the password to hex")); 173054925bf6Swillf memset(passwd, 0, passwd_len); 173154925bf6Swillf goto cleanup; 173254925bf6Swillf } 173354925bf6Swillf /* Password = {CRYPT}<encrypted password>:<encrypted key> */ 173454925bf6Swillf encrypted_passwd.value = (unsigned char *)malloc(strlen(service_object) + 173554925bf6Swillf 1 + 5 + hex.length + 2); 173654925bf6Swillf if (encrypted_passwd.value == NULL) { 173754925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 173854925bf6Swillf memset(passwd, 0, passwd_len); 173954925bf6Swillf memset(hex.data, 0, hex.length); 174054925bf6Swillf free(hex.data); 174154925bf6Swillf goto cleanup; 174254925bf6Swillf } 174354925bf6Swillf encrypted_passwd.value[strlen(service_object) + 174454925bf6Swillf 1 + 5 + hex.length + 1] = '\0'; 174554925bf6Swillf sprintf((char *)encrypted_passwd.value, "%s#{HEX}%s\n", service_object, hex.data); 174654925bf6Swillf encrypted_passwd.len = strlen((char *)encrypted_passwd.value); 174754925bf6Swillf memset(hex.data, 0, hex.length); 174854925bf6Swillf free(hex.data); 174954925bf6Swillf } 175054925bf6Swillf 175154925bf6Swillf /* We should check if the file exists and we have permission to write into that file */ 175254925bf6Swillf if (access(file_name, W_OK) == -1) { 175354925bf6Swillf if (errno == ENOENT) { 175454925bf6Swillf mode_t omask; 175554925bf6Swillf int fd = -1; 175654925bf6Swillf 175754925bf6Swillf printf(gettext("File does not exist. Creating the file %s...\n"), file_name); 175854925bf6Swillf omask = umask(077); 175954925bf6Swillf fd = creat(file_name, S_IRUSR|S_IWUSR); 176054925bf6Swillf umask(omask); 176154925bf6Swillf if (fd == -1) { 176254925bf6Swillf com_err(me, errno, gettext("Error creating file %s"), file_name); 176354925bf6Swillf memset(passwd, 0, passwd_len); 176454925bf6Swillf goto cleanup; 176554925bf6Swillf } 176654925bf6Swillf close(fd); 176754925bf6Swillf } else { 176854925bf6Swillf com_err(me, errno, gettext("Unable to access the file %s"), file_name); 176954925bf6Swillf memset(passwd, 0, passwd_len); 177054925bf6Swillf goto cleanup; 177154925bf6Swillf } 177254925bf6Swillf } 177354925bf6Swillf 177454925bf6Swillf if (set_dir_pwd) { 177554925bf6Swillf if ((errcode = krb5_ldap_set_service_passwd(util_context, service_object, passwd)) != 0) { 177654925bf6Swillf com_err(me, errcode, gettext("Failed to set password for service object %s"), service_object); 177754925bf6Swillf memset(passwd, 0, passwd_len); 177854925bf6Swillf goto cleanup; 177954925bf6Swillf } 178054925bf6Swillf } 178154925bf6Swillf 178254925bf6Swillf memset(passwd, 0, passwd_len); 178354925bf6Swillf 178454925bf6Swillf 178554925bf6Swillf /* TODO: file lock for the service password file */ 178654925bf6Swillf /* set password in the file */ 178754925bf6Swillf pfile = fopen(file_name, "r+F"); 178854925bf6Swillf if (pfile == NULL) { 178954925bf6Swillf com_err(me, errno, gettext("Failed to open file %s"), file_name); 179054925bf6Swillf goto cleanup; 179154925bf6Swillf } 179254925bf6Swillf 179354925bf6Swillf while (fgets(line, MAX_LEN, pfile) != NULL) { 179454925bf6Swillf if ((str = strstr(line, service_object)) != NULL) { 179554925bf6Swillf if (line[strlen(service_object)] == '#') { 179654925bf6Swillf break; 179754925bf6Swillf } 179854925bf6Swillf str = NULL; 179954925bf6Swillf } 180054925bf6Swillf } 180154925bf6Swillf if (str == NULL) { 180254925bf6Swillf if (feof(pfile)) { 180354925bf6Swillf /* If the service object dn is not present in the service password file */ 180454925bf6Swillf if (fwrite(encrypted_passwd.value, (unsigned int)encrypted_passwd.len, 1, pfile) != 1) { 180554925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file")); 180654925bf6Swillf goto cleanup; 180754925bf6Swillf } 180854925bf6Swillf } else { 180954925bf6Swillf com_err(me, errno, gettext("Error reading service object password file")); 181054925bf6Swillf goto cleanup; 181154925bf6Swillf } 181254925bf6Swillf fclose(pfile); 181354925bf6Swillf pfile = NULL; 181454925bf6Swillf } else { 181554925bf6Swillf /* Password entry for the service object is already present in the file */ 181654925bf6Swillf /* Delete the existing entry and add the new entry */ 181754925bf6Swillf FILE *newfile = NULL; 181854925bf6Swillf mode_t omask; 181954925bf6Swillf 182054925bf6Swillf /* Create a new file with the extension .tmp */ 182154925bf6Swillf tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1)); 182254925bf6Swillf if (tmp_file == NULL) { 182354925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 182454925bf6Swillf goto cleanup; 182554925bf6Swillf } 182654925bf6Swillf sprintf(tmp_file,"%s.%s",file_name,"tmp"); 182754925bf6Swillf 182854925bf6Swillf omask = umask(077); 182954925bf6Swillf newfile = fopen(tmp_file, "w+F"); 183054925bf6Swillf umask(omask); 183154925bf6Swillf if (newfile == NULL) { 183254925bf6Swillf com_err(me, errno, gettext("Error creating file %s"), tmp_file); 183354925bf6Swillf goto cleanup; 183454925bf6Swillf } 183554925bf6Swillf 183654925bf6Swillf 183754925bf6Swillf fseek(pfile, 0, SEEK_SET); 183854925bf6Swillf while (fgets(line, MAX_LEN, pfile) != NULL) { 183954925bf6Swillf if (((str = strstr(line, service_object)) != NULL) && (line[strlen(service_object)] == '#')) { 184054925bf6Swillf if (fprintf(newfile, "%s", encrypted_passwd.value) < 0) { 184154925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file")); 184254925bf6Swillf fclose(newfile); 184354925bf6Swillf unlink(tmp_file); 184454925bf6Swillf goto cleanup; 184554925bf6Swillf } 184654925bf6Swillf } else { 184754925bf6Swillf len = strlen(line); 184854925bf6Swillf if (fprintf(newfile, "%s", line) < 0) { 184954925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file")); 185054925bf6Swillf fclose(newfile); 185154925bf6Swillf unlink(tmp_file); 185254925bf6Swillf goto cleanup; 185354925bf6Swillf } 185454925bf6Swillf } 185554925bf6Swillf } 185654925bf6Swillf 185754925bf6Swillf if (!feof(pfile)) { 185854925bf6Swillf com_err(me, errno, gettext("Error reading service object password file")); 185954925bf6Swillf fclose(newfile); 186054925bf6Swillf unlink(tmp_file); 186154925bf6Swillf goto cleanup; 186254925bf6Swillf } 186354925bf6Swillf 186454925bf6Swillf /* TODO: file lock for the service password file */ 186554925bf6Swillf fclose(pfile); 186654925bf6Swillf pfile = NULL; 186754925bf6Swillf 186854925bf6Swillf fclose(newfile); 186954925bf6Swillf newfile = NULL; 187054925bf6Swillf 187154925bf6Swillf if (unlink(file_name) == 0) { 187254925bf6Swillf link(tmp_file, file_name); 187354925bf6Swillf } else { 187454925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file")); 187554925bf6Swillf unlink(tmp_file); 187654925bf6Swillf goto cleanup; 187754925bf6Swillf } 187854925bf6Swillf unlink(tmp_file); 187954925bf6Swillf } 188054925bf6Swillf errcode = 0; 188154925bf6Swillf 188254925bf6Swillf cleanup: 188354925bf6Swillf if (db_init_local) 188454925bf6Swillf krb5_ldap_close(util_context); 188554925bf6Swillf 188654925bf6Swillf if (service_object) 188754925bf6Swillf free(service_object); 188854925bf6Swillf 188954925bf6Swillf if (file_name) 189054925bf6Swillf free(file_name); 189154925bf6Swillf 189254925bf6Swillf if (passwd) 189354925bf6Swillf free(passwd); 189454925bf6Swillf 189554925bf6Swillf if (encrypted_passwd.value) { 189654925bf6Swillf memset(encrypted_passwd.value, 0, encrypted_passwd.len); 189754925bf6Swillf free(encrypted_passwd.value); 189854925bf6Swillf } 189954925bf6Swillf 190054925bf6Swillf if (pfile) 190154925bf6Swillf fclose(pfile); 190254925bf6Swillf 190354925bf6Swillf if (tmp_file) 190454925bf6Swillf free(tmp_file); 190554925bf6Swillf 190654925bf6Swillf if (print_usage) 190754925bf6Swillf db_usage(SET_SRV_PW); 190854925bf6Swillf 190954925bf6Swillf return errcode; 191054925bf6Swillf } 191154925bf6Swillf 191254925bf6Swillf #else /* #ifdef HAVE_EDIRECTORY */ 191354925bf6Swillf 191454925bf6Swillf /* 191554925bf6Swillf * Convert the user supplied password into hexadecimal and stash it. Only a 191654925bf6Swillf * little more secure than storing plain password in the file ... 191754925bf6Swillf */ 191854925bf6Swillf void 191954925bf6Swillf kdb5_ldap_stash_service_password(argc, argv) 192054925bf6Swillf int argc; 192154925bf6Swillf char **argv; 192254925bf6Swillf { 192354925bf6Swillf int ret = 0; 192454925bf6Swillf unsigned int passwd_len = 0; 1925*dd9ccd46S /* Solaris Kerberos */ 1926*dd9ccd46S char *me = progname; 192754925bf6Swillf char *service_object = NULL; 192854925bf6Swillf char *file_name = NULL, *tmp_file = NULL; 192954925bf6Swillf char passwd[MAX_SERVICE_PASSWD_LEN]; 193054925bf6Swillf char *str = NULL; 193154925bf6Swillf char line[MAX_LEN]; 193254925bf6Swillf int fd; 193354925bf6Swillf FILE *pfile = NULL; 193454925bf6Swillf krb5_boolean print_usage = FALSE; 193554925bf6Swillf krb5_data hexpasswd = {0, 0, NULL}; 193654925bf6Swillf mode_t old_mode = 0; 193754925bf6Swillf 193854925bf6Swillf /* 193954925bf6Swillf * Format: 194054925bf6Swillf * stashsrvpw [-f filename] service_dn 194154925bf6Swillf * where 194254925bf6Swillf * 'service_dn' is the DN of the service object 194354925bf6Swillf * 'filename' is the path of the stash file 194454925bf6Swillf */ 194554925bf6Swillf if (argc != 2 && argc != 4) { 194654925bf6Swillf print_usage = TRUE; 194754925bf6Swillf goto cleanup; 194854925bf6Swillf } 194954925bf6Swillf 195054925bf6Swillf if (argc == 4) { 195154925bf6Swillf /* Find the stash file name */ 195254925bf6Swillf if (strcmp (argv[1], "-f") == 0) { 195354925bf6Swillf if (((file_name = strdup (argv[2])) == NULL) || 195454925bf6Swillf ((service_object = strdup (argv[3])) == NULL)) { 195554925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 195654925bf6Swillf goto cleanup; 195754925bf6Swillf } 195854925bf6Swillf } else if (strcmp (argv[2], "-f") == 0) { 195954925bf6Swillf if (((file_name = strdup (argv[3])) == NULL) || 196054925bf6Swillf ((service_object = strdup (argv[1])) == NULL)) { 196154925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 196254925bf6Swillf goto cleanup; 196354925bf6Swillf } 196454925bf6Swillf } else { 196554925bf6Swillf print_usage = TRUE; 196654925bf6Swillf goto cleanup; 196754925bf6Swillf } 196854925bf6Swillf if (file_name == NULL) { 196954925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 197054925bf6Swillf goto cleanup; 197154925bf6Swillf } 197254925bf6Swillf } else { /* argc == 2 */ 197354925bf6Swillf char *section; 197454925bf6Swillf 197554925bf6Swillf service_object = strdup (argv[1]); 197654925bf6Swillf if (service_object == NULL) { 197754925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 197854925bf6Swillf goto cleanup; 197954925bf6Swillf } 198054925bf6Swillf 198154925bf6Swillf /* Pick up the stash-file name from krb5.conf */ 198254925bf6Swillf profile_get_string(util_context->profile, KDB_REALM_SECTION, 198354925bf6Swillf util_context->default_realm, KDB_MODULE_POINTER, NULL, §ion); 198454925bf6Swillf 198554925bf6Swillf if (section == NULL) { 198654925bf6Swillf profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION, 198754925bf6Swillf KDB_MODULE_POINTER, NULL, NULL, §ion); 198854925bf6Swillf if (section == NULL) { 198954925bf6Swillf /* Stash file path neither in krb5.conf nor on command line */ 199054925bf6Swillf file_name = strdup(DEF_SERVICE_PASSWD_FILE); 199154925bf6Swillf if (file_name == NULL) { 199254925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 199354925bf6Swillf goto cleanup; 199454925bf6Swillf } 199554925bf6Swillf goto done; 199654925bf6Swillf } 199754925bf6Swillf } 199854925bf6Swillf 199954925bf6Swillf profile_get_string (util_context->profile, KDB_MODULE_SECTION, section, 200054925bf6Swillf "ldap_service_password_file", NULL, &file_name); 200154925bf6Swillf 200254925bf6Swillf /* 200354925bf6Swillf * Solaris Kerberos: use default if ldap_service_password_file not set 200454925bf6Swillf */ 200554925bf6Swillf if (file_name == NULL) { 200654925bf6Swillf file_name = strdup(DEF_SERVICE_PASSWD_FILE); 200754925bf6Swillf if (file_name == NULL) { 200854925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 200954925bf6Swillf goto cleanup; 201054925bf6Swillf } 201154925bf6Swillf } 201254925bf6Swillf } 201354925bf6Swillf done: 201454925bf6Swillf 201554925bf6Swillf /* Get password from user */ 201654925bf6Swillf { 201754925bf6Swillf char prompt1[256], prompt2[256]; 201854925bf6Swillf 201954925bf6Swillf /* Get the service object password from the terminal */ 202054925bf6Swillf memset(passwd, 0, sizeof (passwd)); 202154925bf6Swillf passwd_len = sizeof (passwd); 202254925bf6Swillf 202354925bf6Swillf /* size of prompt = strlen of servicedn + strlen("Password for \" \"") */ 202454925bf6Swillf assert (sizeof (prompt1) > (strlen (service_object) 202554925bf6Swillf + sizeof ("Password for \" \""))); 202654925bf6Swillf sprintf(prompt1, gettext("Password for \"%s\""), service_object); 202754925bf6Swillf 202854925bf6Swillf /* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */ 202954925bf6Swillf assert (sizeof (prompt2) > (strlen (service_object) 203054925bf6Swillf + sizeof ("Re-enter Password for \" \""))); 203154925bf6Swillf sprintf(prompt2, gettext("Re-enter password for \"%s\""), service_object); 203254925bf6Swillf 203354925bf6Swillf ret = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len); 203454925bf6Swillf if (ret != 0) { 203554925bf6Swillf com_err(me, ret, gettext("while setting service object password")); 203654925bf6Swillf memset(passwd, 0, sizeof (passwd)); 203754925bf6Swillf goto cleanup; 203854925bf6Swillf } 203954925bf6Swillf 204054925bf6Swillf if (passwd_len == 0) { 204154925bf6Swillf printf(gettext("%s: Invalid password\n"), me); 204254925bf6Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN); 204354925bf6Swillf goto cleanup; 204454925bf6Swillf } 204554925bf6Swillf } 204654925bf6Swillf 204754925bf6Swillf /* Convert the password to hexadecimal */ 204854925bf6Swillf { 204954925bf6Swillf krb5_data pwd; 205054925bf6Swillf 205154925bf6Swillf pwd.length = passwd_len; 205254925bf6Swillf pwd.data = passwd; 205354925bf6Swillf 205454925bf6Swillf ret = tohex(pwd, &hexpasswd); 205554925bf6Swillf if (ret != 0) { 205654925bf6Swillf com_err(me, ret, gettext("Failed to convert the password to hexadecimal")); 205754925bf6Swillf memset(passwd, 0, passwd_len); 205854925bf6Swillf goto cleanup; 205954925bf6Swillf } 206054925bf6Swillf } 206154925bf6Swillf memset(passwd, 0, passwd_len); 206254925bf6Swillf 206354925bf6Swillf /* TODO: file lock for the service passowrd file */ 206454925bf6Swillf 206554925bf6Swillf /* set password in the file */ 206654925bf6Swillf #if 0 /* ************ Begin IFDEF'ed OUT ***************************** */ 206754925bf6Swillf old_mode = umask(0177); 206854925bf6Swillf pfile = fopen(file_name, "a+"); 206954925bf6Swillf if (pfile == NULL) { 207054925bf6Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name, 207154925bf6Swillf strerror (errno)); 207254925bf6Swillf goto cleanup; 207354925bf6Swillf } 207454925bf6Swillf rewind (pfile); 207554925bf6Swillf umask(old_mode); 207654925bf6Swillf #else 207754925bf6Swillf /* Solaris Kerberos: safer than the above */ 207854925bf6Swillf fd = open(file_name, O_CREAT|O_RDWR|O_APPEND, 0600); 207954925bf6Swillf if (fd < 0) { 208054925bf6Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name, 208154925bf6Swillf strerror (errno)); 208254925bf6Swillf goto cleanup; 208354925bf6Swillf } 208454925bf6Swillf pfile = fdopen(fd, "a+F"); 208554925bf6Swillf if (pfile == NULL) { 208654925bf6Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name, 208754925bf6Swillf strerror (errno)); 208854925bf6Swillf goto cleanup; 208954925bf6Swillf } 209054925bf6Swillf rewind (pfile); 209154925bf6Swillf #endif 209254925bf6Swillf 209354925bf6Swillf while (fgets (line, MAX_LEN, pfile) != NULL) { 209454925bf6Swillf if ((str = strstr (line, service_object)) != NULL) { 209554925bf6Swillf /* 209654925bf6Swillf * White spaces not allowed, # delimits the service dn from the 209754925bf6Swillf * password 209854925bf6Swillf */ 209954925bf6Swillf if (line [strlen (service_object)] == '#') 210054925bf6Swillf break; 210154925bf6Swillf str = NULL; 210254925bf6Swillf } 210354925bf6Swillf } 210454925bf6Swillf 210554925bf6Swillf if (str == NULL) { 210654925bf6Swillf if (feof(pfile)) { 210754925bf6Swillf /* If the service object dn is not present in the service password file */ 210854925bf6Swillf if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) { 210954925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file")); 211054925bf6Swillf fclose(pfile); 211154925bf6Swillf goto cleanup; 211254925bf6Swillf } 211354925bf6Swillf } else { 211454925bf6Swillf com_err(me, errno, gettext("Error reading service object password file")); 211554925bf6Swillf fclose(pfile); 211654925bf6Swillf goto cleanup; 211754925bf6Swillf } 211854925bf6Swillf fclose(pfile); 211954925bf6Swillf } else { 212054925bf6Swillf /* 212154925bf6Swillf * Password entry for the service object is already present in the file 212254925bf6Swillf * Delete the existing entry and add the new entry 212354925bf6Swillf */ 212454925bf6Swillf FILE *newfile; 212554925bf6Swillf 212654925bf6Swillf mode_t omask; 212754925bf6Swillf 212854925bf6Swillf /* Create a new file with the extension .tmp */ 212954925bf6Swillf tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1)); 213054925bf6Swillf if (tmp_file == NULL) { 213154925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password")); 213254925bf6Swillf fclose(pfile); 213354925bf6Swillf goto cleanup; 213454925bf6Swillf } 213554925bf6Swillf sprintf(tmp_file,"%s.%s",file_name,"tmp"); 213654925bf6Swillf 213754925bf6Swillf omask = umask(077); 213854925bf6Swillf newfile = fopen(tmp_file, "wF"); 213954925bf6Swillf umask (omask); 214054925bf6Swillf if (newfile == NULL) { 214154925bf6Swillf com_err(me, errno, gettext("Error creating file %s"), tmp_file); 214254925bf6Swillf fclose(pfile); 214354925bf6Swillf goto cleanup; 214454925bf6Swillf } 214554925bf6Swillf 214654925bf6Swillf fseek(pfile, 0, SEEK_SET); 214754925bf6Swillf while (fgets(line, MAX_LEN, pfile) != NULL) { 214854925bf6Swillf if (((str = strstr(line, service_object)) != NULL) && 214954925bf6Swillf (line[strlen(service_object)] == '#')) { 215054925bf6Swillf if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) { 215154925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file")); 215254925bf6Swillf fclose(newfile); 215354925bf6Swillf unlink(tmp_file); 215454925bf6Swillf fclose(pfile); 215554925bf6Swillf goto cleanup; 215654925bf6Swillf } 215754925bf6Swillf } else { 215854925bf6Swillf if (fprintf (newfile, "%s", line) < 0) { 215954925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file")); 216054925bf6Swillf fclose(newfile); 216154925bf6Swillf unlink(tmp_file); 216254925bf6Swillf fclose(pfile); 216354925bf6Swillf goto cleanup; 216454925bf6Swillf } 216554925bf6Swillf } 216654925bf6Swillf } 216754925bf6Swillf 216854925bf6Swillf if (!feof(pfile)) { 216954925bf6Swillf com_err(me, errno, gettext("Error reading service object password file")); 217054925bf6Swillf fclose(newfile); 217154925bf6Swillf unlink(tmp_file); 217254925bf6Swillf fclose(pfile); 217354925bf6Swillf goto cleanup; 217454925bf6Swillf } 217554925bf6Swillf 217654925bf6Swillf /* TODO: file lock for the service passowrd file */ 217754925bf6Swillf 217854925bf6Swillf fclose(pfile); 217954925bf6Swillf fclose(newfile); 218054925bf6Swillf 218154925bf6Swillf ret = rename(tmp_file, file_name); 218254925bf6Swillf if (ret != 0) { 218354925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to " 218454925bf6Swillf "file")); 218554925bf6Swillf goto cleanup; 218654925bf6Swillf } 218754925bf6Swillf } 218854925bf6Swillf ret = 0; 218954925bf6Swillf 219054925bf6Swillf cleanup: 219154925bf6Swillf 219254925bf6Swillf if (hexpasswd.length != 0) { 219354925bf6Swillf memset(hexpasswd.data, 0, hexpasswd.length); 219454925bf6Swillf free(hexpasswd.data); 219554925bf6Swillf } 219654925bf6Swillf 219754925bf6Swillf if (service_object) 219854925bf6Swillf free(service_object); 219954925bf6Swillf 220054925bf6Swillf if (file_name) 220154925bf6Swillf free(file_name); 220254925bf6Swillf 220354925bf6Swillf if (tmp_file) 220454925bf6Swillf free(tmp_file); 220554925bf6Swillf 220654925bf6Swillf if (print_usage) 220754925bf6Swillf usage(); 220854925bf6Swillf /* db_usage(STASH_SRV_PW); */ 220954925bf6Swillf 221054925bf6Swillf if (ret) 221154925bf6Swillf exit_status++; 221254925bf6Swillf } 221354925bf6Swillf 221454925bf6Swillf #endif /* #ifdef HAVE_EDIRECTORY */ 2215