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, §ion);
198454925bf6Swillf
198554925bf6Swillf if (section == NULL) {
198654925bf6Swillf profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION,
198754925bf6Swillf KDB_MODULE_POINTER, NULL, NULL, §ion);
198854925bf6Swillf if (section == NULL) {
198954925bf6Swillf /* Stash file path neither in krb5.conf nor on command line */
199054925bf6Swillf file_name = strdup(DEF_SERVICE_PASSWD_FILE);
199154925bf6Swillf if (file_name == NULL) {
199254925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
199354925bf6Swillf goto cleanup;
199454925bf6Swillf }
199554925bf6Swillf goto done;
199654925bf6Swillf }
199754925bf6Swillf }
199854925bf6Swillf
199954925bf6Swillf profile_get_string (util_context->profile, KDB_MODULE_SECTION, section,
200054925bf6Swillf "ldap_service_password_file", NULL, &file_name);
200154925bf6Swillf
200254925bf6Swillf /*
200354925bf6Swillf * Solaris Kerberos: use default if ldap_service_password_file not set
200454925bf6Swillf */
200554925bf6Swillf if (file_name == NULL) {
200654925bf6Swillf file_name = strdup(DEF_SERVICE_PASSWD_FILE);
200754925bf6Swillf if (file_name == NULL) {
200854925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
200954925bf6Swillf goto cleanup;
201054925bf6Swillf }
201154925bf6Swillf }
201254925bf6Swillf }
201354925bf6Swillf done:
201454925bf6Swillf
201554925bf6Swillf /* Get password from user */
201654925bf6Swillf {
201754925bf6Swillf char prompt1[256], prompt2[256];
201854925bf6Swillf
201954925bf6Swillf /* Get the service object password from the terminal */
202054925bf6Swillf memset(passwd, 0, sizeof (passwd));
202154925bf6Swillf passwd_len = sizeof (passwd);
202254925bf6Swillf
202354925bf6Swillf /* size of prompt = strlen of servicedn + strlen("Password for \" \"") */
202454925bf6Swillf assert (sizeof (prompt1) > (strlen (service_object)
202554925bf6Swillf + sizeof ("Password for \" \"")));
202654925bf6Swillf sprintf(prompt1, gettext("Password for \"%s\""), service_object);
202754925bf6Swillf
202854925bf6Swillf /* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */
202954925bf6Swillf assert (sizeof (prompt2) > (strlen (service_object)
203054925bf6Swillf + sizeof ("Re-enter Password for \" \"")));
203154925bf6Swillf sprintf(prompt2, gettext("Re-enter password for \"%s\""), service_object);
203254925bf6Swillf
203354925bf6Swillf ret = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len);
203454925bf6Swillf if (ret != 0) {
203554925bf6Swillf com_err(me, ret, gettext("while setting service object password"));
203654925bf6Swillf memset(passwd, 0, sizeof (passwd));
203754925bf6Swillf goto cleanup;
203854925bf6Swillf }
203954925bf6Swillf
204054925bf6Swillf if (passwd_len == 0) {
204154925bf6Swillf printf(gettext("%s: Invalid password\n"), me);
204254925bf6Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
204354925bf6Swillf goto cleanup;
204454925bf6Swillf }
204554925bf6Swillf }
204654925bf6Swillf
204754925bf6Swillf /* Convert the password to hexadecimal */
204854925bf6Swillf {
204954925bf6Swillf krb5_data pwd;
205054925bf6Swillf
205154925bf6Swillf pwd.length = passwd_len;
205254925bf6Swillf pwd.data = passwd;
205354925bf6Swillf
205454925bf6Swillf ret = tohex(pwd, &hexpasswd);
205554925bf6Swillf if (ret != 0) {
205654925bf6Swillf com_err(me, ret, gettext("Failed to convert the password to hexadecimal"));
205754925bf6Swillf memset(passwd, 0, passwd_len);
205854925bf6Swillf goto cleanup;
205954925bf6Swillf }
206054925bf6Swillf }
206154925bf6Swillf memset(passwd, 0, passwd_len);
206254925bf6Swillf
206354925bf6Swillf /* TODO: file lock for the service passowrd file */
206454925bf6Swillf
206554925bf6Swillf /* set password in the file */
206654925bf6Swillf #if 0 /* ************ Begin IFDEF'ed OUT ***************************** */
206754925bf6Swillf old_mode = umask(0177);
206854925bf6Swillf pfile = fopen(file_name, "a+");
206954925bf6Swillf if (pfile == NULL) {
207054925bf6Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name,
207154925bf6Swillf strerror (errno));
207254925bf6Swillf goto cleanup;
207354925bf6Swillf }
207454925bf6Swillf rewind (pfile);
207554925bf6Swillf umask(old_mode);
207654925bf6Swillf #else
207754925bf6Swillf /* Solaris Kerberos: safer than the above */
207854925bf6Swillf fd = open(file_name, O_CREAT|O_RDWR|O_APPEND, 0600);
207954925bf6Swillf if (fd < 0) {
208054925bf6Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name,
208154925bf6Swillf strerror (errno));
208254925bf6Swillf goto cleanup;
208354925bf6Swillf }
208454925bf6Swillf pfile = fdopen(fd, "a+F");
208554925bf6Swillf if (pfile == NULL) {
208654925bf6Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name,
208754925bf6Swillf strerror (errno));
208854925bf6Swillf goto cleanup;
208954925bf6Swillf }
209054925bf6Swillf rewind (pfile);
209154925bf6Swillf #endif
209254925bf6Swillf
209354925bf6Swillf while (fgets (line, MAX_LEN, pfile) != NULL) {
209454925bf6Swillf if ((str = strstr (line, service_object)) != NULL) {
209554925bf6Swillf /*
209654925bf6Swillf * White spaces not allowed, # delimits the service dn from the
209754925bf6Swillf * password
209854925bf6Swillf */
209954925bf6Swillf if (line [strlen (service_object)] == '#')
210054925bf6Swillf break;
210154925bf6Swillf str = NULL;
210254925bf6Swillf }
210354925bf6Swillf }
210454925bf6Swillf
210554925bf6Swillf if (str == NULL) {
210654925bf6Swillf if (feof(pfile)) {
210754925bf6Swillf /* If the service object dn is not present in the service password file */
210854925bf6Swillf if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
210954925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
211054925bf6Swillf fclose(pfile);
211154925bf6Swillf goto cleanup;
211254925bf6Swillf }
211354925bf6Swillf } else {
211454925bf6Swillf com_err(me, errno, gettext("Error reading service object password file"));
211554925bf6Swillf fclose(pfile);
211654925bf6Swillf goto cleanup;
211754925bf6Swillf }
211854925bf6Swillf fclose(pfile);
211954925bf6Swillf } else {
212054925bf6Swillf /*
212154925bf6Swillf * Password entry for the service object is already present in the file
212254925bf6Swillf * Delete the existing entry and add the new entry
212354925bf6Swillf */
212454925bf6Swillf FILE *newfile;
212554925bf6Swillf
212654925bf6Swillf mode_t omask;
212754925bf6Swillf
212854925bf6Swillf /* Create a new file with the extension .tmp */
212954925bf6Swillf tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1));
213054925bf6Swillf if (tmp_file == NULL) {
213154925bf6Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
213254925bf6Swillf fclose(pfile);
213354925bf6Swillf goto cleanup;
213454925bf6Swillf }
213554925bf6Swillf sprintf(tmp_file,"%s.%s",file_name,"tmp");
213654925bf6Swillf
213754925bf6Swillf omask = umask(077);
213854925bf6Swillf newfile = fopen(tmp_file, "wF");
213954925bf6Swillf umask (omask);
214054925bf6Swillf if (newfile == NULL) {
214154925bf6Swillf com_err(me, errno, gettext("Error creating file %s"), tmp_file);
214254925bf6Swillf fclose(pfile);
214354925bf6Swillf goto cleanup;
214454925bf6Swillf }
214554925bf6Swillf
214654925bf6Swillf fseek(pfile, 0, SEEK_SET);
214754925bf6Swillf while (fgets(line, MAX_LEN, pfile) != NULL) {
214854925bf6Swillf if (((str = strstr(line, service_object)) != NULL) &&
214954925bf6Swillf (line[strlen(service_object)] == '#')) {
215054925bf6Swillf if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
215154925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
215254925bf6Swillf fclose(newfile);
215354925bf6Swillf unlink(tmp_file);
215454925bf6Swillf fclose(pfile);
215554925bf6Swillf goto cleanup;
215654925bf6Swillf }
215754925bf6Swillf } else {
215854925bf6Swillf if (fprintf (newfile, "%s", line) < 0) {
215954925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
216054925bf6Swillf fclose(newfile);
216154925bf6Swillf unlink(tmp_file);
216254925bf6Swillf fclose(pfile);
216354925bf6Swillf goto cleanup;
216454925bf6Swillf }
216554925bf6Swillf }
216654925bf6Swillf }
216754925bf6Swillf
216854925bf6Swillf if (!feof(pfile)) {
216954925bf6Swillf com_err(me, errno, gettext("Error reading service object password file"));
217054925bf6Swillf fclose(newfile);
217154925bf6Swillf unlink(tmp_file);
217254925bf6Swillf fclose(pfile);
217354925bf6Swillf goto cleanup;
217454925bf6Swillf }
217554925bf6Swillf
217654925bf6Swillf /* TODO: file lock for the service passowrd file */
217754925bf6Swillf
217854925bf6Swillf fclose(pfile);
217954925bf6Swillf fclose(newfile);
218054925bf6Swillf
218154925bf6Swillf ret = rename(tmp_file, file_name);
218254925bf6Swillf if (ret != 0) {
218354925bf6Swillf com_err(me, errno, gettext("Failed to write service object password to "
218454925bf6Swillf "file"));
218554925bf6Swillf goto cleanup;
218654925bf6Swillf }
218754925bf6Swillf }
218854925bf6Swillf ret = 0;
218954925bf6Swillf
219054925bf6Swillf cleanup:
219154925bf6Swillf
219254925bf6Swillf if (hexpasswd.length != 0) {
219354925bf6Swillf memset(hexpasswd.data, 0, hexpasswd.length);
219454925bf6Swillf free(hexpasswd.data);
219554925bf6Swillf }
219654925bf6Swillf
219754925bf6Swillf if (service_object)
219854925bf6Swillf free(service_object);
219954925bf6Swillf
220054925bf6Swillf if (file_name)
220154925bf6Swillf free(file_name);
220254925bf6Swillf
220354925bf6Swillf if (tmp_file)
220454925bf6Swillf free(tmp_file);
220554925bf6Swillf
220654925bf6Swillf if (print_usage)
220754925bf6Swillf usage();
220854925bf6Swillf /* db_usage(STASH_SRV_PW); */
220954925bf6Swillf
221054925bf6Swillf if (ret)
221154925bf6Swillf exit_status++;
221254925bf6Swillf }
221354925bf6Swillf
221454925bf6Swillf #endif /* #ifdef HAVE_EDIRECTORY */
2215