1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson * All rights reserved.
5c19800e8SDoug Rabson *
6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson * are met:
9c19800e8SDoug Rabson *
10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson *
13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson *
17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors
18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software
19c19800e8SDoug Rabson * without specific prior written permission.
20c19800e8SDoug Rabson *
21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c19800e8SDoug Rabson * SUCH DAMAGE.
32c19800e8SDoug Rabson */
33c19800e8SDoug Rabson
34c19800e8SDoug Rabson #include "hx_locl.h"
35c19800e8SDoug Rabson
36c19800e8SDoug Rabson /**
37c19800e8SDoug Rabson * @page page_error Hx509 error reporting functions
38c19800e8SDoug Rabson *
39c19800e8SDoug Rabson * See the library functions here: @ref hx509_error
40c19800e8SDoug Rabson */
41c19800e8SDoug Rabson
42c19800e8SDoug Rabson struct hx509_error_data {
43c19800e8SDoug Rabson hx509_error next;
44c19800e8SDoug Rabson int code;
45c19800e8SDoug Rabson char *msg;
46c19800e8SDoug Rabson };
47c19800e8SDoug Rabson
48c19800e8SDoug Rabson static void
free_error_string(hx509_error msg)49c19800e8SDoug Rabson free_error_string(hx509_error msg)
50c19800e8SDoug Rabson {
51c19800e8SDoug Rabson while(msg) {
52c19800e8SDoug Rabson hx509_error m2 = msg->next;
53c19800e8SDoug Rabson free(msg->msg);
54c19800e8SDoug Rabson free(msg);
55c19800e8SDoug Rabson msg = m2;
56c19800e8SDoug Rabson }
57c19800e8SDoug Rabson }
58c19800e8SDoug Rabson
59c19800e8SDoug Rabson /**
60c19800e8SDoug Rabson * Resets the error strings the hx509 context.
61c19800e8SDoug Rabson *
62c19800e8SDoug Rabson * @param context A hx509 context.
63c19800e8SDoug Rabson *
64c19800e8SDoug Rabson * @ingroup hx509_error
65c19800e8SDoug Rabson */
66c19800e8SDoug Rabson
67c19800e8SDoug Rabson void
hx509_clear_error_string(hx509_context context)68c19800e8SDoug Rabson hx509_clear_error_string(hx509_context context)
69c19800e8SDoug Rabson {
70*ae771770SStanislav Sedov if (context) {
71c19800e8SDoug Rabson free_error_string(context->error);
72c19800e8SDoug Rabson context->error = NULL;
73c19800e8SDoug Rabson }
74*ae771770SStanislav Sedov }
75c19800e8SDoug Rabson
76c19800e8SDoug Rabson /**
77c19800e8SDoug Rabson * Add an error message to the hx509 context.
78c19800e8SDoug Rabson *
79c19800e8SDoug Rabson * @param context A hx509 context.
80c19800e8SDoug Rabson * @param flags
81c19800e8SDoug Rabson * - HX509_ERROR_APPEND appends the error string to the old messages
82c19800e8SDoug Rabson (code is updated).
83c19800e8SDoug Rabson * @param code error code related to error message
84c19800e8SDoug Rabson * @param fmt error message format
85c19800e8SDoug Rabson * @param ap arguments to error message format
86c19800e8SDoug Rabson *
87c19800e8SDoug Rabson * @ingroup hx509_error
88c19800e8SDoug Rabson */
89c19800e8SDoug Rabson
90c19800e8SDoug Rabson void
hx509_set_error_stringv(hx509_context context,int flags,int code,const char * fmt,va_list ap)91c19800e8SDoug Rabson hx509_set_error_stringv(hx509_context context, int flags, int code,
92c19800e8SDoug Rabson const char *fmt, va_list ap)
93c19800e8SDoug Rabson {
94c19800e8SDoug Rabson hx509_error msg;
95c19800e8SDoug Rabson
96*ae771770SStanislav Sedov if (context == NULL)
97*ae771770SStanislav Sedov return;
98*ae771770SStanislav Sedov
99c19800e8SDoug Rabson msg = calloc(1, sizeof(*msg));
100c19800e8SDoug Rabson if (msg == NULL) {
101c19800e8SDoug Rabson hx509_clear_error_string(context);
102c19800e8SDoug Rabson return;
103c19800e8SDoug Rabson }
104c19800e8SDoug Rabson
105c19800e8SDoug Rabson if (vasprintf(&msg->msg, fmt, ap) == -1) {
106c19800e8SDoug Rabson hx509_clear_error_string(context);
107c19800e8SDoug Rabson free(msg);
108c19800e8SDoug Rabson return;
109c19800e8SDoug Rabson }
110c19800e8SDoug Rabson msg->code = code;
111c19800e8SDoug Rabson
112c19800e8SDoug Rabson if (flags & HX509_ERROR_APPEND) {
113c19800e8SDoug Rabson msg->next = context->error;
114c19800e8SDoug Rabson context->error = msg;
115c19800e8SDoug Rabson } else {
116c19800e8SDoug Rabson free_error_string(context->error);
117c19800e8SDoug Rabson context->error = msg;
118c19800e8SDoug Rabson }
119c19800e8SDoug Rabson }
120c19800e8SDoug Rabson
121c19800e8SDoug Rabson /**
122c19800e8SDoug Rabson * See hx509_set_error_stringv().
123c19800e8SDoug Rabson *
124c19800e8SDoug Rabson * @param context A hx509 context.
125c19800e8SDoug Rabson * @param flags
126c19800e8SDoug Rabson * - HX509_ERROR_APPEND appends the error string to the old messages
127c19800e8SDoug Rabson (code is updated).
128c19800e8SDoug Rabson * @param code error code related to error message
129c19800e8SDoug Rabson * @param fmt error message format
130c19800e8SDoug Rabson * @param ... arguments to error message format
131c19800e8SDoug Rabson *
132c19800e8SDoug Rabson * @ingroup hx509_error
133c19800e8SDoug Rabson */
134c19800e8SDoug Rabson
135c19800e8SDoug Rabson void
hx509_set_error_string(hx509_context context,int flags,int code,const char * fmt,...)136c19800e8SDoug Rabson hx509_set_error_string(hx509_context context, int flags, int code,
137c19800e8SDoug Rabson const char *fmt, ...)
138c19800e8SDoug Rabson {
139c19800e8SDoug Rabson va_list ap;
140c19800e8SDoug Rabson
141c19800e8SDoug Rabson va_start(ap, fmt);
142c19800e8SDoug Rabson hx509_set_error_stringv(context, flags, code, fmt, ap);
143c19800e8SDoug Rabson va_end(ap);
144c19800e8SDoug Rabson }
145c19800e8SDoug Rabson
146c19800e8SDoug Rabson /**
147c19800e8SDoug Rabson * Get an error string from context associated with error_code.
148c19800e8SDoug Rabson *
149c19800e8SDoug Rabson * @param context A hx509 context.
150c19800e8SDoug Rabson * @param error_code Get error message for this error code.
151c19800e8SDoug Rabson *
152c19800e8SDoug Rabson * @return error string, free with hx509_free_error_string().
153c19800e8SDoug Rabson *
154c19800e8SDoug Rabson * @ingroup hx509_error
155c19800e8SDoug Rabson */
156c19800e8SDoug Rabson
157c19800e8SDoug Rabson char *
hx509_get_error_string(hx509_context context,int error_code)158c19800e8SDoug Rabson hx509_get_error_string(hx509_context context, int error_code)
159c19800e8SDoug Rabson {
160c19800e8SDoug Rabson struct rk_strpool *p = NULL;
161c19800e8SDoug Rabson hx509_error msg = context->error;
162c19800e8SDoug Rabson
163c19800e8SDoug Rabson if (msg == NULL || msg->code != error_code) {
164c19800e8SDoug Rabson const char *cstr;
165c19800e8SDoug Rabson char *str;
166c19800e8SDoug Rabson
167c19800e8SDoug Rabson cstr = com_right(context->et_list, error_code);
168c19800e8SDoug Rabson if (cstr)
169c19800e8SDoug Rabson return strdup(cstr);
170c19800e8SDoug Rabson cstr = strerror(error_code);
171c19800e8SDoug Rabson if (cstr)
172c19800e8SDoug Rabson return strdup(cstr);
173c19800e8SDoug Rabson if (asprintf(&str, "<unknown error: %d>", error_code) == -1)
174c19800e8SDoug Rabson return NULL;
175c19800e8SDoug Rabson return str;
176c19800e8SDoug Rabson }
177c19800e8SDoug Rabson
178c19800e8SDoug Rabson for (msg = context->error; msg; msg = msg->next)
179c19800e8SDoug Rabson p = rk_strpoolprintf(p, "%s%s", msg->msg,
180c19800e8SDoug Rabson msg->next != NULL ? "; " : "");
181c19800e8SDoug Rabson
182c19800e8SDoug Rabson return rk_strpoolcollect(p);
183c19800e8SDoug Rabson }
184c19800e8SDoug Rabson
185c19800e8SDoug Rabson /**
186c19800e8SDoug Rabson * Free error string returned by hx509_get_error_string().
187c19800e8SDoug Rabson *
188c19800e8SDoug Rabson * @param str error string to free.
189c19800e8SDoug Rabson *
190c19800e8SDoug Rabson * @ingroup hx509_error
191c19800e8SDoug Rabson */
192c19800e8SDoug Rabson
193c19800e8SDoug Rabson void
hx509_free_error_string(char * str)194c19800e8SDoug Rabson hx509_free_error_string(char *str)
195c19800e8SDoug Rabson {
196c19800e8SDoug Rabson free(str);
197c19800e8SDoug Rabson }
198c19800e8SDoug Rabson
199c19800e8SDoug Rabson /**
200c19800e8SDoug Rabson * Print error message and fatally exit from error code
201c19800e8SDoug Rabson *
202c19800e8SDoug Rabson * @param context A hx509 context.
203c19800e8SDoug Rabson * @param exit_code exit() code from process.
204c19800e8SDoug Rabson * @param error_code Error code for the reason to exit.
205c19800e8SDoug Rabson * @param fmt format string with the exit message.
206c19800e8SDoug Rabson * @param ... argument to format string.
207c19800e8SDoug Rabson *
208c19800e8SDoug Rabson * @ingroup hx509_error
209c19800e8SDoug Rabson */
210c19800e8SDoug Rabson
211c19800e8SDoug Rabson void
hx509_err(hx509_context context,int exit_code,int error_code,const char * fmt,...)212c19800e8SDoug Rabson hx509_err(hx509_context context, int exit_code,
213c19800e8SDoug Rabson int error_code, const char *fmt, ...)
214c19800e8SDoug Rabson {
215c19800e8SDoug Rabson va_list ap;
216c19800e8SDoug Rabson const char *msg;
217c19800e8SDoug Rabson char *str;
218c19800e8SDoug Rabson
219c19800e8SDoug Rabson va_start(ap, fmt);
220c19800e8SDoug Rabson vasprintf(&str, fmt, ap);
221c19800e8SDoug Rabson va_end(ap);
222c19800e8SDoug Rabson msg = hx509_get_error_string(context, error_code);
223c19800e8SDoug Rabson if (msg == NULL)
224c19800e8SDoug Rabson msg = "no error";
225c19800e8SDoug Rabson
226c19800e8SDoug Rabson errx(exit_code, "%s: %s", str, msg);
227c19800e8SDoug Rabson }
228