1 /*
2 * XML Security Library (http://www.aleksey.com/xmlsec).
3 *
4 *
5 * This is free software; see Copyright file in the source
6 * distribution for preciese wording.
7 *
8 * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9 */
10 /**
11 * SECTION:errors
12 * @Short_description: Error reporting and logging functions.
13 * @Stability: Stable
14 *
15 */
16
17 #include "globals.h"
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <time.h>
23 #include <string.h>
24
25 #include <libxml/tree.h>
26
27 #include <xmlsec/xmlsec.h>
28 #include <xmlsec/xmltree.h>
29 #include <xmlsec/private.h>
30 #include <xmlsec/errors.h>
31
32 /* Must be bigger than fatal_error */
33 #define XMLSEC_ERRORS_BUFFER_SIZE 1024
34
35 /* Must fit into xmlChar[XMLSEC_ERRORS_BUFFER_SIZE] */
36 static const xmlChar fatal_error[] = "Can not format error message";
37
38 typedef struct _xmlSecErrorDescription xmlSecErrorDescription, *xmlSecErrorDescriptionPtr;
39 struct _xmlSecErrorDescription {
40 int errorCode;
41 const char* errorMsg;
42 };
43
44 static xmlSecErrorDescription xmlSecErrorsTable[XMLSEC_ERRORS_MAX_NUMBER + 1] = {
45 { XMLSEC_ERRORS_R_XMLSEC_FAILED, "xmlsec library function failed" },
46 { XMLSEC_ERRORS_R_MALLOC_FAILED, "malloc function failed" },
47 { XMLSEC_ERRORS_R_STRDUP_FAILED, "strdup function failed" },
48 { XMLSEC_ERRORS_R_CRYPTO_FAILED, "crypto library function failed" },
49 { XMLSEC_ERRORS_R_XML_FAILED, "libxml2 library function failed" },
50 { XMLSEC_ERRORS_R_XSLT_FAILED, "libxslt library function failed" },
51 { XMLSEC_ERRORS_R_IO_FAILED, "io function failed" },
52 { XMLSEC_ERRORS_R_DISABLED, "feature is disabled" },
53 { XMLSEC_ERRORS_R_NOT_IMPLEMENTED, "feature is not implemented" },
54 { XMLSEC_ERRORS_R_INVALID_CONFIG, "invalid configuration" },
55 { XMLSEC_ERRORS_R_INVALID_SIZE, "invalid size" },
56 { XMLSEC_ERRORS_R_INVALID_DATA, "invalid data" },
57 { XMLSEC_ERRORS_R_INVALID_RESULT, "invalid result" },
58 { XMLSEC_ERRORS_R_INVALID_TYPE, "invalid type" },
59 { XMLSEC_ERRORS_R_INVALID_OPERATION, "invalid operation" },
60 { XMLSEC_ERRORS_R_INVALID_STATUS, "invalid status" },
61 { XMLSEC_ERRORS_R_INVALID_FORMAT, "invalid format" },
62 { XMLSEC_ERRORS_R_DATA_NOT_MATCH, "data do not match" },
63 { XMLSEC_ERRORS_R_INVALID_VERSION, "invalid version" },
64 { XMLSEC_ERRORS_R_INVALID_NODE, "invalid node" },
65 { XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, "invalid node content" },
66 { XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, "invalid node attribute" },
67 { XMLSEC_ERRORS_R_MISSING_NODE_ATTRIBUTE, "missing node attribute" },
68 { XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, "node already present" },
69 { XMLSEC_ERRORS_R_UNEXPECTED_NODE, "unexpected node" },
70 { XMLSEC_ERRORS_R_NODE_NOT_FOUND, "node node found" },
71 { XMLSEC_ERRORS_R_INVALID_TRANSFORM, "invalid transform" },
72 { XMLSEC_ERRORS_R_INVALID_TRANSFORM_KEY, "invalid transform key" },
73 { XMLSEC_ERRORS_R_INVALID_URI_TYPE, "invalid URI type" },
74 { XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED, "same document is required for transform" },
75 { XMLSEC_ERRORS_R_TRANSFORM_DISABLED, "transform is disabled" },
76 { XMLSEC_ERRORS_R_INVALID_KEY_DATA, "invalid key data" },
77 { XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND, "key data is not found" },
78 { XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST, "key data already exist" },
79 { XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, "invalid key data size" },
80 { XMLSEC_ERRORS_R_KEY_NOT_FOUND, "key is not found" },
81 { XMLSEC_ERRORS_R_KEYDATA_DISABLED, "key data is disabled" },
82 { XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL, "maximum key retrieval level" },
83 { XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,"key retrieval type mismatch" },
84 { XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL, "maximum encrypted key level" },
85 { XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, "certificate verification failed" },
86 { XMLSEC_ERRORS_R_CERT_NOT_FOUND, "certificate is not found" },
87 { XMLSEC_ERRORS_R_CERT_REVOKED, "certificate is revoked" },
88 { XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "certificate issuer check failed" },
89 { XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, "certificate is not yet valid" },
90 { XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "certificate has expired" },
91 { XMLSEC_ERRORS_R_DSIG_NO_REFERENCES, "Reference nodes are not found" },
92 { XMLSEC_ERRORS_R_DSIG_INVALID_REFERENCE, "Reference verification failed" },
93 { XMLSEC_ERRORS_R_ASSERTION, "assertion" },
94 { 0, NULL}
95 };
96
97 static xmlSecErrorsCallback xmlSecErrorsClbk = xmlSecErrorsDefaultCallback;
98 static int xmlSecPrintErrorMessages = 1; /* whether the error messages will be printed immediately */
99
100 /**
101 * xmlSecErrorsInit:
102 *
103 * Initializes the errors reporting. It is called from #xmlSecInit function.
104 * and applications must not call this function directly.
105 */
106 void
xmlSecErrorsInit(void)107 xmlSecErrorsInit(void) {
108 }
109
110 /**
111 * xmlSecErrorsShutdown:
112 *
113 * Cleanups the errors reporting. It is called from #xmlSecShutdown function.
114 * and applications must not call this function directly.
115 */
116 void
xmlSecErrorsShutdown(void)117 xmlSecErrorsShutdown(void) {
118 }
119
120 /**
121 * xmlSecErrorsSetCallback:
122 * @callback: the new errors callback function.
123 *
124 * Sets the errors callback function to @callback that will be called
125 * every time an error occurs.
126 */
127 void
xmlSecErrorsSetCallback(xmlSecErrorsCallback callback)128 xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) {
129 xmlSecErrorsClbk = callback;
130 }
131
132 /**
133 * xmlSecErrorsDefaultCallback:
134 * @file: the error location file name (__FILE__ macro).
135 * @line: the error location line number (__LINE__ macro).
136 * @func: the error location function name (__FUNCTION__ macro).
137 * @errorObject: the error specific error object
138 * @errorSubject: the error specific error subject.
139 * @reason: the error code.
140 * @msg: the additional error message.
141 *
142 * The default error reporting callback that utilizes LibXML
143 * error reporting #xmlGenericError function.
144 */
145 void
xmlSecErrorsDefaultCallback(const char * file,int line,const char * func,const char * errorObject,const char * errorSubject,int reason,const char * msg)146 xmlSecErrorsDefaultCallback(const char* file, int line, const char* func,
147 const char* errorObject, const char* errorSubject,
148 int reason, const char* msg) {
149 if(xmlSecPrintErrorMessages) {
150 const char* error_msg = NULL;
151 xmlSecSize i;
152
153 for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) {
154 if(xmlSecErrorsGetCode(i) == reason) {
155 error_msg = xmlSecErrorsGetMsg(i);
156 break;
157 }
158 }
159 xmlGenericError(xmlGenericErrorContext,
160 "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s:%s\n",
161 (func != NULL) ? func : "unknown",
162 (file != NULL) ? file : "unknown",
163 line,
164 (errorObject != NULL) ? errorObject : "unknown",
165 (errorSubject != NULL) ? errorSubject : "unknown",
166 reason,
167 (error_msg != NULL) ? error_msg : "",
168 (msg != NULL) ? msg : "");
169 }
170 }
171
172 /**
173 * xmlSecErrorsDefaultCallbackEnableOutput:
174 * @enabled: the flag.
175 *
176 * Enables or disables calling LibXML2 callback from the default
177 * errors callback.
178 */
179 void
xmlSecErrorsDefaultCallbackEnableOutput(int enabled)180 xmlSecErrorsDefaultCallbackEnableOutput(int enabled) {
181 xmlSecPrintErrorMessages = enabled;
182 }
183
184 /**
185 * xmlSecErrorsGetCode:
186 * @pos: the error position.
187 *
188 * Gets the known error code at position @pos.
189 *
190 * Returns: the known error code or 0 if @pos is greater than
191 * total number of known error codes.
192 */
193 int
xmlSecErrorsGetCode(xmlSecSize pos)194 xmlSecErrorsGetCode(xmlSecSize pos) {
195 /* could not use asserts here! */
196 if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
197 return(xmlSecErrorsTable[pos].errorCode);
198 }
199 return(0);
200 }
201
202 /**
203 * xmlSecErrorsGetMsg:
204 * @pos: the error position.
205 *
206 * Gets the known error message at position @pos.
207 *
208 * Returns: the known error message or NULL if @pos is greater than
209 * total number of known error codes.
210 */
211 const char*
xmlSecErrorsGetMsg(xmlSecSize pos)212 xmlSecErrorsGetMsg(xmlSecSize pos) {
213 /* could not use asserts here! */
214 if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
215 return(xmlSecErrorsTable[pos].errorMsg);
216 }
217 return(NULL);
218 }
219
220 /**
221 * xmlSecError:
222 * @file: the error location filename (__FILE__).
223 * @line: the error location line number (__LINE__).
224 * @func: the error location function (__FUNCTION__).
225 * @errorObject: the error specific error object (e.g. transform, key data, etc).
226 * @errorSubject: the error specific error subject (e.g. failed function name).
227 * @reason: the error code.
228 * @msg: the error message in printf format.
229 * @...: the parameters for the @msg.
230 *
231 * Reports an error to the default (#xmlSecErrorsDefaultCallback) or
232 * application specific callback installed using #xmlSecErrorsSetCallback
233 * function.
234 */
235 void
xmlSecError(const char * file,int line,const char * func,const char * errorObject,const char * errorSubject,int reason,const char * msg,...)236 xmlSecError(const char* file, int line, const char* func,
237 const char* errorObject, const char* errorSubject,
238 int reason, const char* msg, ...) {
239 if(xmlSecErrorsClbk != NULL) {
240 xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE];
241 int ret;
242
243 if(msg != NULL) {
244 va_list va;
245
246 va_start(va, msg);
247 ret = xmlStrVPrintf(error_msg, sizeof(error_msg), msg, va);
248 if(ret < 0) {
249 /* Can't really report an error from an error callback */
250 memcpy(error_msg, fatal_error, sizeof(fatal_error));
251 }
252 error_msg[sizeof(error_msg) - 1] = '\0'; /* just in case */
253 va_end(va);
254 } else {
255 error_msg[0] = '\0';
256 }
257 xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg);
258 }
259 }
260