2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2N/A/*
2N/A * COPYRIGHT (C) 2006,2007
2N/A * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
2N/A * ALL RIGHTS RESERVED
2N/A *
2N/A * Permission is granted to use, copy, create derivative works
2N/A * and redistribute this software and such derivative works
2N/A * for any purpose, so long as the name of The University of
2N/A * Michigan is not used in any advertising or publicity
2N/A * pertaining to the use of distribution of this software
2N/A * without specific, written prior authorization. If the
2N/A * above copyright notice or any other identification of the
2N/A * University of Michigan is included in any copy of any
2N/A * portion of this software, then the disclaimer below must
2N/A * also be included.
2N/A *
2N/A * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
2N/A * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
2N/A * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
2N/A * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
2N/A * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
2N/A * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
2N/A * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
2N/A * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
2N/A * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
2N/A * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
2N/A * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
2N/A * SUCH DAMAGES.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <errno.h>
2N/A#include <string.h>
2N/A
2N/A#include "k5-int.h"
2N/A#include "pkinit.h"
2N/A
2N/A/*
2N/A * Routines for handling profile [config file] options
2N/A */
2N/A
2N/A/* Forward prototypes */
2N/Astatic int _krb5_conf_boolean(const char *s);
2N/A
2N/A/*
2N/A * XXX
2N/A * The following is duplicated verbatim from src/lib/krb5/krb/get_in_tkt.c,
2N/A * which is duplicated from somewhere else. :-/
2N/A * XXX
2N/A */
2N/Astatic const char *const conf_yes[] = {
2N/A "y", "yes", "true", "t", "1", "on",
2N/A 0,
2N/A};
2N/A
2N/Astatic const char *const conf_no[] = {
2N/A "n", "no", "false", "nil", "0", "off",
2N/A 0,
2N/A};
2N/A
2N/Astatic int
2N/A_krb5_conf_boolean(const char *s)
2N/A{
2N/A const char *const *p;
2N/A
2N/A for(p=conf_yes; *p; p++) {
2N/A if (strcasecmp(*p,s) == 0)
2N/A return 1;
2N/A }
2N/A
2N/A for(p=conf_no; *p; p++) {
2N/A if (strcasecmp(*p,s) == 0)
2N/A return 0;
2N/A }
2N/A
2N/A /* Default to "no" */
2N/A return 0;
2N/A}
2N/A
2N/A/*
2N/A * XXX
2N/A * End duplicated code from src/lib/krb5/krb/get_in_tkt.c
2N/A * XXX
2N/A */
2N/A
2N/A/*
2N/A * The following are based on krb5_libdefault_* functions in
2N/A * src/lib/krb5/krb/get_in_tkt.c
2N/A * N.B. This assumes that context->default_realm has
2N/A * already been established.
2N/A */
2N/Akrb5_error_code
2N/Apkinit_kdcdefault_strings(krb5_context context, const char *realmname,
2N/A const char *option, char ***ret_value)
2N/A{
2N/A profile_t profile = NULL;
2N/A const char *names[5];
2N/A char **values = NULL;
2N/A krb5_error_code retval;
2N/A
2N/A if (context == NULL)
2N/A return KV5M_CONTEXT;
2N/A
2N/A profile = context->profile;
2N/A
2N/A if (realmname != NULL) {
2N/A /*
2N/A * Try number one:
2N/A *
2N/A * [realms]
2N/A * REALM = {
2N/A * option = <value>
2N/A * }
2N/A */
2N/A
2N/A names[0] = KRB5_CONF_REALMS;
2N/A names[1] = realmname;
2N/A names[2] = option;
2N/A names[3] = 0;
2N/A retval = profile_get_values(profile, names, &values);
2N/A if (retval == 0 && values != NULL)
2N/A goto goodbye;
2N/A }
2N/A
2N/A /*
2N/A * Try number two:
2N/A *
2N/A * [kdcdefaults]
2N/A * option = <value>
2N/A */
2N/A
2N/A names[0] = KRB5_CONF_KDCDEFAULTS;
2N/A names[1] = option;
2N/A names[2] = 0;
2N/A retval = profile_get_values(profile, names, &values);
2N/A if (retval == 0 && values != NULL)
2N/A goto goodbye;
2N/A
2N/Agoodbye:
2N/A if (values == NULL)
2N/A retval = ENOENT;
2N/A
2N/A *ret_value = values;
2N/A
2N/A return retval;
2N/A
2N/A}
2N/A
2N/Akrb5_error_code
2N/Apkinit_kdcdefault_string(krb5_context context, const char *realmname,
2N/A const char *option, char **ret_value)
2N/A{
2N/A krb5_error_code retval;
2N/A char **values = NULL;
2N/A
2N/A retval = pkinit_kdcdefault_strings(context, realmname, option, &values);
2N/A if (retval)
2N/A return retval;
2N/A
2N/A if (values[0] == NULL) {
2N/A retval = ENOENT;
2N/A } else {
2N/A *ret_value = strdup(values[0]);
2N/A if (*ret_value == NULL)
2N/A retval = ENOMEM;
2N/A }
2N/A
2N/A profile_free_list(values);
2N/A return retval;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Apkinit_kdcdefault_boolean(krb5_context context, const char *realmname,
2N/A const char *option, int default_value, int *ret_value)
2N/A{
2N/A char *string = NULL;
2N/A krb5_error_code retval;
2N/A
2N/A retval = pkinit_kdcdefault_string(context, realmname, option, &string);
2N/A
2N/A if (retval == 0) {
2N/A *ret_value = _krb5_conf_boolean(string);
2N/A free(string);
2N/A } else
2N/A *ret_value = default_value;
2N/A
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Apkinit_kdcdefault_integer(krb5_context context, const char *realmname,
2N/A const char *option, int default_value, int *ret_value)
2N/A{
2N/A char *string = NULL;
2N/A krb5_error_code retval;
2N/A
2N/A retval = pkinit_kdcdefault_string(context, realmname, option, &string);
2N/A
2N/A if (retval == 0) {
2N/A char *endptr;
2N/A long l;
2N/A l = strtol(string, &endptr, 0);
2N/A if (endptr == string)
2N/A *ret_value = default_value;
2N/A else
2N/A *ret_value = l;
2N/A free(string);
2N/A } else
2N/A *ret_value = default_value;
2N/A
2N/A return 0;
2N/A}
2N/A
2N/A
2N/A/*
2N/A * krb5_libdefault_string() is defined as static in
2N/A * src/lib/krb5/krb/get_in_tkt.c. Create local versions of
2N/A * krb5_libdefault_* functions here. We need a libdefaults_strings()
2N/A * function which is not currently supported there anyway. Also,
2N/A * add the ability to supply a default value for the boolean and
2N/A * integer functions.
2N/A */
2N/A
2N/Akrb5_error_code
2N/Apkinit_libdefault_strings(krb5_context context, const krb5_data *realm,
2N/A const char *option, char ***ret_value)
2N/A{
2N/A profile_t profile;
2N/A const char *names[5];
2N/A char **values = NULL;
2N/A krb5_error_code retval;
2N/A char realmstr[1024];
2N/A
2N/A if (realm != NULL && realm->length > sizeof(realmstr)-1)
2N/A return EINVAL;
2N/A
2N/A if (realm != NULL) {
2N/A strncpy(realmstr, realm->data, realm->length);
2N/A realmstr[realm->length] = '\0';
2N/A }
2N/A
2N/A if (!context || (context->magic != KV5M_CONTEXT))
2N/A return KV5M_CONTEXT;
2N/A
2N/A profile = context->profile;
2N/A
2N/A
2N/A if (realm != NULL) {
2N/A /*
2N/A * Try number one:
2N/A *
2N/A * [libdefaults]
2N/A * REALM = {
2N/A * option = <value>
2N/A * }
2N/A */
2N/A
2N/A names[0] = KRB5_CONF_LIBDEFAULTS;
2N/A names[1] = realmstr;
2N/A names[2] = option;
2N/A names[3] = 0;
2N/A retval = profile_get_values(profile, names, &values);
2N/A if (retval == 0 && values != NULL && values[0] != NULL)
2N/A goto goodbye;
2N/A
2N/A /*
2N/A * Try number two:
2N/A *
2N/A * [realms]
2N/A * REALM = {
2N/A * option = <value>
2N/A * }
2N/A */
2N/A
2N/A names[0] = KRB5_CONF_REALMS;
2N/A names[1] = realmstr;
2N/A names[2] = option;
2N/A names[3] = 0;
2N/A retval = profile_get_values(profile, names, &values);
2N/A if (retval == 0 && values != NULL && values[0] != NULL)
2N/A goto goodbye;
2N/A }
2N/A
2N/A /*
2N/A * Try number three:
2N/A *
2N/A * [libdefaults]
2N/A * option = <value>
2N/A */
2N/A
2N/A names[0] = KRB5_CONF_LIBDEFAULTS;
2N/A names[1] = option;
2N/A names[2] = 0;
2N/A retval = profile_get_values(profile, names, &values);
2N/A if (retval == 0 && values != NULL && values[0] != NULL)
2N/A goto goodbye;
2N/A
2N/Agoodbye:
2N/A if (values == NULL)
2N/A return ENOENT;
2N/A
2N/A *ret_value = values;
2N/A
2N/A return retval;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Apkinit_libdefault_string(krb5_context context, const krb5_data *realm,
2N/A const char *option, char **ret_value)
2N/A{
2N/A krb5_error_code retval;
2N/A char **values = NULL;
2N/A
2N/A retval = pkinit_libdefault_strings(context, realm, option, &values);
2N/A if (retval)
2N/A return retval;
2N/A
2N/A if (values[0] == NULL) {
2N/A retval = ENOENT;
2N/A } else {
2N/A *ret_value = strdup(values[0]);
2N/A if (*ret_value == NULL)
2N/A retval = ENOMEM;
2N/A }
2N/A
2N/A profile_free_list(values);
2N/A return retval;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Apkinit_libdefault_boolean(krb5_context context, const krb5_data *realm,
2N/A const char *option, int default_value,
2N/A int *ret_value)
2N/A{
2N/A char *string = NULL;
2N/A krb5_error_code retval;
2N/A
2N/A retval = pkinit_libdefault_string(context, realm, option, &string);
2N/A
2N/A if (retval == 0) {
2N/A *ret_value = _krb5_conf_boolean(string);
2N/A free(string);
2N/A } else
2N/A *ret_value = default_value;
2N/A
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Apkinit_libdefault_integer(krb5_context context, const krb5_data *realm,
2N/A const char *option, int default_value,
2N/A int *ret_value)
2N/A{
2N/A char *string = NULL;
2N/A krb5_error_code retval;
2N/A
2N/A retval = pkinit_libdefault_string(context, realm, option, &string);
2N/A
2N/A if (retval == 0) {
2N/A char *endptr;
2N/A long l;
2N/A l = strtol(string, &endptr, 0);
2N/A if (endptr == string)
2N/A *ret_value = default_value;
2N/A else
2N/A *ret_value = l;
2N/A free(string);
2N/A }
2N/A
2N/A return retval;
2N/A}