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