14960Swillf /*
2*8092SMark.Phalan@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
34960Swillf * Use is subject to license terms.
44960Swillf */
54960Swillf
64960Swillf /*
74960Swillf * kadmin/ldap_util/kdb5_ldap_services.c
84960Swillf */
94960Swillf
104960Swillf /* Copyright (c) 2004-2005, Novell, Inc.
114960Swillf * All rights reserved.
124960Swillf *
134960Swillf * Redistribution and use in source and binary forms, with or without
144960Swillf * modification, are permitted provided that the following conditions are met:
154960Swillf *
164960Swillf * * Redistributions of source code must retain the above copyright notice,
174960Swillf * this list of conditions and the following disclaimer.
184960Swillf * * Redistributions in binary form must reproduce the above copyright
194960Swillf * notice, this list of conditions and the following disclaimer in the
204960Swillf * documentation and/or other materials provided with the distribution.
214960Swillf * * The copyright holder's name is not used to endorse or promote products
224960Swillf * derived from this software without specific prior written permission.
234960Swillf *
244960Swillf * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
254960Swillf * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
264960Swillf * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
274960Swillf * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
284960Swillf * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
294960Swillf * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
304960Swillf * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
314960Swillf * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
324960Swillf * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
334960Swillf * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
344960Swillf * POSSIBILITY OF SUCH DAMAGE.
354960Swillf */
364960Swillf
374960Swillf /*
384960Swillf * Create / Delete / Modify / View / List service objects.
394960Swillf */
404960Swillf
414960Swillf /*
424960Swillf * Service objects have rights over realm objects and principals. The following
434960Swillf * functions manage the service objects.
444960Swillf */
454960Swillf
464960Swillf #include <stdio.h>
474960Swillf #include <k5-int.h>
484960Swillf #include <libintl.h> /* Solaris Kerberos */
494960Swillf #include <locale.h> /* Solaris Kerberos */
504960Swillf #include "kdb5_ldap_util.h"
514960Swillf #include "kdb5_ldap_list.h"
524960Swillf
534960Swillf #ifdef HAVE_EDIRECTORY
544960Swillf
554960Swillf krb5_error_code
564960Swillf rem_service_entry_from_file(int argc,
574960Swillf char *argv[],
584960Swillf char *file_name,
594960Swillf char *service_object);
604960Swillf
614960Swillf extern char *yes;
624960Swillf extern krb5_boolean db_inited;
634960Swillf
process_host_list(char ** host_list,int servicetype)644960Swillf static int process_host_list(char **host_list, int servicetype)
654960Swillf {
664960Swillf krb5_error_code retval = 0;
674960Swillf char *pchr = NULL;
684960Swillf char host_str[MAX_LEN_LIST_ENTRY] = "", proto_str[PROTOCOL_STR_LEN + 1] = "", port_str[PORT_STR_LEN + 1] = "";
694960Swillf int j = 0;
704960Swillf
714960Swillf /* Protocol and port number processing */
724960Swillf for (j = 0; host_list[j]; j++) {
734960Swillf /* Look for one hash */
744960Swillf if ((pchr = strchr(host_list[j], HOST_INFO_DELIMITER))) {
754960Swillf unsigned int hostname_len = pchr - host_list[j];
764960Swillf
774960Swillf /* Check input for buffer overflow */
784960Swillf if (hostname_len >= MAX_LEN_LIST_ENTRY) {
794960Swillf retval = EINVAL;
804960Swillf goto cleanup;
814960Swillf }
824960Swillf
834960Swillf /* First copy off the host name portion */
844960Swillf strncpy (host_str, host_list[j], hostname_len);
854960Swillf
864960Swillf /* Parse for the protocol string and translate to number */
874960Swillf strncpy (proto_str, pchr + 1, PROTOCOL_STR_LEN);
884960Swillf if (!strcmp(proto_str, "udp"))
894960Swillf sprintf (proto_str, "%d", PROTOCOL_NUM_UDP);
904960Swillf else if (!strcmp(proto_str, "tcp"))
914960Swillf sprintf (proto_str, "%d", PROTOCOL_NUM_TCP);
924960Swillf else
934960Swillf proto_str[0] = '\0'; /* Make the string null if invalid */
944960Swillf
954960Swillf /* Look for one more hash */
964960Swillf if ((pchr = strchr(pchr + 1, HOST_INFO_DELIMITER))) {
974960Swillf /* Parse for the port string and check if it is numeric */
984960Swillf strncpy (port_str, pchr + 1, PORT_STR_LEN);
994960Swillf if (!strtol(port_str, NULL, 10)) /* Not a valid number */
1004960Swillf port_str[0] = '\0';
1014960Swillf } else
1024960Swillf port_str[0] = '\0';
1034960Swillf } else { /* We have only host name */
1044960Swillf strncpy (host_str, host_list[j], MAX_LEN_LIST_ENTRY - 1);
1054960Swillf proto_str[0] = '\0';
1064960Swillf port_str[0] = '\0';
1074960Swillf }
1084960Swillf
1094960Swillf /* Now, based on service type, fill in suitable protocol
1104960Swillf and port values if they are absent or not matching */
1114960Swillf if (servicetype == LDAP_KDC_SERVICE) {
1124960Swillf if (proto_str[0] == '\0')
1134960Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_KDC);
1144960Swillf
1154960Swillf if (port_str[0] == '\0')
1164960Swillf sprintf (port_str, "%d", PORT_DEFAULT_KDC);
1174960Swillf } else if (servicetype == LDAP_ADMIN_SERVICE) {
1184960Swillf if (proto_str[0] == '\0')
1194960Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM);
1204960Swillf else if (strcmp(proto_str, "1")) {
1214960Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM);
1224960Swillf
1234960Swillf /* Print warning message */
1244960Swillf printf (gettext("Admin Server supports only TCP protocol, hence setting that\n"));
1254960Swillf }
1264960Swillf
1274960Swillf if (port_str[0] == '\0')
1284960Swillf sprintf (port_str, "%d", PORT_DEFAULT_ADM);
1294960Swillf } else if (servicetype == LDAP_PASSWD_SERVICE) {
1304960Swillf if (proto_str[0] == '\0')
1314960Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD);
1324960Swillf else if (strcmp(proto_str, "0")) {
1334960Swillf sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD);
1344960Swillf
1354960Swillf /* Print warning message */
1364960Swillf printf (gettext("Password Server supports only UDP protocol, hence setting that\n"));
1374960Swillf }
1384960Swillf
1394960Swillf if (port_str[0] == '\0')
1404960Swillf sprintf (port_str, "%d", PORT_DEFAULT_PWD);
1414960Swillf }
1424960Swillf
1434960Swillf /* Finally form back the string */
1444960Swillf free (host_list[j]);
1454960Swillf host_list[j] = (char*) malloc(sizeof(char) *
1464960Swillf (strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1));
1474960Swillf if (host_list[j] == NULL) {
1484960Swillf retval = ENOMEM;
1494960Swillf goto cleanup;
1504960Swillf }
1514960Swillf snprintf (host_list[j], strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1,
1524960Swillf "%s#%s#%s", host_str, proto_str, port_str);
1534960Swillf }
1544960Swillf
1554960Swillf cleanup:
1564960Swillf return retval;
1574960Swillf }
1584960Swillf
1594960Swillf
1604960Swillf /*
1614960Swillf * Given a realm name, this function will convert it to a DN by appending the
1624960Swillf * Kerberos container location.
1634960Swillf */
1644960Swillf static krb5_error_code
convert_realm_name2dn_list(list,krbcontainer_loc)1654960Swillf convert_realm_name2dn_list(list, krbcontainer_loc)
1664960Swillf char **list;
1674960Swillf const char *krbcontainer_loc;
1684960Swillf {
1694960Swillf krb5_error_code retval = 0;
1704960Swillf char temp_str[MAX_DN_CHARS] = "\0";
1714960Swillf char *temp_node = NULL;
1724960Swillf int i = 0;
1734960Swillf
1744960Swillf if (list == NULL) {
1754960Swillf return EINVAL;
1764960Swillf }
1774960Swillf
1784960Swillf for (i = 0; (list[i] != NULL) && (i < MAX_LIST_ENTRIES); i++) {
1794960Swillf /* Restrict copying to max. length to avoid buffer overflow */
1804960Swillf snprintf (temp_str, MAX_DN_CHARS, "cn=%s,%s", list[i], krbcontainer_loc);
1814960Swillf
1824960Swillf /* Make copy of string to temporary node */
1834960Swillf temp_node = strdup(temp_str);
1844960Swillf if (list[i] == NULL) {
1854960Swillf retval = ENOMEM;
1864960Swillf goto cleanup;
1874960Swillf }
1884960Swillf
1894960Swillf /* On success, free list node and attach new one */
1904960Swillf free (list[i]);
1914960Swillf list[i] = temp_node;
1924960Swillf temp_node = NULL;
1934960Swillf }
1944960Swillf
1954960Swillf cleanup:
1964960Swillf return retval;
1974960Swillf }
1984960Swillf
1994960Swillf
2004960Swillf /*
2014960Swillf * This function will create a service object on the LDAP Server, with the
2024960Swillf * specified attributes.
2034960Swillf */
kdb5_ldap_create_service(argc,argv)2044960Swillf void kdb5_ldap_create_service(argc, argv)
2054960Swillf int argc;
2064960Swillf char *argv[];
2074960Swillf {
208*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
209*8092SMark.Phalan@Sun.COM char *me = progname;
2104960Swillf krb5_error_code retval = 0;
2114960Swillf krb5_ldap_service_params *srvparams = NULL;
2124960Swillf krb5_boolean print_usage = FALSE;
2134960Swillf krb5_boolean no_msg = FALSE;
2144960Swillf int mask = 0;
2154960Swillf char **extra_argv = NULL;
2164960Swillf int extra_argc = 0;
2174960Swillf int i = 0;
2184960Swillf krb5_ldap_realm_params *rparams = NULL;
2194960Swillf int rmask = 0;
2204960Swillf int rightsmask =0;
2214960Swillf char **temprdns = NULL;
2224960Swillf char *realmName = NULL;
2234960Swillf kdb5_dal_handle *dal_handle = NULL;
2244960Swillf krb5_ldap_context *ldap_context=NULL;
2254960Swillf krb5_boolean service_obj_created = FALSE;
2264960Swillf
2274960Swillf /* Check for number of arguments */
2284960Swillf if ((argc < 3) || (argc > 10)) {
2294960Swillf exit_status++;
2304960Swillf goto err_usage;
2314960Swillf }
2324960Swillf
2334960Swillf /* Allocate memory for service parameters structure */
2344960Swillf srvparams = (krb5_ldap_service_params*) calloc(1, sizeof(krb5_ldap_service_params));
2354960Swillf if (srvparams == NULL) {
2364960Swillf retval = ENOMEM;
2374960Swillf goto cleanup;
2384960Swillf }
2394960Swillf
2404960Swillf dal_handle = (kdb5_dal_handle *) util_context->db_context;
2414960Swillf ldap_context = (krb5_ldap_context *) dal_handle->db_context;
2424960Swillf
2434960Swillf /* Allocate memory for extra arguments to be used for setting
2444960Swillf password -- it's OK to allocate as much as the total number
2454960Swillf of arguments */
2464960Swillf extra_argv = (char **) calloc((unsigned int)argc, sizeof(char*));
2474960Swillf if (extra_argv == NULL) {
2484960Swillf retval = ENOMEM;
2494960Swillf goto cleanup;
2504960Swillf }
2514960Swillf
2524960Swillf /* Set first of the extra arguments as the program name */
2534960Swillf extra_argv[0] = me;
2544960Swillf extra_argc++;
2554960Swillf
2564960Swillf /* Read Kerberos container info, to construct realm DN from name
2574960Swillf * and for assigning rights
2584960Swillf */
2594960Swillf if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
2604960Swillf &(ldap_context->krbcontainer)))) {
2614960Swillf com_err(me, retval, gettext("while reading Kerberos container information"));
2624960Swillf goto cleanup;
2634960Swillf }
2644960Swillf
2654960Swillf /* Parse all arguments */
2664960Swillf for (i = 1; i < argc; i++) {
2674960Swillf if (!strcmp(argv[i], "-kdc")) {
2684960Swillf srvparams->servicetype = LDAP_KDC_SERVICE;
2694960Swillf } else if (!strcmp(argv[i], "-admin")) {
2704960Swillf srvparams->servicetype = LDAP_ADMIN_SERVICE;
2714960Swillf } else if (!strcmp(argv[i], "-pwd")) {
2724960Swillf srvparams->servicetype = LDAP_PASSWD_SERVICE;
2734960Swillf } else if (!strcmp(argv[i], "-servicehost")) {
2744960Swillf if (++i > argc - 1)
2754960Swillf goto err_usage;
2764960Swillf
2774960Swillf srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES,
2784960Swillf sizeof(char *));
2794960Swillf if (srvparams->krbhostservers == NULL) {
2804960Swillf retval = ENOMEM;
2814960Swillf goto cleanup;
2824960Swillf }
2834960Swillf
2844960Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
2854960Swillf srvparams->krbhostservers))) {
2864960Swillf goto cleanup;
2874960Swillf }
2884960Swillf
2894960Swillf if ((retval = process_host_list (srvparams->krbhostservers,
2904960Swillf srvparams->servicetype))) {
2914960Swillf goto cleanup;
2924960Swillf }
2934960Swillf
2944960Swillf mask |= LDAP_SERVICE_HOSTSERVER;
2954960Swillf } else if (!strcmp(argv[i], "-realm")) {
2964960Swillf if (++i > argc - 1)
2974960Swillf goto err_usage;
2984960Swillf
2994960Swillf srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES,
3004960Swillf sizeof(char *));
3014960Swillf if (srvparams->krbrealmreferences == NULL) {
3024960Swillf retval = ENOMEM;
3034960Swillf goto cleanup;
3044960Swillf }
3054960Swillf
3064960Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
3074960Swillf srvparams->krbrealmreferences))) {
3084960Swillf goto cleanup;
3094960Swillf }
3104960Swillf
3114960Swillf /* Convert realm names to realm DNs */
3124960Swillf if ((retval = convert_realm_name2dn_list(
3134960Swillf srvparams->krbrealmreferences,
3144960Swillf ldap_context->krbcontainer->DN))) {
3154960Swillf goto cleanup;
3164960Swillf }
3174960Swillf
3184960Swillf mask |= LDAP_SERVICE_REALMREFERENCE;
3194960Swillf }
3204960Swillf /* If argument is none of the above and beginning with '-',
3214960Swillf * it must be related to password -- collect it
3224960Swillf * to pass onto kdb5_ldap_set_service_password()
3234960Swillf */
3244960Swillf else if (*(argv[i]) == '-') {
3254960Swillf /* Checking for options of setting the password for the
3264960Swillf * service (by using 'setsrvpw') is not modular. --need to
3274960Swillf * have a common function that can be shared with 'setsrvpw'
3284960Swillf */
3294960Swillf if (!strcmp(argv[i], "-randpw")) {
3304960Swillf extra_argv[extra_argc] = argv[i];
3314960Swillf extra_argc++;
3324960Swillf } else if (!strcmp(argv[i], "-fileonly")) {
3334960Swillf extra_argv[extra_argc] = argv[i];
3344960Swillf extra_argc++;
3354960Swillf }
3364960Swillf /* For '-f' option alone, pick up the following argument too */
3374960Swillf else if (!strcmp(argv[i], "-f")) {
3384960Swillf extra_argv[extra_argc] = argv[i];
3394960Swillf extra_argc++;
3404960Swillf
3414960Swillf if (++i > argc - 1)
3424960Swillf goto err_usage;
3434960Swillf
3444960Swillf extra_argv[extra_argc] = argv[i];
3454960Swillf extra_argc++;
3464960Swillf } else { /* Any other option is invalid */
3474960Swillf exit_status++;
3484960Swillf goto err_usage;
3494960Swillf }
3504960Swillf } else { /* Any other argument must be service DN */
3514960Swillf /* First check if service DN is already provided --
3524960Swillf * if so, there's a usage error
3534960Swillf */
3544960Swillf if (srvparams->servicedn != NULL) {
3554960Swillf com_err(me, EINVAL, gettext("while creating service object"));
3564960Swillf goto err_usage;
3574960Swillf }
3584960Swillf
3594960Swillf /* If not present already, fill up service DN */
3604960Swillf srvparams->servicedn = strdup(argv[i]);
3614960Swillf if (srvparams->servicedn == NULL) {
3624960Swillf com_err(me, ENOMEM, gettext("while creating service object"));
3634960Swillf goto err_nomsg;
3644960Swillf }
3654960Swillf }
3664960Swillf }
3674960Swillf
3684960Swillf /* No point in proceeding further if service DN value is not available */
3694960Swillf if (srvparams->servicedn == NULL) {
3704960Swillf com_err(me, EINVAL, gettext("while creating service object"));
3714960Swillf goto err_usage;
3724960Swillf }
3734960Swillf
3744960Swillf if (srvparams->servicetype == 0) { /* Not provided and hence not set */
3754960Swillf com_err(me, EINVAL, gettext("while creating service object"));
3764960Swillf goto err_usage;
3774960Swillf }
3784960Swillf
3794960Swillf /* Create object with all attributes provided */
3804960Swillf if ((retval = krb5_ldap_create_service(util_context, srvparams, mask)))
3814960Swillf goto cleanup;
3824960Swillf
3834960Swillf service_obj_created = TRUE;
3844960Swillf
3854960Swillf /* ** NOTE ** srvparams structure should not be modified, as it is
3864960Swillf * used for deletion of the service object in case of any failures
3874960Swillf * from now on.
3884960Swillf */
3894960Swillf
3904960Swillf /* Set password too */
3914960Swillf if (extra_argc >= 1) {
3924960Swillf /* Set service DN as the last argument */
3934960Swillf extra_argv[extra_argc] = strdup(srvparams->servicedn);
3944960Swillf if (extra_argv[extra_argc] == NULL) {
3954960Swillf retval = ENOMEM;
3964960Swillf goto cleanup;
3974960Swillf }
3984960Swillf extra_argc++;
3994960Swillf
4004960Swillf if ((retval = kdb5_ldap_set_service_password(extra_argc, extra_argv)) != 0) {
4014960Swillf goto err_nomsg;
4024960Swillf }
4034960Swillf }
4044960Swillf /* Rights assignment */
4054960Swillf if (mask & LDAP_SERVICE_REALMREFERENCE) {
4064960Swillf
4074960Swillf printf("%s", gettext("Changing rights for the service object. Please wait ... "));
4084960Swillf fflush(stdout);
4094960Swillf
4104960Swillf rightsmask =0;
4114960Swillf rightsmask |= LDAP_REALM_RIGHTS;
4124960Swillf rightsmask |= LDAP_SUBTREE_RIGHTS;
4134960Swillf
4144960Swillf if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) {
4154960Swillf for (i=0; (srvparams->krbrealmreferences[i] != NULL); i++) {
4164960Swillf
4174960Swillf /* Get the realm name, not the dn */
4184960Swillf temprdns = ldap_explode_dn(srvparams->krbrealmreferences[i], 1);
4194960Swillf
4204960Swillf if (temprdns[0] == NULL) {
4214960Swillf retval = EINVAL;
4224960Swillf goto cleanup;
4234960Swillf }
4244960Swillf
4254960Swillf realmName = strdup(temprdns[0]);
4264960Swillf if (realmName == NULL) {
4274960Swillf retval = ENOMEM;
4284960Swillf goto cleanup;
4294960Swillf }
4304960Swillf
4314960Swillf if ((retval = krb5_ldap_read_realm_params(util_context,
4324960Swillf realmName, &rparams, &rmask))) {
4334960Swillf com_err(me, retval, gettext("while reading information of realm '%s'"),
4344960Swillf realmName);
4354960Swillf goto cleanup;
4364960Swillf }
4374960Swillf
4384960Swillf if ((retval = krb5_ldap_add_service_rights(util_context,
4394960Swillf srvparams->servicetype, srvparams->servicedn,
4404960Swillf realmName, rparams->subtree, rightsmask))) {
4414960Swillf printf(gettext("failed\n"));
4424960Swillf com_err(me, retval, gettext("while assigning rights '%s'"),
4434960Swillf srvparams->servicedn);
4444960Swillf goto cleanup;
4454960Swillf }
4464960Swillf
4474960Swillf if (rparams)
4484960Swillf krb5_ldap_free_realm_params(rparams);
4494960Swillf }
4504960Swillf }
4514960Swillf printf(gettext("done\n"));
4524960Swillf }
4534960Swillf goto cleanup;
4544960Swillf
4554960Swillf err_usage:
4564960Swillf print_usage = TRUE;
4574960Swillf
4584960Swillf err_nomsg:
4594960Swillf no_msg = TRUE;
4604960Swillf
4614960Swillf cleanup:
4624960Swillf
4634960Swillf if ((retval != 0) && (service_obj_created == TRUE)) {
4644960Swillf /* This is for deleting the service object if something goes
4654960Swillf * wrong in creating the service object
4664960Swillf */
4674960Swillf
4684960Swillf /* srvparams is populated from the user input and should be correct as
4694960Swillf * we were successful in creating a service object. Reusing the same
4704960Swillf */
4714960Swillf krb5_ldap_delete_service(util_context, srvparams, srvparams->servicedn);
4724960Swillf }
4734960Swillf
4744960Swillf /* Clean-up structure */
4754960Swillf krb5_ldap_free_service (util_context, srvparams);
4764960Swillf
4774960Swillf if (extra_argv) {
4784960Swillf free (extra_argv);
4794960Swillf extra_argv = NULL;
4804960Swillf }
4814960Swillf if (realmName) {
4824960Swillf free(realmName);
4834960Swillf realmName = NULL;
4844960Swillf }
4854960Swillf if (print_usage)
4864960Swillf db_usage (CREATE_SERVICE);
4874960Swillf
4884960Swillf if (retval) {
4894960Swillf if (!no_msg)
4904960Swillf com_err(me, retval, gettext("while creating service object"));
4914960Swillf
4924960Swillf exit_status++;
4934960Swillf }
4944960Swillf
4954960Swillf return;
4964960Swillf }
4974960Swillf
4984960Swillf
4994960Swillf /*
5004960Swillf * This function will modify the attributes of a given service
5014960Swillf * object on the LDAP Server
5024960Swillf */
kdb5_ldap_modify_service(argc,argv)5034960Swillf void kdb5_ldap_modify_service(argc, argv)
5044960Swillf int argc;
5054960Swillf char *argv[];
5064960Swillf {
507*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
508*8092SMark.Phalan@Sun.COM char *me = progname;
5094960Swillf krb5_error_code retval = 0;
5104960Swillf krb5_ldap_service_params *srvparams = NULL;
5114960Swillf krb5_boolean print_usage = FALSE;
5124960Swillf krb5_boolean no_msg = FALSE;
5134960Swillf char *servicedn = NULL;
5144960Swillf int i = 0;
5154960Swillf int in_mask = 0, out_mask = 0;
5164960Swillf int srvhost_flag = 0, realmdn_flag = 0;
5174960Swillf char **list = NULL;
5184960Swillf int existing_entries = 0, new_entries = 0;
5194960Swillf char **temp_ptr = NULL;
5204960Swillf krb5_ldap_realm_params *rparams = NULL;
5214960Swillf int j = 0;
5224960Swillf int rmask = 0;
5234960Swillf int rightsmask =0;
5244960Swillf char **oldrealmrefs = NULL;
5254960Swillf char **newrealmrefs = NULL;
5264960Swillf char **temprdns = NULL;
5274960Swillf char *realmName = NULL;
5284960Swillf kdb5_dal_handle *dal_handle = NULL;
5294960Swillf krb5_ldap_context *ldap_context=NULL;
5304960Swillf
5314960Swillf /* Check for number of arguments */
5324960Swillf if ((argc < 3) || (argc > 10)) {
5334960Swillf exit_status++;
5344960Swillf goto err_usage;
5354960Swillf }
5364960Swillf
5374960Swillf dal_handle = (kdb5_dal_handle *) util_context->db_context;
5384960Swillf ldap_context = (krb5_ldap_context *) dal_handle->db_context;
5394960Swillf
5404960Swillf /* Parse all arguments, only to pick up service DN (Pass 1) */
5414960Swillf for (i = 1; i < argc; i++) {
5424960Swillf /* Skip arguments next to 'servicehost'
5434960Swillf and 'realmdn' arguments */
5444960Swillf if (!strcmp(argv[i], "-servicehost")) {
5454960Swillf ++i;
5464960Swillf } else if (!strcmp(argv[i], "-clearservicehost")) {
5474960Swillf ++i;
5484960Swillf } else if (!strcmp(argv[i], "-addservicehost")) {
5494960Swillf ++i;
5504960Swillf } else if (!strcmp(argv[i], "-realm")) {
5514960Swillf ++i;
5524960Swillf } else if (!strcmp(argv[i], "-clearrealm")) {
5534960Swillf ++i;
5544960Swillf } else if (!strcmp(argv[i], "-addrealm")) {
5554960Swillf ++i;
5564960Swillf } else { /* Any other argument must be service DN */
5574960Swillf /* First check if service DN is already provided --
5584960Swillf if so, there's a usage error */
5594960Swillf if (servicedn != NULL) {
5604960Swillf com_err(me, EINVAL, gettext("while modifying service object"));
5614960Swillf goto err_usage;
5624960Swillf }
5634960Swillf
5644960Swillf /* If not present already, fill up service DN */
5654960Swillf servicedn = strdup(argv[i]);
5664960Swillf if (servicedn == NULL) {
5674960Swillf com_err(me, ENOMEM, gettext("while modifying service object"));
5684960Swillf goto err_nomsg;
5694960Swillf }
5704960Swillf }
5714960Swillf }
5724960Swillf
5734960Swillf /* No point in proceeding further if service DN value is not available */
5744960Swillf if (servicedn == NULL) {
5754960Swillf com_err(me, EINVAL, gettext("while modifying service object"));
5764960Swillf goto err_usage;
5774960Swillf }
5784960Swillf
5794960Swillf retval = krb5_ldap_read_service(util_context, servicedn, &srvparams, &in_mask);
5804960Swillf if (retval) {
581*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
582*8092SMark.Phalan@Sun.COM com_err(me, retval, gettext("while reading information of service '%s'"),
5834960Swillf servicedn);
5844960Swillf goto err_nomsg;
5854960Swillf }
5864960Swillf
5874960Swillf /* Read Kerberos container info, to construct realm DN from name
5884960Swillf * and for assigning rights
5894960Swillf */
5904960Swillf if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
5914960Swillf &(ldap_context->krbcontainer)))) {
5924960Swillf com_err(me, retval, gettext("while reading Kerberos container information"));
5934960Swillf goto cleanup;
5944960Swillf }
5954960Swillf
5964960Swillf /* Parse all arguments, but skip the service DN (Pass 2) */
5974960Swillf for (i = 1; i < argc; i++) {
5984960Swillf if (!strcmp(argv[i], "-servicehost")) {
5994960Swillf if (++i > argc - 1)
6004960Swillf goto err_usage;
6014960Swillf
6024960Swillf /* Free the old list if available */
6034960Swillf if (srvparams->krbhostservers) {
6044960Swillf krb5_free_list_entries (srvparams->krbhostservers);
6054960Swillf free (srvparams->krbhostservers);
6064960Swillf }
6074960Swillf
6084960Swillf srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES,
6094960Swillf sizeof(char *));
6104960Swillf if (srvparams->krbhostservers == NULL) {
6114960Swillf retval = ENOMEM;
6124960Swillf goto cleanup;
6134960Swillf }
6144960Swillf
6154960Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
6164960Swillf srvparams->krbhostservers))) {
6174960Swillf goto cleanup;
6184960Swillf }
6194960Swillf
6204960Swillf if ((retval = process_host_list (srvparams->krbhostservers,
6214960Swillf srvparams->servicetype))) {
6224960Swillf goto cleanup;
6234960Swillf }
6244960Swillf
6254960Swillf out_mask |= LDAP_SERVICE_HOSTSERVER;
6264960Swillf
6274960Swillf /* Set flag to ignore 'add' and 'clear' */
6284960Swillf srvhost_flag = 1;
6294960Swillf } else if (!strcmp(argv[i], "-clearservicehost")) {
6304960Swillf if (++i > argc - 1)
6314960Swillf goto err_usage;
6324960Swillf
6334960Swillf if (!srvhost_flag) {
6344960Swillf /* If attribute doesn't exist, don't permit 'clear' option */
6354960Swillf if ((in_mask & LDAP_SERVICE_HOSTSERVER) == 0) {
6364960Swillf /* Send out some proper error message here */
6374960Swillf com_err(me, EINVAL, gettext("service host list is empty\n"));
6384960Swillf goto err_nomsg;
6394960Swillf }
6404960Swillf
6414960Swillf /* Allocate list for processing */
6424960Swillf list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
6434960Swillf if (list == NULL) {
6444960Swillf retval = ENOMEM;
6454960Swillf goto cleanup;
6464960Swillf }
6474960Swillf
6484960Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
6494960Swillf goto cleanup;
6504960Swillf
6514960Swillf if ((retval = process_host_list (list, srvparams->servicetype))) {
6524960Swillf goto cleanup;
6534960Swillf }
6544960Swillf
6554960Swillf list_modify_str_array(&(srvparams->krbhostservers),
6564960Swillf (const char**)list, LIST_MODE_DELETE);
6574960Swillf
6584960Swillf out_mask |= LDAP_SERVICE_HOSTSERVER;
6594960Swillf
6604960Swillf /* Clean up */
6614960Swillf free (list);
6624960Swillf list = NULL;
6634960Swillf }
6644960Swillf } else if (!strcmp(argv[i], "-addservicehost")) {
6654960Swillf if (++i > argc - 1)
6664960Swillf goto err_usage;
6674960Swillf
6684960Swillf if (!srvhost_flag) {
6694960Swillf /* Allocate list for processing */
6704960Swillf list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
6714960Swillf if (list == NULL) {
6724960Swillf retval = ENOMEM;
6734960Swillf goto cleanup;
6744960Swillf }
6754960Swillf
6764960Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
6774960Swillf goto cleanup;
6784960Swillf
6794960Swillf if ((retval = process_host_list (list, srvparams->servicetype))) {
6804960Swillf goto cleanup;
6814960Swillf }
6824960Swillf
6834960Swillf /* Call list_modify_str_array() only if host server attribute
6844960Swillf * exists already --Actually, it's better to handle this
6854960Swillf * within list_modify_str_array()
6864960Swillf */
6874960Swillf if (in_mask & LDAP_SERVICE_HOSTSERVER) {
6884960Swillf /* Re-size existing list */
6894960Swillf existing_entries = list_count_str_array(srvparams->krbhostservers);
6904960Swillf new_entries = list_count_str_array(list);
6914960Swillf temp_ptr = (char **) realloc(srvparams->krbhostservers,
6924960Swillf sizeof(char *) * (existing_entries + new_entries + 1));
6934960Swillf if (temp_ptr == NULL) {
6944960Swillf retval = ENOMEM;
6954960Swillf goto cleanup;
6964960Swillf }
6974960Swillf srvparams->krbhostservers = temp_ptr;
6984960Swillf
6994960Swillf list_modify_str_array(&(srvparams->krbhostservers),
7004960Swillf (const char**)list, LIST_MODE_ADD);
7014960Swillf
7024960Swillf /* Clean up */
7034960Swillf free (list);
7044960Swillf list = NULL;
7054960Swillf } else
7064960Swillf srvparams->krbhostservers = list;
7074960Swillf
7084960Swillf out_mask |= LDAP_SERVICE_HOSTSERVER;
7094960Swillf }
7104960Swillf } else if (!strcmp(argv[i], "-realm")) {
7114960Swillf if (++i > argc - 1)
7124960Swillf goto err_usage;
7134960Swillf
7144960Swillf if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences)) {
7154960Swillf if (!oldrealmrefs) {
7164960Swillf /* Store the old realm list for removing rights */
7174960Swillf oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
7184960Swillf if (oldrealmrefs == NULL) {
7194960Swillf retval = ENOMEM;
7204960Swillf goto cleanup;
7214960Swillf }
7224960Swillf
7234960Swillf for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
7244960Swillf oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
7254960Swillf if (oldrealmrefs[j] == NULL) {
7264960Swillf retval = ENOMEM;
7274960Swillf goto cleanup;
7284960Swillf }
7294960Swillf }
7304960Swillf oldrealmrefs[j] = NULL;
7314960Swillf }
7324960Swillf
7334960Swillf /* Free the old list if available */
7344960Swillf krb5_free_list_entries (srvparams->krbrealmreferences);
7354960Swillf free (srvparams->krbrealmreferences);
7364960Swillf }
7374960Swillf
7384960Swillf srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES,
7394960Swillf sizeof(char *));
7404960Swillf if (srvparams->krbrealmreferences == NULL) {
7414960Swillf retval = ENOMEM;
7424960Swillf goto cleanup;
7434960Swillf }
7444960Swillf
7454960Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
7464960Swillf srvparams->krbrealmreferences))) {
7474960Swillf goto cleanup;
7484960Swillf }
7494960Swillf
7504960Swillf /* Convert realm names to realm DNs */
7514960Swillf if ((retval = convert_realm_name2dn_list(
7524960Swillf srvparams->krbrealmreferences,
7534960Swillf ldap_context->krbcontainer->DN))) {
7544960Swillf goto cleanup;
7554960Swillf }
7564960Swillf
7574960Swillf out_mask |= LDAP_SERVICE_REALMREFERENCE;
7584960Swillf
7594960Swillf /* Set flag to ignore 'add' and 'clear' */
7604960Swillf realmdn_flag = 1;
7614960Swillf } else if (!strcmp(argv[i], "-clearrealm")) {
7624960Swillf if (++i > argc - 1)
7634960Swillf goto err_usage;
7644960Swillf
7654960Swillf if (!realmdn_flag) {
7664960Swillf /* If attribute doesn't exist, don't permit 'clear' option */
7674960Swillf if (((in_mask & LDAP_SERVICE_REALMREFERENCE) == 0) || (srvparams->krbrealmreferences == NULL)) {
7684960Swillf /* Send out some proper error message here */
7694960Swillf goto err_nomsg;
7704960Swillf }
7714960Swillf
7724960Swillf if (!oldrealmrefs) {
7734960Swillf /* Store the old realm list for removing rights */
7744960Swillf oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
7754960Swillf if (oldrealmrefs == NULL) {
7764960Swillf retval = ENOMEM;
7774960Swillf goto cleanup;
7784960Swillf }
7794960Swillf
7804960Swillf for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
7814960Swillf oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
7824960Swillf if (oldrealmrefs[j] == NULL) {
7834960Swillf retval = ENOMEM;
7844960Swillf goto cleanup;
7854960Swillf }
7864960Swillf }
7874960Swillf oldrealmrefs[j] = NULL;
7884960Swillf }
7894960Swillf
7904960Swillf /* Allocate list for processing */
7914960Swillf list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
7924960Swillf if (list == NULL) {
7934960Swillf retval = ENOMEM;
7944960Swillf goto cleanup;
7954960Swillf }
7964960Swillf
7974960Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
7984960Swillf goto cleanup;
7994960Swillf
8004960Swillf /* Convert realm names to realm DNs */
8014960Swillf if ((retval = convert_realm_name2dn_list(list,
8024960Swillf ldap_context->krbcontainer->DN))) {
8034960Swillf goto cleanup;
8044960Swillf }
8054960Swillf
8064960Swillf list_modify_str_array(&(srvparams->krbrealmreferences),
8074960Swillf (const char**)list, LIST_MODE_DELETE);
8084960Swillf
8094960Swillf out_mask |= LDAP_SERVICE_REALMREFERENCE;
8104960Swillf
8114960Swillf /* Clean up */
8124960Swillf free (list);
8134960Swillf list = NULL;
8144960Swillf }
8154960Swillf } else if (!strcmp(argv[i], "-addrealm")) {
8164960Swillf if (++i > argc - 1)
8174960Swillf goto err_usage;
8184960Swillf
8194960Swillf if (!realmdn_flag) {
8204960Swillf /* Allocate list for processing */
8214960Swillf list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
8224960Swillf if (list == NULL) {
8234960Swillf retval = ENOMEM;
8244960Swillf goto cleanup;
8254960Swillf }
8264960Swillf
8274960Swillf if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
8284960Swillf goto cleanup;
8294960Swillf
8304960Swillf /* Convert realm names to realm DNs */
8314960Swillf if ((retval = convert_realm_name2dn_list(list,
8324960Swillf ldap_context->krbcontainer->DN))) {
8334960Swillf goto cleanup;
8344960Swillf }
8354960Swillf
8364960Swillf if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences) && (!oldrealmrefs)) {
8374960Swillf /* Store the old realm list for removing rights */
8384960Swillf oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
8394960Swillf if (oldrealmrefs == NULL) {
8404960Swillf retval = ENOMEM;
8414960Swillf goto cleanup;
8424960Swillf }
8434960Swillf
8444960Swillf for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
8454960Swillf oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
8464960Swillf if (oldrealmrefs[j] == NULL) {
8474960Swillf retval = ENOMEM;
8484960Swillf goto cleanup;
8494960Swillf }
8504960Swillf }
8514960Swillf oldrealmrefs[j] = NULL;
8524960Swillf }
8534960Swillf
8544960Swillf /* Call list_modify_str_array() only if realm DN attribute
8554960Swillf * exists already -- Actually, it's better to handle this
8564960Swillf * within list_modify_str_array() */
8574960Swillf if (in_mask & LDAP_SERVICE_REALMREFERENCE) {
8584960Swillf /* Re-size existing list */
8594960Swillf existing_entries = list_count_str_array(
8604960Swillf srvparams->krbrealmreferences);
8614960Swillf new_entries = list_count_str_array(list);
8624960Swillf temp_ptr = (char **) realloc(srvparams->krbrealmreferences,
8634960Swillf sizeof(char *) * (existing_entries + new_entries + 1));
8644960Swillf if (temp_ptr == NULL) {
8654960Swillf retval = ENOMEM;
8664960Swillf goto cleanup;
8674960Swillf }
8684960Swillf srvparams->krbrealmreferences = temp_ptr;
8694960Swillf
8704960Swillf list_modify_str_array(&(srvparams->krbrealmreferences),
8714960Swillf (const char**)list, LIST_MODE_ADD);
8724960Swillf
8734960Swillf /* Clean up */
8744960Swillf free (list);
8754960Swillf list = NULL;
8764960Swillf } else
8774960Swillf srvparams->krbrealmreferences = list;
8784960Swillf
8794960Swillf out_mask |= LDAP_SERVICE_REALMREFERENCE;
8804960Swillf }
8814960Swillf } else {
8824960Swillf /* Any other argument must be service DN
8834960Swillf -- skip it */
8844960Swillf }
8854960Swillf }
8864960Swillf
8874960Swillf /* Modify attributes of object */
8884960Swillf if ((retval = krb5_ldap_modify_service(util_context, srvparams, out_mask)))
8894960Swillf goto cleanup;
8904960Swillf
8914960Swillf /* Service rights modification code */
8924960Swillf if (out_mask & LDAP_SERVICE_REALMREFERENCE) {
8934960Swillf
8944960Swillf printf("%s", gettext("Changing rights for the service object. Please wait ... "));
8954960Swillf fflush(stdout);
8964960Swillf
8974960Swillf newrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
8984960Swillf if (newrealmrefs == NULL) {
8994960Swillf retval = ENOMEM;
9004960Swillf goto cleanup;
9014960Swillf }
9024960Swillf
9034960Swillf if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) {
9044960Swillf for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
9054960Swillf newrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
9064960Swillf if (newrealmrefs[j] == NULL) {
9074960Swillf retval = ENOMEM;
9084960Swillf goto cleanup;
9094960Swillf }
9104960Swillf }
9114960Swillf newrealmrefs[j] = NULL;
9124960Swillf }
9134960Swillf disjoint_members(oldrealmrefs, newrealmrefs);
9144960Swillf
9154960Swillf /* Delete the rights for the given service, on each of the realm
9164960Swillf * container & subtree in the old realm reference list.
9174960Swillf */
9184960Swillf if (oldrealmrefs) {
9194960Swillf rightsmask = 0;
9204960Swillf rightsmask |= LDAP_REALM_RIGHTS;
9214960Swillf rightsmask |= LDAP_SUBTREE_RIGHTS;
9224960Swillf
9234960Swillf for (i = 0; (oldrealmrefs[i] != NULL); i++) {
9244960Swillf /* Get the realm name, not the dn */
9254960Swillf temprdns = ldap_explode_dn(oldrealmrefs[i], 1);
9264960Swillf
9274960Swillf if (temprdns[0] == NULL) {
9284960Swillf retval = EINVAL;
9294960Swillf goto cleanup;
9304960Swillf }
9314960Swillf
9324960Swillf realmName = strdup(temprdns[0]);
9334960Swillf if (realmName == NULL) {
9344960Swillf retval = ENOMEM;
9354960Swillf goto cleanup;
9364960Swillf }
9374960Swillf
9384960Swillf if ((retval = krb5_ldap_read_realm_params(util_context,
9394960Swillf realmName, &rparams, &rmask))) {
9404960Swillf com_err(me, retval, gettext("while reading information of realm '%s'"),
9414960Swillf realmName);
9424960Swillf goto err_nomsg;
9434960Swillf }
9444960Swillf
9454960Swillf if ((retval = krb5_ldap_delete_service_rights(util_context,
9464960Swillf srvparams->servicetype, srvparams->servicedn,
9474960Swillf realmName, rparams->subtree, rightsmask))) {
9484960Swillf printf(gettext("failed\n"));
9494960Swillf com_err(me, retval, gettext("while assigning rights '%s'"),
9504960Swillf srvparams->servicedn);
9514960Swillf goto err_nomsg;
9524960Swillf }
9534960Swillf
9544960Swillf if (rparams)
9554960Swillf krb5_ldap_free_realm_params(rparams);
9564960Swillf }
9574960Swillf }
9584960Swillf
9594960Swillf /* Add the rights for the given service, on each of the realm
9604960Swillf * container & subtree in the new realm reference list.
9614960Swillf */
9624960Swillf if (newrealmrefs) {
9634960Swillf rightsmask = 0;
9644960Swillf rightsmask |= LDAP_REALM_RIGHTS;
9654960Swillf rightsmask |= LDAP_SUBTREE_RIGHTS;
9664960Swillf
9674960Swillf for (i = 0; (newrealmrefs[i] != NULL); i++) {
9684960Swillf /* Get the realm name, not the dn */
9694960Swillf temprdns = ldap_explode_dn(newrealmrefs[i], 1);
9704960Swillf
9714960Swillf if (temprdns[0] == NULL) {
9724960Swillf retval = EINVAL;
9734960Swillf goto cleanup;
9744960Swillf }
9754960Swillf
9764960Swillf realmName = strdup(temprdns[0]);
9774960Swillf if (realmName == NULL) {
9784960Swillf retval = ENOMEM;
9794960Swillf goto cleanup;
9804960Swillf }
9814960Swillf
9824960Swillf if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
9834960Swillf &(ldap_context->krbcontainer)))) {
9844960Swillf com_err(me, retval,
9854960Swillf gettext("while reading Kerberos container information"));
9864960Swillf goto cleanup;
9874960Swillf }
9884960Swillf
9894960Swillf if ((retval = krb5_ldap_read_realm_params(util_context,
9904960Swillf realmName, &rparams, &rmask))) {
9914960Swillf com_err(me, retval, gettext("while reading information of realm '%s'"),
9924960Swillf realmName);
9934960Swillf goto err_nomsg;
9944960Swillf }
9954960Swillf
9964960Swillf if ((retval = krb5_ldap_add_service_rights(util_context,
9974960Swillf srvparams->servicetype, srvparams->servicedn,
9984960Swillf realmName, rparams->subtree, rightsmask))) {
9994960Swillf printf(gettext("failed\n"));
10004960Swillf com_err(me, retval, gettext("while assigning rights '%s'"),
10014960Swillf srvparams->servicedn);
10024960Swillf goto err_nomsg;
10034960Swillf }
10044960Swillf
10054960Swillf if (rparams) {
10064960Swillf krb5_ldap_free_realm_params(rparams);
10074960Swillf rparams = NULL;
10084960Swillf }
10094960Swillf }
10104960Swillf printf(gettext("done\n"));
10114960Swillf }
10124960Swillf }
10134960Swillf goto cleanup;
10144960Swillf
10154960Swillf err_usage:
10164960Swillf print_usage = TRUE;
10174960Swillf
10184960Swillf err_nomsg:
10194960Swillf no_msg = TRUE;
10204960Swillf
10214960Swillf cleanup:
10224960Swillf /* Clean-up structure */
10234960Swillf krb5_ldap_free_service(util_context, srvparams);
10244960Swillf
10254960Swillf if (servicedn)
10264960Swillf free(servicedn);
10274960Swillf
10284960Swillf if (list) {
10294960Swillf free(list);
10304960Swillf list = NULL;
10314960Swillf }
10324960Swillf
10334960Swillf if (oldrealmrefs) {
10344960Swillf for (i = 0; oldrealmrefs[i] != NULL; i++)
10354960Swillf free(oldrealmrefs[i]);
10364960Swillf free(oldrealmrefs);
10374960Swillf }
10384960Swillf
10394960Swillf if (newrealmrefs) {
10404960Swillf for (i = 0; newrealmrefs[i] != NULL; i++)
10414960Swillf free(newrealmrefs[i]);
10424960Swillf free(newrealmrefs);
10434960Swillf }
10444960Swillf if (realmName) {
10454960Swillf free(realmName);
10464960Swillf realmName = NULL;
10474960Swillf }
10484960Swillf
10494960Swillf if (print_usage)
10504960Swillf db_usage(MODIFY_SERVICE);
10514960Swillf
10524960Swillf if (retval) {
10534960Swillf if (!no_msg)
10544960Swillf com_err(me, retval, gettext("while modifying service object"));
10554960Swillf exit_status++;
10564960Swillf }
10574960Swillf
10584960Swillf return;
10594960Swillf }
10604960Swillf
10614960Swillf
10624960Swillf /*
10634960Swillf * This function will delete the entry corresponding to the service object
10644960Swillf * from the service password file.
10654960Swillf */
10664960Swillf static krb5_error_code
rem_service_entry_from_file(argc,argv,file_name,service_object)10674960Swillf rem_service_entry_from_file(argc, argv, file_name, service_object)
10684960Swillf int argc;
10694960Swillf char *argv[];
10704960Swillf char *file_name;
10714960Swillf char *service_object;
10724960Swillf {
10734960Swillf int st = EINVAL;
1074*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1075*8092SMark.Phalan@Sun.COM char *me = progname;
10764960Swillf char *tmp_file = NULL;
10774960Swillf int tmpfd = -1;
10784960Swillf FILE *pfile = NULL;
10794960Swillf unsigned int len = 0;
10804960Swillf char line[MAX_LEN]={0};
10814960Swillf mode_t omask = umask(077);
10824960Swillf
10834960Swillf /* Check for permissions on the password file */
10844960Swillf if (access(file_name, W_OK) == -1) {
10854960Swillf /* If the specified file itself is not there, no need to show error */
10864960Swillf if (errno == ENOENT) {
10874960Swillf st=0;
10884960Swillf goto cleanup;
10894960Swillf } else {
10904960Swillf com_err(me, errno, gettext("while deleting entry from file %s", file_name));
10914960Swillf goto cleanup;
10924960Swillf }
10934960Swillf }
10944960Swillf
10954960Swillf /* Create a temporary file which contains all the entries except the
10964960Swillf entry for the given service dn */
10974960Swillf pfile = fopen(file_name, "r+F");
10984960Swillf if (pfile == NULL) {
10994960Swillf com_err(me, errno, gettext("while deleting entry from file %s"), file_name);
11004960Swillf goto cleanup;
11014960Swillf }
11024960Swillf
11034960Swillf /* Create a new file with the extension .tmp */
11044960Swillf tmp_file = (char *)malloc(strlen(file_name) + 4 + 1);
11054960Swillf if (tmp_file == NULL) {
11064960Swillf com_err(me, ENOMEM, gettext("while deleting entry from file"));
11074960Swillf fclose(pfile);
11084960Swillf goto cleanup;
11094960Swillf }
11104960Swillf snprintf (tmp_file, strlen(file_name) + 4 + 1, "%s%s", file_name, ".tmp");
11114960Swillf
11124960Swillf
11134960Swillf tmpfd = creat(tmp_file, S_IRUSR|S_IWUSR);
11144960Swillf umask(omask);
11154960Swillf if (tmpfd == -1) {
11164960Swillf com_err(me, errno, gettext("while deleting entry from file\n"));
11174960Swillf fclose(pfile);
11184960Swillf goto cleanup;
11194960Swillf }
11204960Swillf
11214960Swillf /* Copy only those lines which donot have the specified service dn */
11224960Swillf while (fgets(line, MAX_LEN, pfile) != NULL) {
11234960Swillf if ((strstr(line, service_object) != NULL) &&
11244960Swillf (line[strlen(service_object)] == '#')) {
11254960Swillf continue;
11264960Swillf } else {
11274960Swillf len = strlen(line);
11284960Swillf if (write(tmpfd, line, len) != len) {
11294960Swillf com_err(me, errno, gettext("while deleting entry from file\n"));
11304960Swillf close(tmpfd);
11314960Swillf unlink(tmp_file);
11324960Swillf fclose(pfile);
11334960Swillf goto cleanup;
11344960Swillf }
11354960Swillf }
11364960Swillf }
11374960Swillf
11384960Swillf fclose(pfile);
11394960Swillf if (unlink(file_name) == 0) {
11404960Swillf link(tmp_file, file_name);
11414960Swillf } else {
11424960Swillf com_err(me, errno, gettext("while deleting entry from file\n"));
11434960Swillf }
11444960Swillf unlink(tmp_file);
11454960Swillf
11464960Swillf st=0;
11474960Swillf
11484960Swillf cleanup:
11494960Swillf
11504960Swillf if (tmp_file)
11514960Swillf free(tmp_file);
11524960Swillf
11534960Swillf return st;
11544960Swillf }
11554960Swillf
11564960Swillf
11574960Swillf /*
11584960Swillf * This function will delete the service object from the LDAP Server
11594960Swillf * and unlink the references to the Realm objects (if any)
11604960Swillf */
11614960Swillf void
kdb5_ldap_destroy_service(argc,argv)11624960Swillf kdb5_ldap_destroy_service(argc, argv)
11634960Swillf int argc;
11644960Swillf char *argv[];
11654960Swillf {
11664960Swillf int i = 0;
11674960Swillf char buf[5] = {0};
11684960Swillf krb5_error_code retval = EINVAL;
11694960Swillf int force = 0;
11704960Swillf char *servicedn = NULL;
11714960Swillf char *stashfilename = NULL;
11724960Swillf int mask = 0;
11734960Swillf krb5_ldap_service_params *lserparams = NULL;
11744960Swillf krb5_boolean print_usage = FALSE;
11754960Swillf
11764960Swillf if ((argc < 2) || (argc > 5)) {
11774960Swillf exit_status++;
11784960Swillf goto err_usage;
11794960Swillf }
11804960Swillf
11814960Swillf for (i=1; i < argc; i++) {
11824960Swillf
11834960Swillf if (strcmp(argv[i],"-force")==0) {
11844960Swillf force++;
11854960Swillf } else if (strcmp(argv[i],"-f")==0) {
11864960Swillf if (argv[i+1]) {
11874960Swillf stashfilename=strdup(argv[i+1]);
11884960Swillf if (stashfilename == NULL) {
1189*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1190*8092SMark.Phalan@Sun.COM com_err(progname, ENOMEM, gettext("while destroying service"));
11914960Swillf exit_status++;
11924960Swillf goto cleanup;
11934960Swillf }
11944960Swillf i++;
11954960Swillf } else {
11964960Swillf exit_status++;
11974960Swillf goto err_usage;
11984960Swillf }
11994960Swillf } else {
12004960Swillf if ((argv[i]) && (servicedn == NULL)) {
12014960Swillf servicedn=strdup(argv[i]);
12024960Swillf if (servicedn == NULL) {
1203*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1204*8092SMark.Phalan@Sun.COM com_err(progname, ENOMEM, gettext("while destroying service"));
12054960Swillf exit_status++;
12064960Swillf goto cleanup;
12074960Swillf }
12084960Swillf } else {
12094960Swillf exit_status++;
12104960Swillf goto err_usage;
12114960Swillf }
12124960Swillf }
12134960Swillf }
12144960Swillf
12154960Swillf if (!servicedn) {
12164960Swillf exit_status++;
12174960Swillf goto err_usage;
12184960Swillf }
12194960Swillf
12204960Swillf if (!force) {
12214960Swillf printf(gettext("This will delete the service object '%s', are you sure?\n"), servicedn);
12224960Swillf printf(gettext("(type 'yes' to confirm)? "));
12234960Swillf if (fgets(buf, sizeof(buf), stdin) == NULL) {
12244960Swillf exit_status++;
12254960Swillf goto cleanup;;
12264960Swillf }
12274960Swillf if (strcmp(buf, yes)) {
12284960Swillf exit_status++;
12294960Swillf goto cleanup;
12304960Swillf }
12314960Swillf }
12324960Swillf
12334960Swillf if ((retval = krb5_ldap_read_service(util_context, servicedn,
12344960Swillf &lserparams, &mask))) {
1235*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1236*8092SMark.Phalan@Sun.COM com_err(progname, retval, gettext("while destroying service '%s'"), servicedn);
12374960Swillf exit_status++;
12384960Swillf goto cleanup;
12394960Swillf }
12404960Swillf
12414960Swillf retval = krb5_ldap_delete_service(util_context, lserparams, servicedn);
12424960Swillf
12434960Swillf if (retval) {
1244*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1245*8092SMark.Phalan@Sun.COM com_err(progname, retval, gettext("while destroying service '%s'"), servicedn);
12464960Swillf exit_status++;
12474960Swillf goto cleanup;
12484960Swillf }
12494960Swillf
12504960Swillf if (stashfilename == NULL) {
12514960Swillf stashfilename = strdup(DEF_SERVICE_PASSWD_FILE);
12524960Swillf if (stashfilename == NULL) {
1253*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1254*8092SMark.Phalan@Sun.COM com_err(progname, ENOMEM, gettext("while destroying service"));
12554960Swillf exit_status++;
12564960Swillf goto cleanup;
12574960Swillf }
12584960Swillf }
12594960Swillf printf(gettext("** service object '%s' deleted.\n"), servicedn);
12604960Swillf retval = rem_service_entry_from_file(argc, argv, stashfilename, servicedn);
12614960Swillf
12624960Swillf if (retval)
12634960Swillf printf(gettext("** error removing service object entry '%s' from password file.\n"),
12644960Swillf servicedn);
12654960Swillf
12664960Swillf goto cleanup;
12674960Swillf
12684960Swillf
12694960Swillf err_usage:
12704960Swillf print_usage = TRUE;
12714960Swillf
12724960Swillf cleanup:
12734960Swillf
12744960Swillf if (lserparams) {
12754960Swillf krb5_ldap_free_service(util_context, lserparams);
12764960Swillf }
12774960Swillf
12784960Swillf if (servicedn) {
12794960Swillf free(servicedn);
12804960Swillf }
12814960Swillf
12824960Swillf if (stashfilename) {
12834960Swillf free(stashfilename);
12844960Swillf }
12854960Swillf
12864960Swillf if (print_usage) {
12874960Swillf db_usage(DESTROY_SERVICE);
12884960Swillf }
12894960Swillf
12904960Swillf return;
12914960Swillf }
12924960Swillf
12934960Swillf
12944960Swillf /*
12954960Swillf * This function will display information about the given service object
12964960Swillf */
kdb5_ldap_view_service(argc,argv)12974960Swillf void kdb5_ldap_view_service(argc, argv)
12984960Swillf int argc;
12994960Swillf char *argv[];
13004960Swillf {
13014960Swillf krb5_ldap_service_params *lserparams = NULL;
13024960Swillf krb5_error_code retval = 0;
13034960Swillf char *servicedn = NULL;
13044960Swillf int mask = 0;
13054960Swillf krb5_boolean print_usage = FALSE;
13064960Swillf
13074960Swillf if (!(argc == 2)) {
13084960Swillf exit_status++;
13094960Swillf goto err_usage;
13104960Swillf }
13114960Swillf
13124960Swillf servicedn=strdup(argv[1]);
13134960Swillf if (servicedn == NULL) {
1314*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1315*8092SMark.Phalan@Sun.COM com_err(progname, ENOMEM, gettext("while viewing service"));
13164960Swillf exit_status++;
13174960Swillf goto cleanup;
13184960Swillf }
13194960Swillf
13204960Swillf if ((retval = krb5_ldap_read_service(util_context, servicedn, &lserparams, &mask))) {
1321*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1322*8092SMark.Phalan@Sun.COM com_err(progname, retval, gettext("while viewing service '%s'"), servicedn);
13234960Swillf exit_status++;
13244960Swillf goto cleanup;
13254960Swillf }
13264960Swillf
13274960Swillf print_service_params(lserparams, mask);
13284960Swillf
13294960Swillf goto cleanup;
13304960Swillf
13314960Swillf err_usage:
13324960Swillf print_usage = TRUE;
13334960Swillf
13344960Swillf cleanup:
13354960Swillf
13364960Swillf if (lserparams) {
13374960Swillf krb5_ldap_free_service(util_context, lserparams);
13384960Swillf }
13394960Swillf
13404960Swillf if (servicedn)
13414960Swillf free(servicedn);
13424960Swillf
13434960Swillf if (print_usage) {
13444960Swillf db_usage(VIEW_SERVICE);
13454960Swillf }
13464960Swillf
13474960Swillf return;
13484960Swillf }
13494960Swillf
13504960Swillf
13514960Swillf /*
13524960Swillf * This function will list the DNs of kerberos services present on
13534960Swillf * the LDAP Server under a specific sub-tree (entire tree by default)
13544960Swillf */
kdb5_ldap_list_services(argc,argv)13554960Swillf void kdb5_ldap_list_services(argc, argv)
13564960Swillf int argc;
13574960Swillf char *argv[];
13584960Swillf {
1359*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1360*8092SMark.Phalan@Sun.COM char *me = progname;
13614960Swillf krb5_error_code retval = 0;
13624960Swillf char *basedn = NULL;
13634960Swillf char **list = NULL;
13644960Swillf char **plist = NULL;
13654960Swillf krb5_boolean print_usage = FALSE;
13664960Swillf
13674960Swillf /* Check for number of arguments */
13684960Swillf if ((argc != 1) && (argc != 3)) {
13694960Swillf exit_status++;
13704960Swillf goto err_usage;
13714960Swillf }
13724960Swillf
13734960Swillf /* Parse base DN argument if present */
13744960Swillf if (argc == 3) {
13754960Swillf if (strcmp(argv[1], "-basedn")) {
13764960Swillf retval = EINVAL;
13774960Swillf goto err_usage;
13784960Swillf }
13794960Swillf
13804960Swillf basedn = strdup(argv[2]);
13814960Swillf if (basedn == NULL) {
13824960Swillf com_err(me, ENOMEM, gettext("while listing services"));
13834960Swillf exit_status++;
13844960Swillf goto cleanup;
13854960Swillf }
13864960Swillf }
13874960Swillf
13884960Swillf retval = krb5_ldap_list_services(util_context, basedn, &list);
13894960Swillf if ((retval != 0) || (list == NULL)) {
13904960Swillf exit_status++;
13914960Swillf goto cleanup;
13924960Swillf }
13934960Swillf
13944960Swillf for (plist = list; *plist != NULL; plist++) {
13954960Swillf printf("%s\n", *plist);
13964960Swillf }
13974960Swillf
13984960Swillf goto cleanup;
13994960Swillf
14004960Swillf err_usage:
14014960Swillf print_usage = TRUE;
14024960Swillf
14034960Swillf cleanup:
14044960Swillf if (list != NULL) {
14054960Swillf krb5_free_list_entries (list);
14064960Swillf free (list);
14074960Swillf }
14084960Swillf
14094960Swillf if (basedn)
14104960Swillf free (basedn);
14114960Swillf
14124960Swillf if (print_usage) {
14134960Swillf db_usage(LIST_SERVICE);
14144960Swillf }
14154960Swillf
14164960Swillf if (retval) {
14174960Swillf com_err(me, retval, gettext("while listing policy objects"));
14184960Swillf exit_status++;
14194960Swillf }
14204960Swillf
14214960Swillf return;
14224960Swillf }
14234960Swillf
14244960Swillf
14254960Swillf /*
14264960Swillf * This function will print the service object information
14274960Swillf * to the standard output
14284960Swillf */
14294960Swillf static void
print_service_params(lserparams,mask)14304960Swillf print_service_params(lserparams, mask)
14314960Swillf krb5_ldap_service_params *lserparams;
14324960Swillf int mask;
14334960Swillf {
14344960Swillf int i=0;
14354960Swillf
14364960Swillf /* Print the service dn */
14374960Swillf printf("%20s%-20s\n", gettext("Service dn: "), lserparams->servicedn);
14384960Swillf
14394960Swillf /* Print the service type of the object to be read */
14404960Swillf if (lserparams->servicetype == LDAP_KDC_SERVICE) {
14414960Swillf printf("%20s%-20s\n", gettext("Service type: "), "kdc");
14424960Swillf } else if (lserparams->servicetype == LDAP_ADMIN_SERVICE) {
14434960Swillf printf("%20s%-20s\n", gettext("Service type: "), "admin");
14444960Swillf } else if (lserparams->servicetype == LDAP_PASSWD_SERVICE) {
14454960Swillf printf("%20s%-20s\n", gettext("Service type: "), "pwd");
14464960Swillf }
14474960Swillf
14484960Swillf /* Print the host server values */
14494960Swillf printf("%20s\n", gettext("Service host list: "));
14504960Swillf if (mask & LDAP_SERVICE_HOSTSERVER) {
14514960Swillf for (i=0; lserparams->krbhostservers[i] != NULL; ++i) {
14524960Swillf printf("%20s%-50s\n","",lserparams->krbhostservers[i]);
14534960Swillf }
14544960Swillf }
14554960Swillf
14564960Swillf /* Print the realm reference dn values */
14574960Swillf printf("%20s\n", gettext("Realm DN list: "));
14584960Swillf if (mask & LDAP_SERVICE_REALMREFERENCE) {
14594960Swillf for (i=0; lserparams && lserparams->krbrealmreferences && lserparams->krbrealmreferences[i] != NULL; ++i) {
14604960Swillf printf("%20s%-50s\n","",lserparams->krbrealmreferences[i]);
14614960Swillf }
14624960Swillf }
14634960Swillf
14644960Swillf return;
14654960Swillf }
14664960Swillf
14674960Swillf
14684960Swillf /*
14694960Swillf * This function will generate random password of length(RANDOM_PASSWD_LEN)
14704960Swillf *
14714960Swillf *
14724960Swillf * INPUT:
14734960Swillf * ctxt - context
14744960Swillf *
14754960Swillf * OUTPUT:
14764960Swillf * RANDOM_PASSWD_LEN length random password
14774960Swillf */
generate_random_password(krb5_context ctxt,char ** randpwd,unsigned int * passlen)14784960Swillf static int generate_random_password(krb5_context ctxt, char **randpwd, unsigned int *passlen)
14794960Swillf {
14804960Swillf char *random_pwd = NULL;
14814960Swillf int ret = 0;
14824960Swillf krb5_data data;
14834960Swillf int i=0;
14844960Swillf /*int len = 0;*/
14854960Swillf
14864960Swillf /* setting random password length in the range 16-32 */
14874960Swillf srand((unsigned int)(time(0) ^ getpid()));
14884960Swillf
14894960Swillf data.length = RANDOM_PASSWD_LEN;
14904960Swillf random_pwd = (char *)malloc(data.length + 1);
14914960Swillf if (random_pwd == NULL) {
14924960Swillf com_err("setsrvpw", ENOMEM, gettext("while generating random password"));
14934960Swillf return ENOMEM;
14944960Swillf }
14954960Swillf memset(random_pwd, 0, data.length + 1);
14964960Swillf data.data = random_pwd;
14974960Swillf
14984960Swillf ret = krb5_c_random_make_octets(ctxt, &data);
14994960Swillf if (ret) {
15004960Swillf com_err("setsrvpw", ret, gettext("Error generating random password"));
15014960Swillf free(random_pwd);
15024960Swillf return ret;
15034960Swillf }
15044960Swillf
15054960Swillf for (i=0; i<data.length; i++) {
15064960Swillf /* restricting to ascii chars. Need to change this when 8.8 supports */
15074960Swillf if ((unsigned char)random_pwd[i] > 127) {
15084960Swillf random_pwd[i] = (unsigned char)random_pwd[i] % 128;
15094960Swillf } else if (random_pwd[i] == 0) {
15104960Swillf random_pwd[i] = (rand()/(RAND_MAX/127 + 1))+1;
15114960Swillf }
15124960Swillf }
15134960Swillf
15144960Swillf *randpwd = random_pwd;
15154960Swillf *passlen = data.length;
15164960Swillf
15174960Swillf return 0;
15184960Swillf }
15194960Swillf
15204960Swillf
15214960Swillf /*
15224960Swillf * This function will set the password of the service object in the directory
15234960Swillf * and/or the specified service password file.
15244960Swillf *
15254960Swillf *
15264960Swillf * INPUT:
15274960Swillf * argc - contains the number of arguments for this sub-command
15284960Swillf * argv - array of arguments for this sub-command
15294960Swillf *
15304960Swillf * OUTPUT:
15314960Swillf * void
15324960Swillf */
15334960Swillf int
kdb5_ldap_set_service_password(argc,argv)15344960Swillf kdb5_ldap_set_service_password(argc, argv)
15354960Swillf int argc;
15364960Swillf char **argv;
15374960Swillf {
15384960Swillf krb5_ldap_context *lparams = NULL;
15394960Swillf char *file_name = NULL;
15404960Swillf char *tmp_file = NULL;
1541*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1542*8092SMark.Phalan@Sun.COM char *me = progname;
15434960Swillf int filelen = 0;
15444960Swillf int random_passwd = 0;
15454960Swillf int set_dir_pwd = 1;
15464960Swillf krb5_boolean db_init_local = FALSE;
15474960Swillf char *service_object = NULL;
15484960Swillf char *passwd = NULL;
15494960Swillf char *prompt1 = NULL;
15504960Swillf char *prompt2 = NULL;
15514960Swillf unsigned int passwd_len = 0;
15524960Swillf krb5_error_code errcode = -1;
15534960Swillf int retval = 0, i = 0;
15544960Swillf unsigned int len = 0;
15554960Swillf krb5_boolean print_usage = FALSE;
15564960Swillf FILE *pfile = NULL;
15574960Swillf char *str = NULL;
15584960Swillf char line[MAX_LEN];
15594960Swillf kdb5_dal_handle *dal_handle = NULL;
15604960Swillf struct data encrypted_passwd = {0, NULL};
15614960Swillf
15624960Swillf /* The arguments for setsrv password should contain the service object DN
15634960Swillf * and options to specify whether the password should be updated in file only
15644960Swillf * or both file and directory. So the possible combination of arguments are:
15654960Swillf * setsrvpw servicedn wherein argc is 2
15664960Swillf * setsrvpw -fileonly servicedn wherein argc is 3
15674960Swillf * setsrvpw -randpw servicedn wherein argc is 3
15684960Swillf * setsrvpw -f filename servicedn wherein argc is 4
15694960Swillf * setsrvpw -fileonly -f filename servicedn wherein argc is 5
15704960Swillf * setsrvpw -randpw -f filename servicedn wherein argc is 5
15714960Swillf */
15724960Swillf if ((argc < 2) || (argc > 5)) {
15734960Swillf print_usage = TRUE;
15744960Swillf goto cleanup;
15754960Swillf }
15764960Swillf
15774960Swillf dal_handle = (kdb5_dal_handle *)util_context->db_context;
15784960Swillf lparams = (krb5_ldap_context *) dal_handle->db_context;
15794960Swillf
15804960Swillf if (lparams == NULL) {
15814960Swillf printf(gettext("%s: Invalid LDAP handle\n"), me);
15824960Swillf goto cleanup;
15834960Swillf }
15844960Swillf
15854960Swillf /* Parse the arguments */
15864960Swillf for (i = 1; i < argc -1 ; i++) {
15874960Swillf if (strcmp(argv[i], "-randpw") == 0) {
15884960Swillf random_passwd = 1;
15894960Swillf } else if (strcmp(argv[i], "-fileonly") == 0) {
15904960Swillf set_dir_pwd = 0;
15914960Swillf } else if (strcmp(argv[i], "-f") == 0) {
15924960Swillf if (argv[++i] == NULL) {
15934960Swillf print_usage = TRUE;
15944960Swillf goto cleanup;
15954960Swillf }
15964960Swillf
15974960Swillf file_name = strdup(argv[i]);
15984960Swillf if (file_name == NULL) {
15994960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
16004960Swillf goto cleanup;
16014960Swillf }
16024960Swillf /* Verify if the file location has the proper file name
16034960Swillf * for eg, if the file location is a directory like /home/temp/,
16044960Swillf * we reject it.
16054960Swillf */
16064960Swillf filelen = strlen(file_name);
16074960Swillf if ((filelen == 0) || (file_name[filelen-1] == '/')) {
16084960Swillf printf(gettext("%s: Filename not specified for setting service object password\n"), me);
16094960Swillf print_usage = TRUE;
16104960Swillf goto cleanup;
16114960Swillf }
16124960Swillf } else {
16134960Swillf printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me);
16144960Swillf print_usage = TRUE;
16154960Swillf goto cleanup;
16164960Swillf }
16174960Swillf }
16184960Swillf
16194960Swillf if (i != argc-1) {
16204960Swillf print_usage = TRUE;
16214960Swillf goto cleanup;
16224960Swillf }
16234960Swillf
16244960Swillf service_object = strdup(argv[i]);
16254960Swillf if (service_object == NULL) {
16264960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
16274960Swillf goto cleanup;
16284960Swillf }
16294960Swillf
16304960Swillf if (strlen(service_object) == 0) {
16314960Swillf printf(gettext("%s: Service object not specified for \"setsrvpw\" command\n"), me);
16324960Swillf print_usage = TRUE;
16334960Swillf goto cleanup;
16344960Swillf }
16354960Swillf
16364960Swillf if (service_object[0] == '-') {
16374960Swillf print_usage = TRUE;
16384960Swillf goto cleanup;
16394960Swillf }
16404960Swillf
16414960Swillf if (file_name == NULL) {
16424960Swillf file_name = strdup(DEF_SERVICE_PASSWD_FILE);
16434960Swillf if (file_name == NULL) {
16444960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
16454960Swillf goto cleanup;
16464960Swillf }
16474960Swillf }
16484960Swillf
16494960Swillf if (set_dir_pwd) {
16504960Swillf if (db_inited == FALSE) {
16514960Swillf if ((errcode = krb5_ldap_db_init(util_context, lparams))) {
16524960Swillf com_err(me, errcode, gettext("while initializing database"));
16534960Swillf goto cleanup;
16544960Swillf }
16554960Swillf db_init_local = TRUE;
16564960Swillf }
16574960Swillf }
16584960Swillf
16594960Swillf if (random_passwd) {
16604960Swillf if (!set_dir_pwd) {
16614960Swillf printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me);
16624960Swillf print_usage = TRUE;
16634960Swillf goto cleanup;
16644960Swillf } else {
16654960Swillf /* Generate random password */
16664960Swillf
16674960Swillf if ((errcode = generate_random_password(util_context, &passwd, &passwd_len))) {
16684960Swillf printf(gettext("%s: Failed to set service object password\n"), me);
16694960Swillf goto cleanup;
16704960Swillf }
16714960Swillf passwd_len = strlen(passwd);
16724960Swillf }
16734960Swillf } else {
16744960Swillf /* Get the service object password from the terminal */
16754960Swillf passwd = (char *)malloc(MAX_SERVICE_PASSWD_LEN + 1);
16764960Swillf if (passwd == NULL) {
16774960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
16784960Swillf goto cleanup;
16794960Swillf }
16804960Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN + 1);
16814960Swillf passwd_len = MAX_SERVICE_PASSWD_LEN;
16824960Swillf
16834960Swillf len = strlen(service_object);
16844960Swillf /* size of allocation=strlen of servicedn + strlen("Password for \" \"")=20 */
16854960Swillf prompt1 = (char *)malloc(len + 20);
16864960Swillf if (prompt1 == NULL) {
16874960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
16884960Swillf goto cleanup;
16894960Swillf }
16904960Swillf sprintf(prompt1, gettext("Password for \"%s\""), service_object);
16914960Swillf
16924960Swillf /* size of allocation=strlen of servicedn + strlen("Re-enter Password for \" \"")=30 */
16934960Swillf prompt2 = (char *)malloc(len + 30);
16944960Swillf if (prompt2 == NULL) {
16954960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
16964960Swillf free(prompt1);
16974960Swillf goto cleanup;
16984960Swillf }
16994960Swillf sprintf(prompt2, gettext("Re-enter password for \"%s\""), service_object);
17004960Swillf
17014960Swillf retval = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len);
17024960Swillf free(prompt1);
17034960Swillf free(prompt2);
17044960Swillf if (retval) {
17054960Swillf com_err(me, retval, gettext("while setting service object password"));
17064960Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
17074960Swillf goto cleanup;
17084960Swillf }
17094960Swillf if (passwd_len == 0) {
17104960Swillf printf(gettext("%s: Invalid password\n"), me);
17114960Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
17124960Swillf goto cleanup;
17134960Swillf }
17144960Swillf passwd_len = strlen(passwd);
17154960Swillf }
17164960Swillf
17174960Swillf /* Hex the password */
17184960Swillf {
17194960Swillf krb5_data pwd, hex;
17204960Swillf pwd.length = passwd_len;
17214960Swillf pwd.data = passwd;
17224960Swillf
17234960Swillf errcode = tohex(pwd, &hex);
17244960Swillf if (errcode != 0) {
17254960Swillf if (hex.length != 0) {
17264960Swillf memset(hex.data, 0, hex.length);
17274960Swillf free(hex.data);
17284960Swillf }
17294960Swillf com_err(me, errcode, gettext("Failed to convert the password to hex"));
17304960Swillf memset(passwd, 0, passwd_len);
17314960Swillf goto cleanup;
17324960Swillf }
17334960Swillf /* Password = {CRYPT}<encrypted password>:<encrypted key> */
17344960Swillf encrypted_passwd.value = (unsigned char *)malloc(strlen(service_object) +
17354960Swillf 1 + 5 + hex.length + 2);
17364960Swillf if (encrypted_passwd.value == NULL) {
17374960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
17384960Swillf memset(passwd, 0, passwd_len);
17394960Swillf memset(hex.data, 0, hex.length);
17404960Swillf free(hex.data);
17414960Swillf goto cleanup;
17424960Swillf }
17434960Swillf encrypted_passwd.value[strlen(service_object) +
17444960Swillf 1 + 5 + hex.length + 1] = '\0';
17454960Swillf sprintf((char *)encrypted_passwd.value, "%s#{HEX}%s\n", service_object, hex.data);
17464960Swillf encrypted_passwd.len = strlen((char *)encrypted_passwd.value);
17474960Swillf memset(hex.data, 0, hex.length);
17484960Swillf free(hex.data);
17494960Swillf }
17504960Swillf
17514960Swillf /* We should check if the file exists and we have permission to write into that file */
17524960Swillf if (access(file_name, W_OK) == -1) {
17534960Swillf if (errno == ENOENT) {
17544960Swillf mode_t omask;
17554960Swillf int fd = -1;
17564960Swillf
17574960Swillf printf(gettext("File does not exist. Creating the file %s...\n"), file_name);
17584960Swillf omask = umask(077);
17594960Swillf fd = creat(file_name, S_IRUSR|S_IWUSR);
17604960Swillf umask(omask);
17614960Swillf if (fd == -1) {
17624960Swillf com_err(me, errno, gettext("Error creating file %s"), file_name);
17634960Swillf memset(passwd, 0, passwd_len);
17644960Swillf goto cleanup;
17654960Swillf }
17664960Swillf close(fd);
17674960Swillf } else {
17684960Swillf com_err(me, errno, gettext("Unable to access the file %s"), file_name);
17694960Swillf memset(passwd, 0, passwd_len);
17704960Swillf goto cleanup;
17714960Swillf }
17724960Swillf }
17734960Swillf
17744960Swillf if (set_dir_pwd) {
17754960Swillf if ((errcode = krb5_ldap_set_service_passwd(util_context, service_object, passwd)) != 0) {
17764960Swillf com_err(me, errcode, gettext("Failed to set password for service object %s"), service_object);
17774960Swillf memset(passwd, 0, passwd_len);
17784960Swillf goto cleanup;
17794960Swillf }
17804960Swillf }
17814960Swillf
17824960Swillf memset(passwd, 0, passwd_len);
17834960Swillf
17844960Swillf
17854960Swillf /* TODO: file lock for the service password file */
17864960Swillf /* set password in the file */
17874960Swillf pfile = fopen(file_name, "r+F");
17884960Swillf if (pfile == NULL) {
17894960Swillf com_err(me, errno, gettext("Failed to open file %s"), file_name);
17904960Swillf goto cleanup;
17914960Swillf }
17924960Swillf
17934960Swillf while (fgets(line, MAX_LEN, pfile) != NULL) {
17944960Swillf if ((str = strstr(line, service_object)) != NULL) {
17954960Swillf if (line[strlen(service_object)] == '#') {
17964960Swillf break;
17974960Swillf }
17984960Swillf str = NULL;
17994960Swillf }
18004960Swillf }
18014960Swillf if (str == NULL) {
18024960Swillf if (feof(pfile)) {
18034960Swillf /* If the service object dn is not present in the service password file */
18044960Swillf if (fwrite(encrypted_passwd.value, (unsigned int)encrypted_passwd.len, 1, pfile) != 1) {
18054960Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
18064960Swillf goto cleanup;
18074960Swillf }
18084960Swillf } else {
18094960Swillf com_err(me, errno, gettext("Error reading service object password file"));
18104960Swillf goto cleanup;
18114960Swillf }
18124960Swillf fclose(pfile);
18134960Swillf pfile = NULL;
18144960Swillf } else {
18154960Swillf /* Password entry for the service object is already present in the file */
18164960Swillf /* Delete the existing entry and add the new entry */
18174960Swillf FILE *newfile = NULL;
18184960Swillf mode_t omask;
18194960Swillf
18204960Swillf /* Create a new file with the extension .tmp */
18214960Swillf tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1));
18224960Swillf if (tmp_file == NULL) {
18234960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
18244960Swillf goto cleanup;
18254960Swillf }
18264960Swillf sprintf(tmp_file,"%s.%s",file_name,"tmp");
18274960Swillf
18284960Swillf omask = umask(077);
18294960Swillf newfile = fopen(tmp_file, "w+F");
18304960Swillf umask(omask);
18314960Swillf if (newfile == NULL) {
18324960Swillf com_err(me, errno, gettext("Error creating file %s"), tmp_file);
18334960Swillf goto cleanup;
18344960Swillf }
18354960Swillf
18364960Swillf
18374960Swillf fseek(pfile, 0, SEEK_SET);
18384960Swillf while (fgets(line, MAX_LEN, pfile) != NULL) {
18394960Swillf if (((str = strstr(line, service_object)) != NULL) && (line[strlen(service_object)] == '#')) {
18404960Swillf if (fprintf(newfile, "%s", encrypted_passwd.value) < 0) {
18414960Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
18424960Swillf fclose(newfile);
18434960Swillf unlink(tmp_file);
18444960Swillf goto cleanup;
18454960Swillf }
18464960Swillf } else {
18474960Swillf len = strlen(line);
18484960Swillf if (fprintf(newfile, "%s", line) < 0) {
18494960Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
18504960Swillf fclose(newfile);
18514960Swillf unlink(tmp_file);
18524960Swillf goto cleanup;
18534960Swillf }
18544960Swillf }
18554960Swillf }
18564960Swillf
18574960Swillf if (!feof(pfile)) {
18584960Swillf com_err(me, errno, gettext("Error reading service object password file"));
18594960Swillf fclose(newfile);
18604960Swillf unlink(tmp_file);
18614960Swillf goto cleanup;
18624960Swillf }
18634960Swillf
18644960Swillf /* TODO: file lock for the service password file */
18654960Swillf fclose(pfile);
18664960Swillf pfile = NULL;
18674960Swillf
18684960Swillf fclose(newfile);
18694960Swillf newfile = NULL;
18704960Swillf
18714960Swillf if (unlink(file_name) == 0) {
18724960Swillf link(tmp_file, file_name);
18734960Swillf } else {
18744960Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
18754960Swillf unlink(tmp_file);
18764960Swillf goto cleanup;
18774960Swillf }
18784960Swillf unlink(tmp_file);
18794960Swillf }
18804960Swillf errcode = 0;
18814960Swillf
18824960Swillf cleanup:
18834960Swillf if (db_init_local)
18844960Swillf krb5_ldap_close(util_context);
18854960Swillf
18864960Swillf if (service_object)
18874960Swillf free(service_object);
18884960Swillf
18894960Swillf if (file_name)
18904960Swillf free(file_name);
18914960Swillf
18924960Swillf if (passwd)
18934960Swillf free(passwd);
18944960Swillf
18954960Swillf if (encrypted_passwd.value) {
18964960Swillf memset(encrypted_passwd.value, 0, encrypted_passwd.len);
18974960Swillf free(encrypted_passwd.value);
18984960Swillf }
18994960Swillf
19004960Swillf if (pfile)
19014960Swillf fclose(pfile);
19024960Swillf
19034960Swillf if (tmp_file)
19044960Swillf free(tmp_file);
19054960Swillf
19064960Swillf if (print_usage)
19074960Swillf db_usage(SET_SRV_PW);
19084960Swillf
19094960Swillf return errcode;
19104960Swillf }
19114960Swillf
19124960Swillf #else /* #ifdef HAVE_EDIRECTORY */
19134960Swillf
19144960Swillf /*
19154960Swillf * Convert the user supplied password into hexadecimal and stash it. Only a
19164960Swillf * little more secure than storing plain password in the file ...
19174960Swillf */
19184960Swillf void
kdb5_ldap_stash_service_password(argc,argv)19194960Swillf kdb5_ldap_stash_service_password(argc, argv)
19204960Swillf int argc;
19214960Swillf char **argv;
19224960Swillf {
19234960Swillf int ret = 0;
19244960Swillf unsigned int passwd_len = 0;
1925*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
1926*8092SMark.Phalan@Sun.COM char *me = progname;
19274960Swillf char *service_object = NULL;
19284960Swillf char *file_name = NULL, *tmp_file = NULL;
19294960Swillf char passwd[MAX_SERVICE_PASSWD_LEN];
19304960Swillf char *str = NULL;
19314960Swillf char line[MAX_LEN];
19324960Swillf int fd;
19334960Swillf FILE *pfile = NULL;
19344960Swillf krb5_boolean print_usage = FALSE;
19354960Swillf krb5_data hexpasswd = {0, 0, NULL};
19364960Swillf mode_t old_mode = 0;
19374960Swillf
19384960Swillf /*
19394960Swillf * Format:
19404960Swillf * stashsrvpw [-f filename] service_dn
19414960Swillf * where
19424960Swillf * 'service_dn' is the DN of the service object
19434960Swillf * 'filename' is the path of the stash file
19444960Swillf */
19454960Swillf if (argc != 2 && argc != 4) {
19464960Swillf print_usage = TRUE;
19474960Swillf goto cleanup;
19484960Swillf }
19494960Swillf
19504960Swillf if (argc == 4) {
19514960Swillf /* Find the stash file name */
19524960Swillf if (strcmp (argv[1], "-f") == 0) {
19534960Swillf if (((file_name = strdup (argv[2])) == NULL) ||
19544960Swillf ((service_object = strdup (argv[3])) == NULL)) {
19554960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
19564960Swillf goto cleanup;
19574960Swillf }
19584960Swillf } else if (strcmp (argv[2], "-f") == 0) {
19594960Swillf if (((file_name = strdup (argv[3])) == NULL) ||
19604960Swillf ((service_object = strdup (argv[1])) == NULL)) {
19614960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
19624960Swillf goto cleanup;
19634960Swillf }
19644960Swillf } else {
19654960Swillf print_usage = TRUE;
19664960Swillf goto cleanup;
19674960Swillf }
19684960Swillf if (file_name == NULL) {
19694960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
19704960Swillf goto cleanup;
19714960Swillf }
19724960Swillf } else { /* argc == 2 */
19734960Swillf char *section;
19744960Swillf
19754960Swillf service_object = strdup (argv[1]);
19764960Swillf if (service_object == NULL) {
19774960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
19784960Swillf goto cleanup;
19794960Swillf }
19804960Swillf
19814960Swillf /* Pick up the stash-file name from krb5.conf */
19824960Swillf profile_get_string(util_context->profile, KDB_REALM_SECTION,
19834960Swillf util_context->default_realm, KDB_MODULE_POINTER, NULL, §ion);
19844960Swillf
19854960Swillf if (section == NULL) {
19864960Swillf profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION,
19874960Swillf KDB_MODULE_POINTER, NULL, NULL, §ion);
19884960Swillf if (section == NULL) {
19894960Swillf /* Stash file path neither in krb5.conf nor on command line */
19904960Swillf file_name = strdup(DEF_SERVICE_PASSWD_FILE);
19914960Swillf if (file_name == NULL) {
19924960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
19934960Swillf goto cleanup;
19944960Swillf }
19954960Swillf goto done;
19964960Swillf }
19974960Swillf }
19984960Swillf
19994960Swillf profile_get_string (util_context->profile, KDB_MODULE_SECTION, section,
20004960Swillf "ldap_service_password_file", NULL, &file_name);
20014960Swillf
20024960Swillf /*
20034960Swillf * Solaris Kerberos: use default if ldap_service_password_file not set
20044960Swillf */
20054960Swillf if (file_name == NULL) {
20064960Swillf file_name = strdup(DEF_SERVICE_PASSWD_FILE);
20074960Swillf if (file_name == NULL) {
20084960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
20094960Swillf goto cleanup;
20104960Swillf }
20114960Swillf }
20124960Swillf }
20134960Swillf done:
20144960Swillf
20154960Swillf /* Get password from user */
20164960Swillf {
20174960Swillf char prompt1[256], prompt2[256];
20184960Swillf
20194960Swillf /* Get the service object password from the terminal */
20204960Swillf memset(passwd, 0, sizeof (passwd));
20214960Swillf passwd_len = sizeof (passwd);
20224960Swillf
20234960Swillf /* size of prompt = strlen of servicedn + strlen("Password for \" \"") */
20244960Swillf assert (sizeof (prompt1) > (strlen (service_object)
20254960Swillf + sizeof ("Password for \" \"")));
20264960Swillf sprintf(prompt1, gettext("Password for \"%s\""), service_object);
20274960Swillf
20284960Swillf /* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */
20294960Swillf assert (sizeof (prompt2) > (strlen (service_object)
20304960Swillf + sizeof ("Re-enter Password for \" \"")));
20314960Swillf sprintf(prompt2, gettext("Re-enter password for \"%s\""), service_object);
20324960Swillf
20334960Swillf ret = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len);
20344960Swillf if (ret != 0) {
20354960Swillf com_err(me, ret, gettext("while setting service object password"));
20364960Swillf memset(passwd, 0, sizeof (passwd));
20374960Swillf goto cleanup;
20384960Swillf }
20394960Swillf
20404960Swillf if (passwd_len == 0) {
20414960Swillf printf(gettext("%s: Invalid password\n"), me);
20424960Swillf memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
20434960Swillf goto cleanup;
20444960Swillf }
20454960Swillf }
20464960Swillf
20474960Swillf /* Convert the password to hexadecimal */
20484960Swillf {
20494960Swillf krb5_data pwd;
20504960Swillf
20514960Swillf pwd.length = passwd_len;
20524960Swillf pwd.data = passwd;
20534960Swillf
20544960Swillf ret = tohex(pwd, &hexpasswd);
20554960Swillf if (ret != 0) {
20564960Swillf com_err(me, ret, gettext("Failed to convert the password to hexadecimal"));
20574960Swillf memset(passwd, 0, passwd_len);
20584960Swillf goto cleanup;
20594960Swillf }
20604960Swillf }
20614960Swillf memset(passwd, 0, passwd_len);
20624960Swillf
20634960Swillf /* TODO: file lock for the service passowrd file */
20644960Swillf
20654960Swillf /* set password in the file */
20664960Swillf #if 0 /* ************ Begin IFDEF'ed OUT ***************************** */
20674960Swillf old_mode = umask(0177);
20684960Swillf pfile = fopen(file_name, "a+");
20694960Swillf if (pfile == NULL) {
20704960Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name,
20714960Swillf strerror (errno));
20724960Swillf goto cleanup;
20734960Swillf }
20744960Swillf rewind (pfile);
20754960Swillf umask(old_mode);
20764960Swillf #else
20774960Swillf /* Solaris Kerberos: safer than the above */
20784960Swillf fd = open(file_name, O_CREAT|O_RDWR|O_APPEND, 0600);
20794960Swillf if (fd < 0) {
20804960Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name,
20814960Swillf strerror (errno));
20824960Swillf goto cleanup;
20834960Swillf }
20844960Swillf pfile = fdopen(fd, "a+F");
20854960Swillf if (pfile == NULL) {
20864960Swillf com_err(me, errno, gettext("Failed to open file %s: %s"), file_name,
20874960Swillf strerror (errno));
20884960Swillf goto cleanup;
20894960Swillf }
20904960Swillf rewind (pfile);
20914960Swillf #endif
20924960Swillf
20934960Swillf while (fgets (line, MAX_LEN, pfile) != NULL) {
20944960Swillf if ((str = strstr (line, service_object)) != NULL) {
20954960Swillf /*
20964960Swillf * White spaces not allowed, # delimits the service dn from the
20974960Swillf * password
20984960Swillf */
20994960Swillf if (line [strlen (service_object)] == '#')
21004960Swillf break;
21014960Swillf str = NULL;
21024960Swillf }
21034960Swillf }
21044960Swillf
21054960Swillf if (str == NULL) {
21064960Swillf if (feof(pfile)) {
21074960Swillf /* If the service object dn is not present in the service password file */
21084960Swillf if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
21094960Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
21104960Swillf fclose(pfile);
21114960Swillf goto cleanup;
21124960Swillf }
21134960Swillf } else {
21144960Swillf com_err(me, errno, gettext("Error reading service object password file"));
21154960Swillf fclose(pfile);
21164960Swillf goto cleanup;
21174960Swillf }
21184960Swillf fclose(pfile);
21194960Swillf } else {
21204960Swillf /*
21214960Swillf * Password entry for the service object is already present in the file
21224960Swillf * Delete the existing entry and add the new entry
21234960Swillf */
21244960Swillf FILE *newfile;
21254960Swillf
21264960Swillf mode_t omask;
21274960Swillf
21284960Swillf /* Create a new file with the extension .tmp */
21294960Swillf tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1));
21304960Swillf if (tmp_file == NULL) {
21314960Swillf com_err(me, ENOMEM, gettext("while setting service object password"));
21324960Swillf fclose(pfile);
21334960Swillf goto cleanup;
21344960Swillf }
21354960Swillf sprintf(tmp_file,"%s.%s",file_name,"tmp");
21364960Swillf
21374960Swillf omask = umask(077);
21384960Swillf newfile = fopen(tmp_file, "wF");
21394960Swillf umask (omask);
21404960Swillf if (newfile == NULL) {
21414960Swillf com_err(me, errno, gettext("Error creating file %s"), tmp_file);
21424960Swillf fclose(pfile);
21434960Swillf goto cleanup;
21444960Swillf }
21454960Swillf
21464960Swillf fseek(pfile, 0, SEEK_SET);
21474960Swillf while (fgets(line, MAX_LEN, pfile) != NULL) {
21484960Swillf if (((str = strstr(line, service_object)) != NULL) &&
21494960Swillf (line[strlen(service_object)] == '#')) {
21504960Swillf if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
21514960Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
21524960Swillf fclose(newfile);
21534960Swillf unlink(tmp_file);
21544960Swillf fclose(pfile);
21554960Swillf goto cleanup;
21564960Swillf }
21574960Swillf } else {
21584960Swillf if (fprintf (newfile, "%s", line) < 0) {
21594960Swillf com_err(me, errno, gettext("Failed to write service object password to file"));
21604960Swillf fclose(newfile);
21614960Swillf unlink(tmp_file);
21624960Swillf fclose(pfile);
21634960Swillf goto cleanup;
21644960Swillf }
21654960Swillf }
21664960Swillf }
21674960Swillf
21684960Swillf if (!feof(pfile)) {
21694960Swillf com_err(me, errno, gettext("Error reading service object password file"));
21704960Swillf fclose(newfile);
21714960Swillf unlink(tmp_file);
21724960Swillf fclose(pfile);
21734960Swillf goto cleanup;
21744960Swillf }
21754960Swillf
21764960Swillf /* TODO: file lock for the service passowrd file */
21774960Swillf
21784960Swillf fclose(pfile);
21794960Swillf fclose(newfile);
21804960Swillf
21814960Swillf ret = rename(tmp_file, file_name);
21824960Swillf if (ret != 0) {
21834960Swillf com_err(me, errno, gettext("Failed to write service object password to "
21844960Swillf "file"));
21854960Swillf goto cleanup;
21864960Swillf }
21874960Swillf }
21884960Swillf ret = 0;
21894960Swillf
21904960Swillf cleanup:
21914960Swillf
21924960Swillf if (hexpasswd.length != 0) {
21934960Swillf memset(hexpasswd.data, 0, hexpasswd.length);
21944960Swillf free(hexpasswd.data);
21954960Swillf }
21964960Swillf
21974960Swillf if (service_object)
21984960Swillf free(service_object);
21994960Swillf
22004960Swillf if (file_name)
22014960Swillf free(file_name);
22024960Swillf
22034960Swillf if (tmp_file)
22044960Swillf free(tmp_file);
22054960Swillf
22064960Swillf if (print_usage)
22074960Swillf usage();
22084960Swillf /* db_usage(STASH_SRV_PW); */
22094960Swillf
22104960Swillf if (ret)
22114960Swillf exit_status++;
22124960Swillf }
22134960Swillf
22144960Swillf #endif /* #ifdef HAVE_EDIRECTORY */
2215