4
* Copyright 2006 Massachusetts Institute of Technology.
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
28
#include "kim_private.h"
30
#include <CredentialsCache.h>
32
static k5_mutex_t kim_error_lock = K5_MUTEX_PARTIAL_INITIALIZER;
34
MAKE_INIT_FUNCTION(kim_error_initialize);
35
MAKE_FINI_FUNCTION(kim_error_terminate);
37
/* ------------------------------------------------------------------------ */
39
typedef struct kim_last_error {
44
/* ------------------------------------------------------------------------ */
46
static kim_error kim_error_set_message (kim_error in_error,
47
kim_string in_message)
50
kim_error err = KIM_NO_ERROR;
51
kim_last_error last_error = NULL;
53
err = lock_err = k5_mutex_lock (&kim_error_lock);
56
last_error = k5_getspecific (K5_KEY_KIM_ERROR_MESSAGE);
59
last_error = malloc (sizeof (*last_error));
61
err = KIM_OUT_OF_MEMORY_ERR;
63
last_error->code = KIM_NO_ERROR;
64
err = k5_setspecific (K5_KEY_KIM_ERROR_MESSAGE, last_error);
70
strncpy (last_error->message, in_message, sizeof (last_error->message));
71
last_error->message[sizeof (last_error->message)-1] = '\0';
72
last_error->code = in_error;
75
if (!lock_err) { k5_mutex_unlock (&kim_error_lock); }
80
/* ------------------------------------------------------------------------ */
82
static void kim_error_free_message (void *io_error)
84
kim_last_error error = io_error;
88
free (error->message);
96
/* ------------------------------------------------------------------------ */
98
static kim_boolean kim_error_is_builtin (kim_error in_error)
100
return (in_error == KIM_NO_ERROR ||
101
in_error == KIM_OUT_OF_MEMORY_ERR);
104
/* ------------------------------------------------------------------------ */
105
/* Warning: only remap to error strings with the same format! */
107
static kim_error kim_error_remap (kim_error in_error)
109
/* some krb5 errors are confusing. remap to better ones */
111
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
112
return KIM_BAD_PASSWORD_ERR;
114
case KRB5KDC_ERR_PREAUTH_FAILED:
115
return KIM_PREAUTH_FAILED_ERR;
117
case KRB5KRB_AP_ERR_SKEW:
118
return KIM_CLOCK_SKEW_ERR;
124
/* ------------------------------------------------------------------------ */
126
kim_string kim_error_message (kim_error in_error)
129
kim_last_error last_error = NULL;
130
kim_string message = NULL;
132
lock_err = k5_mutex_lock (&kim_error_lock);
135
last_error = k5_getspecific (K5_KEY_KIM_ERROR_MESSAGE);
136
if (last_error && last_error->code == in_error) {
137
message = last_error->message;
141
if (!lock_err) { k5_mutex_unlock (&kim_error_lock); }
143
return message ? message : error_message (kim_error_remap (in_error));
146
#pragma mark -- Generic Functions --
148
/* ------------------------------------------------------------------------ */
150
kim_error kim_error_set_message_for_code (kim_error in_error,
153
kim_error err = KIM_NO_ERROR;
156
va_start (args, in_error);
157
err = kim_error_set_message_for_code_va (in_error, args);
160
return check_error (err);
163
/* ------------------------------------------------------------------------ */
165
kim_error kim_error_set_message_for_code_va (kim_error in_code,
168
kim_error err = KIM_NO_ERROR;
169
kim_error code = kim_error_remap (in_code);
171
if (!kim_error_is_builtin (code)) {
172
kim_string message = NULL;
174
err = kim_string_create_from_format_va_retcode (&message,
175
error_message (code),
179
err = kim_error_set_message (code, message);
182
kim_string_free (&message);
185
return err ? err : code;
189
/* ------------------------------------------------------------------------ */
191
kim_error kim_error_set_message_for_krb5_error (krb5_context in_context,
192
krb5_error_code in_code)
194
kim_error err = KIM_NO_ERROR;
195
krb5_error_code code = kim_error_remap (in_code);
197
if (code != in_code) {
198
/* error was remapped to a KIM error */
199
err = kim_error_set_message (code, error_message (code));
201
} else if (!kim_error_is_builtin (code)) {
202
const char *message = krb5_get_error_message (in_context, code);
205
err = kim_error_set_message (code, message);
207
krb5_free_error_message (in_context, message);
211
return err ? err : code;
214
#pragma mark -- Debugging Functions --
216
/* ------------------------------------------------------------------------ */
218
int kim_error_initialize (void)
223
err = k5_mutex_finish_init (&kim_error_lock);
227
err = k5_key_register (K5_KEY_KIM_ERROR_MESSAGE,
228
kim_error_free_message);
234
/* ------------------------------------------------------------------------ */
236
void kim_error_terminate (void)
238
if (!INITIALIZER_RAN (kim_error_initialize) || PROGRAM_EXITING ()) {
242
k5_key_delete (K5_KEY_KIM_ERROR_MESSAGE);
243
k5_mutex_destroy (&kim_error_lock);