154925bf6Swillf /*
2dd9ccd46S  * 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 
process_host_list(char ** host_list,int servicetype)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
convert_realm_name2dn_list(list,krbcontainer_loc)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  */
kdb5_ldap_create_service(argc,argv)20454925bf6Swillf void kdb5_ldap_create_service(argc, argv)
20554925bf6Swillf     int argc;
20654925bf6Swillf     char *argv[];
20754925bf6Swillf {
208dd9ccd46S     /* Solaris Kerberos */
209dd9ccd46S     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  */
kdb5_ldap_modify_service(argc,argv)50354925bf6Swillf void kdb5_ldap_modify_service(argc, argv)
50454925bf6Swillf     int argc;
50554925bf6Swillf     char *argv[];
50654925bf6Swillf {
507dd9ccd46S     /* Solaris Kerberos */
508*55fea89dSDan Cross     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) {
581dd9ccd46S 	/* Solaris Kerberos */
582dd9ccd46S 	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
rem_service_entry_from_file(argc,argv,file_name,service_object)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;
1074dd9ccd46S     /* Solaris Kerberos */
1075dd9ccd46S     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
kdb5_ldap_destroy_service(argc,argv)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) {
1189dd9ccd46S 		    /* Solaris Kerberos */
1190dd9ccd46S 		    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) {
1203dd9ccd46S 		    /* Solaris Kerberos */
1204dd9ccd46S 		    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))) {
1235dd9ccd46S 	/* Solaris Kerberos */
1236dd9ccd46S 	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) {
1244dd9ccd46S 	/* Solaris Kerberos */
1245dd9ccd46S 	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) {
1253dd9ccd46S 	    /* Solaris Kerberos */
1254dd9ccd46S 	    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  */
kdb5_ldap_view_service(argc,argv)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) {
1314dd9ccd46S 	/* Solaris Kerberos */
1315dd9ccd46S 	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))) {
1321dd9ccd46S 	/* Solaris Kerberos */
1322dd9ccd46S 	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  */
kdb5_ldap_list_services(argc,argv)135554925bf6Swillf void kdb5_ldap_list_services(argc, argv)
135654925bf6Swillf     int argc;
135754925bf6Swillf     char *argv[];
135854925bf6Swillf {
1359dd9ccd46S     /* Solaris Kerberos */
1360dd9ccd46S     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
print_service_params(lserparams,mask)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  */
generate_random_password(krb5_context ctxt,char ** randpwd,unsigned int * passlen)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
kdb5_ldap_set_service_password(argc,argv)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;
1541dd9ccd46S     /* Solaris Kerberos */
1542dd9ccd46S     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
kdb5_ldap_stash_service_password(argc,argv)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;
1925dd9ccd46S     /* Solaris Kerberos */
1926dd9ccd46S     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, &section);
198454925bf6Swillf 
198554925bf6Swillf 	if (section == NULL) {
198654925bf6Swillf 	    profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION,
198754925bf6Swillf 			       KDB_MODULE_POINTER, NULL, NULL, &section);
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