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