summaryrefslogtreecommitdiff
path: root/src/errors.c
blob: 2cb0801d661cf703019452ab53dfba35311be6a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/**
 * XML Security Library (http://www.aleksey.com/xmlsec).
 *
 * Error codes and error reporting functions.
 *
 * This is free software; see Copyright file in the source
 * distribution for preciese wording.
 *
 * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
 */
#include "globals.h"

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>

#include <libxml/tree.h>

#include <xmlsec/xmlsec.h>
#include <xmlsec/xmltree.h>
#include <xmlsec/private.h>
#include <xmlsec/errors.h>

#define XMLSEC_ERRORS_BUFFER_SIZE       1024

typedef struct _xmlSecErrorDescription                  xmlSecErrorDescription, *xmlSecErrorDescriptionPtr;
struct _xmlSecErrorDescription {
    int                 errorCode;
    const char*         errorMsg;
};

static xmlSecErrorDescription xmlSecErrorsTable[XMLSEC_ERRORS_MAX_NUMBER + 1] = {
  { XMLSEC_ERRORS_R_XMLSEC_FAILED,              "xmlsec library function failed" },
  { XMLSEC_ERRORS_R_MALLOC_FAILED,              "malloc function failed" },
  { XMLSEC_ERRORS_R_STRDUP_FAILED,              "strdup function failed" },
  { XMLSEC_ERRORS_R_CRYPTO_FAILED,              "crypto library function failed" },
  { XMLSEC_ERRORS_R_XML_FAILED,                 "libxml2 library function failed" },
  { XMLSEC_ERRORS_R_XSLT_FAILED,                "libxslt library function failed" },
  { XMLSEC_ERRORS_R_IO_FAILED,                  "io function failed" },
  { XMLSEC_ERRORS_R_DISABLED,                   "feature is disabled" },
  { XMLSEC_ERRORS_R_NOT_IMPLEMENTED,            "feature is not implemented" },
  { XMLSEC_ERRORS_R_INVALID_SIZE,               "invalid size" },
  { XMLSEC_ERRORS_R_INVALID_DATA,               "invalid data" },
  { XMLSEC_ERRORS_R_INVALID_RESULT,             "invalid result" },
  { XMLSEC_ERRORS_R_INVALID_TYPE,               "invalid type" },
  { XMLSEC_ERRORS_R_INVALID_OPERATION,          "invalid operation" },
  { XMLSEC_ERRORS_R_INVALID_STATUS,             "invalid status" },
  { XMLSEC_ERRORS_R_INVALID_FORMAT,             "invalid format" },
  { XMLSEC_ERRORS_R_DATA_NOT_MATCH,             "data do not match" },
  { XMLSEC_ERRORS_R_INVALID_NODE,               "invalid node" },
  { XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,       "invalid node content" },
  { XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,     "invalid node attribute" },
  { XMLSEC_ERRORS_R_MISSING_NODE_ATTRIBUTE,     "missing node attribute" },
  { XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,       "node already present" },
  { XMLSEC_ERRORS_R_UNEXPECTED_NODE,            "unexpected node" },
  { XMLSEC_ERRORS_R_NODE_NOT_FOUND,             "node node found" },
  { XMLSEC_ERRORS_R_INVALID_TRANSFORM,          "invalid transform" },
  { XMLSEC_ERRORS_R_INVALID_TRANSFORM_KEY,      "invalid transform key" },
  { XMLSEC_ERRORS_R_INVALID_URI_TYPE,           "invalid URI type" },
  { XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED,   "same document is required for transform" },
  { XMLSEC_ERRORS_R_TRANSFORM_DISABLED,         "transform is disabled" },
  { XMLSEC_ERRORS_R_INVALID_KEY_DATA,           "invalid key data" },
  { XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND,         "key data is not found" },
  { XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,     "key data already exist" },
  { XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,      "invalid key data size" },
  { XMLSEC_ERRORS_R_KEY_NOT_FOUND,              "key is not found" },
  { XMLSEC_ERRORS_R_KEYDATA_DISABLED,           "key data is disabled" },
  { XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,       "maximum key retrieval level" },
  { XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,"key retrieval type mismatch" },
  { XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL,           "maximum encrypted key level" },
  { XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,         "certificate verification failed" },
  { XMLSEC_ERRORS_R_CERT_NOT_FOUND,             "certificate is not found" },
  { XMLSEC_ERRORS_R_CERT_REVOKED,               "certificate is revoked" },
  { XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,         "certificate issuer check failed" },
  { XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,         "certificate is not yet valid" },
  { XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,           "certificate has expirred" },
  { XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,         "Reference nodes are not found" },
  { XMLSEC_ERRORS_R_DSIG_INVALID_REFERENCE,     "Reference verification failed" },
  { XMLSEC_ERRORS_R_ASSERTION,                  "assertion" },
  { 0,                                          NULL}
};

static xmlSecErrorsCallback xmlSecErrorsClbk = xmlSecErrorsDefaultCallback;
static int  xmlSecPrintErrorMessages = 1;       /* whether the error messages will be printed immidiatelly */

