]> eyrie.org Git - kerberos/krb5-strength.git/blob - plugin/config.c
d60ef509befcc1a32097f0af7b7c0fa8f1849e27
[kerberos/krb5-strength.git] / plugin / config.c
1 /*
2  * Retrieve configuration settings from krb5.conf.
3  *
4  * Provided here are functions to retrieve boolean, numeric, and string
5  * settings from krb5.conf.  This wraps the somewhat awkward
6  * krb5_appdefaults_* functions.
7  *
8  * Written by Russ Allbery <eagle@eyrie.org>
9  * Copyright 2013
10  *     The Board of Trustees of the Leland Stanford Junior University
11  *
12  * See LICENSE for licensing terms.
13  */
14
15 #include <config.h>
16 #include <portable/krb5.h>
17 #include <portable/system.h>
18
19 #include <errno.h>
20
21 #include <plugin/internal.h>
22 #include <util/macros.h>
23
24 /* The representation of the realm differs between MIT and Kerberos. */
25 #ifdef HAVE_KRB5_REALM
26 typedef krb5_realm realm_type;
27 #else
28 typedef krb5_data *realm_type;
29 #endif
30
31
32 /*
33  * Obtain the default realm and translate it into the format required by
34  * krb5_appdefault_*.  This is obnoxious for MIT Kerberos, which returns the
35  * default realm as a string but expects the realm as a krb5_data type when
36  * calling krb5_appdefault_*.
37  */
38 #ifdef HAVE_KRB5_REALM
39
40 static realm_type
41 default_realm(krb5_context ctx)
42 {
43     krb5_error_code code;
44     realm_type realm;
45
46     code = krb5_get_default_realm(ctx, &realm);
47     if (code != 0)
48         realm = NULL;
49     return realm;
50 }
51
52 #else /* !HAVE_KRB5_REALM */
53
54 static realm_type
55 default_realm(krb5_context ctx)
56 {
57     char *realm = NULL;
58     krb5_error_code code;
59     krb5_data *realm_data;
60
61     realm_data = calloc(1, sizeof(krb5_data));
62     if (realm_data == NULL)
63         return NULL;
64     code = krb5_get_default_realm(ctx, &realm);
65     if (code != 0) {
66         free(realm);
67         return NULL;
68     }
69     realm_data->magic = KV5M_DATA;
70     realm_data->data = strdup(realm);
71     if (realm_data->data == NULL) {
72         free(realm_data);
73         krb5_free_default_realm(ctx, realm);
74         return NULL;
75     }
76     realm_data->length = strlen(realm);
77     krb5_free_default_realm(ctx, realm);
78     return realm_data;
79 }
80
81 #endif /* !HAVE_KRB5_REALM */
82
83
84 /*
85  * Free the default realm data in whatever form it was generated for the calls
86  * to krb5_appdefault_*.
87  */
88 #ifdef HAVE_KRB5_REALM
89
90 static void
91 free_default_realm(krb5_context ctx UNUSED, realm_type realm)
92 {
93     krb5_free_default_realm(ctx, realm);
94 }
95
96 #else /* !HAVE_KRB5_REALM */
97
98 static void
99 free_default_realm(krb5_context ctx UNUSED, realm_type realm)
100 {
101     free(realm->data);
102     free(realm);
103 }
104
105 #endif /* !HAVE_KRB5_REALM */
106
107
108 /*
109  * Load a boolean option from Kerberos appdefaults.  Takes the Kerberos
110  * context, the option, and the result location.
111  */
112 void
113 strength_config_boolean(krb5_context ctx, const char *opt, bool *result)
114 {
115     realm_type realm;
116     int tmp;
117
118     /*
119      * The MIT version of krb5_appdefault_boolean takes an int * and the
120      * Heimdal version takes a krb5_boolean *, so hope that Heimdal always
121      * defines krb5_boolean to int or this will require more portability work.
122      */
123     realm = default_realm(ctx);
124     krb5_appdefault_boolean(ctx, "krb5-strength", realm, opt, *result, &tmp);
125     *result = tmp;
126     free_default_realm(ctx, realm);
127 }
128
129
130 /*
131  * Load a number option from Kerberos appdefaults.  Takes the Kerberos
132  * context, the option, and the result location.  The native interface doesn't
133  * support numbers, so we actually read a string and then convert.
134  */
135 void
136 strength_config_number(krb5_context ctx, const char *opt, long *result)
137 {
138     realm_type realm;
139     char *tmp = NULL;
140     char *end;
141     long value;
142
143     /* Obtain the setting in string form from [appdefaults]. */
144     realm = default_realm(ctx);
145     krb5_appdefault_string(ctx, "krb5-strength", realm, opt, "", &tmp);
146     free_default_realm(ctx, realm);
147
148     /*
149      * If we found anything, convert it to a number.  Currently, we ignore
150      * errors here.
151      */
152     if (tmp != NULL && tmp[0] != '\0') {
153         errno = 0;
154         value = strtol(tmp, &end, 10);
155         if (errno == 0 && *end == '\0')
156             *result = value;
157     }
158     if (tmp != NULL)
159         krb5_free_string(ctx, tmp);
160 }
161
162
163 /*
164  * Load a string option from Kerberos appdefaults.  Takes the Kerberos
165  * context, the option, and the result location.
166  *
167  * This requires an annoying workaround because one cannot specify a default
168  * value of NULL with MIT Kerberos, since MIT Kerberos unconditionally calls
169  * strdup on the default value.  There's also no way to determine if memory
170  * allocation failed while parsing or while setting the default value, so we
171  * don't return an error code.
172  */
173 void
174 strength_config_string(krb5_context ctx, const char *opt, char **result)
175 {
176     realm_type realm;
177     char *value = NULL;
178
179     /* Obtain the string from [appdefaults]. */
180     realm = default_realm(ctx);
181     krb5_appdefault_string(ctx, "krb5-strength", realm, opt, "", &value);
182     free_default_realm(ctx, realm);
183
184     /* If we got something back, store it in result. */
185     if (value != NULL) {
186         if (value[0] != '\0') {
187             free(*result);
188             *result = strdup(value);
189         }
190         krb5_free_string(ctx, value);
191     }
192 }