2 * XML Security Library (http://www.aleksey.com/xmlsec).
4 * Input uri transform and utility functions.
6 * This is free software; see Copyright file in the source
7 * distribution for preciese wording.
9 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
17 #include <libxml/uri.h>
18 #include <libxml/tree.h>
19 #include <libxml/xmlIO.h>
21 #ifdef LIBXML_HTTP_ENABLED
22 #include <libxml/nanohttp.h>
23 #endif /* LIBXML_HTTP_ENABLED */
25 #ifdef LIBXML_FTP_ENABLED
26 #include <libxml/nanoftp.h>
27 #endif /* LIBXML_FTP_ENABLED */
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>
36 /*******************************************************************
38 * Input I/O callback sets
40 ******************************************************************/
41 typedef struct _xmlSecIOCallback {
42 xmlInputMatchCallback matchcallback;
43 xmlInputOpenCallback opencallback;
44 xmlInputReadCallback readcallback;
45 xmlInputCloseCallback closecallback;
46 } xmlSecIOCallback, *xmlSecIOCallbackPtr;
48 static xmlSecIOCallbackPtr xmlSecIOCallbackCreate (xmlInputMatchCallback matchFunc,
49 xmlInputOpenCallback openFunc,
50 xmlInputReadCallback readFunc,
51 xmlInputCloseCallback closeFunc);
52 static void xmlSecIOCallbackDestroy (xmlSecIOCallbackPtr callbacks);
54 static xmlSecIOCallbackPtr
55 xmlSecIOCallbackCreate(xmlInputMatchCallback matchFunc, xmlInputOpenCallback openFunc,
56 xmlInputReadCallback readFunc, xmlInputCloseCallback closeFunc) {
57 xmlSecIOCallbackPtr callbacks;
59 xmlSecAssert2(matchFunc != NULL, NULL);
61 /* Allocate a new xmlSecIOCallback and fill the fields. */
62 callbacks = (xmlSecIOCallbackPtr)xmlMalloc(sizeof(xmlSecIOCallback));
63 if(callbacks == NULL) {
64 xmlSecError(XMLSEC_ERRORS_HERE,
67 XMLSEC_ERRORS_R_MALLOC_FAILED,
68 "sizeof(xmlSecIOCallback)=%d",
69 sizeof(xmlSecIOCallback));
72 memset(callbacks, 0, sizeof(xmlSecIOCallback));
74 callbacks->matchcallback = matchFunc;
75 callbacks->opencallback = openFunc;
76 callbacks->readcallback = readFunc;
77 callbacks->closecallback = closeFunc;
83 xmlSecIOCallbackDestroy(xmlSecIOCallbackPtr callbacks) {
84 xmlSecAssert(callbacks != NULL);
86 memset(callbacks, 0, sizeof(xmlSecIOCallback));
90 /*******************************************************************
92 * Input I/O callback list
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; */
103 #define xmlSecIOCallbackPtrListId xmlSecIOCallbackPtrListGetKlass ()
104 static xmlSecPtrListId xmlSecIOCallbackPtrListGetKlass (void);
105 static xmlSecIOCallbackPtr xmlSecIOCallbackPtrListFind (xmlSecPtrListPtr list,
109 * xmlSecIOCallbackPtrListGetKlass:
111 * The keys list klass.
113 * Returns: keys list id.
115 static xmlSecPtrListId
116 xmlSecIOCallbackPtrListGetKlass(void) {
117 return(&xmlSecIOCallbackPtrListKlass);
120 static xmlSecIOCallbackPtr
121 xmlSecIOCallbackPtrListFind(xmlSecPtrListPtr list, const char* uri) {
122 xmlSecIOCallbackPtr callbacks;
125 xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecIOCallbackPtrListId), NULL);
126 xmlSecAssert2(uri != NULL, NULL);
128 size = xmlSecPtrListGetSize(list);
129 for(i = 0; i < size; ++i) {
130 callbacks = (xmlSecIOCallbackPtr)xmlSecPtrListGetItem(list, i);
131 xmlSecAssert2(callbacks != NULL, NULL);
132 xmlSecAssert2(callbacks->matchcallback != NULL, NULL);
134 if((callbacks->matchcallback(uri)) != 0) {
141 static xmlSecPtrList xmlSecAllIOCallbacks;
146 * The IO initialization (called from #xmlSecInit function).
147 * Applications should not call this function directly.
149 * Returns: 0 on success or a negative value otherwise.
155 ret = xmlSecPtrListInitialize(&xmlSecAllIOCallbacks, xmlSecIOCallbackPtrListId);
157 xmlSecError(XMLSEC_ERRORS_HERE,
159 "xmlSecPtrListPtrInitialize",
160 XMLSEC_ERRORS_R_XMLSEC_FAILED,
161 XMLSEC_ERRORS_NO_MESSAGE);
165 #ifdef LIBXML_HTTP_ENABLED
167 #endif /* LIBXML_HTTP_ENABLED */
169 #ifdef LIBXML_FTP_ENABLED
171 #endif /* LIBXML_FTP_ENABLED */
173 return(xmlSecIORegisterDefaultCallbacks());
179 * The IO clenaup (called from #xmlSecShutdown function).
180 * Applications should not call this function directly.
183 xmlSecIOShutdown(void) {
185 #ifdef LIBXML_HTTP_ENABLED
186 xmlNanoHTTPCleanup();
187 #endif /* LIBXML_HTTP_ENABLED */
189 #ifdef LIBXML_FTP_ENABLED
191 #endif /* LIBXML_FTP_ENABLED */
193 xmlSecPtrListFinalize(&xmlSecAllIOCallbacks);
197 * xmlSecIOCleanupCallbacks:
199 * Clears the entire input callback table. this includes the
203 xmlSecIOCleanupCallbacks(void) {
204 xmlSecPtrListEmpty(&xmlSecAllIOCallbacks);
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.
214 * Register a new set of I/O callback for handling parser input.
216 * Returns: the 0 on success or a negative value if an error occurs.
219 xmlSecIORegisterCallbacks(xmlInputMatchCallback matchFunc,
220 xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
221 xmlInputCloseCallback closeFunc) {
222 xmlSecIOCallbackPtr callbacks;
225 xmlSecAssert2(matchFunc != NULL, -1);
227 callbacks = xmlSecIOCallbackCreate(matchFunc, openFunc, readFunc, closeFunc);
228 if(callbacks == NULL) {
229 xmlSecError(XMLSEC_ERRORS_HERE,
231 "xmlSecIOCallbackCreate",
232 XMLSEC_ERRORS_R_XMLSEC_FAILED,
233 XMLSEC_ERRORS_NO_MESSAGE);
237 ret = xmlSecPtrListAdd(&xmlSecAllIOCallbacks, callbacks);
239 xmlSecError(XMLSEC_ERRORS_HERE,
242 XMLSEC_ERRORS_R_XMLSEC_FAILED,
243 XMLSEC_ERRORS_NO_MESSAGE);
244 xmlSecIOCallbackDestroy(callbacks);
252 * xmlSecIORegisterDefaultCallbacks:
254 * Registers the default compiled-in I/O handlers.
256 * Returns: 0 on success or a negative value otherwise.
259 xmlSecIORegisterDefaultCallbacks(void) {
262 #ifdef LIBXML_HTTP_ENABLED
263 ret = xmlSecIORegisterCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
264 xmlIOHTTPRead, xmlIOHTTPClose);
266 xmlSecError(XMLSEC_ERRORS_HERE,
268 "xmlSecIORegisterCallbacks",
269 XMLSEC_ERRORS_R_XMLSEC_FAILED,
273 #endif /* LIBXML_HTTP_ENABLED */
275 #ifdef LIBXML_FTP_ENABLED
276 ret = xmlSecIORegisterCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
277 xmlIOFTPRead, xmlIOFTPClose);
279 xmlSecError(XMLSEC_ERRORS_HERE,
281 "xmlSecIORegisterCallbacks",
282 XMLSEC_ERRORS_R_XMLSEC_FAILED,
286 #endif /* LIBXML_FTP_ENABLED */
288 ret = xmlSecIORegisterCallbacks(xmlFileMatch, xmlFileOpen,
289 xmlFileRead, xmlFileClose);
291 xmlSecError(XMLSEC_ERRORS_HERE,
293 "xmlSecIORegisterCallbacks",
294 XMLSEC_ERRORS_R_XMLSEC_FAILED,
305 /**************************************************************
307 * Input URI Transform
309 * xmlSecInputURICtx is located after xmlSecTransform
311 **************************************************************/
312 typedef struct _xmlSecInputURICtx xmlSecInputURICtx,
313 *xmlSecInputURICtxPtr;
314 struct _xmlSecInputURICtx {
315 xmlSecIOCallbackPtr clbks;
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)
325 static int xmlSecTransformInputURIInitialize (xmlSecTransformPtr transform);
326 static void xmlSecTransformInputURIFinalize (xmlSecTransformPtr transform);
327 static int xmlSecTransformInputURIPopBin (xmlSecTransformPtr transform,
329 xmlSecSize maxDataSize,
330 xmlSecSize* dataSize,
331 xmlSecTransformCtxPtr transformCtx);
333 static xmlSecTransformKlass xmlSecTransformInputURIKlass = {
334 /* klass/object sizes */
335 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
336 xmlSecTransformInputUriSize, /* xmlSecSize objSize */
338 BAD_CAST "input-uri", /* const xmlChar* name; */
339 NULL, /* const xmlChar* href; */
340 0, /* xmlSecAlgorithmUsage usage; */
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; */
356 NULL, /* void* reserved0; */
357 NULL, /* void* reserved1; */
361 * xmlSecTransformInputURIGetKlass:
363 * The input uri transform klass. Reads binary data from an uri.
365 * Returns: input URI transform id.
368 xmlSecTransformInputURIGetKlass(void) {
369 return(&xmlSecTransformInputURIKlass);
373 * xmlSecTransformInputURIOpen:
374 * @transform: the pointer to IO transform.
375 * @uri: the URL to open.
377 * Opens the given @uri for reading.
379 * Returns: 0 on success or a negative value otherwise.
382 xmlSecTransformInputURIOpen(xmlSecTransformPtr transform, const xmlChar *uri) {
383 xmlSecInputURICtxPtr ctx;
385 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
386 xmlSecAssert2(uri != NULL, -1);
388 ctx = xmlSecTransformInputUriGetCtx(transform);
389 xmlSecAssert2(ctx != NULL, -1);
390 xmlSecAssert2(ctx->clbks == NULL, -1);
391 xmlSecAssert2(ctx->clbksCtx == NULL, -1);
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
398 if(ctx->clbks == NULL) {
401 unescaped = xmlURIUnescapeString((char*)uri, 0, NULL);
402 if (unescaped != NULL) {
403 ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, unescaped);
404 if(ctx->clbks != NULL) {
405 ctx->clbksCtx = ctx->clbks->opencallback(unescaped);
412 * If this failed try with a non-escaped uri this may be a strange
415 if (ctx->clbks == NULL) {
416 ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, (char*)uri);
417 if(ctx->clbks != NULL) {
418 ctx->clbksCtx = ctx->clbks->opencallback((char*)uri);
422 if((ctx->clbks == NULL) || (ctx->clbksCtx == NULL)) {
423 xmlSecError(XMLSEC_ERRORS_HERE,
424 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
426 XMLSEC_ERRORS_R_IO_FAILED,
428 xmlSecErrorsSafeString(uri),
437 xmlSecTransformInputURIInitialize(xmlSecTransformPtr transform) {
438 xmlSecInputURICtxPtr ctx;
440 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
442 ctx = xmlSecTransformInputUriGetCtx(transform);
443 xmlSecAssert2(ctx != NULL, -1);
445 memset(ctx, 0, sizeof(xmlSecInputURICtx));
450 xmlSecTransformInputURIFinalize(xmlSecTransformPtr transform) {
451 xmlSecInputURICtxPtr ctx;
453 xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId));
455 ctx = xmlSecTransformInputUriGetCtx(transform);
456 xmlSecAssert(ctx != NULL);
458 if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->closecallback != NULL)) {
459 (ctx->clbks->closecallback)(ctx->clbksCtx);
461 memset(ctx, 0, sizeof(xmlSecInputURICtx));
465 xmlSecTransformInputURIPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
466 xmlSecSize maxDataSize, xmlSecSize* dataSize,
467 xmlSecTransformCtxPtr transformCtx) {
468 xmlSecInputURICtxPtr ctx;
472 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
473 xmlSecAssert2(data != NULL, -1);
474 xmlSecAssert2(dataSize != NULL, -1);
475 xmlSecAssert2(transformCtx != NULL, -1);
477 ctx = xmlSecTransformInputUriGetCtx(transform);
478 xmlSecAssert2(ctx != NULL, -1);
480 if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->readcallback != NULL)) {
481 ret = (ctx->clbks->readcallback)(ctx->clbksCtx, (char*)data, (int)maxDataSize);
483 xmlSecError(XMLSEC_ERRORS_HERE,
484 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
486 XMLSEC_ERRORS_R_IO_FAILED,