diff options
Diffstat (limited to 'src/io.c')
-rw-r--r-- | src/io.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/src/io.c b/src/io.c new file mode 100644 index 00000000..42e91337 --- /dev/null +++ b/src/io.c @@ -0,0 +1,496 @@ +/** + * XML Security Library (http://www.aleksey.com/xmlsec). + * + * Input uri transform and utility functions. + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <libxml/uri.h> +#include <libxml/tree.h> +#include <libxml/xmlIO.h> + +#ifdef LIBXML_HTTP_ENABLED +#include <libxml/nanohttp.h> +#endif /* LIBXML_HTTP_ENABLED */ + +#ifdef LIBXML_FTP_ENABLED +#include <libxml/nanoftp.h> +#endif /* LIBXML_FTP_ENABLED */ + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/keys.h> +#include <xmlsec/io.h> +#include <xmlsec/errors.h> + +/******************************************************************* + * + * Input I/O callback sets + * + ******************************************************************/ +typedef struct _xmlSecIOCallback { + xmlInputMatchCallback matchcallback; + xmlInputOpenCallback opencallback; + xmlInputReadCallback readcallback; + xmlInputCloseCallback closecallback; +} xmlSecIOCallback, *xmlSecIOCallbackPtr; + +static xmlSecIOCallbackPtr xmlSecIOCallbackCreate (xmlInputMatchCallback matchFunc, + xmlInputOpenCallback openFunc, + xmlInputReadCallback readFunc, + xmlInputCloseCallback closeFunc); +static void xmlSecIOCallbackDestroy (xmlSecIOCallbackPtr callbacks); + +static xmlSecIOCallbackPtr +xmlSecIOCallbackCreate(xmlInputMatchCallback matchFunc, xmlInputOpenCallback openFunc, + xmlInputReadCallback readFunc, xmlInputCloseCallback closeFunc) { + xmlSecIOCallbackPtr callbacks; + + xmlSecAssert2(matchFunc != NULL, NULL); + + /* Allocate a new xmlSecIOCallback and fill the fields. */ + callbacks = (xmlSecIOCallbackPtr)xmlMalloc(sizeof(xmlSecIOCallback)); + if(callbacks == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + "sizeof(xmlSecIOCallback)=%d", + sizeof(xmlSecIOCallback)); + return(NULL); + } + memset(callbacks, 0, sizeof(xmlSecIOCallback)); + + callbacks->matchcallback = matchFunc; + callbacks->opencallback = openFunc; + callbacks->readcallback = readFunc; + callbacks->closecallback = closeFunc; + + return(callbacks); +} + +static void +xmlSecIOCallbackDestroy(xmlSecIOCallbackPtr callbacks) { + xmlSecAssert(callbacks != NULL); + + memset(callbacks, 0, sizeof(xmlSecIOCallback)); + xmlFree(callbacks); +} + +/******************************************************************* + * + * Input I/O callback list + * + ******************************************************************/ +static xmlSecPtrListKlass xmlSecIOCallbackPtrListKlass = { + BAD_CAST "io-callbacks-list", + NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ + (xmlSecPtrDestroyItemMethod)xmlSecIOCallbackDestroy,/* xmlSecPtrDestroyItemMethod destroyItem; */ + NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ + NULL /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ +}; + +#define xmlSecIOCallbackPtrListId xmlSecIOCallbackPtrListGetKlass () +static xmlSecPtrListId xmlSecIOCallbackPtrListGetKlass (void); +static xmlSecIOCallbackPtr xmlSecIOCallbackPtrListFind (xmlSecPtrListPtr list, + const char* uri); + +/** + * xmlSecIOCallbackPtrListGetKlass: + * + * The keys list klass. + * + * Returns: keys list id. + */ +static xmlSecPtrListId +xmlSecIOCallbackPtrListGetKlass(void) { + return(&xmlSecIOCallbackPtrListKlass); +} + +static xmlSecIOCallbackPtr +xmlSecIOCallbackPtrListFind(xmlSecPtrListPtr list, const char* uri) { + xmlSecIOCallbackPtr callbacks; + xmlSecSize i, size; + + xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecIOCallbackPtrListId), NULL); + xmlSecAssert2(uri != NULL, NULL); + + size = xmlSecPtrListGetSize(list); + for(i = 0; i < size; ++i) { + callbacks = (xmlSecIOCallbackPtr)xmlSecPtrListGetItem(list, i); + xmlSecAssert2(callbacks != NULL, NULL); + xmlSecAssert2(callbacks->matchcallback != NULL, NULL); + + if((callbacks->matchcallback(uri)) != 0) { + return(callbacks); + } + } + return(NULL); +} + +static xmlSecPtrList xmlSecAllIOCallbacks; + +/** + * xmlSecIOInit: + * + * The IO initialization (called from #xmlSecInit function). + * Applications should not call this function directly. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecIOInit(void) { + int ret; + + ret = xmlSecPtrListInitialize(&xmlSecAllIOCallbacks, xmlSecIOCallbackPtrListId); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListPtrInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + +#ifdef LIBXML_HTTP_ENABLED + xmlNanoHTTPInit(); +#endif /* LIBXML_HTTP_ENABLED */ + +#ifdef LIBXML_FTP_ENABLED + xmlNanoFTPInit(); +#endif /* LIBXML_FTP_ENABLED */ + + return(xmlSecIORegisterDefaultCallbacks()); +} + +/** + * xmlSecIOShutdown: + * + * The IO clenaup (called from #xmlSecShutdown function). + * Applications should not call this function directly. + */ +void +xmlSecIOShutdown(void) { + +#ifdef LIBXML_HTTP_ENABLED + xmlNanoHTTPCleanup(); +#endif /* LIBXML_HTTP_ENABLED */ + +#ifdef LIBXML_FTP_ENABLED + xmlNanoFTPCleanup(); +#endif /* LIBXML_FTP_ENABLED */ + + xmlSecPtrListFinalize(&xmlSecAllIOCallbacks); +} + +/** + * xmlSecIOCleanupCallbacks: + * + * Clears the entire input callback table. this includes the + * compiled-in I/O. + */ +void +xmlSecIOCleanupCallbacks(void) { + xmlSecPtrListEmpty(&xmlSecAllIOCallbacks); +} + +/** + * xmlSecIORegisterCallbacks: + * @matchFunc: the protocol match callback. + * @openFunc: the open stream callback. + * @readFunc: the read from stream callback. + * @closeFunc: the close stream callback. + * + * Register a new set of I/O callback for handling parser input. + * + * Returns: the 0 on success or a negative value if an error occurs. + */ +int +xmlSecIORegisterCallbacks(xmlInputMatchCallback matchFunc, + xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc, + xmlInputCloseCallback closeFunc) { + xmlSecIOCallbackPtr callbacks; + int ret; + + xmlSecAssert2(matchFunc != NULL, -1); + + callbacks = xmlSecIOCallbackCreate(matchFunc, openFunc, readFunc, closeFunc); + if(callbacks == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecIOCallbackCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecPtrListAdd(&xmlSecAllIOCallbacks, callbacks); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecPtrListAdd", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecIOCallbackDestroy(callbacks); + return(-1); + } + return(0); +} + + +/** + * xmlSecIORegisterDefaultCallbacks: + * + * Registers the default compiled-in I/O handlers. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecIORegisterDefaultCallbacks(void) { + int ret; + +#ifdef LIBXML_HTTP_ENABLED + ret = xmlSecIORegisterCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen, + xmlIOHTTPRead, xmlIOHTTPClose); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecIORegisterCallbacks", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "http"); + return(-1); + } +#endif /* LIBXML_HTTP_ENABLED */ + +#ifdef LIBXML_FTP_ENABLED + ret = xmlSecIORegisterCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, + xmlIOFTPRead, xmlIOFTPClose); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecIORegisterCallbacks", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ftp"); + return(-1); + } +#endif /* LIBXML_FTP_ENABLED */ + + ret = xmlSecIORegisterCallbacks(xmlFileMatch, xmlFileOpen, + xmlFileRead, xmlFileClose); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecIORegisterCallbacks", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "file"); + return(-1); + } + + return(0); +} + + + + +/************************************************************** + * + * Input URI Transform + * + * xmlSecInputURICtx is located after xmlSecTransform + * + **************************************************************/ +typedef struct _xmlSecInputURICtx xmlSecInputURICtx, + *xmlSecInputURICtxPtr; +struct _xmlSecInputURICtx { + xmlSecIOCallbackPtr clbks; + void* clbksCtx; +}; +#define xmlSecTransformInputUriSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecInputURICtx)) +#define xmlSecTransformInputUriGetCtx(transform) \ + ((xmlSecTransformCheckSize((transform), xmlSecTransformInputUriSize)) ? \ + (xmlSecInputURICtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \ + (xmlSecInputURICtxPtr)NULL) + +static int xmlSecTransformInputURIInitialize (xmlSecTransformPtr transform); +static void xmlSecTransformInputURIFinalize (xmlSecTransformPtr transform); +static int xmlSecTransformInputURIPopBin (xmlSecTransformPtr transform, + xmlSecByte* data, + xmlSecSize maxDataSize, + xmlSecSize* dataSize, + xmlSecTransformCtxPtr transformCtx); + +static xmlSecTransformKlass xmlSecTransformInputURIKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecTransformInputUriSize, /* xmlSecSize objSize */ + + BAD_CAST "input-uri", /* const xmlChar* name; */ + NULL, /* const xmlChar* href; */ + 0, /* xmlSecAlgorithmUsage usage; */ + + xmlSecTransformInputURIInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecTransformInputURIFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + NULL, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformInputURIPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + NULL, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecTransformInputURIGetKlass: + * + * The input uri transform klass. Reads binary data from an uri. + * + * Returns: input URI transform id. + */ +xmlSecTransformId +xmlSecTransformInputURIGetKlass(void) { + return(&xmlSecTransformInputURIKlass); +} + +/** + * xmlSecTransformInputURIOpen: + * @transform: the pointer to IO transform. + * @uri: the URL to open. + * + * Opens the given @uri for reading. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecTransformInputURIOpen(xmlSecTransformPtr transform, const xmlChar *uri) { + xmlSecInputURICtxPtr ctx; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1); + xmlSecAssert2(uri != NULL, -1); + + ctx = xmlSecTransformInputUriGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->clbks == NULL, -1); + xmlSecAssert2(ctx->clbksCtx == NULL, -1); + + /* + * Try to find one of the input accept method accepting that scheme + * Go in reverse to give precedence to user defined handlers. + * try with an unescaped version of the uri + */ + if(ctx->clbks == NULL) { + char *unescaped; + + unescaped = xmlURIUnescapeString((char*)uri, 0, NULL); + if (unescaped != NULL) { + ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, unescaped); + if(ctx->clbks != NULL) { + ctx->clbksCtx = ctx->clbks->opencallback(unescaped); + } + xmlFree(unescaped); + } + } + + /* + * If this failed try with a non-escaped uri this may be a strange + * filename + */ + if (ctx->clbks == NULL) { + ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, (char*)uri); + if(ctx->clbks != NULL) { + ctx->clbksCtx = ctx->clbks->opencallback((char*)uri); + } + } + + if((ctx->clbks == NULL) || (ctx->clbksCtx == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "opencallback", + XMLSEC_ERRORS_R_IO_FAILED, + "uri=%s;errno=%d", + xmlSecErrorsSafeString(uri), + errno); + return(-1); + } + + return(0); +} + +static int +xmlSecTransformInputURIInitialize(xmlSecTransformPtr transform) { + xmlSecInputURICtxPtr ctx; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1); + + ctx = xmlSecTransformInputUriGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecInputURICtx)); + return(0); +} + +static void +xmlSecTransformInputURIFinalize(xmlSecTransformPtr transform) { + xmlSecInputURICtxPtr ctx; + + xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId)); + + ctx = xmlSecTransformInputUriGetCtx(transform); + xmlSecAssert(ctx != NULL); + + if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->closecallback != NULL)) { + (ctx->clbks->closecallback)(ctx->clbksCtx); + } + memset(ctx, 0, sizeof(xmlSecInputURICtx)); +} + +static int +xmlSecTransformInputURIPopBin(xmlSecTransformPtr transform, xmlSecByte* data, + xmlSecSize maxDataSize, xmlSecSize* dataSize, + xmlSecTransformCtxPtr transformCtx) { + xmlSecInputURICtxPtr ctx; + + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(dataSize != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecTransformInputUriGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->readcallback != NULL)) { + ret = (ctx->clbks->readcallback)(ctx->clbksCtx, (char*)data, (int)maxDataSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "readcallback", + XMLSEC_ERRORS_R_IO_FAILED, + "errno=%d", errno); + return(-1); + } + (*dataSize) = ret; + } else { + (*dataSize) = 0; + } + return(0); +} + |