summaryrefslogtreecommitdiff
path: root/client/options.c
blob: 7b1f04e42e9e060e0decd5b8749fc0c89c8586ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * Set default options for wallet clients.
 *
 * This file provides the functions to set default options from the krb5.conf
 * file for both wallet and wallet-rekey.
 *
 * Written by Russ Allbery <eagle@eyrie.org>
 * Copyright 2018 Russ Allbery <eagle@eyrie.org>
 * Copyright 2006-2008, 2010
 *     The Board of Trustees of the Leland Stanford Junior University
 *
 * SPDX-License-Identifier: MIT
 */

#include <config.h>
#include <portable/krb5.h>
#include <portable/system.h>

#include <errno.h>

#include <client/internal.h>
#include <util/messages.h>


/*
 * Load a number option from Kerberos appdefaults.  Takes the Kerberos
 * context, the realm, the option, and the result location.  The native
 * interface doesn't support numbers, so we actually read a string and then
 * convert.
 */
static void
default_number(krb5_context ctx, const char *realm, const char *opt,
               long defval, long *result)
{
    char *tmp = NULL;
    char *end;
    long value;
#ifdef HAVE_KRB5_REALM
    krb5_const_realm rdata = realm;
#else
    krb5_data realm_struct;
    const krb5_data *rdata;

    if (realm == NULL)
        rdata = NULL;
    else {
        rdata = &realm_struct;
        realm_struct.magic = KV5M_DATA;
        realm_struct.data = (void *) realm;
        realm_struct.length = (unsigned int) strlen(realm);
    }
#endif

    *result = defval;
    krb5_appdefault_string(ctx, "wallet", rdata, opt, "", &tmp);
    if (tmp != NULL && tmp[0] != '\0') {
        errno = 0;
        value = strtol(tmp, &end, 10);
        if (errno != 0 || *end != '\0')
            warn("invalid number in krb5.conf setting for %s: %s", opt, tmp);
        else
            *result = value;
    }
    free(tmp);
}


/*
 * Load a string option from Kerberos appdefaults.  Takes the Kerberos
 * context, the realm, the option, and the result location.
 *
 * This requires an annoying workaround because one cannot specify a default
 * value of NULL with MIT Kerberos, since MIT Kerberos unconditionally calls
 * strdup on the default value.  There's also no way to determine if memory
 * allocation failed while parsing or while setting the default value, so we
 * don't return an error code.
 */
static void
default_string(krb5_context ctx, const char *realm, const char *opt,
               const char *defval, char **result)
{
    char *value = NULL;
#ifdef HAVE_KRB5_REALM
    krb5_const_realm rdata = realm;
#else
    krb5_data realm_struct;
    const krb5_data *rdata;

    if (realm == NULL)
        rdata = NULL;
    else {
        rdata = &realm_struct;
        realm_struct.magic = KV5M_DATA;
        realm_struct.data = (void *) realm;
        realm_struct.length = (unsigned int) strlen(realm);
    }
#endif

    if (defval == NULL)
        defval = "";
    krb5_appdefault_string(ctx, "wallet", rdata, opt, defval, &value);
    if (value != NULL) {
        if (value[0] == '\0')
            free(value);
        else {
            if (*result != NULL)
                free(*result);
            *result = value;
        }
    }
}


/*
 * Set option defaults and then get krb5.conf configuration, if any, and
 * override the defaults.  Later, command-line options will override those
 * defaults.
 */
void
default_options(krb5_context ctx, struct options *options)
{
    long port;
    char *realm = NULL;

    /* Having no local realm may be intentional, so don't report an error. */
    krb5_get_default_realm(ctx, &realm);
        
    /* Load the options. */
    default_string(ctx, realm, "wallet_type", "wallet", &options->type);
    default_string(ctx, realm, "wallet_server", WALLET_SERVER,
                   &options->server);
    default_string(ctx, realm, "wallet_principal", NULL, &options->principal);
    default_number(ctx, realm, "wallet_port", WALLET_PORT, &port);

    /* Additional checks on the option values. */
    if (port != WALLET_PORT && (port <= 0 || port > 65535)) {
        warn("invalid number in krb5.conf setting for wallet_port: %ld", port);
        options->port = WALLET_PORT;
    } else {
        options->port = (unsigned short) port;
    }

    /* Clean up. */
    if (realm != NULL)
        krb5_free_default_realm(ctx, realm);
}