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