Path: blob/main/crypto/krb5/src/lib/kadm5/alt_prof.c
39536 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* lib/kadm5/alt_prof.c */2/*3* Copyright 1995,2001,2008,2009 by the Massachusetts Institute of Technology.4* All Rights Reserved.5*6* Export of this software from the United States of America may7* require a specific license from the United States Government.8* It is the responsibility of any person or organization contemplating9* export to obtain such a license before exporting.10*11* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and12* distribute this software and its documentation for any purpose and13* without fee is hereby granted, provided that the above copyright14* notice appear in all copies and that both that copyright notice and15* this permission notice appear in supporting documentation, and that16* the name of M.I.T. not be used in advertising or publicity pertaining17* to distribution of the software without specific, written prior18* permission. Furthermore if you modify this software you must label19* your software as modified software and not distribute it in such a20* fashion that it might be confused with the original M.I.T. software.21* M.I.T. makes no representations about the suitability of22* this software for any purpose. It is provided "as is" without express23* or implied warranty.24*/25/*26* Copyright 2004 Sun Microsystems, Inc. All rights reserved.27* Use is subject to license terms.28*/2930/* Implement alternate profile file handling. */31#include "k5-int.h"32#include "fake-addrinfo.h"33#include <kadm5/admin.h>34#include "adm_proto.h"35#include <stdio.h>36#include <ctype.h>37#include <kdb_log.h>3839static krb5_key_salt_tuple *40copy_key_salt_tuple(krb5_key_salt_tuple *ksalt, krb5_int32 len)41{42krb5_key_salt_tuple *knew;4344knew = calloc(len, sizeof(krb5_key_salt_tuple));45if (knew == NULL)46return NULL;47memcpy(knew, ksalt, len * sizeof(krb5_key_salt_tuple));48return knew;49}5051/*52* krb5_aprof_getvals() - Get values from alternate profile.53*54* Parameters:55* acontext - opaque context for alternate profile.56* hierarchy - hierarchy of value to retrieve.57* retdata - Returned data values.58*59* Returns:60* error codes from profile_get_values()61*/62krb5_error_code63krb5_aprof_getvals(krb5_pointer acontext, const char **hierarchy,64char ***retdata)65{66return profile_get_values(acontext, hierarchy, retdata);67}6869/*70* krb5_aprof_get_boolean()71*72* Parameters:73* acontext - opaque context for alternate profile74* hierarchy - hierarchy of value to retrieve75* retdata - Returned data value76* Returns:77* error codes78*/7980static krb5_error_code81string_to_boolean(const char *string, krb5_boolean *out)82{83static const char *const yes[] = { "y", "yes", "true", "t", "1", "on" };84static const char *const no[] = { "n", "no", "false", "f", "nil", "0",85"off" };86unsigned int i;8788for (i = 0; i < sizeof(yes) / sizeof(yes[0]); i++) {89if (!strcasecmp(string, yes[i])) {90*out = TRUE;91return 0;92}93}94for (i = 0; i < sizeof(no) / sizeof(no[0]); i++) {95if (!strcasecmp(string, no[i])) {96*out = FALSE;97return 0;98}99}100return PROF_BAD_BOOLEAN;101}102103krb5_error_code104krb5_aprof_get_boolean(krb5_pointer acontext, const char **hierarchy,105int uselast, krb5_boolean *retdata)106{107krb5_error_code ret;108char **values, *valp;109int idx;110krb5_boolean val;111112ret = krb5_aprof_getvals(acontext, hierarchy, &values);113if (ret)114return ret;115idx = 0;116if (uselast) {117while (values[idx] != NULL)118idx++;119idx--;120}121valp = values[idx];122ret = string_to_boolean(valp, &val);123profile_free_list(values);124if (ret)125return ret;126*retdata = val;127return 0;128}129130/*131* krb5_aprof_get_deltat() - Get a delta time value from the alternate132* profile.133*134* Parameters:135* acontext - opaque context for alternate profile.136* hierarchy - hierarchy of value to retrieve.137* uselast - if true, use last value, otherwise use first138* value found.139* deltatp - returned delta time value.140*141* Returns:142* error codes from profile_get_values()143* error codes from krb5_string_to_deltat()144*/145krb5_error_code146krb5_aprof_get_deltat(krb5_pointer acontext, const char **hierarchy,147krb5_boolean uselast, krb5_deltat *deltatp)148{149krb5_error_code ret;150char **values, *valp;151int idx;152153ret = krb5_aprof_getvals(acontext, hierarchy, &values);154if (ret)155return ret;156157idx = 0;158if (uselast) {159for (idx = 0; values[idx] != NULL; idx++);160idx--;161}162valp = values[idx];163164ret = krb5_string_to_deltat(valp, deltatp);165profile_free_list(values);166return ret;167}168169/*170* krb5_aprof_get_string() - Get a string value from the alternate profile.171*172* Parameters:173* acontext - opaque context for alternate profile.174* hierarchy - hierarchy of value to retrieve.175* uselast - if true, use last value, otherwise use first176* value found.177* stringp - returned string value.178*179* Returns:180* error codes from profile_get_values()181*/182krb5_error_code183krb5_aprof_get_string(krb5_pointer acontext, const char **hierarchy,184krb5_boolean uselast, char **stringp)185{186krb5_error_code ret;187char **values;188int lastidx;189190ret = krb5_aprof_getvals(acontext, hierarchy, &values);191if (ret)192return ret;193194for (lastidx = 0; values[lastidx] != NULL; lastidx++);195lastidx--;196197/* Excise the entry we want from the null-terminated list,198* and free up the rest. */199if (uselast) {200*stringp = values[lastidx];201values[lastidx] = NULL;202} else {203*stringp = values[0];204values[0] = values[lastidx];205values[lastidx] = NULL;206}207208profile_free_list(values);209return 0;210}211212/*213* krb5_aprof_get_string_all() - When the attr identified by "hierarchy" is214* specified multiple times, concatenate all of215* its string values from the alternate profile,216* separated with spaces.217*218* Parameters:219* acontext - opaque context for alternate profile.220* hierarchy - hierarchy of value to retrieve.221* stringp - Returned string value.222*223* Returns:224* error codes from profile_get_values() or ENOMEM225* Caller is responsible for deallocating stringp buffer226*/227krb5_error_code228krb5_aprof_get_string_all(krb5_pointer acontext, const char **hierarchy,229char **stringp)230{231krb5_error_code ret;232char **values;233int idx = 0;234size_t buf_size = 0;235236ret = krb5_aprof_getvals(acontext, hierarchy, &values);237if (ret)238return ret;239240buf_size = strlen(values[0]) + 3;241for (idx = 1; values[idx] != NULL; idx++)242buf_size += strlen(values[idx]) + 3;243244*stringp = calloc(1, buf_size);245if (*stringp == NULL) {246profile_free_list(values);247return ENOMEM;248}249strlcpy(*stringp, values[0], buf_size);250for (idx = 1; values[idx] != NULL; idx++) {251strlcat(*stringp, " ", buf_size);252strlcat(*stringp, values[idx], buf_size);253}254255profile_free_list(values);256return 0;257}258259260/*261* krb5_aprof_get_int32() - Get a 32-bit integer value from the alternate262* profile.263*264* Parameters:265* acontext - opaque context for alternate profile.266* hierarchy - hierarchy of value to retrieve.267* uselast - if true, use last value, otherwise use first268* value found.269* intp - returned 32-bit integer value.270*271* Returns:272* error codes from profile_get_values()273* EINVAL - value is not an integer274*/275krb5_error_code276krb5_aprof_get_int32(krb5_pointer acontext, const char **hierarchy,277krb5_boolean uselast, krb5_int32 *intp)278{279krb5_error_code ret;280char **values;281int idx;282283ret = krb5_aprof_getvals(acontext, hierarchy, &values);284if (ret)285return ret;286287idx = 0;288if (uselast) {289for (idx = 0; values[idx] != NULL; idx++);290idx--;291}292293if (sscanf(values[idx], "%d", intp) != 1)294ret = EINVAL;295296profile_free_list(values);297return ret;298}299300/*301* Returns nonzero if it found something to copy; the caller may still need to302* check the output field or mask to see if the copy (allocation) was303* successful. Returns zero if nothing was found to copy, and thus the caller304* may want to apply some default heuristic. If the default action is just to305* use a fixed, compiled-in string, supply it as the default value here and306* ignore the return value.307*/308static int309get_string_param(char **param_out, char *param_in, long *mask_out,310long mask_in, long mask_bit, krb5_pointer aprofile,311const char **hierarchy, const char *config_name,312const char *default_value)313{314char *svalue;315316hierarchy[2] = config_name;317if (mask_in & mask_bit) {318*param_out = strdup(param_in);319if (*param_out)320*mask_out |= mask_bit;321return 1;322} else if (aprofile != NULL &&323!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {324*param_out = svalue;325*mask_out |= mask_bit;326return 1;327} else if (default_value) {328*param_out = strdup(default_value);329if (*param_out)330*mask_out |= mask_bit;331return 1;332} else {333return 0;334}335}336/*337* Similar, for (host-order) port number, if not already set in the output338* field; default_value == 0 means no default.339*/340static void341get_port_param(int *param_out, int param_in, long *mask_out, long mask_in,342long mask_bit, krb5_pointer aprofile, const char **hierarchy,343const char *config_name, int default_value)344{345krb5_int32 ivalue;346347if (*mask_out & mask_bit)348return;349hierarchy[2] = config_name;350if (mask_in & mask_bit) {351*mask_out |= mask_bit;352*param_out = param_in;353} else if (aprofile != NULL &&354!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) {355*param_out = ivalue;356*mask_out |= mask_bit;357} else if (default_value) {358*param_out = default_value;359*mask_out |= mask_bit;360}361}362363/*364* Similar, for delta_t; default is required.365*/366static void367get_deltat_param(krb5_deltat *param_out, krb5_deltat param_in, long *mask_out,368long mask_in, long mask_bit, krb5_pointer aprofile,369const char **hierarchy, const char *config_name,370krb5_deltat default_value)371{372krb5_deltat dtvalue;373374hierarchy[2] = config_name;375if (mask_in & mask_bit) {376*mask_out |= mask_bit;377*param_out = param_in;378} else if (aprofile &&379!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {380*param_out = dtvalue;381*mask_out |= mask_bit;382} else {383*param_out = default_value;384*mask_out |= mask_bit;385}386}387388/*389* Parse out the port number from an admin_server setting. Modify server to390* contain just the hostname or address. If a port is given, set *port, and391* set the appropriate bit in *mask.392*/393static void394parse_admin_server_port(char *server, int *port, long *mask)395{396char *end, *portstr;397398/* Allow the name or addr to be enclosed in brackets, for IPv6 addrs. */399if (*server == '[' && (end = strchr(server + 1, ']')) != NULL) {400portstr = (*(end + 1) == ':') ? end + 2 : NULL;401/* Shift the bracketed name or address back into server. */402memmove(server, server + 1, end - (server + 1));403*(end - 1) = '\0';404} else {405/* Terminate the name at the colon, if any. */406end = server + strcspn(server, ":");407portstr = (*end == ':') ? end + 1 : NULL;408*end = '\0';409}410411/* If we found a port string, parse it and set the appropriate bit. */412if (portstr) {413*port = atoi(portstr);414*mask |= KADM5_CONFIG_KADMIND_PORT;415}416}417418/*419* Function: kadm5_get_config_params420*421* Purpose: Merge configuration parameters provided by the caller with values422* specified in configuration files and with default values.423*424* Arguments:425*426* context (r) krb5_context to use427* profile (r) profile file to use428* envname (r) envname that contains a profile name to429* override profile430* params_in (r) params structure containing user-supplied431* values, or NULL432* params_out (w) params structure to be filled in433*434* Effects:435*436* The fields and mask of params_out are filled in with values obtained from437* params_in, the specified profile, and default values. Only and all fields438* specified in params_out->mask are set. The context of params_out must be439* freed with kadm5_free_config_params.440*441* params_in and params_out may be the same pointer. However, all pointers in442* params_in for which the mask is set will be re-assigned to newly copied443* versions, overwriting the old pointer value.444*/445krb5_error_code kadm5_get_config_params(krb5_context context,446int use_kdc_config,447kadm5_config_params *params_in,448kadm5_config_params *params_out)449{450char *lrealm, *svalue, *sp, *ep, *tp;451krb5_pointer aprofile = context->profile;452const char *hierarchy[4];453krb5_int32 ivalue;454kadm5_config_params params, empty_params;455krb5_boolean bvalue;456krb5_error_code ret = 0;457458memset(¶ms, 0, sizeof(params));459memset(&empty_params, 0, sizeof(empty_params));460461if (params_in == NULL)462params_in = &empty_params;463464if (params_in->mask & KADM5_CONFIG_REALM) {465lrealm = params.realm = strdup(params_in->realm);466if (params.realm == NULL) {467ret = ENOMEM;468goto cleanup;469}470params.mask |= KADM5_CONFIG_REALM;471} else {472ret = krb5_get_default_realm(context, &lrealm);473if (ret)474goto cleanup;475params.realm = lrealm;476params.mask |= KADM5_CONFIG_REALM;477}478479if (params_in->mask & KADM5_CONFIG_KVNO) {480params.kvno = params_in->kvno;481params.mask |= KADM5_CONFIG_KVNO;482}483484/* Initialize realm parameters. */485hierarchy[0] = KRB5_CONF_REALMS;486hierarchy[1] = lrealm;487hierarchy[3] = NULL;488489#define GET_STRING_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \490get_string_param(¶ms.FIELD, params_in->FIELD, \491¶ms.mask, params_in->mask, BIT, \492aprofile, hierarchy, CONFTAG, DEFAULT)493494/* Get the value for the admin server. */495GET_STRING_PARAM(admin_server, KADM5_CONFIG_ADMIN_SERVER,496KRB5_CONF_ADMIN_SERVER, NULL);497498if (params.mask & KADM5_CONFIG_ADMIN_SERVER) {499parse_admin_server_port(params.admin_server, ¶ms.kadmind_port,500¶ms.mask);501}502503/* Get the value for the database. */504GET_STRING_PARAM(dbname, KADM5_CONFIG_DBNAME, KRB5_CONF_DATABASE_NAME,505DEFAULT_KDB_FILE);506507/* Get the name of the acl file. */508GET_STRING_PARAM(acl_file, KADM5_CONFIG_ACL_FILE, KRB5_CONF_ACL_FILE,509DEFAULT_KADM5_ACL_FILE);510511/* Get the name of the dict file. */512GET_STRING_PARAM(dict_file, KADM5_CONFIG_DICT_FILE, KRB5_CONF_DICT_FILE,513NULL);514515/* Get the kadmind listen addresses. */516GET_STRING_PARAM(kadmind_listen, KADM5_CONFIG_KADMIND_LISTEN,517KRB5_CONF_KADMIND_LISTEN, NULL);518GET_STRING_PARAM(kpasswd_listen, KADM5_CONFIG_KPASSWD_LISTEN,519KRB5_CONF_KPASSWD_LISTEN, NULL);520GET_STRING_PARAM(iprop_listen, KADM5_CONFIG_IPROP_LISTEN,521KRB5_CONF_IPROP_LISTEN, NULL);522523#define GET_PORT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \524get_port_param(¶ms.FIELD, params_in->FIELD, \525¶ms.mask, params_in->mask, BIT, \526aprofile, hierarchy, CONFTAG, DEFAULT)527528/* Get the value for the kadmind port. */529GET_PORT_PARAM(kadmind_port, KADM5_CONFIG_KADMIND_PORT,530KRB5_CONF_KADMIND_PORT, DEFAULT_KADM5_PORT);531532/* Get the value for the kpasswd port. */533GET_PORT_PARAM(kpasswd_port, KADM5_CONFIG_KPASSWD_PORT,534KRB5_CONF_KPASSWD_PORT, DEFAULT_KPASSWD_PORT);535536/* Get the value for the master key name. */537GET_STRING_PARAM(mkey_name, KADM5_CONFIG_MKEY_NAME,538KRB5_CONF_MASTER_KEY_NAME, NULL);539540/* Get the value for the master key type. */541hierarchy[2] = KRB5_CONF_MASTER_KEY_TYPE;542if (params_in->mask & KADM5_CONFIG_ENCTYPE) {543params.mask |= KADM5_CONFIG_ENCTYPE;544params.enctype = params_in->enctype;545} else if (aprofile != NULL &&546!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {547if (!krb5_string_to_enctype(svalue, ¶ms.enctype)) {548params.mask |= KADM5_CONFIG_ENCTYPE;549free(svalue);550}551} else {552params.mask |= KADM5_CONFIG_ENCTYPE;553params.enctype = DEFAULT_KDC_ENCTYPE;554}555556/* Get the value for mkey_from_kbd. */557if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) {558params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;559params.mkey_from_kbd = params_in->mkey_from_kbd;560}561562/* Get the value for the stashfile. */563GET_STRING_PARAM(stash_file, KADM5_CONFIG_STASH_FILE,564KRB5_CONF_KEY_STASH_FILE, NULL);565566/* Get the value for maximum ticket lifetime. */567#define GET_DELTAT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \568get_deltat_param(¶ms.FIELD, params_in->FIELD, \569¶ms.mask, params_in->mask, BIT, \570aprofile, hierarchy, CONFTAG, DEFAULT)571572GET_DELTAT_PARAM(max_life, KADM5_CONFIG_MAX_LIFE, KRB5_CONF_MAX_LIFE,57324 * 60 * 60); /* 1 day */574575/* Get the value for maximum renewable ticket lifetime. */576GET_DELTAT_PARAM(max_rlife, KADM5_CONFIG_MAX_RLIFE,577KRB5_CONF_MAX_RENEWABLE_LIFE, 0);578579/* Get the value for the default principal expiration */580hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION;581if (params_in->mask & KADM5_CONFIG_EXPIRATION) {582params.mask |= KADM5_CONFIG_EXPIRATION;583params.expiration = params_in->expiration;584} else if (aprofile &&585!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {586if (!krb5_string_to_timestamp(svalue, ¶ms.expiration)) {587params.mask |= KADM5_CONFIG_EXPIRATION;588free(svalue);589}590} else {591params.mask |= KADM5_CONFIG_EXPIRATION;592params.expiration = 0;593}594595/* Get the value for the default principal flags */596hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS;597if (params_in->mask & KADM5_CONFIG_FLAGS) {598params.mask |= KADM5_CONFIG_FLAGS;599params.flags = params_in->flags;600} else if (aprofile != NULL &&601!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {602sp = svalue;603params.flags = 0;604while (sp != NULL) {605if ((ep = strchr(sp, ',')) != NULL ||606(ep = strchr(sp, ' ')) != NULL ||607(ep = strchr(sp, '\t')) != NULL) {608/* Fill in trailing whitespace of sp. */609tp = ep - 1;610while (isspace((unsigned char)*tp) && tp > sp) {611*tp = '\0';612tp--;613}614*ep = '\0';615ep++;616/* Skip over trailing whitespace of ep. */617while (isspace((unsigned char)*ep) && *ep != '\0')618ep++;619}620/* Convert this flag. */621if (krb5_flagspec_to_mask(sp, ¶ms.flags, ¶ms.flags))622break;623sp = ep;624}625if (sp == NULL)626params.mask |= KADM5_CONFIG_FLAGS;627free(svalue);628} else {629params.mask |= KADM5_CONFIG_FLAGS;630params.flags = KRB5_KDB_DEF_FLAGS;631}632633/* Get the value for the supported enctype/salttype matrix. */634hierarchy[2] = KRB5_CONF_SUPPORTED_ENCTYPES;635if (params_in->mask & KADM5_CONFIG_ENCTYPES) {636if (params_in->keysalts) {637params.keysalts = copy_key_salt_tuple(params_in->keysalts,638params_in->num_keysalts);639if (params.keysalts) {640params.mask |= KADM5_CONFIG_ENCTYPES;641params.num_keysalts = params_in->num_keysalts;642}643} else {644params.mask |= KADM5_CONFIG_ENCTYPES;645params.keysalts = NULL;646params.num_keysalts = params_in->num_keysalts;647}648} else {649svalue = NULL;650if (aprofile != NULL)651krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue);652if (svalue == NULL)653svalue = strdup(KRB5_DEFAULT_SUPPORTED_ENCTYPES);654if (svalue == NULL) {655ret = ENOMEM;656goto cleanup;657}658659params.keysalts = NULL;660params.num_keysalts = 0;661krb5_string_to_keysalts(svalue,662NULL, /* Tuple separators */663NULL, /* Key/salt separators */6640, /* No duplicates */665¶ms.keysalts,666¶ms.num_keysalts);667if (params.num_keysalts)668params.mask |= KADM5_CONFIG_ENCTYPES;669670free(svalue);671}672673hierarchy[2] = KRB5_CONF_IPROP_ENABLE;674675params.iprop_enabled = FALSE;676params.mask |= KADM5_CONFIG_IPROP_ENABLED;677678if (params_in->mask & KADM5_CONFIG_IPROP_ENABLED) {679params.mask |= KADM5_CONFIG_IPROP_ENABLED;680params.iprop_enabled = params_in->iprop_enabled;681} else {682if (aprofile &&683!krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) {684params.iprop_enabled = bvalue;685params.mask |= KADM5_CONFIG_IPROP_ENABLED;686}687}688689if (!GET_STRING_PARAM(iprop_logfile, KADM5_CONFIG_IPROP_LOGFILE,690KRB5_CONF_IPROP_LOGFILE, NULL)) {691if (params.mask & KADM5_CONFIG_DBNAME) {692if (asprintf(¶ms.iprop_logfile, "%s.ulog",693params.dbname) >= 0)694params.mask |= KADM5_CONFIG_IPROP_LOGFILE;695}696}697698GET_PORT_PARAM(iprop_port, KADM5_CONFIG_IPROP_PORT, KRB5_CONF_IPROP_PORT,6990);700701/* 5 min for large KDBs */702GET_DELTAT_PARAM(iprop_resync_timeout, KADM5_CONFIG_IPROP_RESYNC_TIMEOUT,703KRB5_CONF_IPROP_RESYNC_TIMEOUT, 60 * 5);704705if (params_in->mask & KADM5_CONFIG_ULOG_SIZE) {706params.mask |= KADM5_CONFIG_ULOG_SIZE;707params.iprop_ulogsize = params_in->iprop_ulogsize;708} else {709params.iprop_ulogsize = 0;710hierarchy[2] = KRB5_CONF_IPROP_ULOGSIZE;711if (aprofile != NULL &&712!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue) &&713ivalue > 0)714params.iprop_ulogsize = ivalue;715hierarchy[2] = KRB5_CONF_IPROP_MASTER_ULOGSIZE;716if (params.iprop_ulogsize == 0 && aprofile != NULL &&717!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue) &&718ivalue > 0)719params.iprop_ulogsize = ivalue;720if (params.iprop_ulogsize == 0)721params.iprop_ulogsize = DEF_ULOGENTRIES;722}723params.mask |= KADM5_CONFIG_ULOG_SIZE;724725GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME,726KRB5_CONF_IPROP_REPLICA_POLL, -1);727if (params.iprop_poll_time == -1) {728GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME,729KRB5_CONF_IPROP_SLAVE_POLL, 2 * 60);730}731732*params_out = params;733734cleanup:735if (ret) {736kadm5_free_config_params(context, ¶ms);737params_out->mask = 0;738}739return ret;740}741742/*743* kadm5_free_config_params() - Free data allocated by above.744*/745krb5_error_code746kadm5_free_config_params(krb5_context context, kadm5_config_params *params)747{748if (params == NULL)749return 0;750free(params->dbname);751free(params->mkey_name);752free(params->stash_file);753free(params->keysalts);754free(params->admin_server);755free(params->dict_file);756free(params->acl_file);757free(params->realm);758free(params->iprop_logfile);759free(params->iprop_listen);760free(params->kadmind_listen);761free(params->kpasswd_listen);762return 0;763}764765krb5_error_code766kadm5_get_admin_service_name(krb5_context ctx, char *realm_in,767char *admin_name, size_t maxlen)768{769krb5_error_code ret;770kadm5_config_params params_in, params_out;771char *canonhost = NULL;772773memset(¶ms_in, 0, sizeof(params_in));774memset(¶ms_out, 0, sizeof(params_out));775776params_in.mask |= KADM5_CONFIG_REALM;777params_in.realm = realm_in;778ret = kadm5_get_config_params(ctx, 0, ¶ms_in, ¶ms_out);779if (ret)780return ret;781782if (!(params_out.mask & KADM5_CONFIG_ADMIN_SERVER)) {783ret = KADM5_MISSING_KRB5_CONF_PARAMS;784goto err_params;785}786787ret = krb5_expand_hostname(ctx, params_out.admin_server, &canonhost);788if (ret)789goto err_params;790791if (strlen(canonhost) + sizeof("kadmin/") > maxlen) {792ret = ENOMEM;793goto err_params;794}795snprintf(admin_name, maxlen, "kadmin/%s", canonhost);796797err_params:798krb5_free_string(ctx, canonhost);799kadm5_free_config_params(ctx, ¶ms_out);800return ret;801}802803804