/src/samba/third_party/heimdal/lib/base/context.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020 Kungliga Tekniska Högskolan |
3 | | * (Royal Institute of Technology, Stockholm, Sweden). |
4 | | * All rights reserved. |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions |
8 | | * are met: |
9 | | * |
10 | | * 1. Redistributions of source code must retain the above copyright |
11 | | * notice, this list of conditions and the following disclaimer. |
12 | | * |
13 | | * 2. Redistributions in binary form must reproduce the above copyright |
14 | | * notice, this list of conditions and the following disclaimer in the |
15 | | * documentation and/or other materials provided with the distribution. |
16 | | * |
17 | | * 3. Neither the name of the Institute nor the names of its contributors |
18 | | * may be used to endorse or promote products derived from this software |
19 | | * without specific prior written permission. |
20 | | * |
21 | | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND |
22 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE |
25 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
26 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
27 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
28 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
29 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
30 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
31 | | * SUCH DAMAGE. |
32 | | */ |
33 | | |
34 | | #include "baselocl.h" |
35 | | |
36 | | #undef __attribute__ |
37 | | #define __attribute__(X) |
38 | | |
39 | | heim_context |
40 | | heim_context_init(void) |
41 | 0 | { |
42 | 0 | heim_context context; |
43 | |
|
44 | 0 | if ((context = calloc(1, sizeof(*context))) == NULL) |
45 | 0 | return NULL; |
46 | | |
47 | 0 | context->homedir_access = !issuid(); |
48 | 0 | context->log_utc = 1; |
49 | 0 | context->error_string = NULL; |
50 | 0 | context->debug_dest = NULL; |
51 | 0 | context->warn_dest = NULL; |
52 | 0 | context->log_dest = NULL; |
53 | 0 | context->time_fmt = NULL; |
54 | 0 | context->et_list = NULL; |
55 | 0 | return context; |
56 | 0 | } |
57 | | |
58 | | void |
59 | | heim_context_free(heim_context *contextp) |
60 | 0 | { |
61 | 0 | heim_context context = *contextp; |
62 | |
|
63 | 0 | *contextp = NULL; |
64 | 0 | if (!context) |
65 | 0 | return; |
66 | 0 | heim_closelog(context, context->debug_dest); |
67 | 0 | heim_closelog(context, context->warn_dest); |
68 | 0 | heim_closelog(context, context->log_dest); |
69 | 0 | free_error_table(context->et_list); |
70 | 0 | free(context->time_fmt); |
71 | 0 | free(context->error_string); |
72 | 0 | free(context); |
73 | 0 | } |
74 | | |
75 | | heim_error_code |
76 | | heim_add_et_list(heim_context context, void (*func)(struct et_list **)) |
77 | 0 | { |
78 | 0 | (*func)(&context->et_list); |
79 | 0 | return 0; |
80 | 0 | } |
81 | | |
82 | | heim_error_code |
83 | | heim_context_set_time_fmt(heim_context context, const char *fmt) |
84 | 0 | { |
85 | 0 | char *s; |
86 | |
|
87 | 0 | if (fmt == NULL) { |
88 | 0 | free(context->time_fmt); |
89 | 0 | return 0; |
90 | 0 | } |
91 | 0 | if ((s = strdup(fmt)) == NULL) |
92 | 0 | return heim_enomem(context); |
93 | 0 | free(context->time_fmt); |
94 | 0 | context->time_fmt = s; |
95 | 0 | return 0; |
96 | 0 | } |
97 | | |
98 | | const char * |
99 | | heim_context_get_time_fmt(heim_context context) |
100 | 0 | { |
101 | 0 | return context->time_fmt ? context->time_fmt : "%Y-%m-%dT%H:%M:%S"; |
102 | 0 | } |
103 | | |
104 | | unsigned int |
105 | | heim_context_set_log_utc(heim_context context, unsigned int log_utc) |
106 | 0 | { |
107 | 0 | unsigned int old = context->log_utc; |
108 | |
|
109 | 0 | context->log_utc = log_utc ? 1 : 0; |
110 | 0 | return old; |
111 | 0 | } |
112 | | |
113 | | int |
114 | | heim_context_get_log_utc(heim_context context) |
115 | 0 | { |
116 | 0 | return context->log_utc; |
117 | 0 | } |
118 | | |
119 | | unsigned int |
120 | | heim_context_set_homedir_access(heim_context context, unsigned int homedir_access) |
121 | 0 | { |
122 | 0 | unsigned int old = context->homedir_access; |
123 | |
|
124 | 0 | context->homedir_access = homedir_access ? 1 : 0; |
125 | 0 | return old; |
126 | 0 | } |
127 | | |
128 | | unsigned int |
129 | | heim_context_get_homedir_access(heim_context context) |
130 | 0 | { |
131 | 0 | return context->homedir_access; |
132 | 0 | } |
133 | | |
134 | | heim_error_code |
135 | | heim_enomem(heim_context context) |
136 | 0 | { |
137 | 0 | heim_set_error_message(context, ENOMEM, "malloc: out of memory"); |
138 | 0 | return ENOMEM; |
139 | 0 | } |
140 | | |
141 | | heim_log_facility * |
142 | | heim_get_log_dest(heim_context context) |
143 | 0 | { |
144 | 0 | return context->log_dest; |
145 | 0 | } |
146 | | |
147 | | heim_log_facility * |
148 | | heim_get_warn_dest(heim_context context) |
149 | 0 | { |
150 | 0 | return context->warn_dest; |
151 | 0 | } |
152 | | |
153 | | heim_log_facility * |
154 | | heim_get_debug_dest(heim_context context) |
155 | 0 | { |
156 | 0 | return context->debug_dest; |
157 | 0 | } |
158 | | |
159 | | heim_error_code |
160 | | heim_set_log_dest(heim_context context, heim_log_facility *fac) |
161 | 0 | { |
162 | 0 | context->log_dest = heim_log_ref(fac); |
163 | 0 | return 0; |
164 | 0 | } |
165 | | |
166 | | heim_error_code |
167 | | heim_set_warn_dest(heim_context context, heim_log_facility *fac) |
168 | 0 | { |
169 | 0 | context->warn_dest = fac; |
170 | 0 | return 0; |
171 | 0 | } |
172 | | |
173 | | heim_error_code |
174 | | heim_set_debug_dest(heim_context context, heim_log_facility *fac) |
175 | 0 | { |
176 | 0 | context->debug_dest = fac; |
177 | 0 | return 0; |
178 | 0 | } |
179 | | |
180 | | #ifndef PATH_SEP |
181 | 0 | # define PATH_SEP ":" |
182 | | #endif |
183 | | |
184 | | static heim_error_code |
185 | | add_file(char ***pfilenames, int *len, char *file) |
186 | 0 | { |
187 | 0 | char **pp = *pfilenames; |
188 | 0 | int i; |
189 | |
|
190 | 0 | for(i = 0; i < *len; i++) { |
191 | 0 | if(strcmp(pp[i], file) == 0) { |
192 | 0 | free(file); |
193 | 0 | return 0; |
194 | 0 | } |
195 | 0 | } |
196 | | |
197 | 0 | pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp)); |
198 | 0 | if (pp == NULL) { |
199 | 0 | free(file); |
200 | 0 | return ENOMEM; |
201 | 0 | } |
202 | | |
203 | 0 | pp[*len] = file; |
204 | 0 | pp[*len + 1] = NULL; |
205 | 0 | *pfilenames = pp; |
206 | 0 | *len += 1; |
207 | 0 | return 0; |
208 | 0 | } |
209 | | |
210 | | #ifdef WIN32 |
211 | | static char * |
212 | | get_default_config_config_files_from_registry(const char *envvar) |
213 | | { |
214 | | static const char *KeyName = "Software\\Heimdal"; /* XXX #define this */ |
215 | | const char *ValueName; |
216 | | char *config_file = NULL; |
217 | | LONG rcode; |
218 | | HKEY key; |
219 | | |
220 | | if (stricmp(envvar, "KRB5_CONFIG") == 0) |
221 | | ValueName = "config"; |
222 | | else |
223 | | ValueName = envvar; |
224 | | |
225 | | rcode = RegOpenKeyEx(HKEY_CURRENT_USER, KeyName, 0, KEY_READ, &key); |
226 | | if (rcode == ERROR_SUCCESS) { |
227 | | config_file = heim_parse_reg_value_as_multi_string(NULL, key, ValueName, |
228 | | REG_NONE, 0, PATH_SEP); |
229 | | RegCloseKey(key); |
230 | | } |
231 | | |
232 | | if (config_file) |
233 | | return config_file; |
234 | | |
235 | | rcode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &key); |
236 | | if (rcode == ERROR_SUCCESS) { |
237 | | config_file = heim_parse_reg_value_as_multi_string(NULL, key, ValueName, |
238 | | REG_NONE, 0, PATH_SEP); |
239 | | RegCloseKey(key); |
240 | | } |
241 | | |
242 | | return config_file; |
243 | | } |
244 | | #endif |
245 | | |
246 | | heim_error_code |
247 | | heim_prepend_config_files(const char *filelist, |
248 | | char **pq, |
249 | | char ***ret_pp) |
250 | 0 | { |
251 | 0 | heim_error_code ret; |
252 | 0 | const char *p, *q; |
253 | 0 | char **pp; |
254 | 0 | int len; |
255 | 0 | char *fn; |
256 | |
|
257 | 0 | pp = NULL; |
258 | |
|
259 | 0 | len = 0; |
260 | 0 | p = filelist; |
261 | 0 | while(1) { |
262 | 0 | ssize_t l; |
263 | 0 | q = p; |
264 | 0 | l = strsep_copy(&q, PATH_SEP, NULL, 0); |
265 | 0 | if(l == -1) |
266 | 0 | break; |
267 | 0 | fn = malloc(l + 1); |
268 | 0 | if(fn == NULL) { |
269 | 0 | heim_free_config_files(pp); |
270 | 0 | return ENOMEM; |
271 | 0 | } |
272 | 0 | (void) strsep_copy(&p, PATH_SEP, fn, l + 1); |
273 | 0 | ret = add_file(&pp, &len, fn); |
274 | 0 | if (ret) { |
275 | 0 | heim_free_config_files(pp); |
276 | 0 | return ret; |
277 | 0 | } |
278 | 0 | } |
279 | | |
280 | 0 | if (pq != NULL) { |
281 | 0 | int i; |
282 | |
|
283 | 0 | for (i = 0; pq[i] != NULL; i++) { |
284 | 0 | fn = strdup(pq[i]); |
285 | 0 | if (fn == NULL) { |
286 | 0 | heim_free_config_files(pp); |
287 | 0 | return ENOMEM; |
288 | 0 | } |
289 | 0 | ret = add_file(&pp, &len, fn); |
290 | 0 | if (ret) { |
291 | 0 | heim_free_config_files(pp); |
292 | 0 | return ret; |
293 | 0 | } |
294 | 0 | } |
295 | 0 | } |
296 | | |
297 | 0 | *ret_pp = pp; |
298 | 0 | return 0; |
299 | 0 | } |
300 | | |
301 | | heim_error_code |
302 | | heim_prepend_config_files_default(const char *prepend, |
303 | | const char *def, |
304 | | const char *envvar, |
305 | | char ***pfilenames) |
306 | 0 | { |
307 | 0 | heim_error_code ret; |
308 | 0 | char **defpp, **pp = NULL; |
309 | |
|
310 | 0 | ret = heim_get_default_config_files(def, envvar, &defpp); |
311 | 0 | if (ret) |
312 | 0 | return ret; |
313 | | |
314 | 0 | ret = heim_prepend_config_files(prepend, defpp, &pp); |
315 | 0 | heim_free_config_files(defpp); |
316 | 0 | if (ret) { |
317 | 0 | return ret; |
318 | 0 | } |
319 | 0 | *pfilenames = pp; |
320 | 0 | return 0; |
321 | 0 | } |
322 | | |
323 | | heim_error_code |
324 | | heim_get_default_config_files(const char *def, |
325 | | const char *envvar, |
326 | | char ***pfilenames) |
327 | 0 | { |
328 | 0 | const char *files = NULL; |
329 | |
|
330 | 0 | files = secure_getenv(envvar); |
331 | |
|
332 | | #ifdef _WIN32 |
333 | | if (files == NULL) { |
334 | | char * reg_files; |
335 | | reg_files = get_default_config_config_files_from_registry(envvar); |
336 | | if (reg_files != NULL) { |
337 | | heim_error_code code; |
338 | | |
339 | | code = heim_prepend_config_files(reg_files, NULL, pfilenames); |
340 | | free(reg_files); |
341 | | |
342 | | return code; |
343 | | } |
344 | | } |
345 | | #endif |
346 | |
|
347 | 0 | if (files == NULL) |
348 | 0 | files = def; |
349 | 0 | return heim_prepend_config_files(files, NULL, pfilenames); |
350 | 0 | } |
351 | | |
352 | | #ifdef _WIN32 |
353 | | #define REGPATH_KERBEROS "SOFTWARE\\Kerberos" |
354 | | #define REGPATH_HEIMDAL "SOFTWARE\\Heimdal" |
355 | | #endif |
356 | | |
357 | | heim_error_code |
358 | | heim_set_config_files(heim_context context, char **filenames, |
359 | | heim_config_binding **res) |
360 | 0 | { |
361 | 0 | heim_error_code ret = 0; |
362 | |
|
363 | 0 | *res = NULL; |
364 | 0 | while (filenames != NULL && *filenames != NULL && **filenames != '\0') { |
365 | 0 | ret = heim_config_parse_file_multi(context, *filenames, res); |
366 | 0 | if (ret != 0 && ret != ENOENT && ret != EACCES && ret != EPERM |
367 | 0 | && ret != HEIM_ERR_CONFIG_BADFORMAT) { |
368 | 0 | heim_config_file_free(context, *res); |
369 | 0 | *res = NULL; |
370 | 0 | return ret; |
371 | 0 | } |
372 | 0 | filenames++; |
373 | 0 | } |
374 | | |
375 | | #ifdef _WIN32 |
376 | | /* |
377 | | * We always ignored errors from loading from the registry, so we still do. |
378 | | */ |
379 | | heim_load_config_from_registry(context, REGPATH_KERBEROS, |
380 | | REGPATH_HEIMDAL, res); |
381 | | |
382 | | #endif |
383 | 0 | return 0; |
384 | 0 | } |
385 | | |
386 | | void |
387 | | heim_free_config_files(char **filenames) |
388 | 0 | { |
389 | 0 | char **p; |
390 | |
|
391 | 0 | for (p = filenames; p && *p != NULL; p++) |
392 | 0 | free(*p); |
393 | 0 | free(filenames); |
394 | 0 | } |