/**
* 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 "xmlsec_globals.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h> //added for symbian
#include <libxml2_tree.h>
#include <libxml2_uri.h>
#include <libxml2_xmlio.h>
#include <libxml2_globals.h>
#ifdef LIBXML_HTTP_ENABLED
#include <libxml2_nanohttp.h>
#endif /* LIBXML_HTTP_ENABLED */
#ifdef LIBXML_FTP_ENABLED
#include <libxml2_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.
*/
EXPORT_C
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.
*/
EXPORT_C
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.
*/
EXPORT_C
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.
*/
EXPORT_C
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.
*/
EXPORT_C
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.
*/
EXPORT_C
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.
*/
EXPORT_C
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);
}