s4:torture: Adapt KDC canon test to Heimdal upstream changes
[samba.git] / third_party / heimdal / lib / hx509 / error.c
1 /*
2  * Copyright (c) 2006 - 2007 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 "hx_locl.h"
35
36 /**
37  * @page page_error Hx509 error reporting functions
38  *
39  * See the library functions here: @ref hx509_error
40  */
41
42 struct hx509_error_data {
43     hx509_error next;
44     int code;
45     char *msg;
46 };
47
48 /**
49  * Resets the error strings the hx509 context.
50  *
51  * @param context A hx509 context.
52  *
53  * @ingroup hx509_error
54  */
55
56 HX509_LIB_FUNCTION void HX509_LIB_CALL
57 hx509_clear_error_string(hx509_context context)
58 {
59     if (context) {
60         heim_release(context->error);
61         context->error = NULL;
62     }
63 }
64
65 /**
66  * Add an error message to the hx509 context.
67  *
68  * @param context A hx509 context.
69  * @param flags
70  * - HX509_ERROR_APPEND appends the error string to the old messages
71      (code is updated).
72  * @param code error code related to error message
73  * @param fmt error message format
74  * @param ap arguments to error message format
75  *
76  * @ingroup hx509_error
77  */
78
79 HX509_LIB_FUNCTION void HX509_LIB_CALL
80 hx509_set_error_stringv(hx509_context context, int flags, int code,
81                         const char *fmt, va_list ap)
82 {
83     heim_error_t msg;
84
85     if (context == NULL)
86         return;
87
88     msg = heim_error_createv(code, fmt, ap);
89     if (msg) {
90         if (flags & HX509_ERROR_APPEND)
91             heim_error_append(msg, context->error);
92         heim_release(context->error);
93     }
94     context->error = msg;
95 }
96
97 /**
98  * See hx509_set_error_stringv().
99  *
100  * @param context A hx509 context.
101  * @param flags
102  * - HX509_ERROR_APPEND appends the error string to the old messages
103      (code is updated).
104  * @param code error code related to error message
105  * @param fmt error message format
106  * @param ... arguments to error message format
107  *
108  * @ingroup hx509_error
109  */
110
111 HX509_LIB_FUNCTION void HX509_LIB_CALL
112 hx509_set_error_string(hx509_context context, int flags, int code,
113                        const char *fmt, ...)
114 {
115     va_list ap;
116
117     va_start(ap, fmt);
118     hx509_set_error_stringv(context, flags, code, fmt, ap);
119     va_end(ap);
120 }
121
122 /**
123  * Sets ENOMEM as the error on a hx509 context.
124  *
125  * @param context A hx509 context.
126  *
127  * @ingroup hx509_error
128  */
129
130 HX509_LIB_FUNCTION int HX509_LIB_CALL
131 hx509_enomem(hx509_context context)
132 {
133     return heim_enomem(context->hcontext);
134 }
135
136 /**
137  * Get an error string from context associated with error_code.
138  *
139  * @param context A hx509 context.
140  * @param error_code Get error message for this error code.
141  *
142  * @return error string, free with hx509_free_error_string().
143  *
144  * @ingroup hx509_error
145  */
146
147 HX509_LIB_FUNCTION char * HX509_LIB_CALL
148 hx509_get_error_string(hx509_context context, int error_code)
149 {
150     heim_error_t msg;
151     heim_string_t s;
152     char *str = NULL;
153
154     if (context == NULL) {
155         const char *sys_err_msg;
156
157         /* This case should only happen on hx509_context_init() failure */
158         if ((sys_err_msg = strerror(error_code))) {
159             if (asprintf(&str, "hx509_context_init system error: %s (%d)",
160                          sys_err_msg, error_code) == -1)
161                 return NULL;
162             return str;
163         }
164         if (asprintf(&str, "hx509_context_init unknown error: %d",
165                      error_code) == -1)
166             return NULL;
167         return str;
168     }
169
170     msg = context->error;
171     if (msg == NULL || heim_error_get_code(msg) != error_code) {
172         const char *cstr;
173
174         cstr = com_right(context->et_list, error_code);
175         if (cstr)
176             return strdup(cstr);
177         cstr = strerror(error_code);
178         if (cstr)
179             return strdup(cstr);
180         if (asprintf(&str, "<unknown error: %d>", error_code) == -1)
181             return NULL;
182         return str;
183     }
184
185     s = heim_error_copy_string(msg);
186     if (s) {
187         const char *cstr = heim_string_get_utf8(s);
188         if (cstr)
189             str = strdup(cstr);
190         heim_release(s);
191     }
192     return str;
193 }
194
195 /**
196  * Free error string returned by hx509_get_error_string().
197  *
198  * @param str error string to free.
199  *
200  * @ingroup hx509_error
201  */
202
203 HX509_LIB_FUNCTION void HX509_LIB_CALL
204 hx509_free_error_string(char *str)
205 {
206     free(str);
207 }
208
209 /**
210  * Print error message and fatally exit from error code
211  *
212  * @param context A hx509 context.
213  * @param exit_code exit() code from process.
214  * @param error_code Error code for the reason to exit.
215  * @param fmt format string with the exit message.
216  * @param ... argument to format string.
217  *
218  * @ingroup hx509_error
219  */
220
221 HX509_LIB_FUNCTION void HX509_LIB_CALL
222 hx509_err(hx509_context context, int exit_code,
223           int error_code, const char *fmt, ...)
224 {
225     va_list ap;
226     const char *msg;
227     char *str;
228     int ret;
229
230     va_start(ap, fmt);
231     ret = vasprintf(&str, fmt, ap);
232     va_end(ap);
233     msg = hx509_get_error_string(context, error_code);
234     if (msg == NULL)
235         msg = "no error";
236
237     errx(exit_code, "%s: %s", ret != -1 ? str : "ENOMEM", msg);
238 }