|
1 /** |
|
2 * XML Security Library (http://www.aleksey.com/xmlsec). |
|
3 * |
|
4 * Input uri transform and utility functions. |
|
5 * |
|
6 * This is free software; see Copyright file in the source |
|
7 * distribution for preciese wording. |
|
8 * |
|
9 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> |
|
10 */ |
|
11 #include "xmlsec_globals.h" |
|
12 |
|
13 #include <stdlib.h> |
|
14 #include <string.h> |
|
15 #include <errno.h> |
|
16 |
|
17 #include <stdio.h> //added for symbian |
|
18 |
|
19 #include <libxml2_tree.h> |
|
20 #include <libxml2_uri.h> |
|
21 #include <libxml2_xmlio.h> |
|
22 #include <libxml2_globals.h> |
|
23 |
|
24 #ifdef LIBXML_HTTP_ENABLED |
|
25 #include <libxml2_nanohttp.h> |
|
26 #endif /* LIBXML_HTTP_ENABLED */ |
|
27 |
|
28 #ifdef LIBXML_FTP_ENABLED |
|
29 #include <libxml2_nanoftp.h> |
|
30 #endif /* LIBXML_FTP_ENABLED */ |
|
31 |
|
32 #include "xmlsec_xmlsec.h" |
|
33 #include "xmlsec_keys.h" |
|
34 #include "xmlsec_transforms.h" |
|
35 #include "xmlsec_keys.h" |
|
36 #include "xmlsec_io.h" |
|
37 #include "xmlsec_errors.h" |
|
38 |
|
39 /******************************************************************* |
|
40 * |
|
41 * Input I/O callback sets |
|
42 * |
|
43 ******************************************************************/ |
|
44 typedef struct _xmlSecIOCallback { |
|
45 xmlInputMatchCallback matchcallback; |
|
46 xmlInputOpenCallback opencallback; |
|
47 xmlInputReadCallback readcallback; |
|
48 xmlInputCloseCallback closecallback; |
|
49 } xmlSecIOCallback, *xmlSecIOCallbackPtr; |
|
50 |
|
51 static xmlSecIOCallbackPtr xmlSecIOCallbackCreate (xmlInputMatchCallback matchFunc, |
|
52 xmlInputOpenCallback openFunc, |
|
53 xmlInputReadCallback readFunc, |
|
54 xmlInputCloseCallback closeFunc); |
|
55 static void xmlSecIOCallbackDestroy (xmlSecIOCallbackPtr callbacks); |
|
56 |
|
57 static xmlSecIOCallbackPtr |
|
58 xmlSecIOCallbackCreate(xmlInputMatchCallback matchFunc, xmlInputOpenCallback openFunc, |
|
59 xmlInputReadCallback readFunc, xmlInputCloseCallback closeFunc) { |
|
60 xmlSecIOCallbackPtr callbacks; |
|
61 |
|
62 xmlSecAssert2(matchFunc != NULL, NULL); |
|
63 |
|
64 /* Allocate a new xmlSecIOCallback and fill the fields. */ |
|
65 callbacks = (xmlSecIOCallbackPtr)xmlMalloc(sizeof(xmlSecIOCallback)); |
|
66 if(callbacks == NULL) { |
|
67 xmlSecError(XMLSEC_ERRORS_HERE, |
|
68 NULL, |
|
69 NULL, |
|
70 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
71 "sizeof(xmlSecIOCallback)=%d", |
|
72 sizeof(xmlSecIOCallback)); |
|
73 return(NULL); |
|
74 } |
|
75 memset(callbacks, 0, sizeof(xmlSecIOCallback)); |
|
76 |
|
77 callbacks->matchcallback = matchFunc; |
|
78 callbacks->opencallback = openFunc; |
|
79 callbacks->readcallback = readFunc; |
|
80 callbacks->closecallback = closeFunc; |
|
81 |
|
82 return(callbacks); |
|
83 } |
|
84 |
|
85 static void |
|
86 xmlSecIOCallbackDestroy(xmlSecIOCallbackPtr callbacks) { |
|
87 xmlSecAssert(callbacks != NULL); |
|
88 |
|
89 memset(callbacks, 0, sizeof(xmlSecIOCallback)); |
|
90 xmlFree(callbacks); |
|
91 } |
|
92 |
|
93 /******************************************************************* |
|
94 * |
|
95 * Input I/O callback list |
|
96 * |
|
97 ******************************************************************/ |
|
98 static xmlSecPtrListKlass xmlSecIOCallbackPtrListKlass = { |
|
99 BAD_CAST "io-callbacks-list", |
|
100 NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ |
|
101 (xmlSecPtrDestroyItemMethod)xmlSecIOCallbackDestroy,/* xmlSecPtrDestroyItemMethod destroyItem; */ |
|
102 NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ |
|
103 NULL /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ |
|
104 }; |
|
105 |
|
106 #define xmlSecIOCallbackPtrListId xmlSecIOCallbackPtrListGetKlass () |
|
107 static xmlSecPtrListId xmlSecIOCallbackPtrListGetKlass (void); |
|
108 static xmlSecIOCallbackPtr xmlSecIOCallbackPtrListFind (xmlSecPtrListPtr list, |
|
109 const char* uri); |
|
110 |
|
111 /** |
|
112 * xmlSecIOCallbackPtrListGetKlass: |
|
113 * |
|
114 * The keys list klass. |
|
115 * |
|
116 * Returns keys list id. |
|
117 */ |
|
118 static xmlSecPtrListId |
|
119 xmlSecIOCallbackPtrListGetKlass(void) { |
|
120 return(&xmlSecIOCallbackPtrListKlass); |
|
121 } |
|
122 |
|
123 static xmlSecIOCallbackPtr |
|
124 xmlSecIOCallbackPtrListFind(xmlSecPtrListPtr list, const char* uri) { |
|
125 xmlSecIOCallbackPtr callbacks; |
|
126 xmlSecSize i, size; |
|
127 |
|
128 xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecIOCallbackPtrListId), NULL); |
|
129 xmlSecAssert2(uri != NULL, NULL); |
|
130 |
|
131 size = xmlSecPtrListGetSize(list); |
|
132 for(i = 0; i < size; ++i) { |
|
133 callbacks = (xmlSecIOCallbackPtr)xmlSecPtrListGetItem(list, i); |
|
134 xmlSecAssert2(callbacks != NULL, NULL); |
|
135 xmlSecAssert2(callbacks->matchcallback != NULL, NULL); |
|
136 |
|
137 if((callbacks->matchcallback(uri)) != 0) { |
|
138 return(callbacks); |
|
139 } |
|
140 } |
|
141 return(NULL); |
|
142 } |
|
143 |
|
144 static xmlSecPtrList xmlSecAllIOCallbacks; |
|
145 |
|
146 /** |
|
147 * xmlSecIOInit: |
|
148 * |
|
149 * The IO initialization (called from #xmlSecInit function). |
|
150 * Applications should not call this function directly. |
|
151 * |
|
152 * Returns 0 on success or a negative value otherwise. |
|
153 */ |
|
154 EXPORT_C |
|
155 int |
|
156 xmlSecIOInit(void) { |
|
157 int ret; |
|
158 |
|
159 ret = xmlSecPtrListInitialize(&xmlSecAllIOCallbacks, xmlSecIOCallbackPtrListId); |
|
160 if(ret < 0) { |
|
161 xmlSecError(XMLSEC_ERRORS_HERE, |
|
162 NULL, |
|
163 "xmlSecPtrListPtrInitialize", |
|
164 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
165 XMLSEC_ERRORS_NO_MESSAGE); |
|
166 return(-1); |
|
167 } |
|
168 |
|
169 #ifdef LIBXML_HTTP_ENABLED |
|
170 xmlNanoHTTPInit(); |
|
171 #endif /* LIBXML_HTTP_ENABLED */ |
|
172 |
|
173 #ifdef LIBXML_FTP_ENABLED |
|
174 xmlNanoFTPInit(); |
|
175 #endif /* LIBXML_FTP_ENABLED */ |
|
176 |
|
177 return(xmlSecIORegisterDefaultCallbacks()); |
|
178 } |
|
179 |
|
180 /** |
|
181 * xmlSecIOShutdown: |
|
182 * |
|
183 * The IO clenaup (called from #xmlSecShutdown function). |
|
184 * Applications should not call this function directly. |
|
185 */ |
|
186 EXPORT_C |
|
187 void |
|
188 xmlSecIOShutdown(void) { |
|
189 |
|
190 #ifdef LIBXML_HTTP_ENABLED |
|
191 xmlNanoHTTPCleanup(); |
|
192 #endif /* LIBXML_HTTP_ENABLED */ |
|
193 |
|
194 #ifdef LIBXML_FTP_ENABLED |
|
195 xmlNanoFTPCleanup(); |
|
196 #endif /* LIBXML_FTP_ENABLED */ |
|
197 |
|
198 xmlSecPtrListFinalize(&xmlSecAllIOCallbacks); |
|
199 } |
|
200 |
|
201 /** |
|
202 * xmlSecIOCleanupCallbacks: |
|
203 * |
|
204 * Clears the entire input callback table. this includes the |
|
205 * compiled-in I/O. |
|
206 */ |
|
207 EXPORT_C |
|
208 void |
|
209 xmlSecIOCleanupCallbacks(void) { |
|
210 xmlSecPtrListEmpty(&xmlSecAllIOCallbacks); |
|
211 } |
|
212 |
|
213 /** |
|
214 * xmlSecIORegisterCallbacks: |
|
215 * @matchFunc: the protocol match callback. |
|
216 * @openFunc: the open stream callback. |
|
217 * @readFunc: the read from stream callback. |
|
218 * @closeFunc: the close stream callback. |
|
219 * |
|
220 * Register a new set of I/O callback for handling parser input. |
|
221 * |
|
222 * Returns the 0 on success or a negative value if an error occurs. |
|
223 */ |
|
224 EXPORT_C |
|
225 int |
|
226 xmlSecIORegisterCallbacks(xmlInputMatchCallback matchFunc, |
|
227 xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc, |
|
228 xmlInputCloseCallback closeFunc) { |
|
229 xmlSecIOCallbackPtr callbacks; |
|
230 int ret; |
|
231 |
|
232 xmlSecAssert2(matchFunc != NULL, -1); |
|
233 |
|
234 callbacks = xmlSecIOCallbackCreate(matchFunc, openFunc, readFunc, closeFunc); |
|
235 if(callbacks == NULL) { |
|
236 xmlSecError(XMLSEC_ERRORS_HERE, |
|
237 NULL, |
|
238 "xmlSecIOCallbackCreate", |
|
239 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
240 XMLSEC_ERRORS_NO_MESSAGE); |
|
241 return(-1); |
|
242 } |
|
243 |
|
244 ret = xmlSecPtrListAdd(&xmlSecAllIOCallbacks, callbacks); |
|
245 if(ret < 0) { |
|
246 xmlSecError(XMLSEC_ERRORS_HERE, |
|
247 NULL, |
|
248 "xmlSecPtrListAdd", |
|
249 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
250 XMLSEC_ERRORS_NO_MESSAGE); |
|
251 xmlSecIOCallbackDestroy(callbacks); |
|
252 return(-1); |
|
253 } |
|
254 return(0); |
|
255 } |
|
256 |
|
257 |
|
258 /** |
|
259 * xmlSecIORegisterDefaultCallbacks: |
|
260 * |
|
261 * Registers the default compiled-in I/O handlers. |
|
262 * |
|
263 * Returns 0 on success or a negative value otherwise. |
|
264 */ |
|
265 EXPORT_C |
|
266 int |
|
267 xmlSecIORegisterDefaultCallbacks(void) { |
|
268 int ret; |
|
269 |
|
270 #ifdef LIBXML_HTTP_ENABLED |
|
271 ret = xmlSecIORegisterCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen, |
|
272 xmlIOHTTPRead, xmlIOHTTPClose); |
|
273 if(ret < 0) { |
|
274 xmlSecError(XMLSEC_ERRORS_HERE, |
|
275 NULL, |
|
276 "xmlSecIORegisterCallbacks", |
|
277 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
278 "http"); |
|
279 return(-1); |
|
280 } |
|
281 #endif /* LIBXML_HTTP_ENABLED */ |
|
282 |
|
283 #ifdef LIBXML_FTP_ENABLED |
|
284 ret = xmlSecIORegisterCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, |
|
285 xmlIOFTPRead, xmlIOFTPClose); |
|
286 if(ret < 0) { |
|
287 xmlSecError(XMLSEC_ERRORS_HERE, |
|
288 NULL, |
|
289 "xmlSecIORegisterCallbacks", |
|
290 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
291 "ftp"); |
|
292 return(-1); |
|
293 } |
|
294 #endif /* LIBXML_FTP_ENABLED */ |
|
295 |
|
296 ret = xmlSecIORegisterCallbacks(xmlFileMatch, xmlFileOpen, |
|
297 xmlFileRead, xmlFileClose); |
|
298 if(ret < 0) { |
|
299 xmlSecError(XMLSEC_ERRORS_HERE, |
|
300 NULL, |
|
301 "xmlSecIORegisterCallbacks", |
|
302 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
303 "file"); |
|
304 return(-1); |
|
305 } |
|
306 |
|
307 return(0); |
|
308 } |
|
309 |
|
310 |
|
311 |
|
312 |
|
313 /************************************************************** |
|
314 * |
|
315 * Input URI Transform |
|
316 * |
|
317 * xmlSecInputURICtx is located after xmlSecTransform |
|
318 * |
|
319 **************************************************************/ |
|
320 typedef struct _xmlSecInputURICtx xmlSecInputURICtx, |
|
321 *xmlSecInputURICtxPtr; |
|
322 struct _xmlSecInputURICtx { |
|
323 xmlSecIOCallbackPtr clbks; |
|
324 void* clbksCtx; |
|
325 }; |
|
326 #define xmlSecTransformInputUriSize \ |
|
327 (sizeof(xmlSecTransform) + sizeof(xmlSecInputURICtx)) |
|
328 #define xmlSecTransformInputUriGetCtx(transform) \ |
|
329 ((xmlSecTransformCheckSize((transform), xmlSecTransformInputUriSize)) ? \ |
|
330 (xmlSecInputURICtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \ |
|
331 (xmlSecInputURICtxPtr)NULL) |
|
332 |
|
333 static int xmlSecTransformInputURIInitialize (xmlSecTransformPtr transform); |
|
334 static void xmlSecTransformInputURIFinalize (xmlSecTransformPtr transform); |
|
335 static int xmlSecTransformInputURIPopBin (xmlSecTransformPtr transform, |
|
336 xmlSecByte* data, |
|
337 xmlSecSize maxDataSize, |
|
338 xmlSecSize* dataSize, |
|
339 xmlSecTransformCtxPtr transformCtx); |
|
340 |
|
341 static xmlSecTransformKlass xmlSecTransformInputURIKlass = { |
|
342 /* klass/object sizes */ |
|
343 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
344 xmlSecTransformInputUriSize, /* xmlSecSize objSize */ |
|
345 |
|
346 BAD_CAST "input-uri", /* const xmlChar* name; */ |
|
347 NULL, /* const xmlChar* href; */ |
|
348 0, /* xmlSecAlgorithmUsage usage; */ |
|
349 |
|
350 xmlSecTransformInputURIInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
351 xmlSecTransformInputURIFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
352 NULL, /* xmlSecTransformNodeReadMethod readNode; */ |
|
353 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
354 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ |
|
355 NULL, /* xmlSecTransformSetKeyMethod setKey; */ |
|
356 NULL, /* xmlSecTransformValidateMethod validate; */ |
|
357 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
358 NULL, /* xmlSecTransformPushBinMethod pushBin; */ |
|
359 xmlSecTransformInputURIPopBin, /* xmlSecTransformPopBinMethod popBin; */ |
|
360 NULL, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
361 NULL, /* xmlSecTransformPopXmlMethod popXml; */ |
|
362 NULL, /* xmlSecTransformExecuteMethod execute; */ |
|
363 |
|
364 NULL, /* void* reserved0; */ |
|
365 NULL, /* void* reserved1; */ |
|
366 }; |
|
367 |
|
368 /** |
|
369 * xmlSecTransformInputURIGetKlass: |
|
370 * |
|
371 * The input uri transform klass. Reads binary data from an uri. |
|
372 * |
|
373 * Returns input URI transform id. |
|
374 */ |
|
375 EXPORT_C |
|
376 xmlSecTransformId |
|
377 xmlSecTransformInputURIGetKlass(void) { |
|
378 return(&xmlSecTransformInputURIKlass); |
|
379 } |
|
380 |
|
381 /** |
|
382 * xmlSecTransformInputURIOpen: |
|
383 * @transform: the pointer to IO transform. |
|
384 * @uri: the URL to open. |
|
385 * |
|
386 * Opens the given @uri for reading. |
|
387 * |
|
388 * Returns 0 on success or a negative value otherwise. |
|
389 */ |
|
390 EXPORT_C |
|
391 int |
|
392 xmlSecTransformInputURIOpen(xmlSecTransformPtr transform, const xmlChar *uri) { |
|
393 xmlSecInputURICtxPtr ctx; |
|
394 |
|
395 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1); |
|
396 xmlSecAssert2(uri != NULL, -1); |
|
397 |
|
398 ctx = xmlSecTransformInputUriGetCtx(transform); |
|
399 xmlSecAssert2(ctx != NULL, -1); |
|
400 xmlSecAssert2(ctx->clbks == NULL, -1); |
|
401 xmlSecAssert2(ctx->clbksCtx == NULL, -1); |
|
402 |
|
403 /* |
|
404 * Try to find one of the input accept method accepting that scheme |
|
405 * Go in reverse to give precedence to user defined handlers. |
|
406 * try with an unescaped version of the uri |
|
407 */ |
|
408 if(ctx->clbks == NULL) { |
|
409 char *unescaped; |
|
410 |
|
411 unescaped = xmlURIUnescapeString((char*)uri, 0, NULL); |
|
412 if (unescaped != NULL) { |
|
413 ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, unescaped); |
|
414 if(ctx->clbks != NULL) { |
|
415 ctx->clbksCtx = ctx->clbks->opencallback(unescaped); |
|
416 } |
|
417 xmlFree(unescaped); |
|
418 } |
|
419 } |
|
420 |
|
421 /* |
|
422 * If this failed try with a non-escaped uri this may be a strange |
|
423 * filename |
|
424 */ |
|
425 if (ctx->clbks == NULL) { |
|
426 ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, (char*)uri); |
|
427 if(ctx->clbks != NULL) { |
|
428 ctx->clbksCtx = ctx->clbks->opencallback((char*)uri); |
|
429 } |
|
430 } |
|
431 |
|
432 if((ctx->clbks == NULL) || (ctx->clbksCtx == NULL)) { |
|
433 xmlSecError(XMLSEC_ERRORS_HERE, |
|
434 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
435 "opencallback", |
|
436 XMLSEC_ERRORS_R_IO_FAILED, |
|
437 "uri=%s;errno=%d", |
|
438 xmlSecErrorsSafeString(uri), |
|
439 errno); |
|
440 return(-1); |
|
441 } |
|
442 |
|
443 return(0); |
|
444 } |
|
445 |
|
446 static int |
|
447 xmlSecTransformInputURIInitialize(xmlSecTransformPtr transform) { |
|
448 xmlSecInputURICtxPtr ctx; |
|
449 |
|
450 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1); |
|
451 |
|
452 ctx = xmlSecTransformInputUriGetCtx(transform); |
|
453 xmlSecAssert2(ctx != NULL, -1); |
|
454 |
|
455 memset(ctx, 0, sizeof(xmlSecInputURICtx)); |
|
456 return(0); |
|
457 } |
|
458 |
|
459 static void |
|
460 xmlSecTransformInputURIFinalize(xmlSecTransformPtr transform) { |
|
461 xmlSecInputURICtxPtr ctx; |
|
462 |
|
463 xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId)); |
|
464 |
|
465 ctx = xmlSecTransformInputUriGetCtx(transform); |
|
466 xmlSecAssert(ctx != NULL); |
|
467 |
|
468 if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->closecallback != NULL)) { |
|
469 (ctx->clbks->closecallback)(ctx->clbksCtx); |
|
470 } |
|
471 memset(ctx, 0, sizeof(xmlSecInputURICtx)); |
|
472 } |
|
473 |
|
474 static int |
|
475 xmlSecTransformInputURIPopBin(xmlSecTransformPtr transform, xmlSecByte* data, |
|
476 xmlSecSize maxDataSize, xmlSecSize* dataSize, |
|
477 xmlSecTransformCtxPtr transformCtx) { |
|
478 xmlSecInputURICtxPtr ctx; |
|
479 |
|
480 int ret; |
|
481 |
|
482 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1); |
|
483 xmlSecAssert2(data != NULL, -1); |
|
484 xmlSecAssert2(dataSize != NULL, -1); |
|
485 xmlSecAssert2(transformCtx != NULL, -1); |
|
486 |
|
487 ctx = xmlSecTransformInputUriGetCtx(transform); |
|
488 xmlSecAssert2(ctx != NULL, -1); |
|
489 |
|
490 if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->readcallback != NULL)) { |
|
491 ret = (ctx->clbks->readcallback)(ctx->clbksCtx, (char*)data, (int)maxDataSize); |
|
492 if(ret < 0) { |
|
493 xmlSecError(XMLSEC_ERRORS_HERE, |
|
494 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
495 "readcallback", |
|
496 XMLSEC_ERRORS_R_IO_FAILED, |
|
497 "errno=%d", errno); |
|
498 return(-1); |
|
499 } |
|
500 (*dataSize) = ret; |
|
501 } else { |
|
502 (*dataSize) = 0; |
|
503 } |
|
504 return(0); |
|
505 } |
|
506 |