err.c revision 296465
1168777Srwatson/* crypto/err/err.c */
2168777Srwatson/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3168777Srwatson * All rights reserved.
4168777Srwatson *
5168777Srwatson * This package is an SSL implementation written
6168777Srwatson * by Eric Young (eay@cryptsoft.com).
7168777Srwatson * The implementation was written so as to conform with Netscapes SSL.
8168777Srwatson *
9168777Srwatson * This library is free for commercial and non-commercial use as long as
10168777Srwatson * the following conditions are aheared to.  The following conditions
11168777Srwatson * apply to all code found in this distribution, be it the RC4, RSA,
12168777Srwatson * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13168777Srwatson * included with this distribution is covered by the same copyright terms
14168777Srwatson * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15168777Srwatson *
16168777Srwatson * Copyright remains Eric Young's, and as such any Copyright notices in
17168777Srwatson * the code are not to be removed.
18168777Srwatson * If this package is used in a product, Eric Young should be given attribution
19168777Srwatson * as the author of the parts of the library used.
20168777Srwatson * This can be in the form of a textual message at program startup or
21168777Srwatson * in documentation (online or textual) provided with the package.
22168777Srwatson *
23168777Srwatson * Redistribution and use in source and binary forms, with or without
24168777Srwatson * modification, are permitted provided that the following conditions
25168777Srwatson * are met:
26185573Srwatson * 1. Redistributions of source code must retain the copyright
27168777Srwatson *    notice, this list of conditions and the following disclaimer.
28168777Srwatson * 2. Redistributions in binary form must reproduce the above copyright
29168777Srwatson *    notice, this list of conditions and the following disclaimer in the
30168777Srwatson *    documentation and/or other materials provided with the distribution.
31168777Srwatson * 3. All advertising materials mentioning features or use of this software
32168777Srwatson *    must display the following acknowledgement:
33168777Srwatson *    "This product includes cryptographic software written by
34168777Srwatson *     Eric Young (eay@cryptsoft.com)"
35168777Srwatson *    The word 'cryptographic' can be left out if the rouines from the library
36168777Srwatson *    being used are not cryptographic related :-).
37168777Srwatson * 4. If you include any Windows specific code (or a derivative thereof) from
38168777Srwatson *    the apps directory (application code) you must include an acknowledgement:
39168777Srwatson *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40168777Srwatson *
41168777Srwatson * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42168777Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43168777Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44168777Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45168777Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46168777Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47168777Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48168777Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49168777Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50168777Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51168777Srwatson * SUCH DAMAGE.
52168777Srwatson *
53168777Srwatson * The licence and distribution terms for any publically available version or
54168777Srwatson * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58/* ====================================================================
59 * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
60 *
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
63 * are met:
64 *
65 * 1. Redistributions of source code must retain the above copyright
66 *    notice, this list of conditions and the following disclaimer.
67 *
68 * 2. Redistributions in binary form must reproduce the above copyright
69 *    notice, this list of conditions and the following disclaimer in
70 *    the documentation and/or other materials provided with the
71 *    distribution.
72 *
73 * 3. All advertising materials mentioning features or use of this
74 *    software must display the following acknowledgment:
75 *    "This product includes software developed by the OpenSSL Project
76 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77 *
78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79 *    endorse or promote products derived from this software without
80 *    prior written permission. For written permission, please contact
81 *    openssl-core@openssl.org.
82 *
83 * 5. Products derived from this software may not be called "OpenSSL"
84 *    nor may "OpenSSL" appear in their names without prior written
85 *    permission of the OpenSSL Project.
86 *
87 * 6. Redistributions of any form whatsoever must retain the following
88 *    acknowledgment:
89 *    "This product includes software developed by the OpenSSL Project
90 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91 *
92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103 * OF THE POSSIBILITY OF SUCH DAMAGE.
104 * ====================================================================
105 *
106 * This product includes cryptographic software written by Eric Young
107 * (eay@cryptsoft.com).  This product includes software written by Tim
108 * Hudson (tjh@cryptsoft.com).
109 *
110 */
111
112#include <stdio.h>
113#include <stdarg.h>
114#include <string.h>
115#include "cryptlib.h"
116#include <openssl/lhash.h>
117#include <openssl/crypto.h>
118#include <openssl/buffer.h>
119#include <openssl/bio.h>
120#include <openssl/err.h>
121
122static unsigned long get_error_values(int inc, int top,
123                                      const char **file, int *line,
124                                      const char **data, int *flags);
125
126#define err_clear_data(p,i) \
127        do { \
128        if (((p)->err_data[i] != NULL) && \
129                (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
130                {  \
131                OPENSSL_free((p)->err_data[i]); \
132                (p)->err_data[i]=NULL; \
133                } \
134        (p)->err_data_flags[i]=0; \
135        } while(0)
136
137#define err_clear(p,i) \
138        do { \
139        (p)->err_flags[i]=0; \
140        (p)->err_buffer[i]=0; \
141        err_clear_data(p,i); \
142        (p)->err_file[i]=NULL; \
143        (p)->err_line[i]= -1; \
144        } while(0)
145
146void ERR_put_error(int lib, int func, int reason, const char *file, int line)
147{
148    ERR_STATE *es;
149
150#ifdef _OSD_POSIX
151    /*
152     * In the BS2000-OSD POSIX subsystem, the compiler generates path names
153     * in the form "*POSIX(/etc/passwd)". This dirty hack strips them to
154     * something sensible. @@@ We shouldn't modify a const string, though.
155     */
156    if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) {
157        char *end;
158
159        /* Skip the "*POSIX(" prefix */
160        file += sizeof("*POSIX(") - 1;
161        end = &file[strlen(file) - 1];
162        if (*end == ')')
163            *end = '\0';
164        /* Optional: use the basename of the path only. */
165        if ((end = strrchr(file, '/')) != NULL)
166            file = &end[1];
167    }
168#endif
169    es = ERR_get_state();
170
171    es->top = (es->top + 1) % ERR_NUM_ERRORS;
172    if (es->top == es->bottom)
173        es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
174    es->err_flags[es->top] = 0;
175    es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
176    es->err_file[es->top] = file;
177    es->err_line[es->top] = line;
178    err_clear_data(es, es->top);
179}
180
181void ERR_clear_error(void)
182{
183    int i;
184    ERR_STATE *es;
185
186    es = ERR_get_state();
187
188    for (i = 0; i < ERR_NUM_ERRORS; i++) {
189        err_clear(es, i);
190    }
191    es->top = es->bottom = 0;
192}
193
194unsigned long ERR_get_error(void)
195{
196    return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
197}
198
199unsigned long ERR_get_error_line(const char **file, int *line)
200{
201    return (get_error_values(1, 0, file, line, NULL, NULL));
202}
203
204unsigned long ERR_get_error_line_data(const char **file, int *line,
205                                      const char **data, int *flags)
206{
207    return (get_error_values(1, 0, file, line, data, flags));
208}
209
210unsigned long ERR_peek_error(void)
211{
212    return (get_error_values(0, 0, NULL, NULL, NULL, NULL));
213}
214
215unsigned long ERR_peek_error_line(const char **file, int *line)
216{
217    return (get_error_values(0, 0, file, line, NULL, NULL));
218}
219
220unsigned long ERR_peek_error_line_data(const char **file, int *line,
221                                       const char **data, int *flags)
222{
223    return (get_error_values(0, 0, file, line, data, flags));
224}
225
226unsigned long ERR_peek_last_error(void)
227{
228    return (get_error_values(0, 1, NULL, NULL, NULL, NULL));
229}
230
231unsigned long ERR_peek_last_error_line(const char **file, int *line)
232{
233    return (get_error_values(0, 1, file, line, NULL, NULL));
234}
235
236unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
237                                            const char **data, int *flags)
238{
239    return (get_error_values(0, 1, file, line, data, flags));
240}
241
242static unsigned long get_error_values(int inc, int top, const char **file,
243                                      int *line, const char **data,
244                                      int *flags)
245{
246    int i = 0;
247    ERR_STATE *es;
248    unsigned long ret;
249
250    es = ERR_get_state();
251
252    if (inc && top) {
253        if (file)
254            *file = "";
255        if (line)
256            *line = 0;
257        if (data)
258            *data = "";
259        if (flags)
260            *flags = 0;
261
262        return ERR_R_INTERNAL_ERROR;
263    }
264
265    if (es->bottom == es->top)
266        return 0;
267    if (top)
268        i = es->top;            /* last error */
269    else
270        i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
271
272    ret = es->err_buffer[i];
273    if (inc) {
274        es->bottom = i;
275        es->err_buffer[i] = 0;
276    }
277
278    if ((file != NULL) && (line != NULL)) {
279        if (es->err_file[i] == NULL) {
280            *file = "NA";
281            if (line != NULL)
282                *line = 0;
283        } else {
284            *file = es->err_file[i];
285            if (line != NULL)
286                *line = es->err_line[i];
287        }
288    }
289
290    if (data == NULL) {
291        if (inc) {
292            err_clear_data(es, i);
293        }
294    } else {
295        if (es->err_data[i] == NULL) {
296            *data = "";
297            if (flags != NULL)
298                *flags = 0;
299        } else {
300            *data = es->err_data[i];
301            if (flags != NULL)
302                *flags = es->err_data_flags[i];
303        }
304    }
305    return ret;
306}
307
308void ERR_set_error_data(char *data, int flags)
309{
310    ERR_STATE *es;
311    int i;
312
313    es = ERR_get_state();
314
315    i = es->top;
316    if (i == 0)
317        i = ERR_NUM_ERRORS - 1;
318
319    err_clear_data(es, i);
320    es->err_data[i] = data;
321    es->err_data_flags[i] = flags;
322}
323
324void ERR_add_error_data(int num, ...)
325{
326    va_list args;
327    int i, n, s;
328    char *str, *p, *a;
329
330    s = 80;
331    str = OPENSSL_malloc(s + 1);
332    if (str == NULL)
333        return;
334    str[0] = '\0';
335
336    va_start(args, num);
337    n = 0;
338    for (i = 0; i < num; i++) {
339        a = va_arg(args, char *);
340        /* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
341        if (a != NULL) {
342            n += strlen(a);
343            if (n > s) {
344                s = n + 20;
345                p = OPENSSL_realloc(str, s + 1);
346                if (p == NULL) {
347                    OPENSSL_free(str);
348                    goto err;
349                } else
350                    str = p;
351            }
352            BUF_strlcat(str, a, (size_t)s + 1);
353        }
354    }
355    ERR_set_error_data(str, ERR_TXT_MALLOCED | ERR_TXT_STRING);
356
357 err:
358    va_end(args);
359}
360
361int ERR_set_mark(void)
362{
363    ERR_STATE *es;
364
365    es = ERR_get_state();
366
367    if (es->bottom == es->top)
368        return 0;
369    es->err_flags[es->top] |= ERR_FLAG_MARK;
370    return 1;
371}
372
373int ERR_pop_to_mark(void)
374{
375    ERR_STATE *es;
376
377    es = ERR_get_state();
378
379    while (es->bottom != es->top
380           && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
381        err_clear(es, es->top);
382        es->top -= 1;
383        if (es->top == -1)
384            es->top = ERR_NUM_ERRORS - 1;
385    }
386
387    if (es->bottom == es->top)
388        return 0;
389    es->err_flags[es->top] &= ~ERR_FLAG_MARK;
390    return 1;
391}
392
393#ifdef OPENSSL_FIPS
394
395static ERR_STATE *fget_state(void)
396{
397    static ERR_STATE fstate;
398    return &fstate;
399}
400
401ERR_STATE *(*get_state_func) (void) = fget_state;
402void (*remove_state_func) (unsigned long pid);
403
404ERR_STATE *ERR_get_state(void)
405{
406    return get_state_func();
407}
408
409void int_ERR_set_state_func(ERR_STATE *(*get_func) (void),
410                            void (*remove_func) (unsigned long pid))
411{
412    get_state_func = get_func;
413    remove_state_func = remove_func;
414}
415
416void ERR_remove_state(unsigned long pid)
417{
418    if (remove_state_func)
419        remove_state_func(pid);
420}
421
422#endif
423