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