2 * Copyright (c) 2020 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
37 #define __attribute__(X)
39 struct heim_context_s {
40 heim_log_facility *log_dest;
41 heim_log_facility *warn_dest;
42 heim_log_facility *debug_dest;
44 unsigned int log_utc:1;
45 unsigned int homedir_access:1;
46 heim_err_cb_context error_context;
47 heim_err_cb_clear_msg clear_error_message;
48 heim_err_cb_free_msg free_error_message;
49 heim_err_cb_get_msg get_error_message;
50 heim_err_cb_set_msg set_error_message;
51 const char *unknown_error;
56 heim_context_init(void)
60 if ((context = calloc(1, sizeof(*context))) == NULL)
64 context->clear_error_message = NULL;
65 context->free_error_message = NULL;
66 context->get_error_message = NULL;
67 context->set_error_message = NULL;
68 context->error_context = NULL;
69 context->unknown_error = "Unknown error";
70 context->success = "Success";
71 context->debug_dest = NULL;
72 context->warn_dest = NULL;
73 context->log_dest = NULL;
74 context->time_fmt = NULL;
79 heim_context_free(heim_context *contextp)
81 heim_context context = *contextp;
86 heim_closelog(context, context->debug_dest);
87 heim_closelog(context, context->warn_dest);
88 heim_closelog(context, context->log_dest);
89 free(context->time_fmt);
94 heim_context_set_msg_cb(heim_context context,
95 heim_err_cb_context cb_context,
96 heim_err_cb_clear_msg cb_clear_msg,
97 heim_err_cb_free_msg cb_free_msg,
98 heim_err_cb_get_msg cb_get_msg,
99 heim_err_cb_set_msg cb_set_msg)
101 context->error_context = cb_context;
102 context->clear_error_message = cb_clear_msg;
103 context->free_error_message = cb_free_msg;
104 context->set_error_message = cb_set_msg;
105 context->get_error_message = cb_get_msg;
109 heim_context_set_time_fmt(heim_context context, const char *fmt)
114 free(context->time_fmt);
117 if ((s = strdup(fmt)) == NULL)
118 return heim_enomem(context);
119 free(context->time_fmt);
120 context->time_fmt = s;
125 heim_context_get_time_fmt(heim_context context)
127 return context->time_fmt ? context->time_fmt : "%Y-%m-%dT%H:%M:%S";
131 heim_context_set_log_utc(heim_context context, unsigned int log_utc)
133 unsigned int old = context->log_utc;
135 context->log_utc = log_utc ? 1 : 0;
140 heim_context_get_log_utc(heim_context context)
142 return context->log_utc;
146 heim_context_set_homedir_access(heim_context context, unsigned int homedir_access)
148 unsigned int old = context->homedir_access;
150 context->homedir_access = homedir_access ? 1 : 0;
155 heim_context_get_homedir_access(heim_context context)
157 return context->homedir_access;
161 heim_clear_error_message(heim_context context)
163 if (context != NULL && context->clear_error_message != NULL)
164 context->clear_error_message(context->error_context);
168 heim_free_error_message(heim_context context, const char *msg)
170 if (context != NULL && context->free_error_message != NULL &&
171 msg != context->unknown_error && msg != context->success)
172 context->free_error_message(context->error_context, msg);
176 heim_get_error_message(heim_context context, heim_error_code ret)
178 if (context != NULL && context->get_error_message != NULL)
179 return context->get_error_message(context->error_context, ret);
181 return context->unknown_error;
182 return context->success;
186 heim_set_error_message(heim_context context, heim_error_code ret,
187 const char *fmt, ...)
188 __attribute__ ((__format__ (__printf__, 3, 4)))
193 heim_vset_error_message(context, ret, fmt, ap);
198 heim_vset_error_message(heim_context context, heim_error_code ret,
199 const char *fmt, va_list args)
200 __attribute__ ((__format__ (__printf__, 3, 0)))
202 if (context != NULL && context->set_error_message != NULL)
203 context->set_error_message(context->error_context, ret, fmt, args);
207 heim_enomem(heim_context context)
209 heim_set_error_message(context, ENOMEM, "malloc: out of memory");
214 heim_get_log_dest(heim_context context)
216 return context->log_dest;
220 heim_get_warn_dest(heim_context context)
222 return context->warn_dest;
226 heim_get_debug_dest(heim_context context)
228 return context->debug_dest;
232 heim_set_log_dest(heim_context context, heim_log_facility *fac)
234 context->log_dest = fac;
239 heim_set_warn_dest(heim_context context, heim_log_facility *fac)
241 context->warn_dest = fac;
246 heim_set_debug_dest(heim_context context, heim_log_facility *fac)
248 context->debug_dest = fac;
254 static heim_error_code
255 add_file(char ***pfilenames, int *len, char *file)
257 char **pp = *pfilenames;
260 for(i = 0; i < *len; i++) {
261 if(strcmp(pp[i], file) == 0) {
267 pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp));
282 get_default_config_config_files_from_registry(void)
284 static const char *KeyName = "Software\\Heimdal"; /* XXX #define this */
285 char *config_file = NULL;
289 rcode = RegOpenKeyEx(HKEY_CURRENT_USER, KeyName, 0, KEY_READ, &key);
290 if (rcode == ERROR_SUCCESS) {
291 config_file = heim_parse_reg_value_as_multi_string(NULL, key, "config",
292 REG_NONE, 0, PATH_SEP);
299 rcode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &key);
300 if (rcode == ERROR_SUCCESS) {
301 config_file = heim_parse_reg_value_as_multi_string(NULL, key, "config",
302 REG_NONE, 0, PATH_SEP);
311 heim_prepend_config_files(const char *filelist,
328 l = strsep_copy(&q, PATH_SEP, NULL, 0);
333 heim_free_config_files(pp);
336 (void) strsep_copy(&p, PATH_SEP, fn, l + 1);
337 ret = add_file(&pp, &len, fn);
339 heim_free_config_files(pp);
347 for (i = 0; pq[i] != NULL; i++) {
350 heim_free_config_files(pp);
353 ret = add_file(&pp, &len, fn);
355 heim_free_config_files(pp);
366 heim_prepend_config_files_default(const char *prepend,
372 char **defpp, **pp = NULL;
374 ret = heim_get_default_config_files(def, envvar, &defpp);
378 ret = heim_prepend_config_files(prepend, defpp, &pp);
379 heim_free_config_files(defpp);
388 heim_get_default_config_files(const char *def,
392 const char *files = NULL;
394 files = secure_getenv(envvar);
399 reg_files = get_default_config_config_files_from_registry();
400 if (reg_files != NULL) {
401 heim_error_code code;
403 code = heim_prepend_config_files(reg_files, NULL, pfilenames);
413 return heim_prepend_config_files(files, NULL, pfilenames);
417 #define REGPATH_KERBEROS "SOFTWARE\\Kerberos"
418 #define REGPATH_HEIMDAL "SOFTWARE\\Heimdal"
422 heim_set_config_files(heim_context context, char **filenames,
423 heim_config_binding **res)
425 heim_error_code ret = 0;
428 while (filenames != NULL && *filenames != NULL && **filenames != '\0') {
429 ret = heim_config_parse_file_multi(context, *filenames, res);
430 if (ret != 0 && ret != ENOENT && ret != EACCES && ret != EPERM
431 && ret != HEIM_ERR_CONFIG_BADFORMAT) {
432 heim_config_file_free(context, *res);
441 * We always ignored errors from loading from the registry, so we still do.
443 heim_load_config_from_registry(context, REGPATH_KERBEROS,
444 REGPATH_HEIMDAL, res);
451 heim_free_config_files(char **filenames)
455 for (p = filenames; p && *p != NULL; p++)