/**
* XML Security Library (http://www.aleksey.com/xmlsec).
*
* Enveloped transform.
*
* This is free software; see Copyright file in the source
* distribution for preciese wording.
*
* Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
* Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
*/
#include "xmlsec_globals.h"
#include <stdlib.h>
#include <string.h>
#include <stdapis/libxml2/libxml2_tree.h>
#include <stdapis/libxml2/libxml2_xpath.h>
#include <stdapis/libxml2/libxml2_xpathinternals.h>
#include "xmlsec_xmlsec.h"
#include "xmlsec_xmltree.h"
#include "xmlsec_keys.h"
#include "xmlsec_transforms.h"
#include "xmlsec_errors.h"
/**************************************************************************
*
* Enveloped transform
*
*************************************************************************/
static int xmlSecTransformEnvelopedExecute (xmlSecTransformPtr transform,
int last,
xmlSecTransformCtxPtr transformCtx);
static xmlSecTransformKlass xmlSecTransformEnvelopedKlass = {
/* klass/object sizes */
sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
sizeof(xmlSecTransform), /* xmlSecSize objSize */
xmlSecNameEnveloped, /* const xmlChar* name; */
xmlSecHrefEnveloped, /* const xmlChar* href; */
xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
NULL, /* xmlSecTransformInitializeMethod initialize; */
NULL, /* xmlSecTransformFinalizeMethod finalize; */
NULL, /* xmlSecTransformNodeReadMethod readNode; */
NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
NULL, /* xmlSecTransformSetKeyMethod setKey; */
NULL, /* xmlSecTransformValidateMethod validate; */
xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
NULL, /* xmlSecTransformPushBinMethod pushBin; */
NULL, /* xmlSecTransformPopBinMethod popBin; */
xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
xmlSecTransformEnvelopedExecute, /* xmlSecTransformExecuteMethod execute; */
NULL, /* void* reserved0; */
NULL, /* void* reserved1; */
};
/**
* xmlSecTransformEnvelopedGetKlass:
*
* The enveloped transform klass (http://www.w3.org/TR/xmldsig-core/#sec-EnvelopedSignature):
*
* An enveloped signature transform T removes the whole Signature element
* containing T from the digest calculation of the Reference element
* containing T. The entire string of characters used by an XML processor
* to match the Signature with the XML production element is removed.
* The output of the transform is equivalent to the output that would
* result from replacing T with an XPath transform containing the following
* XPath parameter element:
*
* <XPath xmlns:dsig="&dsig;">
* count(ancestor-or-self::dsig:Signature |
* here()/ancestor::dsig:Signature[1]) >
* count(ancestor-or-self::dsig:Signature)</XPath>
*
* The input and output requirements of this transform are identical to
* those of the XPath transform, but may only be applied to a node-set from
* its parent XML document. Note that it is not necessary to use an XPath
* expression evaluator to create this transform. However, this transform
* MUST produce output in exactly the same manner as the XPath transform
* parameterized by the XPath expression above.
*
* Returns enveloped transform id.
*/
EXPORT_C
xmlSecTransformId
xmlSecTransformEnvelopedGetKlass(void) {
return(&xmlSecTransformEnvelopedKlass);
}
static int
xmlSecTransformEnvelopedExecute(xmlSecTransformPtr transform, int last,
xmlSecTransformCtxPtr transformCtx) {
xmlNodePtr node;
xmlSecNodeSetPtr children;
xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformEnvelopedId), -1);
xmlSecAssert2(transform->hereNode != NULL, -1);
xmlSecAssert2(transform->outNodes == NULL, -1);
xmlSecAssert2(last != 0, -1);
xmlSecAssert2(transformCtx != NULL, -1);
if((transform->inNodes != NULL) && (transform->inNodes->doc != transform->hereNode->doc)) {
xmlSecError(XMLSEC_ERRORS_HERE,
xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
NULL,
XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED,
XMLSEC_ERRORS_NO_MESSAGE);
return(-1);
}
/* find signature node and get all its children in the nodes set */
node = xmlSecFindParent(transform->hereNode, xmlSecNodeSignature, xmlSecDSigNs);
if(node == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
xmlSecErrorsSafeString(xmlSecNodeSignature),
XMLSEC_ERRORS_R_NODE_NOT_FOUND,
XMLSEC_ERRORS_NO_MESSAGE);
return(-1);
}
children = xmlSecNodeSetGetChildren(node->doc, node, 1, 1);
if(children == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
"xmlSecNodeSetGetChildren",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
"node=%s",
xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
return(-1);
}
/* intersect <dsig:Signature/> node children with input nodes (if exist) */
transform->outNodes = xmlSecNodeSetAdd(transform->inNodes, children, xmlSecNodeSetIntersection);
if(transform->outNodes == NULL) {
xmlSecError(XMLSEC_ERRORS_HERE,
xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
"xmlSecNodeSetAdd",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
xmlSecNodeSetDestroy(children);
return(-1);
}
return(0);
}