/**
 * xmlSecErrorsInit:
 *
 * Initializes the errors reporting. It is called from #xmlSecInit function.
 * and applications must not call this function directly.
 */
void
xmlSecErrorsInit(void) {
}

/**
 * xmlSecErrorsShutdown:
 *
 * Cleanups the errors reporting. It is called from #xmlSecShutdown function.
 * and applications must not call this function directly.
 */
void
xmlSecErrorsShutdown(void) {
}

/**
 * xmlSecErrorsSetCallback:
 * @callback:           the new errors callback function.
 *
 * Sets the errors callback function to @callback that will be called
 * every time an error occurs.
 */
void
xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) {
    xmlSecErrorsClbk = callback;
    xmlSecErrorsDefaultCallbackEnableOutput(0);
}

/**
 * xmlSecErrorsDefaultCallback:
 * @file:               the error location file name (__FILE__ macro).
 * @line:               the error location line number (__LINE__ macro).
 * @func:               the error location function name (__FUNCTION__ macro).
 * @errorObject:        the error specific error object
 * @errorSubject:       the error specific error subject.
 * @reason:             the error code.
 * @msg:                the additional error message.
 *
 * The default error reporting callback that utilizes LibXML
 * error reporting #xmlGenericError function.
 */
void
xmlSecErrorsDefaultCallback(const char* file, int line, const char* func,
                            const char* errorObject, const char* errorSubject,
                            int reason, const char* msg) {
    if(xmlSecPrintErrorMessages) {
        const char* error_msg = NULL;
        xmlSecSize i;

        for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) {
            if(xmlSecErrorsGetCode(i) == reason) {
                error_msg = xmlSecErrorsGetMsg(i);
                break;
            }
        }
        xmlGenericError(xmlGenericErrorContext,
            "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:<%s>:<%s>\n",
            (func != NULL) ? func : "unknown",
            (file != NULL) ? file : "unknown",
            line,
            (errorObject != NULL) ? errorObject : "unknown",
            (errorSubject != NULL) ? errorSubject : "unknown",
            reason,
            (error_msg != NULL) ? error_msg : "",
            (msg != NULL) ? msg : "");
    }
}

/**
 * xmlSecErrorsDefaultCallbackEnableOutput:
 * @enabled:            the flag.
 *
 * Enables or disables calling LibXML2 callback from the default
 * errors callback.
 */
void
xmlSecErrorsDefaultCallbackEnableOutput(int enabled) {
    xmlSecPrintErrorMessages = enabled;
}

/**
 * xmlSecErrorsGetCode:
 * @pos:                the error position.
 *
 * Gets the known error code at position @pos.
 *
 * Returns: the known error code or 0 if @pos is greater than
 * total number of known error codes.
 */
int
xmlSecErrorsGetCode(xmlSecSize pos) {
    /* could not use asserts here! */
    if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
        return(xmlSecErrorsTable[pos].errorCode);
    }
    return(0);
}

/**
 * xmlSecErrorsGetMsg:
 * @pos:                the error position.
 *
 * Gets the known error message at position @pos.
 *
 * Returns: the known error message or NULL if @pos is greater than
 * total number of known error codes.
 */
const char*
xmlSecErrorsGetMsg(xmlSecSize pos) {
    /* could not use asserts here! */
    if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
        return(xmlSecErrorsTable[pos].errorMsg);
    }
    return(NULL);
}

/**
 * xmlSecError:
 * @file:               the error location filename (__FILE__).
 * @line:               the error location line number (__LINE__).
 * @func:               the error location function (__FUNCTIION__).
 * @errorObject:        the error specific error object
 * @errorSubject:       the error specific error subject.
 * @reason:             the error code.
 * @msg:                the error message in printf format.
 * @...:                the parameters for the @msg.
 *
 * Reports an error to the default (#xmlSecErrorsDefaultCallback) or
 * application specific callback installed using #xmlSecErrorsSetCallback
 * function.
 */
void
xmlSecError(const char* file, int line, const char* func,
            const char* errorObject, const char* errorSubject,
            int reason, const char* msg, ...) {

    if(xmlSecErrorsClbk != NULL) {
        xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE] = {'\0',};
        const char* e_msg = NULL;
        xmlSecSize i;
        int len = 0;

        if(xmlSecPrintErrorMessages == 0) {
            if(reason != XMLSEC_ERRORS_MAX_NUMBER) {
                for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) {
                    if(xmlSecErrorsGetCode(i) == reason) {
                        e_msg = xmlSecErrorsGetMsg(i);
                        snprintf(error_msg, sizeof(error_msg), "%s] [", e_msg);
                        len = strlen(error_msg);
                        break;
                    }
                }
            }
        }

        if(msg != NULL) {
            va_list va;
            va_start(va, msg);
            xmlSecStrVPrintf(error_msg + len, sizeof(error_msg) - len, BAD_CAST msg, va);
            error_msg[sizeof(error_msg) - 1] = '\0';
            va_end(va);
        } else {
            error_msg[0] = '\0';
        }
        xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg);
    }
}