File: config.c

package info (click to toggle)
krb5-sync 3.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 2,556 kB
  • sloc: sh: 11,750; ansic: 7,181; perl: 663; makefile: 135
file content (193 lines) | stat: -rw-r--r-- 5,236 bytes parent folder | download | duplicates (4)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*
 * Retrieve configuratin settings from krb5.conf.
 *
 * Provided here are functions to retrieve boolean, numeric, and string
 * settings from krb5.conf.  This wraps the somewhat awkward
 * krb5_appdefaults_* functions.
 *
 * Written by Russ Allbery <eagle@eyrie.org>
 * Copyright 2013
 *     The Board of Trustees of the Leland Stanford Junior University
 *
 * See LICENSE for licensing terms.
 */

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

#include <errno.h>

#include <plugin/internal.h>
#include <util/macros.h>

/* The representation of the realm differs between MIT and Kerberos. */
#ifdef HAVE_KRB5_REALM
typedef krb5_realm realm_type;
#else
typedef krb5_data *realm_type;
#endif


/*
 * Obtain the default realm and translate it into the format required by
 * krb5_appdefault_*.  This is obnoxious for MIT Kerberos, which returns the
 * default realm as a string but expects the realm as a krb5_data type when
 * calling krb5_appdefault_*.
 */
#ifdef HAVE_KRB5_REALM

static realm_type
default_realm(krb5_context ctx)
{
    krb5_error_code code;
    realm_type realm;

    code = krb5_get_default_realm(ctx, &realm);
    if (code != 0)
        realm = NULL;
    return realm;
}

#else /* !HAVE_KRB5_REALM */

static realm_type
default_realm(krb5_context ctx)
{
    char *realm = NULL;
    krb5_error_code code;
    krb5_data *realm_data;

    realm_data = calloc(1, sizeof(krb5_data));
    if (realm_data == NULL)
        return NULL;
    code = krb5_get_default_realm(ctx, &realm);
    if (code != 0) {
        free(realm);
        return NULL;
    }
    realm_data->magic = KV5M_DATA;
    realm_data->data = strdup(realm);
    if (realm_data->data == NULL) {
        free(realm_data);
        krb5_free_default_realm(ctx, realm);
        return NULL;
    }
    realm_data->length = strlen(realm);
    krb5_free_default_realm(ctx, realm);
    return realm_data;
}

#endif /* !HAVE_KRB5_REALM */


/*
 * Free the default realm data in whatever form it was generated for the calls
 * to krb5_appdefault_*.
 */
#ifdef HAVE_KRB5_REALM

static void
free_default_realm(krb5_context ctx UNUSED, realm_type realm)
{
    krb5_free_default_realm(ctx, realm);
}

#else /* !HAVE_KRB5_REALM */

static void
free_default_realm(krb5_context ctx UNUSED, realm_type realm)
{
    free(realm->data);
    free(realm);
}

#endif /* !HAVE_KRB5_REALM */


/*
 * Load a boolean option from Kerberos appdefaults.  Takes the Kerberos
 * context, the option, and the result location.
 */
void
sync_config_boolean(krb5_context ctx, const char *opt, bool *result)
{
    realm_type realm;
    int tmp;

    /*
     * The MIT version of krb5_appdefault_boolean takes an int * and the
     * Heimdal version takes a krb5_boolean *, so hope that Heimdal always
     * defines krb5_boolean to int or this will require more portability work.
     */
    realm = default_realm(ctx);
    krb5_appdefault_boolean(ctx, "krb5-sync", realm, opt, *result, &tmp);
    *result = tmp;
    free_default_realm(ctx, realm);
}


/*
 * Load a list option from Kerberos appdefaults.  Takes the Kerberos context,
 * the option, and the result location.  The option is read as a string and
 * the split on spaces and tabs into a list.
 *
 * 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.
 */
krb5_error_code
sync_config_list(krb5_context ctx, const char *opt, struct vector **result)
{
    realm_type realm;
    char *value = NULL;

    /* Obtain the string from [appdefaults]. */
    realm = default_realm(ctx);
    krb5_appdefault_string(ctx, "krb5-sync", realm, opt, "", &value);
    free_default_realm(ctx, realm);

    /* If we got something back, store it in result. */
    if (value != NULL) {
        if (value[0] != '\0') {
            *result = sync_vector_split_multi(value, " \t", *result);
            if (*result == NULL)
                return sync_error_system(ctx, "cannot allocate memory");
        }
        krb5_free_string(ctx, value);
    }
    return 0;
}


/*
 * Load a string option from Kerberos appdefaults.  Takes the Kerberos
 * context, 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.
 */
void
sync_config_string(krb5_context ctx, const char *opt, char **result)
{
    realm_type realm;
    char *value = NULL;

    /* Obtain the string from [appdefaults]. */
    realm = default_realm(ctx);
    krb5_appdefault_string(ctx, "krb5-sync", realm, opt, "", &value);
    free_default_realm(ctx, realm);

    /* If we got something back, store it in result. */
    if (value != NULL) {
        if (value[0] != '\0') {
            free(*result);
            *result = strdup(value);
        }
        krb5_free_string(ctx, value);
    }
}